Define audio paced lossless video scheduling interface

This commit is contained in:
evgeny committed 2026-10-19 17:21:07 +02:00
1 parent 02a11f7d0a
commit 7cbe5375d4
3 files changed
+9 -7

No files matched your search

+1
View File
@@ -16,6 +16,7 @@ struct call_clock_snapshot {
uint64_t epoch, source_epoch, played_samples, written_samples; uint64_t epoch, source_epoch, played_samples, written_samples;
int64_t pts_us; int64_t pts_us;
uint32_t held_back_us; uint32_t held_back_us;
uint32_t rate_ppm; // Фактический шаг source PTS в текущем PCM-участке; 1000000 = 1x, 0 = удержание.
int valid, measured; int valid, measured;
}; };
#endif #endif
+1
View File
@@ -169,5 +169,6 @@ call_clock_snapshot CallTimeline::clock(int64_t nowUs) {
result.held_back_us = pts < lastPts ? (uint32_t)(lastPts - pts) : 0; result.held_back_us = pts < lastPts ? (uint32_t)(lastPts - pts) : 0;
lastPts = std::max(pts, lastPts); lastPts = std::max(pts, lastPts);
result.pts_us = lastPts; result.valid = 1; result.pts_us = lastPts; result.valid = 1;
result.rate_ppm = (uint32_t)std::llround(std::max(0.0, (s.end - s.pts) / (s.count * sampleUs)) * 1000000);
return result; return result;
} }
+7 -7
View File
@@ -1,20 +1,20 @@
/* Общий таймер показа видео, один владелец — RX worker. Изображениями не владеет. /* Общий таймер показа видео, один владелец — RX worker. Изображениями не владеет.
* poll вызывается для первого готового decoded кадра; next — следующий готовый кадр или NULL. * poll вызывается для первого готового decoded кадра; next — следующий готовый кадр или NULL.
* SHOW/DROP потребляют первый кадр, WAIT сохраняет его. Подача decoder продолжается независимо от WAIT. * SHOW/DROP_ORDER потребляют первый кадр, WAIT сохраняет его. Decoder работает по свободным output-буферам.
* received_us ставится на входе RX port, до ожидания worker; все локальные времена — MONOTONIC, не BOOTTIME. * received_us ставится на входе RX port, до ожидания worker; все локальные времена — MONOTONIC, не BOOTTIME.
* Поздний poll не сдвигает расписание. Сдвиги разрешены только доступностью данных и границами A/V. * После паузы расписание продолжается от фактического показа; долг снимается ускорением без пропусков.
* Невалидные аудиочасы снимают привязку, но не очищают decoder/очередь и не меняют порядок PTS. */ * Невалидные аудиочасы снимают привязку, но не очищают decoder/очередь и не меняют порядок PTS. */
#ifndef CALL_VIDEO_PLAYOUT_H #ifndef CALL_VIDEO_PLAYOUT_H
#define CALL_VIDEO_PLAYOUT_H #define CALL_VIDEO_PLAYOUT_H
#include <stdint.h> #include <stdint.h>
#include "call_clock.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
struct call_video_playout_frame { int64_t pts_us, received_us; }; struct call_video_playout_frame { int64_t pts_us, received_us; };
enum call_video_playout_action { enum call_video_playout_action {
CALL_VIDEO_PLAYOUT_WAIT, CALL_VIDEO_PLAYOUT_SHOW, CALL_VIDEO_PLAYOUT_DROP_LATE, CALL_VIDEO_PLAYOUT_WAIT, CALL_VIDEO_PLAYOUT_SHOW, CALL_VIDEO_PLAYOUT_DROP_ORDER
CALL_VIDEO_PLAYOUT_DROP_SCHEDULE, CALL_VIDEO_PLAYOUT_DROP_ORDER
}; };
struct call_video_playout { struct call_video_playout {
uint64_t call_id; uint64_t call_id;
@@ -22,8 +22,8 @@ struct call_video_playout {
int64_t last_pts, last_deadline, deadline_us; int64_t last_pts, last_deadline, deadline_us;
int64_t report_us, last_show_us, interval_min, interval_max, av_min, av_max, dispatch_max, data_shift; int64_t report_us, last_show_us, interval_min, interval_max, av_min, av_max, dispatch_max, data_shift;
int64_t last_show_pts, last_received, gap_pts, gap_received, gap_dispatch; int64_t last_show_pts, last_received, gap_pts, gap_received, gap_dispatch;
int64_t late_av_min, late_av_max, late_age_min, late_age_max; // A/V и возраст от RX до пропуска за окно сводки. uint32_t speed_ppm; // Темп аудио + коррекция отставания, максимум 1.6x.
unsigned shown, late, skipped, order, audio_wait, clock_wait; unsigned shown, order, audio_wait, clock_wait;
}; };
int64_t call_video_playout_now_us(void); int64_t call_video_playout_now_us(void);
@@ -33,7 +33,7 @@ void call_video_playout_init(struct call_video_playout *p, uint64_t call_id);
* source_epoch не участвует: коррекция аудио не означает разрыв видеокодека. */ * source_epoch не участвует: коррекция аудио не означает разрыв видеокодека. */
enum call_video_playout_action call_video_playout_poll(struct call_video_playout *p, enum call_video_playout_action call_video_playout_poll(struct call_video_playout *p,
const struct call_video_playout_frame *frame, const struct call_video_playout_frame *next, const struct call_video_playout_frame *frame, const struct call_video_playout_frame *next,
int64_t now_us, int audio_valid, int64_t audio_pts_us); int64_t now_us, const struct call_clock_snapshot *audio);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif