|
|
|
|
@ -63,6 +63,7 @@ enum call_phase {
|
|
|
|
|
P_SEND_MEDIA, /* A: call_send_media (тестовый Opus-кадр) */ |
|
|
|
|
P_WAIT_MEDIA, /* B: media_recv_cb получил кадр */ |
|
|
|
|
P_VIDEO_CONFIG, P_VIDEO_SEND, P_VIDEO_HOLD, P_VIDEO_BUSY, P_VIDEO_RESUME, P_VIDEO_RANGE_WAIT, P_VIDEO_SWITCH, P_VIDEO_SWITCH_WAIT, |
|
|
|
|
P_VIDEO_SHRINK_WAIT, |
|
|
|
|
P_HANGUP, /* A: call_hangup */ |
|
|
|
|
P_WAIT_ENDED1, /* обе ENDED */ |
|
|
|
|
P_CALL2_START, /* A: call_start (2-й звонок) */ |
|
|
|
|
@ -119,7 +120,9 @@ static int g_video_frames, g_video_ready, g_video_error;
|
|
|
|
|
static uint64_t g_rate_generation, g_rate_request; |
|
|
|
|
static uint32_t g_rate_bps; |
|
|
|
|
static unsigned g_rate_commands; |
|
|
|
|
static unsigned g_video_keys[2]; |
|
|
|
|
static void video_caps(void *arg, const struct call_video_caps *caps) { g_video_peer[(size_t)arg] = *caps; } |
|
|
|
|
static void video_need_key(void *arg) { g_video_keys[(size_t)arg]++; } |
|
|
|
|
static int video_ready(void *arg, uint32_t bytes) { (void)arg; return bytes <= sizeof(g_video_data) && g_video_ready; } |
|
|
|
|
static void video_frame(void *arg, const struct call_video_frame *f) { |
|
|
|
|
(void)arg; |
|
|
|
|
@ -132,7 +135,7 @@ static void video_bitrate(void *arg, uint64_t generation, uint64_t request, uint
|
|
|
|
|
(void)arg; g_rate_generation = generation; g_rate_request = request; g_rate_bps = bps; g_rate_commands++; |
|
|
|
|
} |
|
|
|
|
static const struct call_video_ops video_ops = { |
|
|
|
|
.capabilities = video_caps, .receive_ready = video_ready, .frame = video_frame, .bitrate = video_bitrate |
|
|
|
|
.capabilities = video_caps, .receive_ready = video_ready, .frame = video_frame, .bitrate = video_bitrate, .need_key = video_need_key |
|
|
|
|
}; |
|
|
|
|
static struct call_video_frame video_test_frame(uint64_t id, unsigned generation) { |
|
|
|
|
struct call_video_frame f = {0}; |
|
|
|
|
@ -582,8 +585,24 @@ static void call_tick(void* arg) {
|
|
|
|
|
struct call_video_frame f = video_test_frame(t->call_id, 3); |
|
|
|
|
if (call_video_configure_rate(A, t->call_id, &f.format, 350000, 400000)) { t->result = 2; break; } |
|
|
|
|
if (call_video_send_frame(A, &f) != 1) { t->result = 2; break; } |
|
|
|
|
struct call_video_caps caps = g_video_peer[0]; caps.decode[0].maximum_bps = 3000000; |
|
|
|
|
g_video_keys[0] = 0; |
|
|
|
|
if (call_video_configure(B, t->call_id, &caps, &video_ops, (void*)1)) { t->result = 2; break; } |
|
|
|
|
} |
|
|
|
|
t->phase = P_VIDEO_SHRINK_WAIT; break; |
|
|
|
|
case P_VIDEO_SHRINK_WAIT: { |
|
|
|
|
if (g_video_peer[0].decode[0].maximum_bps != 3000000 || !g_video_keys[0]) break; |
|
|
|
|
if (g_video_frames != 2) { DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video escaped changed peer envelope"); t->result = 2; break; } |
|
|
|
|
struct call_video_frame f = video_test_frame(t->call_id, 3); f.format.maximum_bps = 3000000; |
|
|
|
|
if (call_video_configure_rate(A, t->call_id, &f.format, 350000, 400000) != -1) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video envelope changed without new generation"); t->result = 2; break; |
|
|
|
|
} |
|
|
|
|
f.format.generation = f.frame_id = 4; |
|
|
|
|
if (call_video_configure_rate(A, t->call_id, &f.format, 350000, 400000) || call_video_send_frame(A, &f) != 1) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video failed to replace withdrawn envelope"); t->result = 2; break; |
|
|
|
|
} |
|
|
|
|
t->phase = P_HANGUP; break; |
|
|
|
|
} |
|
|
|
|
case P_HANGUP: |
|
|
|
|
call_hangup(A, t->call_id); |
|
|
|
|
t->phase = P_WAIT_ENDED1; |
|
|
|
|
|