mxfdemux: Refactor index table and offset handling

* Streamline offset <=> entry handling. Historically the demuxer didn't support
information from index tables and stored the discovered information in an array
per track. When index table support was added, a parallel system was setup for
that relationship. This commit unifies this into one system with the
`find_edit_entry()` and `find_entry_for_offset()` functions.

* By extension, per-track offset entry tables are only created/used if no index
table is present for those tracks.

* Use index table information as-is. The index table system from MXF is quite
complex and there are various ways to use the information contained
within. Instead of converting that information we store the data from the tables
as-is and extract the needed information when needed.

* Handle index tables without entries (i.e. all content package units are of the
same size).

* Allow collecting index table segments as we go instead of only once if a
random-index-pack is present. This also improves support of some files in
push-mode.

* When searching for keyframe entries, use the keyframe_offset if
present (speeds up searching).

* For interleaved content (i.e. several tracks in the sample essence container),
we use a system to be able to identify the position of each track in the delta
entries of index tables.

* Handle temporal offset only on tracks which *do* need it (as specified in the
delta entries of the index tables). If present, those offsets are stored in a
pre-processed table which allows computing PTS from DTS with a simple offset.

* Add a quirk for files which are known to be have wrongly stored temporal
offsets.

* Overall opens the way to handle more types of MXF files, especially those with
non-frame-wrapping.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2371>
This commit is contained in:
Edward Hervey 2021-07-01 08:35:01 +02:00 committed by Edward Hervey
parent c24d48765d
commit ac483b2384
4 changed files with 1103 additions and 416 deletions

File diff suppressed because it is too large Load diff

View file

@ -49,23 +49,41 @@ typedef struct _GstMXFDemuxClass GstMXFDemuxClass;
typedef struct _GstMXFDemuxPad GstMXFDemuxPad;
typedef struct _GstMXFDemuxPadClass GstMXFDemuxPadClass;
typedef struct
typedef struct _GstMXFDemuxPartition GstMXFDemuxPartition;
typedef struct _GstMXFDemuxEssenceTrack GstMXFDemuxEssenceTrack;
struct _GstMXFDemuxPartition
{
MXFPartitionPack partition;
MXFPrimerPack primer;
gboolean parsed_metadata;
/* Relative offset at which essence starts within this partition.*/
guint64 essence_container_offset;
} GstMXFDemuxPartition;
typedef struct
};
#define MXF_INDEX_DELTA_ID_UNKNOWN -1
#define MXF_INDEX_DELTA_ID_IGNORE -2
struct _GstMXFDemuxEssenceTrack
{
guint32 body_sid;
guint32 index_sid;
guint32 track_number;
/* delta id, the position of this track in the container package delta table
* (if the track is in an interleaved essence container)
*
* Special values:
* * -1 Not discovered yet
* * -2 Ignore delta entry (if index table is not present or not complete)
*/
gint32 delta_id;
guint32 track_id;
MXFUMID source_package_uid;
/* Position and duration in edit units */
gint64 position;
gint64 duration;
@ -82,11 +100,14 @@ typedef struct
GstCaps *caps;
gboolean intra_only;
} GstMXFDemuxEssenceTrack;
MXFEssenceWrapping wrapping;
};
typedef struct
{
/* 0 if uninitialized */
/* absolute byte offset excluding run_in, 0 if uninitialized */
guint64 offset;
/* PTS edit unit number or G_MAXUINT64 */
@ -95,8 +116,14 @@ typedef struct
/* DTS edit unit number if we got here via PTS */
guint64 dts;
/* Duration in edit units */
guint64 duration;
gboolean keyframe;
gboolean initialized;
/* Size, used for non-frame-wrapped content */
guint64 size;
} GstMXFDemuxIndex;
typedef struct
@ -104,12 +131,23 @@ typedef struct
guint32 body_sid;
guint32 index_sid;
/* Array of MXFIndexTableSegment, sorted by DTS
* Note: Can be empty and can be sparse (i.e. not cover every edit unit) */
GArray *segments;
/* Delta entry to which reordering should be applied (-1 == no reordering) */
gint reordered_delta_entry;
/* Array of gint8 reverse temporal offsets.
* Contains the shift to apply to an entry DTS to get the PTS
*
* Can be NULL if the content doesn't have temporal shifts (i.e. all present
* entries have a temporal offset of 0) */
GArray *reverse_temporal_offsets;
/* Greatest temporal offset value contained within offsets.
* Unsigned because the smallest value is 0 (no reordering) */
guint max_temporal_offset;
/* offsets indexed by DTS */
GArray *offsets;
} GstMXFDemuxIndexTable;
struct _GstMXFDemuxPad
@ -121,7 +159,7 @@ struct _GstMXFDemuxPad
GstClockTime position;
gdouble position_accumulated_error;
/* Current position in the material track */
/* Current position in the material track (in edit units) */
gint64 current_material_track_position;
gboolean eos, discont;
@ -143,6 +181,7 @@ struct _GstMXFDemuxPad
gint64 current_component_start;
gint64 current_component_duration;
/* Current essence track and position (in edit units) */
GstMXFDemuxEssenceTrack *current_essence_track;
gint64 current_essence_track_position;
};
@ -212,6 +251,9 @@ struct _GstMXFDemux
/* Properties */
gchar *requested_package_string;
GstClockTime max_drift;
/* Quirks */
gboolean temporal_order_misuse;
};
struct _GstMXFDemuxClass

View file

@ -1285,6 +1285,21 @@ mxf_index_table_segment_parse (const MXFUL * ul,
break;
}
}
/* If edit unit byte count is 0 there *must* be entries */
if (segment->edit_unit_byte_count == 0 && segment->n_index_entries == 0) {
GST_WARNING
("Invalid IndexTableSegment, No entries and no specified edit unit byte count");
goto error;
}
/* Compute initial essence offset */
if (segment->edit_unit_byte_count)
segment->segment_start_offset =
segment->index_start_position * segment->edit_unit_byte_count;
else
segment->segment_start_offset = segment->index_entries[0].stream_offset;
return TRUE;
error:

View file

@ -169,6 +169,11 @@ typedef struct {
guint32 n_index_entries;
MXFIndexEntry *index_entries;
/* Computed fields (i.e. not present in file) */
/* Initial essence offset covered by this segment */
guint64 segment_start_offset;
} MXFIndexTableSegment;
#define GST_TAG_MXF_UMID "mxf-umid"