From 857f6cf2a83139874961773ea9a4f8901866ef52 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 20 Apr 2006 13:23:40 +0000 Subject: [PATCH] gst/matroska/: Set DISCONT flag on first buffer after a discontinuity. Original commit message from CVS: * gst/matroska/matroska-demux.c: (gst_matroska_demux_add_stream), (gst_matroskademux_do_index_seek), (gst_matroska_demux_handle_seek_event), (gst_matroska_demux_parse_blockgroup_or_simpleblock): * gst/matroska/matroska-ids.h: Set DISCONT flag on first buffer after a discontinuity. Fix newsegment events sent when seeking and honour KEY_UNIT seek flag. Create pad with bogus caps if we don't recognise the stream codec id. * gst/matroska/matroska-demux.h: Fix GObject macros. --- ChangeLog | 15 ++++++ gst/matroska/matroska-demux.c | 107 ++++++++++++++++++++++++++++++------------ gst/matroska/matroska-demux.h | 4 +- gst/matroska/matroska-ids.h | 2 + 4 files changed, 97 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index ef83d1c..daaf793 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,20 @@ 2006-04-20 Tim-Philipp Müller + * gst/matroska/matroska-demux.c: (gst_matroska_demux_add_stream), + (gst_matroskademux_do_index_seek), + (gst_matroska_demux_handle_seek_event), + (gst_matroska_demux_parse_blockgroup_or_simpleblock): + * gst/matroska/matroska-ids.h: + Set DISCONT flag on first buffer after a discontinuity. + Fix newsegment events sent when seeking and honour KEY_UNIT + seek flag. Create pad with bogus caps if we don't recognise + the stream codec id. + + * gst/matroska/matroska-demux.h: + Fix GObject macros. + +2006-04-20 Tim-Philipp Müller + Patch by: Mark Nauwelaerts * gst/matroska/matroska-demux.c: diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index f342781..1d4248a 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -315,6 +315,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) context->type = 0; /* no type yet */ context->default_duration = 0; context->pos = 0; + context->set_discont = TRUE; demux->num_streams++; /* start with the master */ @@ -908,9 +909,29 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) GST_TAG_LANGUAGE_CODE, context->language, NULL); } + if (caps == NULL) { + GST_WARNING_OBJECT (demux, "could not determine caps for stream with " + "codec_id='%s'", context->codec_id); + switch (context->type) { + case GST_MATROSKA_TRACK_TYPE_VIDEO: + caps = gst_caps_new_simple ("video/x-unknown", NULL); + break; + case GST_MATROSKA_TRACK_TYPE_AUDIO: + caps = gst_caps_new_simple ("audio/x-unknown", NULL); + break; + case GST_MATROSKA_TRACK_TYPE_SUBTITLE: + caps = gst_caps_new_simple ("application/x-subtitle-unknown", NULL); + break; + case GST_MATROSKA_TRACK_TYPE_COMPLEX: + default: + caps = gst_caps_new_simple ("application/x-matroska-unknown", NULL); + break; + } + } + /* the pad in here */ context->pad = gst_pad_new_from_template (templ, padname); - context->caps = caps ? caps : gst_caps_new_empty (); + context->caps = caps; gst_pad_set_event_function (context->pad, GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_src_event)); @@ -919,20 +940,13 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) gst_pad_set_query_function (context->pad, GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_src_query)); - if (caps) { - GST_LOG ("Adding pad '%s' with caps %" GST_PTR_FORMAT, padname, caps); - if (gst_caps_is_fixed (caps)) { - gst_pad_use_fixed_caps (context->pad); - gst_pad_set_caps (context->pad, context->caps); - gst_pad_set_active (context->pad, TRUE); - gst_element_add_pad (GST_ELEMENT (demux), context->pad); - } else { - g_warning ("FIXME: non-fixed caps: %s", gst_caps_to_string (caps)); - } - } else { - /* FIXME: are we leaking the pad here? can this even happen? */ - GST_LOG ("Not adding pad '%s' with empty caps", padname); - } + GST_INFO_OBJECT (demux, "Adding pad '%s' with caps %" GST_PTR_FORMAT, + padname, caps); + + gst_pad_use_fixed_caps (context->pad); + gst_pad_set_caps (context->pad, context->caps); + gst_pad_set_active (context->pad, TRUE); + gst_element_add_pad (GST_ELEMENT (demux), context->pad); /* tags */ if (list) { @@ -1014,21 +1028,41 @@ gst_matroska_demux_handle_src_query (GstPad * pad, GstQuery * query) static GstMatroskaIndex * -gst_matroskademux_do_index_seek (GstMatroskaDemux * demux, guint64 seek_pos) +gst_matroskademux_do_index_seek (GstMatroskaDemux * demux, gint64 seek_pos, + gint64 segment_stop, gboolean keyunit) { - guint entry = demux->num_indexes - 1; + guint entry; guint n = 0; if (!demux->num_indexes) return NULL; - while (n < demux->num_indexes - 1) { - if ((demux->index[n].time <= seek_pos) && - (demux->index[n + 1].time > seek_pos)) { - entry = n; - break; + if (keyunit) { + /* find index entry closest to the requested position */ + entry = 0; + for (n = 0; n < demux->num_indexes; ++n) { + gdouble d_entry, d_this; + + d_entry = fabs ((gdouble) demux->index[entry].time - (gdouble) seek_pos); + d_this = fabs ((gdouble) demux->index[n].time - (gdouble) seek_pos); + + if (d_this < d_entry && + (demux->index[n].time < segment_stop || segment_stop == -1)) { + entry = n; + } + } + } else { + /* find index entry at or before the requested position */ + entry = demux->num_indexes - 1; + + while (n < demux->num_indexes - 1) { + if ((demux->index[n].time <= seek_pos) && + (demux->index[n + 1].time > seek_pos)) { + entry = n; + break; + } + n++; } - n++; } return &demux->index[entry]; @@ -1080,7 +1114,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, GstSeekType cur_type, stop_type; GstFormat format; GstEvent *newsegment_event; - gboolean flush; + gboolean flush, keyunit; gdouble rate; gint64 cur, stop; gint64 segment_start, segment_stop; @@ -1104,7 +1138,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, /* check sanity before we start flushing and all that */ if (cur_type == GST_SEEK_TYPE_SET) { GST_OBJECT_LOCK (demux); - if (!gst_matroskademux_do_index_seek (demux, cur)) { + if (!gst_matroskademux_do_index_seek (demux, cur, -1, FALSE)) { GST_DEBUG ("No matching seek entry in index"); GST_OBJECT_UNLOCK (demux); return FALSE; @@ -1114,6 +1148,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, } flush = !!(flags & GST_SEEK_FLAG_FLUSH); + keyunit = !!(flags & GST_SEEK_FLAG_KEY_UNIT); if (flush) { GST_DEBUG ("Starting flush"); @@ -1156,7 +1191,9 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, GST_DEBUG ("New segment positions: %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT, GST_TIME_ARGS (segment_start), GST_TIME_ARGS (segment_stop)); - entry = gst_matroskademux_do_index_seek (demux, segment_start); + entry = gst_matroskademux_do_index_seek (demux, segment_start, + segment_stop, keyunit); + if (!entry) { GST_DEBUG ("No matching seek entry in index"); goto seek_error; @@ -1173,6 +1210,12 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, GST_DEBUG ("Seeked to offset %" G_GUINT64_FORMAT, entry->pos + demux->ebml_segment_start); + if (keyunit) { + GST_DEBUG ("seek to key unit, adjusting segment start to %" + GST_TIME_FORMAT, GST_TIME_ARGS (entry->time)); + segment_start = entry->time; + } + GST_DEBUG ("Committing new seek segment"); demux->segment_rate = rate; @@ -1192,9 +1235,8 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, gst_element_post_message (GST_ELEMENT (demux), msg); } - /* FIXME: should be demux->segment_start, not entry->time */ newsegment_event = gst_event_new_new_segment (FALSE, rate, - GST_FORMAT_TIME, entry->time, segment_stop, entry->time); + GST_FORMAT_TIME, segment_start, segment_stop, segment_start); GST_DEBUG ("Stopping flush"); if (flush) { @@ -1204,8 +1246,10 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, /* send newsegment event to all source pads and update the time */ gst_matroska_demux_send_event (demux, newsegment_event); - for (i = 0; i < demux->num_streams; i++) + for (i = 0; i < demux->num_streams; i++) { demux->src[i]->pos = entry->time; + demux->src[i]->set_discont = TRUE; + } demux->pos = entry->time; /* restart our task since it might have been stopped when we did the @@ -2363,6 +2407,11 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT); } + if (stream->set_discont) { + GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DISCONT); + stream->set_discont = FALSE; + } + GST_DEBUG ("Pushing data of size %d for stream %d, time=%" GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT, GST_BUFFER_SIZE (sub), stream_num, diff --git a/gst/matroska/matroska-demux.h b/gst/matroska/matroska-demux.h index 14401a5..49b073b 100644 --- a/gst/matroska/matroska-demux.h +++ b/gst/matroska/matroska-demux.h @@ -34,10 +34,10 @@ G_BEGIN_DECLS #define GST_MATROSKA_DEMUX(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MATROSKA_DEMUX, GstMatroskaDemux)) #define GST_MATROSKA_DEMUX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MATROSKA_DEMUX, GstMatroskaDemux)) + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MATROSKA_DEMUX, GstMatroskaDemuxClass)) #define GST_IS_MATROSKA_DEMUX(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MATROSKA_DEMUX)) -#define GST_IS_MATROSKA_DEMUX_CLASS(obj) \ +#define GST_IS_MATROSKA_DEMUX_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MATROSKA_DEMUX)) #define GST_MATROSKA_DEMUX_MAX_STREAMS 64 diff --git a/gst/matroska/matroska-ids.h b/gst/matroska/matroska-ids.h index 71dfc63..c8c6d37 100644 --- a/gst/matroska/matroska-ids.h +++ b/gst/matroska/matroska-ids.h @@ -243,6 +243,8 @@ typedef struct _GstMatroskaTrackContext { GstMatroskaTrackFlags flags; guint64 default_duration; guint64 pos; + + gboolean set_discont; /* TRUE = set DISCONT flag on next buffer */ } GstMatroskaTrackContext; typedef struct _GstMatroskaTrackVideoContext { -- 2.7.4