Read the next live video frame independently of presentation time
This commit is contained in:
1 parent
47119c73a4
commit
f317d3e989
2 files changed
+13
-14
No files matched your search
@@ -351,7 +351,7 @@ static int cursor_peek(struct stream_media_cursor *c, struct cursor_track *track
|
||||
return STREAM_MORE;
|
||||
}
|
||||
|
||||
/* Сборка одного ближайшего H264 кадра; остальные кадры продолжают храниться только в RS. */
|
||||
/* Сборка одного следующего видеокадра; остальные кадры продолжают храниться только в RS. */
|
||||
static int cursor_video(struct stream_media_cursor *c, struct stream_media_packet *packet) {
|
||||
for (unsigned work = 0; work < 16; work++) {
|
||||
struct stream_media_block b; int64_t pts;
|
||||
@@ -385,12 +385,12 @@ static int cursor_video(struct stream_media_cursor *c, struct stream_media_packe
|
||||
return STREAM_MORE;
|
||||
}
|
||||
|
||||
/* Выдача по времени потребителя оставляет накопленный запас в общем кольце. */
|
||||
int stream_media_cursor_read(struct stream_media_cursor *c, int64_t position, int64_t video_ahead, int64_t audio_ahead,
|
||||
/* Видео выдаётся по готовности decoder, звук — по времени потребителя. */
|
||||
int stream_media_cursor_read(struct stream_media_cursor *c, int64_t position, int want_video, int64_t audio_ahead,
|
||||
struct stream_media_packet *packet) {
|
||||
if (!c || !packet || video_ahead < -1 || video_ahead > 60000000 || audio_ahead < -1 || audio_ahead > 60000000) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "media cursor read invalid arguments ahead=%lld/%lld",
|
||||
(long long)video_ahead, (long long)audio_ahead); return STREAM_ERR_ARGUMENT;
|
||||
if (!c || !packet || (want_video != 0 && want_video != 1) || audio_ahead < -1 || audio_ahead > 60000000) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "media cursor read invalid arguments video=%d audio_ahead=%lld",
|
||||
want_video, (long long)audio_ahead); return STREAM_ERR_ARGUMENT;
|
||||
}
|
||||
int result = cursor_start(c);
|
||||
if (result != STREAM_OK) {
|
||||
@@ -402,18 +402,16 @@ int stream_media_cursor_read(struct stream_media_cursor *c, int64_t position, in
|
||||
struct stream_media_block audio, video; int64_t audio_pts = INT64_MAX, video_pts = INT64_MAX;
|
||||
if (!c->store->format.audio_codec) c->audio.ended = 1;
|
||||
int ar = c->audio.ended ? STREAM_GAP : audio_ahead < 0 ? STREAM_WAIT : cursor_peek(c, &c->audio, 0, &audio, &audio_pts);
|
||||
int vr = video_ahead < 0 ? STREAM_WAIT : cursor_peek(c, &c->video, 1, &video, &video_pts);
|
||||
int vr = want_video ? cursor_peek(c, &c->video, 1, &video, &video_pts) : STREAM_WAIT;
|
||||
if ((ar == STREAM_GAP && !c->audio.ended) || (vr == STREAM_GAP && !c->video.ended)) return STREAM_GAP;
|
||||
if (ar == STREAM_EXPIRED || vr == STREAM_EXPIRED) return STREAM_EXPIRED;
|
||||
if (ar < 0 || vr < 0) return ar < 0 ? ar : vr;
|
||||
if (c->audio.ended && c->video.ended) {
|
||||
*packet = (struct stream_media_packet){.kind = STREAM_MEDIA_READ_END}; return STREAM_OK;
|
||||
}
|
||||
int64_t video_limit = video_ahead < 0 ? -1 : position < 0 ? c->start_us
|
||||
: position > INT64_MAX - video_ahead ? INT64_MAX : position + video_ahead;
|
||||
int64_t audio_limit = audio_ahead < 0 ? -1 : position < 0 ? c->start_us
|
||||
: position > INT64_MAX - audio_ahead ? INT64_MAX : position + audio_ahead;
|
||||
int video_allowed = vr == STREAM_OK && video_ahead >= 0 && video_pts <= video_limit;
|
||||
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. */
|
||||
result = cursor_block(c, c->audio.seq, &audio);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* Индекс медиапотока поверх общего RS-кольца: хранит только позиции/PTS, без копии кодированного потока.
|
||||
* Один uasync-поток; store принадлежит stream-session, cursor — конкретному локальному reader.
|
||||
* feed получает уже проверенные последовательные пачки; gap обозначает окончательно потерянный диапазон.
|
||||
* Независимые audio/video позиции читают оригинал из кольца. Рабочая память cursor — один H264 кадр,
|
||||
* Независимые audio/video позиции читают оригинал из кольца. Рабочая память cursor — один видеокадр,
|
||||
* один Opus-пакет и два scratch медиаблока. Курсоры ничего не закрепляют против вытеснения.
|
||||
* read возвращает заимствованный packet до следующего read/destroy; frontend копирует только ближайшие записи.
|
||||
* WAIT — материал ещё не готов/дальше lookahead. GAP/EXPIRED требуют новой точки KEY; END — весь материал выдан. */
|
||||
* WAIT — материал ещё не готов/дальше audio lookahead. GAP/EXPIRED требуют новой точки KEY; END — весь материал выдан. */
|
||||
#ifndef STREAM_MEDIA_BUFFER_H
|
||||
#define STREAM_MEDIA_BUFFER_H
|
||||
|
||||
@@ -46,10 +46,11 @@ int stream_media_cursor_create(struct stream_media_cursor **out, struct stream_m
|
||||
void stream_media_cursor_destroy(struct stream_media_cursor *cursor);
|
||||
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);
|
||||
/* position_us<0 — старт: прогреть аудио перед выбранным KEY. Затем отдавать только до position_us+lookahead_us.
|
||||
/* want_video=1 запрашивает следующий кадр независимо от часов показа; 0 оставляет видео в кольце.
|
||||
* position_us<0 прогревает аудио перед KEY; затем звук выдаётся до position_us+audio_ahead_us, -1 отключает звук.
|
||||
* При GAP/EXPIRED cursor сбрасывают отдельно: это позволяет frontend сначала обработать разрыв.
|
||||
* Бюджет одного вызова ограничен; MORE требует отложенного продолжения, WAIT — новых данных/позиции. */
|
||||
int stream_media_cursor_read(struct stream_media_cursor *cursor, int64_t position_us, int64_t video_ahead_us, int64_t audio_ahead_us,
|
||||
int stream_media_cursor_read(struct stream_media_cursor *cursor, int64_t position_us, int want_video, int64_t audio_ahead_us,
|
||||
struct stream_media_packet *packet);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in new issue
Block a user