Prime late stream audio without waiting for its playback clock
This commit is contained in:
1 parent
0c26daf3f5
commit
c03fe3da71
2 files changed
+16
-10
No files matched your search
@@ -35,7 +35,7 @@ struct stream_media_cursor {
|
||||
unsigned tracks;
|
||||
int64_t start_us;
|
||||
int audio_started;
|
||||
int64_t audio_blocked_pts;
|
||||
int64_t audio_start_us;
|
||||
uint8_t *scratch[2], *frame;
|
||||
size_t scratch_capacity, frame_capacity;
|
||||
uint64_t scratch_seq[2];
|
||||
@@ -260,7 +260,7 @@ void stream_media_cursor_destroy(struct stream_media_cursor *c) {
|
||||
void stream_media_cursor_reset(struct stream_media_cursor *c) {
|
||||
if (!c) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "media cursor reset: null cursor"); return; }
|
||||
c->initialized = 0; c->video_revision = 0; c->pending_used = 0;
|
||||
c->audio_started = 0; c->audio_blocked_pts = -1;
|
||||
c->audio_started = 0; c->audio_start_us = -1;
|
||||
c->pending = (struct stream_media_video){0}; c->pending_format = (struct stream_media_format){0};
|
||||
c->scratch_valid[0] = c->scratch_valid[1] = 0;
|
||||
c->video = (struct cursor_track){0}; c->audio = (struct cursor_track){0};
|
||||
@@ -274,7 +274,7 @@ static int cursor_start(struct stream_media_cursor *c) {
|
||||
if (s->failed) return STREAM_ERR_FORMAT;
|
||||
if (c->initialized) return STREAM_OK;
|
||||
if (!s->count || s->key_seq == UINT64_MAX || !media_find(s, s->key_seq)) return s->finished ? STREAM_GAP : STREAM_WAIT;
|
||||
c->generation = s->generation; c->start_us = s->key_us;
|
||||
c->generation = s->generation; c->start_us = s->key_us; c->audio_start_us = -1;
|
||||
c->video.seq = s->key_seq; c->audio.seq = s->key_seq;
|
||||
for (unsigned i = 0; i < s->count; i++) {
|
||||
struct media_position *p = media_at(s, i);
|
||||
@@ -426,8 +426,18 @@ int stream_media_cursor_read(struct stream_media_cursor *c, int64_t position, in
|
||||
if (c->audio.ended && c->video.ended) {
|
||||
*packet = (struct stream_media_packet){.kind = STREAM_MEDIA_READ_END}; return STREAM_OK;
|
||||
}
|
||||
/* Поздний первый звук должен прогреть decoder до запуска audio clock. Основание фиксировано,
|
||||
* поэтому неподвижные часы разрешают только один lookahead, а не всё оставшееся аудио. */
|
||||
if (ar == STREAM_OK && c->audio_start_us < 0) {
|
||||
c->audio_start_us = audio_pts > c->start_us ? audio_pts : c->start_us;
|
||||
if (audio_pts > c->start_us) DEBUG_INFO(DEBUG_CATEGORY_STREAM,
|
||||
"media cursor audio startup source=%llx video_pts=%lld audio_pts=%lld gap_us=%lld",
|
||||
(unsigned long long)c->store->descriptor.source_node_id, (long long)c->start_us,
|
||||
(long long)audio_pts, (long long)(audio_pts - c->start_us));
|
||||
}
|
||||
int64_t audio_position = position > c->audio_start_us ? position : c->audio_start_us;
|
||||
int64_t audio_limit = audio_ahead < 0 ? -1 : position < 0 ? c->start_us
|
||||
: position > INT64_MAX - audio_ahead ? INT64_MAX : position + audio_ahead;
|
||||
: audio_position > INT64_MAX - audio_ahead ? INT64_MAX : audio_position + audio_ahead;
|
||||
int video_allowed = want_video && vr == STREAM_OK;
|
||||
if (ar == STREAM_OK && audio_ahead >= 0 && audio_pts <= audio_limit && (audio_pts < video_pts || !video_allowed)) {
|
||||
/* video peek мог переиспользовать scratch аудио: заново взять ту же пачку из двухэлементного cache. */
|
||||
@@ -445,11 +455,5 @@ int stream_media_cursor_read(struct stream_media_cursor *c, int64_t position, in
|
||||
return STREAM_OK;
|
||||
}
|
||||
if (video_allowed) return cursor_video(c, packet);
|
||||
if (!c->audio_started && ar == STREAM_OK && audio_ahead >= 0 && audio_pts > audio_limit && c->audio_blocked_pts != audio_pts) {
|
||||
c->audio_blocked_pts = audio_pts;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "media cursor first audio waits source=%llx seq=%llu pts=%lld position=%lld limit=%lld video_requested=%d",
|
||||
(unsigned long long)c->store->descriptor.source_node_id, (unsigned long long)c->audio.seq,
|
||||
(long long)audio_pts, (long long)position, (long long)audio_limit, want_video);
|
||||
}
|
||||
return ar == STREAM_MORE || vr == STREAM_MORE ? STREAM_MORE : STREAM_WAIT;
|
||||
}
|
||||
@@ -50,6 +50,8 @@ void stream_media_cursor_reset(struct stream_media_cursor *cursor);
|
||||
int stream_media_cursor_status(struct stream_media_cursor *cursor, struct stream_media_status *status);
|
||||
/* want_video=1 запрашивает следующий кадр независимо от часов показа; 0 оставляет видео в кольце.
|
||||
* position_us<0 прогревает аудио перед KEY; затем звук выдаётся до position_us+audio_ahead_us, -1 отключает звук.
|
||||
* Если звук начинается позже KEY, lookahead отсчитывается минимум от первого аудиопакета:
|
||||
* decoder получает стартовый PCM при неподвижных часах; размер разрешённого окна остаётся ограниченным.
|
||||
* При GAP/EXPIRED cursor сбрасывают отдельно: это позволяет frontend сначала обработать разрыв.
|
||||
* Бюджет одного вызова ограничен; MORE требует отложенного продолжения, WAIT — новых данных/позиции. */
|
||||
int stream_media_cursor_read(struct stream_media_cursor *cursor, int64_t position_us, int want_video, int64_t audio_ahead_us,
|
||||
|
||||
Reference in new issue
Block a user