diff --git a/tests/test_android_stream.c b/tests/test_android_stream.c index c5a76597..fa276adf 100644 --- a/tests/test_android_stream.c +++ b/tests/test_android_stream.c @@ -39,7 +39,7 @@ static void chat_event(struct UTUN_INSTANCE *inst, int type, const uint8_t *data static uint8_t *wait_event(uint64_t id, int kind, size_t *size) { for (unsigned i = 0; i < 1000; i++) { - if (id == 2 && kind == 5) CHECK(android_stream_read_request(id, 1000000, 80000, 80000) == 0); + if (id == 2) CHECK(android_stream_read_request(id, kind == 5 ? 1000000 : -1, 1, 80000) == 0); uint8_t *data = android_stream_pull(id, size); if (data && data[0] == kind) return data; u_free(data); test_clock_poll(ua, 100); @@ -91,7 +91,7 @@ int main(void) { CHECK(feed(1, 0, 100000, 0, (const uint8_t *)"ops", 3) == 1); uint8_t *output = NULL; int video_seen = 0, audio_seen = 0; for (unsigned i = 0; i < 1000 && (!video_seen || !audio_seen); i++) { - CHECK(android_stream_read_request(2, 100000, 80000, 80000) == 0); + CHECK(android_stream_read_request(2, 100000, 1, 80000) == 0); output = android_stream_pull(2, &size); if (output && output[0] == 1) { CHECK(size == sizeof(video) + ANDROID_STREAM_HEADER_SIZE && stream_read_be(output + 8, 8) == 100000 && !memcmp(output + ANDROID_STREAM_HEADER_SIZE, video, sizeof(video))); @@ -115,7 +115,7 @@ int main(void) { next_format.video_codec = STREAM_MEDIA_H265; video_seen = audio_seen = 0; for (unsigned i = 0; i < 1000 && (!video_seen || !audio_seen); i++) { - CHECK(android_stream_read_request(2, 300000, 80000, 80000) == 0); + CHECK(android_stream_read_request(2, 300000, 1, 80000) == 0); output = android_stream_pull(2, &size); if (output && output[0] == 1) { CHECK(stream_read_be(output + 8, 8) == 300000 && stream_read_be(output + 20, 4) == 2 && output[24] == STREAM_MEDIA_H265); @@ -135,7 +135,7 @@ int main(void) { CHECK(feed(1, 0, audio_pts, 0, (const uint8_t *)"ops", 3) == 1); video_seen = audio_seen = 0; for (unsigned i = 0; i < 1000 && (!video_seen || !audio_seen); i++) { - CHECK(android_stream_read_request(2, (int64_t)video_pts, 80000, 80000) == 0); + CHECK(android_stream_read_request(2, (int64_t)video_pts, 1, 80000) == 0); output = android_stream_pull(2, &size); if (output && output[0] == 1) { CHECK(stream_read_be(output + 8, 8) == video_pts && stream_read_be(output + 20, 4) == next_format.revision); @@ -150,6 +150,21 @@ int main(void) { struct stream_member_state after_switch; CHECK(stream_member_load(inst, group, inst->node_id, &after_switch, NULL) == STREAM_OK); CHECK(after_switch.published && after_switch.source.source_epoch == member.source.source_epoch); + /* Повторные запросы готовят один ответ; получение ответа не создаёт скрытую следующую копию. */ + for (unsigned i = 0; i < 5; i++) + CHECK(android_stream_feed(1, 1, 800000 + i * 40000, 0, video, sizeof(video), &next_format) == 1); + for (unsigned i = 0; i < 50; i++) { CHECK(android_stream_read_request(2, 700000, 1, -1) == 0); test_clock_poll(ua, 100); } + output = android_stream_pull(2, &size); CHECK(output && output[0] == 1 && stream_read_be(output + 8, 8) == 800000); u_free(output); + test_clock_run_for(ua, 1000); CHECK(!android_stream_pull(2, &size)); + CHECK(android_stream_read_request(2, 700000, 0, -1) == 0); test_clock_run_for(ua, 1000); + CHECK(!android_stream_pull(2, &size)); + for (unsigned frame = 1; frame < 5; frame++) { + output = NULL; + for (unsigned i = 0; i < 1000 && !output; i++) { + CHECK(android_stream_read_request(2, 700000, 1, -1) == 0); test_clock_poll(ua, 100); output = android_stream_pull(2, &size); + } + CHECK(output && output[0] == 1 && stream_read_be(output + 8, 8) == 800000 + frame * 40000); u_free(output); + } android_stream_stop(1); u_free(wait_event(2, 5, &size)); android_stream_stop(2); u_free(wait_event(1, 5, &size)); while ((output = android_stream_pull(2, &size))) u_free(output); CHECK(!strcmp(source_snapshot, "[]")); diff --git a/tests/test_stream_playback.c b/tests/test_stream_playback.c index 5536310c..75120d48 100644 --- a/tests/test_stream_playback.c +++ b/tests/test_stream_playback.c @@ -155,6 +155,30 @@ static void test_shared_media_ring(void) { DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] media ring: independent readers, authenticated frozen parts, lookahead, expiry, GAP and EOF"); } +/* Конвейер decoder получает восемь кадров при неподвижных часах; запрет видео сохраняет его cursor. */ +static void test_decoder_demand(void) { + uint8_t key[32] = {4}; struct stream_encoder *encoder = NULL; struct stream_buffer *buffer = NULL; + struct stream_media_store *store = NULL; struct stream_media_cursor *cursor = NULL; + CHECK(stream_encoder_create(&encoder, &descriptor, key) == STREAM_OK); + CHECK(stream_buffer_create(&buffer, &descriptor, stream_encoder_public_key(encoder), 256 * 1300) == STREAM_OK); + CHECK(stream_media_store_create(&store, buffer, &descriptor) == STREAM_OK); + CHECK(stream_media_cursor_create(&cursor, store, 3) == STREAM_OK); + for (unsigned i = 0; i < 8; i++) append_media(encoder, buffer, store, i, i * 66666u, i ? 0 : STREAM_MEDIA_KEY, 0); + struct stream_media_packet packet; + CHECK(stream_media_cursor_read(cursor, 0, 0, -1, &packet) == STREAM_WAIT); + for (unsigned i = 0; i < 8; i++) { + CHECK(stream_media_cursor_read(cursor, 0, 1, -1, &packet) == STREAM_OK && packet.kind == STREAM_MEDIA_READ_VIDEO); + CHECK(packet.video.pts_us == i * 66666u); + if (i == 2) { + CHECK(stream_media_cursor_read(cursor, 0, 0, 0, &packet) == STREAM_OK && packet.kind == STREAM_MEDIA_READ_AUDIO); + CHECK(packet.audio.pts_us == 0); + } + } + CHECK(stream_media_cursor_read(cursor, 0, 2, -1, &packet) == STREAM_ERR_ARGUMENT); + stream_media_cursor_destroy(cursor); stream_media_store_destroy(store); stream_buffer_destroy(buffer); stream_encoder_destroy(encoder); + DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] decoder demand: eight frames beyond 80ms at frozen PTS, independent audio and disabled video cursor"); +} + /* Полный кадр уже в общем кольце: MORE продолжает ограниченную сборку без новых сетевых событий. */ static void test_large_frame_budget(void) { uint8_t key[32] = {2}; struct stream_encoder *encoder = NULL; struct stream_buffer *buffer = NULL; @@ -239,7 +263,7 @@ int main(void) { size_t allocations = u_get_allocated_count(); for (unsigned i = 0; i < sizeof(video_bytes); i++) video_bytes[i] = (uint8_t)(i * 71 + 3); test_history_correction(); test_catchup_device_queue(); test_invalid_and_sampling_gap(); test_shared_media_ring(); - test_large_frame_budget(); test_media_discontinuity(); + test_decoder_demand(); test_large_frame_budget(); test_media_discontinuity(); CHECK(u_get_allocated_count() == allocations); return 0; }