static GstCaps *
mxf_bwf_create_caps (MXFMetadataTimelineTrack * track,
MXFMetadataGenericSoundEssenceDescriptor * descriptor, GstTagList ** tags,
+ gboolean * intra_only,
MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
{
GstCaps *ret = NULL;
gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_BITRATE,
wa_descriptor->avg_bps * 8, NULL);
+ *intra_only = TRUE;
+
return ret;
}
static GstCaps *
mxf_aes3_create_caps (MXFMetadataTimelineTrack * track,
MXFMetadataGenericSoundEssenceDescriptor * descriptor, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data)
{
GstCaps *ret = NULL;
MXFMetadataWaveAudioEssenceDescriptor *wa_descriptor = NULL;
g_free (codec_name);
*handler = mxf_aes3_handle_essence_element;
+ *intra_only = TRUE;
return ret;
}
static GstCaps *
mxf_aes_bwf_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data)
{
MXFMetadataGenericSoundEssenceDescriptor *s = NULL;
gboolean bwf = FALSE;
GST_ERROR ("No descriptor found for this track");
return NULL;
} else if (bwf) {
- return mxf_bwf_create_caps (track, s, tags, handler, mapping_data);
+ return mxf_bwf_create_caps (track, s, tags, intra_only, handler,
+ mapping_data);
} else {
- return mxf_aes3_create_caps (track, s, tags, handler, mapping_data);
+ return mxf_aes3_create_caps (track, s, tags, intra_only, handler,
+ mapping_data);
}
return NULL;
static GstCaps *
mxf_alaw_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data)
{
MXFMetadataGenericSoundEssenceDescriptor *s = NULL;
guint i;
}
+ *intra_only = TRUE;
+
return caps;
}
static GstCaps *
mxf_d10_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data)
{
MXFMetadataGenericPictureEssenceDescriptor *p = NULL;
MXFMetadataGenericSoundEssenceDescriptor *s = NULL;
gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
"SMPTE D-10 Audio", NULL);
+
+ *intra_only = TRUE;
} else if (p) {
caps =
gst_caps_new_simple ("video/mpeg", "systemstream", G_TYPE_BOOLEAN,
*handler = mxf_d10_picture_handle_essence_element;
gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
"SMPTE D-10 Video", NULL);
+
+ /* Does not allow temporal reordering */
+ *intra_only = TRUE;
}
return caps;
caps = gst_caps_new_empty_simple (name);
g_free (name);
+ etrack->intra_only = FALSE;
} else {
caps =
etrack->handler->create_caps (track, &etrack->tags,
- &etrack->handle_func, &etrack->mapping_data);
+ &etrack->intra_only, &etrack->handle_func, &etrack->mapping_data);
}
GST_DEBUG_OBJECT (demux, "Created caps %" GST_PTR_FORMAT, caps);
GstBuffer *outbuf = NULL;
GstMXFDemuxEssenceTrack *etrack = NULL;
gboolean keyframe = TRUE;
+ /* As in GstMXFDemuxIndex */
+ guint64 pts = G_MAXUINT64, dts = G_MAXUINT64;
GST_DEBUG_OBJECT (demux,
"Handling generic container essence element of size %" G_GSIZE_FORMAT
GstMXFDemuxIndex *idx =
&g_array_index (etrack->offsets, GstMXFDemuxIndex, i);
- if (idx->offset != 0 && idx->offset == demux->offset - demux->run_in) {
+ if (idx->initialized && idx->offset != 0
+ && idx->offset == demux->offset - demux->run_in) {
etrack->position = i;
break;
}
if (etrack->offsets && etrack->offsets->len > etrack->position) {
GstMXFDemuxIndex *index =
&g_array_index (etrack->offsets, GstMXFDemuxIndex, etrack->position);
- if (index->offset != 0)
+ if (index->initialized && index->offset != 0)
keyframe = index->keyframe;
+ if (index->initialized && index->pts != G_MAXUINT64)
+ pts = index->pts;
+ if (index->initialized && index->dts != G_MAXUINT64)
+ dts = index->dts;
}
/* Create subbuffer to be able to change metadata */
keyframe = !GST_BUFFER_FLAG_IS_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
/* Prefer keyframe information from index tables over everything else */
- if (demux->index_tables && outbuf) {
+ if (demux->index_tables) {
GList *l;
GstMXFDemuxIndexTable *index_table = NULL;
GstMXFDemuxIndex *index =
&g_array_index (index_table->offsets, GstMXFDemuxIndex,
etrack->position);
- if (index->offset != 0) {
+ if (index->initialized && index->offset != 0) {
keyframe = index->keyframe;
- if (keyframe)
- GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
- else
- GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
+ if (outbuf) {
+ if (keyframe)
+ GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
+ else
+ GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
+ }
}
+
+ if (index->initialized && index->pts != G_MAXUINT64)
+ pts = index->pts;
+ if (index->initialized && index->dts != G_MAXUINT64)
+ dts = index->dts;
}
}
GstMXFDemuxIndex index;
index.offset = demux->offset - demux->run_in;
+ index.initialized = TRUE;
+ index.pts = pts;
+ index.dts = dts;
index.keyframe = keyframe;
if (etrack->offsets->len < etrack->position)
g_array_set_size (etrack->offsets, etrack->position);
gst_buffer_get_size (inbuf));
GST_BUFFER_DTS (outbuf) = pad->position;
- GST_BUFFER_PTS (outbuf) = pad->position;
+ if (pts != G_MAXUINT64)
+ GST_BUFFER_PTS (outbuf) = gst_util_uint64_scale (pts * GST_SECOND,
+ pad->current_essence_track->source_track->edit_rate.d,
+ pad->current_essence_track->source_track->edit_rate.n);
+ else if (etrack->intra_only)
+ GST_BUFFER_PTS (outbuf) = pad->position;
+ else
+ GST_BUFFER_PTS (outbuf) = GST_CLOCK_TIME_NONE;
+
GST_BUFFER_DURATION (outbuf) =
gst_util_uint64_scale (GST_SECOND,
pad->current_essence_track->source_track->edit_rate.d,
for (i = 0; i < segment->n_index_entries && start + i < t->offsets->len;
i++) {
- GstMXFDemuxIndex *index =
- &g_array_index (t->offsets, GstMXFDemuxIndex, start + i);
guint64 offset = segment->index_entries[i].stream_offset;
GList *m;
GstMXFDemuxPartition *offset_partition = NULL, *next_partition = NULL;
next_partition = NULL;
}
- if (offset_partition && offset >= offset_partition->partition.body_offset
- && (offset - offset_partition->partition.body_offset)) {
+ if (offset_partition && offset >= offset_partition->partition.body_offset) {
offset =
offset_partition->partition.this_partition +
offset_partition->essence_container_offset + (offset -
GST_ERROR_OBJECT (demux,
"Invalid index table segment going into next unrelated partition");
} else {
+ GstMXFDemuxIndex *index;
+ gint8 temporal_offset = segment->index_entries[i].temporal_offset;
+ guint64 pts_i = G_MAXUINT64;
+
+ if (temporal_offset > 0 ||
+ (temporal_offset < 0 && start + i >= -(gint) temporal_offset)) {
+ pts_i = start + i + temporal_offset;
+
+ if (t->offsets->len < pts_i)
+ g_array_set_size (t->offsets, pts_i);
+
+ index = &g_array_index (t->offsets, GstMXFDemuxIndex, pts_i);
+ if (!index->initialized) {
+ index->initialized = TRUE;
+ index->offset = 0;
+ index->pts = G_MAXUINT64;
+ index->dts = G_MAXUINT64;
+ index->keyframe = FALSE;
+ }
+
+ index->pts = start + i;
+ }
+
+ index = &g_array_index (t->offsets, GstMXFDemuxIndex, start + i);
+ if (!index->initialized) {
+ index->initialized = TRUE;
+ index->offset = 0;
+ index->pts = G_MAXUINT64;
+ index->dts = G_MAXUINT64;
+ index->keyframe = FALSE;
+ }
+
index->offset = offset;
index->keyframe = ! !(segment->index_entries[i].flags & 0x80)
|| (segment->index_entries[i].key_frame_offset == 0);
+ index->dts = pts_i;
}
}
}
guint64 essence_container_offset;
} GstMXFDemuxPartition;
-typedef struct
-{
- guint64 offset;
- gboolean keyframe;
-} GstMXFDemuxIndex;
-
typedef struct
{
guint32 body_sid;
GstTagList *tags;
GstCaps *caps;
+ gboolean intra_only;
} GstMXFDemuxEssenceTrack;
+typedef struct
+{
+ /* 0 if uninitialized */
+ guint64 offset;
+
+ /* PTS edit unit number or G_MAXUINT64 */
+ guint64 pts;
+
+ /* DTS edit unit number if we got here via PTS */
+ guint64 dts;
+
+ gboolean keyframe;
+ gboolean initialized;
+} GstMXFDemuxIndex;
+
typedef struct
{
guint32 body_sid;
guint32 index_sid;
+
+ /* offsets indexed by DTS */
GArray *offsets;
} GstMXFDemuxIndexTable;
static GstCaps *
mxf_dv_dif_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data)
{
GstCaps *caps = NULL;
guint i;
gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_CODEC, "DV-DIF", NULL);
+ *intra_only = TRUE;
+
return caps;
}
typedef struct {
gboolean (*handles_track) (const MXFMetadataTimelineTrack *track);
MXFEssenceWrapping (*get_track_wrapping) (const MXFMetadataTimelineTrack *track);
- GstCaps * (*create_caps) (MXFMetadataTimelineTrack *track, GstTagList **tags, MXFEssenceElementHandleFunc *handler, gpointer *mapping_data);
+ GstCaps * (*create_caps) (MXFMetadataTimelineTrack *track, GstTagList **tags, gboolean * intra_only, MXFEssenceElementHandleFunc *handler, gpointer *mapping_data);
} MXFEssenceElementHandler;
typedef GstFlowReturn (*MXFEssenceElementWriteFunc) (GstBuffer *buffer, gpointer mapping_data, GstAdapter *adapter, GstBuffer **outbuf, gboolean flush);
static GstCaps *
mxf_jpeg2000_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data)
{
MXFMetadataFileDescriptor *f = NULL;
MXFMetadataGenericPictureEssenceDescriptor *p = NULL;
gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
"JPEG 2000", NULL);
+ *intra_only = TRUE;
+
return caps;
}
static GstCaps *
mxf_mpeg_es_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data,
- MXFMetadataGenericPictureEssenceDescriptor * p,
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data, MXFMetadataGenericPictureEssenceDescriptor * p,
MXFMetadataGenericSoundEssenceDescriptor * s)
{
GstCaps *caps = NULL;
codec_name = "MPEG-2 Video";
t = MXF_MPEG_ESSENCE_TYPE_VIDEO_MPEG2;
memcpy (mdata, &t, sizeof (MXFMPEGEssenceType));
+ *intra_only = FALSE;
} else if (p->picture_essence_coding.u[0] != 0x06
|| p->picture_essence_coding.u[1] != 0x0e
|| p->picture_essence_coding.u[2] != 0x2b
codec_name = "MPEG-2 Video";
t = MXF_MPEG_ESSENCE_TYPE_VIDEO_MPEG2;
memcpy (mdata, &t, sizeof (MXFMPEGEssenceType));
+ *intra_only = FALSE;
} else if (p->picture_essence_coding.u[13] == 0x10) {
caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
"systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
codec_name = "MPEG-1 Video";
t = MXF_MPEG_ESSENCE_TYPE_VIDEO_MPEG2;
memcpy (mdata, &t, sizeof (MXFMPEGEssenceType));
+ *intra_only = TRUE;
} else if (p->picture_essence_coding.u[13] == 0x20) {
MXFLocalTag *local_tag =
(((MXFMetadataBase *) p)->other_tags) ?
codec_name = "MPEG-4 Video";
t = MXF_MPEG_ESSENCE_TYPE_VIDEO_MPEG4;
memcpy (mdata, &t, sizeof (MXFMPEGEssenceType));
+ *intra_only = FALSE;
} else if ((p->picture_essence_coding.u[13] >> 4) == 0x03) {
/* RP 2008 */
codec_name = "h.264 Video";
t = MXF_MPEG_ESSENCE_TYPE_VIDEO_AVC;
memcpy (mdata, &t, sizeof (MXFMPEGEssenceType));
+ *intra_only = FALSE;
} else {
GST_ERROR ("Unsupported MPEG picture essence coding 0x%02x",
p->picture_essence_coding.u[13]);
mxf_metadata_generic_sound_essence_descriptor_set_caps (s, caps);
*handler = mxf_mpeg_audio_handle_essence_element;
}
+ *intra_only = TRUE;
}
if (caps) {
static GstCaps *
mxf_mpeg_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data)
{
MXFMetadataFileDescriptor *f = NULL;
MXFMetadataGenericPictureEssenceDescriptor *p = NULL;
if (f->essence_container.u[13] == 0x04) {
GST_DEBUG ("Found MPEG ES stream");
- caps = mxf_mpeg_es_create_caps (track, tags, handler, mapping_data, p, s);
+ caps =
+ mxf_mpeg_es_create_caps (track, tags, intra_only, handler, mapping_data,
+ p, s);
} else if (f->essence_container.u[13] == 0x07) {
GST_ERROR ("MPEG PES streams not supported yet");
return NULL;
*tags = gst_tag_list_new_empty ();
gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
"MPEG PS", NULL);
+ *intra_only = FALSE;
} else if (f->essence_container.u[13] == 0x09) {
GST_DEBUG ("Found MPEG TS stream");
caps = gst_caps_new_empty_simple ("video/mpegts");
*tags = gst_tag_list_new_empty ();
gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
"MPEG TS", NULL);
+ *intra_only = FALSE;
} else if (f->essence_container.u[13] == 0x0f) {
GST_DEBUG ("Found h264 NAL unit stream");
/* RP 2008 */
*tags = gst_tag_list_new_empty ();
gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
"h.264 Video", NULL);
+ *intra_only = FALSE;
} else if (f->essence_container.u[13] == 0x10) {
GST_DEBUG ("Found h264 byte-stream stream");
/* RP 2008 */
*tags = gst_tag_list_new_empty ();
gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
"h.264 Video", NULL);
+ *intra_only = FALSE;
}
if (p && caps)
static GstCaps *
mxf_up_rgba_create_caps (MXFMetadataTimelineTrack * track,
MXFMetadataRGBAPictureEssenceDescriptor * d, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data)
{
GstCaps *caps = NULL;
guint i;
((MXFMetadataGenericPictureEssenceDescriptor *) d)->image_end_offset;
*mapping_data = data;
+ *intra_only = TRUE;
} else {
GST_WARNING ("Unsupported pixel layout");
}
static GstCaps *
mxf_up_cdci_create_caps (MXFMetadataTimelineTrack * track,
MXFMetadataCDCIPictureEssenceDescriptor * d, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data)
{
GstCaps *caps = NULL;
guint i;
((MXFMetadataGenericPictureEssenceDescriptor *) d)->image_end_offset;
*mapping_data = data;
+ *intra_only = TRUE;
} else {
GST_WARNING ("Unsupported CDCI format");
}
static GstCaps *
mxf_up_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data)
{
MXFMetadataGenericPictureEssenceDescriptor *p = NULL;
MXFMetadataCDCIPictureEssenceDescriptor *c = NULL;
*handler = mxf_up_handle_essence_element;
if (r) {
- caps = mxf_up_rgba_create_caps (track, r, tags, handler, mapping_data);
+ caps =
+ mxf_up_rgba_create_caps (track, r, tags, intra_only, handler,
+ mapping_data);
} else if (c) {
- caps = mxf_up_cdci_create_caps (track, c, tags, handler, mapping_data);
+ caps =
+ mxf_up_cdci_create_caps (track, c, tags, intra_only, handler,
+ mapping_data);
} else {
return NULL;
}
static GstCaps *
mxf_vc3_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags,
- MXFEssenceElementHandleFunc * handler, gpointer * mapping_data)
+ gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
+ gpointer * mapping_data)
{
MXFMetadataFileDescriptor *f = NULL;
MXFMetadataGenericPictureEssenceDescriptor *p = NULL;
*tags = gst_tag_list_new_empty ();
gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
"VC-3 Video", NULL);
+ *intra_only = TRUE;
return caps;
}