diff options
author | Josep Torra <n770galaxy@gmail.com> | 2009-02-04 16:18:27 +0100 |
---|---|---|
committer | Josep Torra <n770galaxy@gmail.com> | 2009-02-04 16:18:27 +0100 |
commit | b7198258f2ee70e18b16b125603ebd4a1c9debfb (patch) | |
tree | 5e3f318d1e08a39860a951b2258bfb7231944aff /gst | |
parent | 5d1abdbe2c998a5f563928b9b885b2fe6df686a1 (diff) | |
parent | ad2a64870cab550417ac7405c8c88b02429ef89d (diff) | |
download | gst-plugins-bad-b7198258f2ee70e18b16b125603ebd4a1c9debfb.tar.gz gst-plugins-bad-b7198258f2ee70e18b16b125603ebd4a1c9debfb.tar.bz2 gst-plugins-bad-b7198258f2ee70e18b16b125603ebd4a1c9debfb.zip |
Merge branch 'master' of ssh://git.freedesktop.org/git/gstreamer/gst-plugins-bad
Diffstat (limited to 'gst')
-rw-r--r-- | gst/mxf/mxf.c | 8 | ||||
-rw-r--r-- | gst/mxf/mxfdemux.c | 237 | ||||
-rw-r--r-- | gst/mxf/mxfdemux.h | 3 | ||||
-rw-r--r-- | gst/mxf/mxftypes.h | 2 |
4 files changed, 170 insertions, 80 deletions
diff --git a/gst/mxf/mxf.c b/gst/mxf/mxf.c index 236e8358..58fa0302 100644 --- a/gst/mxf/mxf.c +++ b/gst/mxf/mxf.c @@ -36,9 +36,17 @@ GST_DEBUG_CATEGORY (mxf_debug); #define GST_CAT_DEFAULT mxf_debug +static void +mxf_init (void) +{ + gst_tag_register (GST_TAG_MXF_UMID, GST_TAG_FLAG_META, + G_TYPE_STRING, "UMID", "Unique Material Identifier", NULL); +} + static gboolean plugin_init (GstPlugin * plugin) { + mxf_init (); mxf_metadata_init_types (); mxf_aes_bwf_init (); mxf_mpeg_init (); diff --git a/gst/mxf/mxfdemux.c b/gst/mxf/mxfdemux.c index 75b8cea4..b1595fd6 100644 --- a/gst/mxf/mxfdemux.c +++ b/gst/mxf/mxfdemux.c @@ -36,8 +36,7 @@ * The latter are just 16 byte unique identifiers * - Check everything for correctness vs. SMPTE S336M, some things can probably * be generalized/simplified - * - Seeking support: IndexTableSegments and skip-to-position seeks, needs correct - * timestamp calculation, etc. + * - Seeking support: Use IndexTableSegments * - Handle timecode tracks correctly (where is this documented?) * - Handle Generic container system items * - Implement correct support for clip-wrapped essence elements. @@ -49,6 +48,9 @@ * - Correctly handle the different rectangles and aspect-ratio for video * - Add support for non-standard MXF used by Avid (bug #561922). * - Fix frame layout stuff, i.e. interlaced/progressive + * - Extend essence element handlers to set DELTA_UNIT flag. + * - In pull mode first find the first buffer for every pad before pushing + * to prevent jumpy playback in the beginning due to resynchronization. * * - Implement SMPTE D11 essence and the digital cinema/MXF specs * @@ -113,7 +115,8 @@ gst_mxf_demux_pad_init (GstMXFDemuxPad * pad) enum { PROP_0, - PROP_PACKAGE + PROP_PACKAGE, + PROP_MAX_DRIFT }; static gboolean gst_mxf_demux_sink_event (GstPad * pad, GstEvent * event); @@ -132,12 +135,9 @@ gst_mxf_demux_remove_pad (GstMXFDemuxPad * pad, GstMXFDemux * demux) static void gst_mxf_demux_remove_pads (GstMXFDemux * demux) { - if (demux->src) { - g_ptr_array_foreach (demux->src, (GFunc) gst_mxf_demux_remove_pad, demux); - g_ptr_array_foreach (demux->src, (GFunc) gst_object_unref, NULL); - g_ptr_array_free (demux->src, TRUE); - demux->src = NULL; - } + g_ptr_array_foreach (demux->src, (GFunc) gst_mxf_demux_remove_pad, demux); + g_ptr_array_foreach (demux->src, (GFunc) gst_object_unref, NULL); + g_ptr_array_set_size (demux->src, 0); } static void @@ -189,14 +189,12 @@ gst_mxf_demux_reset_linked_metadata (GstMXFDemux * demux) { guint i; - if (demux->src) { - for (i = 0; i < demux->src->len; i++) { - GstMXFDemuxPad *pad = g_ptr_array_index (demux->src, i); + for (i = 0; i < demux->src->len; i++) { + GstMXFDemuxPad *pad = g_ptr_array_index (demux->src, i); - pad->material_track = NULL; - pad->material_package = NULL; - pad->current_component = NULL; - } + pad->material_track = NULL; + pad->material_package = NULL; + pad->current_component = NULL; } if (demux->essence_tracks) { @@ -350,7 +348,7 @@ gst_mxf_demux_push_src_event (GstMXFDemux * demux, GstEvent * event) GST_DEBUG_OBJECT (demux, "Pushing '%s' event downstream", GST_EVENT_TYPE_NAME (event)); - if (!demux->src) + if (demux->src->len == 0) return ret; for (i = 0; i < demux->src->len; i++) { @@ -374,9 +372,6 @@ gst_mxf_demux_get_earliest_pad (GstMXFDemux * demux) GstClockTime earliest = GST_CLOCK_TIME_NONE; GstMXFDemuxPad *pad = NULL; - if (!demux->src) - return NULL; - for (i = 0; i < demux->src->len; i++) { GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i); @@ -638,11 +633,11 @@ gst_mxf_demux_choose_package (GstMXFDemux * demux) for (i = 0; i < demux->preface->content_storage->n_packages; i++) { if (demux->preface->content_storage->packages[i] && - MXF_IS_METADATA_MATERIAL_PACKAGE (demux->preface->content_storage-> - packages[i])) { + MXF_IS_METADATA_MATERIAL_PACKAGE (demux->preface-> + content_storage->packages[i])) { ret = - MXF_METADATA_GENERIC_PACKAGE (demux->preface->content_storage-> - packages[i]); + MXF_METADATA_GENERIC_PACKAGE (demux->preface-> + content_storage->packages[i]); break; } } @@ -655,15 +650,20 @@ gst_mxf_demux_choose_package (GstMXFDemux * demux) done: if (memcmp (&ret->package_uid, &demux->current_package_uid, 32) != 0) { gchar current_package_string[96]; + GstTagList *tags = gst_tag_list_new (); gst_mxf_demux_remove_pads (demux); memcpy (&demux->current_package_uid, &ret->package_uid, 32); mxf_umid_to_string (&ret->package_uid, current_package_string); - demux->current_package = ret; demux->current_package_string = g_strdup (current_package_string); g_object_notify (G_OBJECT (demux), "package"); + + gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_MXF_UMID, + demux->current_package_string, NULL); + gst_element_found_tags (GST_ELEMENT_CAST (demux), tags); } + demux->current_package = ret; return ret; } @@ -859,7 +859,7 @@ gst_mxf_demux_update_tracks (GstMXFDemux * demux) return GST_FLOW_ERROR; } - first_run = (demux->src == NULL); + first_run = (demux->src->len == 0); for (i = 0; i < current_package->n_tracks; i++) { MXFMetadataTimelineTrack *track = NULL; @@ -884,7 +884,7 @@ gst_mxf_demux_update_tracks (GstMXFDemux * demux) track = MXF_METADATA_TIMELINE_TRACK (current_package->tracks[i]); - if (demux->src && demux->src->len > 0) { + if (demux->src->len > 0) { /* Find pad from track_id */ for (j = 0; j < demux->src->len; j++) { GstMXFDemuxPad *tmp = g_ptr_array_index (demux->src, j); @@ -1095,8 +1095,6 @@ gst_mxf_demux_update_tracks (GstMXFDemux * demux) gst_element_add_pad (GST_ELEMENT_CAST (demux), gst_object_ref (pad)); - if (!demux->src) - demux->src = g_ptr_array_new (); g_ptr_array_add (demux->src, pad); pad->discont = TRUE; } @@ -1105,7 +1103,7 @@ gst_mxf_demux_update_tracks (GstMXFDemux * demux) if (first_run) gst_element_no_more_pads (GST_ELEMENT_CAST (demux)); - if (demux->src) { + if (demux->src->len > 0) { for (i = 0; i < demux->src->len; i++) { GstMXFDemuxPad *pad = g_ptr_array_index (demux->src, i); @@ -1336,8 +1334,8 @@ gst_mxf_demux_pad_set_component (GstMXFDemux * demux, GstMXFDemuxPad * pad, pad->current_component_index); pad->current_component = - MXF_METADATA_SOURCE_CLIP (sequence->structural_components[pad-> - current_component_index]); + MXF_METADATA_SOURCE_CLIP (sequence-> + structural_components[pad->current_component_index]); if (pad->current_component == NULL) { GST_ERROR_OBJECT (demux, "No such structural component"); return GST_FLOW_ERROR; @@ -1345,8 +1343,8 @@ gst_mxf_demux_pad_set_component (GstMXFDemux * demux, GstMXFDemuxPad * pad, if (!pad->current_component->source_package || !pad->current_component->source_package->top_level - || !MXF_METADATA_GENERIC_PACKAGE (pad->current_component-> - source_package)->tracks) { + || !MXF_METADATA_GENERIC_PACKAGE (pad-> + current_component->source_package)->tracks) { GST_ERROR_OBJECT (demux, "Invalid component"); return GST_FLOW_ERROR; } @@ -1463,7 +1461,7 @@ gst_mxf_demux_handle_generic_container_essence_element (GstMXFDemux * demux, return GST_FLOW_ERROR; } - if (!demux->src || demux->src->len == 0) { + if (demux->src->len == 0) { GST_ERROR_OBJECT (demux, "No streams created yet"); return GST_FLOW_ERROR; } @@ -1600,7 +1598,7 @@ gst_mxf_demux_handle_generic_container_essence_element (GstMXFDemux * demux, GstMXFDemuxPad *earliest = gst_mxf_demux_get_earliest_pad (demux); if (earliest && earliest != pad && earliest->last_stop < pad->last_stop && - pad->last_stop - earliest->last_stop > 500 * GST_MSECOND) { + pad->last_stop - earliest->last_stop > demux->max_drift) { GST_DEBUG_OBJECT (demux, "Pad is too far ahead of time"); continue; } @@ -2244,7 +2242,7 @@ gst_mxf_demux_set_partition_for_offset (GstMXFDemux * demux, guint64 offset) for (l = demux->partitions; l; l = l->next) { GstMXFDemuxPartition *p = l->data; - if (p->partition.this_partition <= offset) + if (p->partition.this_partition + demux->run_in <= offset) demux->current_partition = p; } } @@ -2421,7 +2419,7 @@ gst_mxf_demux_pull_and_handle_klv_packet (GstMXFDemux * demux) GstFlowReturn ret = GST_FLOW_OK; guint read = 0; - if (demux->src) { + if (demux->src->len > 0) { if (!gst_mxf_demux_get_earliest_pad (demux)) { ret = GST_FLOW_UNEXPECTED; GST_DEBUG_OBJECT (demux, "All tracks are EOS"); @@ -2495,50 +2493,48 @@ gst_mxf_demux_pull_and_handle_klv_packet (GstMXFDemux * demux) demux->offset += read; if (ret == GST_FLOW_OK && demux->src && demux->essence_tracks) { - guint i; GstMXFDemuxPad *earliest = NULL; - guint64 offset; - gint64 position; - - earliest = gst_mxf_demux_get_earliest_pad (demux); - if (!earliest) - goto beach; - /* We allow time drifts of at most 500ms */ - if (demux->segment.last_stop - earliest->last_stop <= 500 * GST_MSECOND) - goto beach; + while ((earliest = gst_mxf_demux_get_earliest_pad (demux)) && + demux->segment.last_stop - earliest->last_stop > demux->max_drift) { + guint i; + guint64 offset; + gint64 position; - GST_WARNING_OBJECT (demux, - "Found synchronization issue -- trying to solve"); + GST_WARNING_OBJECT (demux, + "Found synchronization issue -- trying to solve"); - position = earliest->current_essence_track_position; + position = earliest->current_essence_track_position; - /* FIXME: This can probably be improved by using the - * offset of position-1 if it's in the same partition - * or the start of the position otherwise. - * This way we won't skip elements from the same essence - * container as etrack->position - */ - offset = - gst_mxf_demux_find_essence_element (demux, - earliest->current_essence_track, &position, FALSE); - if (offset == -1) { - GST_ERROR_OBJECT (demux, "Failed to find offset for late essence track"); - earliest->eos = TRUE; - gst_pad_push_event (GST_PAD_CAST (earliest), gst_event_new_eos ()); - goto beach; - } + /* FIXME: This can probably be improved by using the + * offset of position-1 if it's in the same partition + * or the start of the position otherwise. + * This way we won't skip elements from the same essence + * container as etrack->position + */ + offset = + gst_mxf_demux_find_essence_element (demux, + earliest->current_essence_track, &position, FALSE); + if (offset == -1) { + GST_ERROR_OBJECT (demux, + "Failed to find offset for late essence track"); + earliest->eos = TRUE; + gst_pad_push_event (GST_PAD_CAST (earliest), gst_event_new_eos ()); + continue; + } - demux->offset = offset + demux->run_in; - gst_mxf_demux_set_partition_for_offset (demux, demux->offset); + demux->offset = offset + demux->run_in; + gst_mxf_demux_set_partition_for_offset (demux, demux->offset); - for (i = 0; i < demux->essence_tracks->len; i++) { - GstMXFDemuxEssenceTrack *etrack = - &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i); + for (i = 0; i < demux->essence_tracks->len; i++) { + GstMXFDemuxEssenceTrack *etrack = + &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i); - etrack->position = -1; + etrack->position = -1; + } + earliest->current_essence_track->position = position; + break; } - earliest->current_essence_track->position = position; } beach: @@ -2670,7 +2666,7 @@ gst_mxf_demux_chain (GstPad * pad, GstBuffer * inbuf) GST_LOG_OBJECT (demux, "received buffer of %u bytes at offset %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (inbuf), GST_BUFFER_OFFSET (inbuf)); - if (demux->src) { + if (demux->src->len > 0) { if (!gst_mxf_demux_get_earliest_pad (demux)) { ret = GST_FLOW_UNEXPECTED; GST_DEBUG_OBJECT (demux, "All tracks are EOS"); @@ -2687,6 +2683,9 @@ gst_mxf_demux_chain (GstPad * pad, GstBuffer * inbuf) if (G_UNLIKELY (demux->offset == 0 && GST_BUFFER_OFFSET (inbuf) != 0)) { GST_DEBUG_OBJECT (demux, "offset was zero, synchronizing with buffer's"); demux->offset = GST_BUFFER_OFFSET (inbuf); + gst_mxf_demux_set_partition_for_offset (demux, demux->offset); + } else if (demux->current_partition == NULL) { + gst_mxf_demux_set_partition_for_offset (demux, demux->offset); } gst_adapter_push (demux->adapter, inbuf); @@ -2844,8 +2843,8 @@ gst_mxf_demux_pad_set_position (GstMXFDemux * demux, GstMXFDemuxPad * p, for (i = 0; i < p->material_track->parent.sequence->n_structural_components; i++) { clip = - MXF_METADATA_SOURCE_CLIP (p->material_track->parent.sequence-> - structural_components[i]); + MXF_METADATA_SOURCE_CLIP (p->material_track->parent. + sequence->structural_components[i]); if (clip->parent.duration <= 0) break; @@ -3105,6 +3104,7 @@ gst_mxf_demux_seek_pull (GstMXFDemux * demux, GstEvent * event) goto no_new_offset; demux->offset = new_offset + demux->run_in; + gst_mxf_demux_set_partition_for_offset (demux, demux->offset); } if (G_UNLIKELY (demux->close_seg_event)) { @@ -3373,11 +3373,69 @@ gst_mxf_demux_sink_event (GstPad * pad, GstEvent * event) demux->offset = 0; ret = gst_mxf_demux_push_src_event (demux, event); break; - case GST_EVENT_EOS: - if (!gst_mxf_demux_push_src_event (demux, event)) + case GST_EVENT_EOS:{ + GstMXFDemuxPad *p = NULL; + guint i; + + for (i = 0; i < demux->essence_tracks->len; i++) { + GstMXFDemuxEssenceTrack *t = + &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, i); + + if (t->position > 0) + t->duration = t->position; + } + + for (i = 0; i < demux->src->len; i++) { + GstMXFDemuxPad *p = g_ptr_array_index (demux->src, i); + + if (!p->eos + && p->current_essence_track_position >= + p->current_essence_track->duration) { + p->eos = TRUE; + gst_pad_push_event (GST_PAD_CAST (p), gst_event_new_eos ()); + } + } + + while ((p = gst_mxf_demux_get_earliest_pad (demux))) { + guint64 offset; + gint64 position; + + position = p->current_essence_track_position; + + offset = + gst_mxf_demux_find_essence_element (demux, p->current_essence_track, + &position, FALSE); + if (offset == -1) { + GST_ERROR_OBJECT (demux, "Failed to find offset for essence track"); + p->eos = TRUE; + gst_pad_push_event (GST_PAD_CAST (p), gst_event_new_eos ()); + continue; + } + + if (gst_pad_push_event (demux->sinkpad, + gst_event_new_seek (demux->segment.rate, GST_FORMAT_BYTES, + demux->segment.flags | GST_SEEK_FLAG_ACCURATE, + GST_SEEK_TYPE_SET, offset + demux->run_in, + GST_SEEK_TYPE_NONE, 0))) { + + for (i = 0; i < demux->essence_tracks->len; i++) { + GstMXFDemuxEssenceTrack *etrack = + &g_array_index (demux->essence_tracks, GstMXFDemuxEssenceTrack, + i); + etrack->position = -1; + } + ret = TRUE; + goto out; + } else { + GST_WARNING_OBJECT (demux, + "Seek to remaining part of the file failed"); + } + } + + if (!(ret = gst_mxf_demux_push_src_event (demux, event))) GST_WARNING_OBJECT (pad, "failed pushing EOS on streams"); - ret = TRUE; break; + } case GST_EVENT_NEWSEGMENT:{ guint i; @@ -3389,6 +3447,7 @@ gst_mxf_demux_sink_event (GstPad * pad, GstEvent * event) t->position = -1; } } + demux->current_partition = NULL; gst_event_unref (event); ret = TRUE; break; @@ -3398,6 +3457,7 @@ gst_mxf_demux_sink_event (GstPad * pad, GstEvent * event) break; } +out: gst_object_unref (demux); return ret; @@ -3454,7 +3514,7 @@ gst_mxf_demux_query (GstElement * element, GstQuery * query) if (format != GST_FORMAT_TIME) goto error; - if (!demux->src) + if (demux->src->len == 0) goto done; for (i = 0; i < demux->src->len; i++) { @@ -3545,6 +3605,9 @@ gst_mxf_demux_set_property (GObject * object, guint prop_id, g_free (demux->requested_package_string); demux->requested_package_string = g_value_dup_string (value); break; + case PROP_MAX_DRIFT: + demux->max_drift = g_value_get_uint64 (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3561,6 +3624,9 @@ gst_mxf_demux_get_property (GObject * object, guint prop_id, case PROP_PACKAGE: g_value_set_string (value, demux->current_package_string); break; + case PROP_MAX_DRIFT: + g_value_set_uint64 (value, demux->max_drift); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3589,6 +3655,9 @@ gst_mxf_demux_finalize (GObject * object) g_free (demux->requested_package_string); demux->requested_package_string = NULL; + g_ptr_array_free (demux->src, TRUE); + demux->src = NULL; + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -3623,6 +3692,12 @@ gst_mxf_demux_class_init (GstMXFDemuxClass * klass) "Material or Source package to use for playback", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_DRIFT, + g_param_spec_uint64 ("max-drift", "Maximum drift", + "Maximum number of nanoseconds by which tracks can differ", + 100 * GST_MSECOND, G_MAXUINT64, 500 * GST_MSECOND, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_mxf_demux_change_state); gstelement_class->query = GST_DEBUG_FUNCPTR (gst_mxf_demux_query); @@ -3649,6 +3724,8 @@ gst_mxf_demux_init (GstMXFDemux * demux, GstMXFDemuxClass * g_class) gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad); + demux->max_drift = 500 * GST_MSECOND; + demux->adapter = gst_adapter_new (); demux->src = g_ptr_array_new (); gst_segment_init (&demux->segment, GST_FORMAT_TIME); diff --git a/gst/mxf/mxfdemux.h b/gst/mxf/mxfdemux.h index 9ae739fc..8e64e403 100644 --- a/gst/mxf/mxfdemux.h +++ b/gst/mxf/mxfdemux.h @@ -161,7 +161,10 @@ struct _GstMXFDemux MXFUMID current_package_uid; MXFMetadataGenericPackage *current_package; gchar *current_package_string; + + /* Properties */ gchar *requested_package_string; + GstClockTime max_drift; }; struct _GstMXFDemuxClass diff --git a/gst/mxf/mxftypes.h b/gst/mxf/mxftypes.h index 73f4a834..a59ac742 100644 --- a/gst/mxf/mxftypes.h +++ b/gst/mxf/mxftypes.h @@ -154,4 +154,6 @@ typedef struct { GHashTable *other_tags; } MXFIndexTableSegment; +#define GST_TAG_MXF_UMID "mxf-umid" + #endif /* __MXF_TYPES_H__ */ |