mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 05:06:17 +00:00
mxfdemux: Handle temporal reordering shift
This is similar to how the same issue was handled in qtdemux. In order for the "DTS <= PTS" constraint to be respected, we calculate the maximum temporal reordering that can happen (via index tables). If there is a non-0 temporal reordering, we: * Shift all outgoing PTS by that amount * Shift segment for that stream by that amount * Don't modify DTS (i.e. they might end up having negative running-time, before the start of the segment) Also ensure all entries have a valid PTS set, previously this wouldn't be set for entries with a temporal offset of 0. Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/584 (and maybe a lot of other issues) Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2371>
This commit is contained in:
parent
de19e8a84f
commit
dfee771afd
2 changed files with 64 additions and 3 deletions
|
@ -1728,6 +1728,7 @@ gst_mxf_demux_handle_generic_container_essence_element (GstMXFDemux * demux,
|
||||||
gboolean keyframe = TRUE;
|
gboolean keyframe = TRUE;
|
||||||
/* As in GstMXFDemuxIndex */
|
/* As in GstMXFDemuxIndex */
|
||||||
guint64 pts = G_MAXUINT64, dts = G_MAXUINT64;
|
guint64 pts = G_MAXUINT64, dts = G_MAXUINT64;
|
||||||
|
gint32 max_temporal_offset = 0;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux,
|
GST_DEBUG_OBJECT (demux,
|
||||||
"Handling generic container essence element of size %" G_GSIZE_FORMAT
|
"Handling generic container essence element of size %" G_GSIZE_FORMAT
|
||||||
|
@ -1858,6 +1859,19 @@ gst_mxf_demux_handle_generic_container_essence_element (GstMXFDemux * demux,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!index_table)
|
||||||
|
GST_DEBUG_OBJECT (demux,
|
||||||
|
"Couldn't find index table for body_sid:%d index_sid:%d",
|
||||||
|
etrack->body_sid, etrack->index_sid);
|
||||||
|
else {
|
||||||
|
GST_DEBUG_OBJECT (demux,
|
||||||
|
"Looking for position %" G_GINT64_FORMAT
|
||||||
|
" in index table of size %d (max temporal offset %u)",
|
||||||
|
etrack->position, index_table->offsets->len,
|
||||||
|
index_table->max_temporal_offset);
|
||||||
|
max_temporal_offset = index_table->max_temporal_offset;
|
||||||
|
}
|
||||||
|
|
||||||
if (index_table && index_table->offsets->len > etrack->position) {
|
if (index_table && index_table->offsets->len > etrack->position) {
|
||||||
GstMXFDemuxIndex *index =
|
GstMXFDemuxIndex *index =
|
||||||
&g_array_index (index_table->offsets, GstMXFDemuxIndex,
|
&g_array_index (index_table->offsets, GstMXFDemuxIndex,
|
||||||
|
@ -1960,6 +1974,14 @@ gst_mxf_demux_handle_generic_container_essence_element (GstMXFDemux * demux,
|
||||||
gst_util_uint64_scale (pad->current_component_start_position *
|
gst_util_uint64_scale (pad->current_component_start_position *
|
||||||
GST_SECOND, pad->material_track->edit_rate.d,
|
GST_SECOND, pad->material_track->edit_rate.d,
|
||||||
pad->material_track->edit_rate.n);
|
pad->material_track->edit_rate.n);
|
||||||
|
/* We are dealing with reordered data, the PTS is shifted forward by the
|
||||||
|
* maximum temporal reordering (the DTS remain as-is). */
|
||||||
|
if (max_temporal_offset > 0)
|
||||||
|
GST_BUFFER_PTS (outbuf) +=
|
||||||
|
gst_util_uint64_scale (max_temporal_offset * GST_SECOND,
|
||||||
|
pad->current_essence_track->source_track->edit_rate.d,
|
||||||
|
pad->current_essence_track->source_track->edit_rate.n);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
GST_BUFFER_PTS (outbuf) = GST_CLOCK_TIME_NONE;
|
GST_BUFFER_PTS (outbuf) = GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
|
@ -2017,7 +2039,26 @@ gst_mxf_demux_handle_generic_container_essence_element (GstMXFDemux * demux,
|
||||||
gst_pad_push_event (GST_PAD_CAST (pad),
|
gst_pad_push_event (GST_PAD_CAST (pad),
|
||||||
gst_event_ref (demux->close_seg_event));
|
gst_event_ref (demux->close_seg_event));
|
||||||
|
|
||||||
e = gst_event_new_segment (&demux->segment);
|
if (max_temporal_offset > 0) {
|
||||||
|
GstSegment shift_segment;
|
||||||
|
/* Handle maximum temporal offset. We are shifting all output PTS for
|
||||||
|
* this stream by the greatest temporal reordering that can occur. In
|
||||||
|
* order not to change the stream/running time we shift the segment
|
||||||
|
* start and stop values accordingly */
|
||||||
|
gst_segment_copy_into (&demux->segment, &shift_segment);
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (shift_segment.start))
|
||||||
|
shift_segment.start +=
|
||||||
|
gst_util_uint64_scale (max_temporal_offset * GST_SECOND,
|
||||||
|
pad->current_essence_track->source_track->edit_rate.d,
|
||||||
|
pad->current_essence_track->source_track->edit_rate.n);
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (shift_segment.stop))
|
||||||
|
shift_segment.stop +=
|
||||||
|
gst_util_uint64_scale (max_temporal_offset * GST_SECOND,
|
||||||
|
pad->current_essence_track->source_track->edit_rate.d,
|
||||||
|
pad->current_essence_track->source_track->edit_rate.n);
|
||||||
|
e = gst_event_new_segment (&shift_segment);
|
||||||
|
} else
|
||||||
|
e = gst_event_new_segment (&demux->segment);
|
||||||
gst_event_set_seqnum (e, demux->seqnum);
|
gst_event_set_seqnum (e, demux->seqnum);
|
||||||
gst_pad_push_event (GST_PAD_CAST (pad), e);
|
gst_pad_push_event (GST_PAD_CAST (pad), e);
|
||||||
pad->need_segment = FALSE;
|
pad->need_segment = FALSE;
|
||||||
|
@ -3756,6 +3797,7 @@ collect_index_table_segments (GstMXFDemux * demux)
|
||||||
t = g_new0 (GstMXFDemuxIndexTable, 1);
|
t = g_new0 (GstMXFDemuxIndexTable, 1);
|
||||||
t->body_sid = segment->body_sid;
|
t->body_sid = segment->body_sid;
|
||||||
t->index_sid = segment->index_sid;
|
t->index_sid = segment->index_sid;
|
||||||
|
t->max_temporal_offset = 0;
|
||||||
t->offsets = g_array_new (FALSE, TRUE, sizeof (GstMXFDemuxIndex));
|
t->offsets = g_array_new (FALSE, TRUE, sizeof (GstMXFDemuxIndex));
|
||||||
demux->index_tables = g_list_prepend (demux->index_tables, t);
|
demux->index_tables = g_list_prepend (demux->index_tables, t);
|
||||||
}
|
}
|
||||||
|
@ -3808,8 +3850,19 @@ collect_index_table_segments (GstMXFDemux * demux)
|
||||||
gint8 temporal_offset = segment->index_entries[i].temporal_offset;
|
gint8 temporal_offset = segment->index_entries[i].temporal_offset;
|
||||||
guint64 pts_i = G_MAXUINT64;
|
guint64 pts_i = G_MAXUINT64;
|
||||||
|
|
||||||
if (temporal_offset > 0 ||
|
/* Store the highest reordering offset (to ensure we never output
|
||||||
(temporal_offset < 0 && start + i >= -(gint) temporal_offset)) {
|
* buffer with DTS greater than PTS) */
|
||||||
|
if (temporal_offset > (gint) t->max_temporal_offset) {
|
||||||
|
GST_LOG_OBJECT (demux,
|
||||||
|
"bodySID:%d indexSID:%d Stored new max temporal offset %d (was %d)",
|
||||||
|
t->body_sid, t->index_sid, temporal_offset,
|
||||||
|
t->max_temporal_offset);
|
||||||
|
t->max_temporal_offset = temporal_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch the matching entry in presentation order to store the pts (in
|
||||||
|
* edit units). */
|
||||||
|
if (temporal_offset >= 0 || (start + i >= -(gint) temporal_offset)) {
|
||||||
pts_i = start + i + temporal_offset;
|
pts_i = start + i + temporal_offset;
|
||||||
|
|
||||||
if (t->offsets->len < pts_i)
|
if (t->offsets->len < pts_i)
|
||||||
|
@ -3827,6 +3880,10 @@ collect_index_table_segments (GstMXFDemux * demux)
|
||||||
index->pts = start + i;
|
index->pts = start + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fetch the matching entry in encoded/bitstream order to store all
|
||||||
|
* the other values related to the actual content (offset, flag, dts,
|
||||||
|
* ..) */
|
||||||
|
|
||||||
index = &g_array_index (t->offsets, GstMXFDemuxIndex, start + i);
|
index = &g_array_index (t->offsets, GstMXFDemuxIndex, start + i);
|
||||||
if (!index->initialized) {
|
if (!index->initialized) {
|
||||||
index->initialized = TRUE;
|
index->initialized = TRUE;
|
||||||
|
|
|
@ -104,6 +104,10 @@ typedef struct
|
||||||
guint32 body_sid;
|
guint32 body_sid;
|
||||||
guint32 index_sid;
|
guint32 index_sid;
|
||||||
|
|
||||||
|
/* Greatest temporal offset value contained within offsets.
|
||||||
|
* Unsigned because the smallest value is 0 (no reordering) */
|
||||||
|
guint max_temporal_offset;
|
||||||
|
|
||||||
/* offsets indexed by DTS */
|
/* offsets indexed by DTS */
|
||||||
GArray *offsets;
|
GArray *offsets;
|
||||||
} GstMXFDemuxIndexTable;
|
} GstMXFDemuxIndexTable;
|
||||||
|
|
Loading…
Reference in a new issue