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.
This commit is contained in:
Tim-Philipp Müller 2006-04-20 13:23:40 +00:00
parent a0522c2394
commit 857f6cf2a8
4 changed files with 97 additions and 31 deletions

View file

@ -1,3 +1,18 @@
2006-04-20 Tim-Philipp Müller <tim at centricular dot net>
* 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 <tim at centricular dot net>
Patch by: Mark Nauwelaerts <manauw at skynet dot be>

View file

@ -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,

View file

@ -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

View file

@ -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 {