Gate media cursor revision changes on a complete keyframe
This commit is contained in:
1 parent
afa8fd307a
commit
d209ab94ba
2 files changed
+101
-17
No files matched your search
@@ -30,8 +30,8 @@ struct cursor_track { uint64_t seq; unsigned entry; int ended; };
|
||||
struct stream_media_cursor {
|
||||
struct stream_media_store *store;
|
||||
struct cursor_track video, audio;
|
||||
uint32_t generation;
|
||||
int initialized, key_delivered;
|
||||
uint32_t generation, video_revision;
|
||||
int initialized;
|
||||
unsigned tracks;
|
||||
int64_t start_us;
|
||||
uint8_t *scratch[2], *frame;
|
||||
@@ -257,7 +257,8 @@ 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 = c->key_delivered = 0; c->pending_used = 0;
|
||||
c->initialized = 0; c->video_revision = 0; c->pending_used = 0;
|
||||
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};
|
||||
c->audio.ended = !(c->tracks & STREAM_MEDIA_TRACK_AUDIO);
|
||||
@@ -358,10 +359,19 @@ static int cursor_video(struct stream_media_cursor *c, struct stream_media_packe
|
||||
int result = cursor_peek(c, &c->video, 1, &b, &pts);
|
||||
if (result != STREAM_OK) return result;
|
||||
const struct stream_media_video *v = &b.video[c->video.entry++];
|
||||
if (!c->key_delivered && !c->pending.frame_size
|
||||
if (b.format.revision != c->pending_format.revision) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_STREAM, "media cursor revision source=%llx seq=%llu revision=%u->%u pending=%u; require KEY",
|
||||
(unsigned long long)c->store->descriptor.source_node_id, (unsigned long long)c->video.seq,
|
||||
c->pending_format.revision, b.format.revision, c->pending_used);
|
||||
c->pending = (struct stream_media_video){0}; c->pending_used = 0; c->pending_format = b.format;
|
||||
}
|
||||
/* Revision относится к уже выданному видео этого reader, а не к текущему live store. */
|
||||
if (b.format.revision != c->video_revision && !(v->flags & STREAM_MEDIA_KEY)) continue;
|
||||
if (!c->pending.frame_size && v->offset) continue;
|
||||
if (!c->video_revision && !c->pending.frame_size
|
||||
&& (v->offset || !(v->flags & STREAM_MEDIA_KEY) || pts != c->start_us)) continue;
|
||||
if (!v->offset) {
|
||||
if (!c->key_delivered && (!(v->flags & STREAM_MEDIA_KEY) || pts != c->start_us)) continue;
|
||||
if (!c->video_revision && (!(v->flags & STREAM_MEDIA_KEY) || pts != c->start_us)) continue;
|
||||
if (v->frame_size > c->frame_capacity) {
|
||||
uint8_t *frame = u_realloc(c->frame, v->frame_size);
|
||||
if (!frame) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "media cursor frame allocation failed bytes=%u", v->frame_size); return STREAM_ERR_MEMORY; }
|
||||
@@ -370,7 +380,7 @@ static int cursor_video(struct stream_media_cursor *c, struct stream_media_packe
|
||||
c->pending = *v; c->pending.data = NULL; c->pending_used = 0; c->pending_format = b.format;
|
||||
}
|
||||
if (!c->pending.frame_size || v->frame_id != c->pending.frame_id || v->offset != c->pending_used
|
||||
|| v->pts_us != c->pending.pts_us || v->frame_size != c->pending.frame_size) {
|
||||
|| v->pts_us != c->pending.pts_us || v->frame_size != c->pending.frame_size || v->flags != c->pending.flags) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_STREAM, "media cursor fragment conflict seq=%llu frame=%llu offset=%u used=%u",
|
||||
(unsigned long long)c->video.seq, (unsigned long long)v->frame_id, v->offset, c->pending_used);
|
||||
return STREAM_GAP;
|
||||
@@ -379,7 +389,11 @@ static int cursor_video(struct stream_media_cursor *c, struct stream_media_packe
|
||||
if (c->pending_used != c->pending.frame_size) continue;
|
||||
struct stream_media_packet out = {.kind = STREAM_MEDIA_READ_VIDEO, .format = c->pending_format, .video = c->pending};
|
||||
out.video.offset = 0; out.video.length = out.video.frame_size; out.video.data = c->frame;
|
||||
c->pending_used = 0; c->pending.frame_size = 0; c->key_delivered = 1; *packet = out;
|
||||
if (c->video_revision != b.format.revision) DEBUG_INFO(DEBUG_CATEGORY_STREAM,
|
||||
"media cursor KEY ready source=%llx revision=%u frame=%llu pts=%llu bytes=%u",
|
||||
(unsigned long long)c->store->descriptor.source_node_id, b.format.revision,
|
||||
(unsigned long long)v->frame_id, (unsigned long long)v->pts_us, v->frame_size);
|
||||
c->pending_used = 0; c->pending.frame_size = 0; c->video_revision = b.format.revision; *packet = out;
|
||||
return STREAM_OK;
|
||||
}
|
||||
return STREAM_MORE;
|
||||
|
||||
Reference in new issue
Block a user