From 66526ad4a5c3635640ee0bb4ab51c525ee041755 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sun, 18 Oct 2026 17:05:00 +0200 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D1=83=D1=8E=20?= =?UTF-8?q?=D0=BF=D0=B0=D1=87=D0=BA=D1=83=20GPU=20=D1=87=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B7=20=D1=82=D1=80=D0=B0=D0=BD=D1=81=D0=BF=D0=BE=D1=80=D1=82?= =?UTF-8?q?=20=D0=B8=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D1=82=D1=8C=20?= =?UTF-8?q?JNI=20=D0=B2=D0=B8=D0=B4=D0=B5=D0=BE=D0=BF=D0=BE=D1=80=D1=82?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_call.c | 23 +++++++++++++------ .../jni_bridge/android_call_video_jni.c | 2 +- tools/chatgui/src/call_video_engine.cpp | 5 ++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/tests/test_call.c b/tests/test_call.c index 4ec56eee..c0f3b92f 100644 --- a/tests/test_call.c +++ b/tests/test_call.c @@ -151,8 +151,9 @@ static unsigned g_video_keys[2]; static int g_port_frame; static void port_received(void *arg, const struct call_video_frame *f) { (void)arg; - g_port_frame = f->frame_id == 1 && f->format.generation == 1 && f->size == sizeof(g_video_data) - && !memcmp(f->data, g_video_data, sizeof(g_video_data)) ? 1 : -1; + if (g_port_frame >= 0 && f->frame_id == (uint64_t)g_port_frame + 1 && f->format.generation == 1 + && f->size == sizeof(g_video_data) && !memcmp(f->data, g_video_data, sizeof(g_video_data))) ++g_port_frame; + else g_port_frame = -1; } 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]++; } @@ -684,8 +685,15 @@ static void call_tick(void* arg) { struct call_video_port_status status; if (call_video_port_status(t->call_id, &status) || status.configured_generation != 1) break; struct call_video_frame f = video_test_frame(t->call_id, 1); + struct call_video_frame batch[3] = {f, f, f}; + for (unsigned i = 1; i < 3; ++i) { batch[i].frame_id += i; batch[i].pts_us += i * 33333; batch[i].flags = 0; } + ++batch[1].call_id; + if (call_video_port_send(batch, 3) != -1) { + DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video port accepted mixed-call batch"); t->result = 2; break; + } + --batch[1].call_id; if (status.minimum_bps != 300000 || status.maximum_bps != 500000 - || call_video_port_send(&f) != 1 || call_video_port_send(&f) != 0) { + || call_video_port_send(batch, 3) != 1 || call_video_port_send(batch, 3) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video port TX mailbox/range mismatch"); t->result = 2; break; } struct call_capture_time timing = sent_timing; timing.pts_us += 200000; @@ -695,7 +703,8 @@ static void call_tick(void* arg) { } case P_VIDEO_PORT_ACK: { if (!g_port_frame) break; - if (g_port_frame != 1) { DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video port TX payload mismatch"); t->result = 2; break; } + if (g_port_frame < 0) { DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video port TX payload mismatch"); t->result = 2; break; } + if (g_port_frame != 3) break; if (call_video_decode_result(A, t->call_id, 1, 1) || call_video_decode_result(A, t->call_id, 2, 0) != -1) { t->result = 2; break; } t->phase = P_VIDEO_DECODE_OK; break; @@ -710,12 +719,12 @@ static void call_tick(void* arg) { struct call_video_port_status status; if (call_video_port_status(t->call_id, &status) || status.decoded_generation != 1 || status.decoded_accepted) break; if (++t->phase_ticks < 10) break; // Регулятор не должен отменять запрет decoder на следующем tick. - struct call_video_frame f = video_test_frame(t->call_id, 1); f.frame_id = 2; f.pts_us += 33333; + struct call_video_frame f = video_test_frame(t->call_id, 1); f.frame_id = 4; f.pts_us += 99999; if (call_video_send_frame(B, &f) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video ignored decoder rejection"); t->result = 2; break; } // Все команды попадут в uasync после синхронного ENDED; TX ещё принадлежит mailbox. if (call_video_port_format(t->call_id, &f.format, 500000) || call_video_port_applied(t->call_id, 1, 1, 500000) - || call_video_port_decoded(t->call_id, 1, 1) || call_video_port_send(&f) != 1) { + || call_video_port_decoded(t->call_id, 1, 1) || call_video_port_send(&f, 1) != 1) { DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video teardown commands were not queued"); t->result = 2; break; } call_video_port_request_key(t->call_id); @@ -731,7 +740,7 @@ static void call_tick(void* arg) { case P_VIDEO_PORT_CANCELLED: { struct call_video_port_status status; struct call_video_frame f = video_test_frame(t->call_id, 1); - if (call_video_port_status(t->call_id, &status) != -1 || call_video_port_send(&f) != -1 || g_port_frame != 1) { + if (call_video_port_status(t->call_id, &status) != -1 || call_video_port_send(&f, 1) != -1 || g_port_frame != 3) { DEBUG_ERROR(DEBUG_CATEGORY_CALL, "ended video port retained commands or accepted a late frame"); t->result = 2; break; } call_video_port_close(t->call_id); // Повторное закрытие после отмены команд. diff --git a/tools/chatgui-android/jni_bridge/android_call_video_jni.c b/tools/chatgui-android/jni_bridge/android_call_video_jni.c index 18261940..e4ef3ca3 100644 --- a/tools/chatgui-android/jni_bridge/android_call_video_jni.c +++ b/tools/chatgui-android/jni_bridge/android_call_video_jni.c @@ -79,7 +79,7 @@ JNIEXPORT jint JNICALL Java_com_utun_chat_data_CallVideoNative_send( jbyte *data = (*e)->GetByteArrayElements(e, bytes, NULL); if (!data) return -1; f.call_id = id; f.frame_id = values[9]; f.pts_us = values[10]; f.flags = values[11]; f.size = f.length = size; f.data = (uint8_t *)data; - int result = call_video_port_send(&f); (*e)->ReleaseByteArrayElements(e, bytes, data, JNI_ABORT); return result; + int result = call_video_port_send(&f, 1); (*e)->ReleaseByteArrayElements(e, bytes, data, JNI_ABORT); return result; } JNIEXPORT jbyteArray JNICALL Java_com_utun_chat_data_CallVideoNative_pull(JNIEnv *e, jobject o, jlong id, jlongArray meta) { (void)o; diff --git a/tools/chatgui/src/call_video_engine.cpp b/tools/chatgui/src/call_video_engine.cpp index f1c249a1..659f6d06 100644 --- a/tools/chatgui/src/call_video_engine.cpp +++ b/tools/chatgui/src/call_video_engine.cpp @@ -271,12 +271,13 @@ void CallVideoEngine::transmit() { expired += count; forceKey = true; continue; } forceKey = call_video_port_send(packets, count) != 1; } - for (const auto& output : outputs) { + for (unsigned i = 0; i < count; ++i) { + const auto& output = outputs[i]; // Одинаковое окно исходного PTS на всех этапах: примерно один кадр в секунду, без трассы каждого кадра. if (output.pts % 1000000 < 34000) DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "video timing stage=encode call=%llu frame=%llu pts=%lld mono_us=%lld encode_us=%lld accepted=%d", - (unsigned long long)m->id, (unsigned long long)(frameId - count + 1 + &output - outputs.constData()), + (unsigned long long)m->id, (unsigned long long)(frameId - count + i + 1), (long long)output.pts, (long long)nowUs(), (long long)(nowUs() - encodeStarted), !forceKey); }