diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2009-11-23 17:46:57 +0100 |
---|---|---|
committer | Wim Taymans <wim.taymans@collabora.co.uk> | 2009-11-23 18:06:55 +0100 |
commit | a5ca9899aec537e1a03c4c9334f11c4b5520c595 (patch) | |
tree | 9021e3d7626e7ad97997b7b80f2c87a769ce1f66 | |
parent | a36ed417790256615cca95dfb2e740fc101c4ece (diff) |
qtdemux: quick hack to implement seeking in pushjalfrezi/work
While looking for the first moov atom, skip all other atoms by trying to issue a
seek upstream.
-rw-r--r-- | gst/qtdemux/qtdemux.c | 89 | ||||
-rw-r--r-- | gst/qtdemux/qtdemux.h | 1 |
2 files changed, 76 insertions, 14 deletions
diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c index bf3fe3c42..502373aea 100644 --- a/gst/qtdemux/qtdemux.c +++ b/gst/qtdemux/qtdemux.c @@ -467,6 +467,7 @@ gst_qtdemux_init (GstQTDemux * qtdemux) qtdemux->todrop = 0; qtdemux->adapter = gst_adapter_new (); qtdemux->offset = 0; + qtdemux->first_mdat = -1; qtdemux->mdatoffset = GST_CLOCK_TIME_NONE; qtdemux->mdatbuffer = NULL; gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME); @@ -1541,6 +1542,7 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition) qtdemux->todrop = 0; qtdemux->pullbased = FALSE; qtdemux->offset = 0; + qtdemux->first_mdat = -1; qtdemux->mdatoffset = GST_CLOCK_TIME_NONE; if (qtdemux->mdatbuffer) gst_buffer_unref (qtdemux->mdatbuffer); @@ -2259,7 +2261,7 @@ gst_qtdemux_sync_streams (GstQTDemux * demux) } /* UNEXPECTED and NOT_LINKED need to be combined. This means that we return: - * + * * GST_FLOW_NOT_LINKED: when all pads NOT_LINKED. * GST_FLOW_UNEXPECTED: when all pads UNEXPECTED or NOT_LINKED. */ @@ -2858,6 +2860,24 @@ gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom) gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL))); } +static gboolean +qtdemux_do_push_seek (GstQTDemux * demux, guint64 offset) +{ + GstEvent *event; + gboolean res; + + GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset); + + event = + gst_event_new_seek (1.0, GST_FORMAT_BYTES, + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset, + GST_SEEK_TYPE_NONE, -1); + + res = gst_pad_push_event (demux->sinkpad, event); + + return res; +} + /* FIXME, unverified after edit list updates */ static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf) @@ -2912,24 +2932,52 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf) } if (fourcc == FOURCC_mdat) { if (demux->n_streams > 0) { + /* we have the headers, start playback */ demux->state = QTDEMUX_STATE_MOVIE; demux->neededbytes = next_entry_size (demux); } else { + /* no headers yet, try to get them */ guint bs; + gboolean res; + guint64 old, target; buffer_data: - /* there may be multiple mdat (or alike) buffers */ - /* sanity check */ - if (demux->mdatbuffer) - bs = GST_BUFFER_SIZE (demux->mdatbuffer); - else - bs = 0; - if (size + bs > 10 * (1 << 20)) - goto no_moov; - demux->state = QTDEMUX_STATE_BUFFER_MDAT; - demux->neededbytes = size; - if (!demux->mdatbuffer) - demux->mdatoffset = demux->offset; + old = demux->offset; + target = old + size; + + /* try to jump over the atom with a seek */ + res = qtdemux_do_push_seek (demux, target); + + if (res) { + GST_DEBUG_OBJECT (demux, "seek success"); + /* remember the offset fo the first mdat so we can seek back to it + * after we have the headers */ + if (fourcc == FOURCC_mdat && demux->first_mdat == -1) { + demux->first_mdat = old; + GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT, + demux->first_mdat); + } + /* seek worked, continue reading */ + demux->offset = target; + demux->neededbytes = 16; + demux->state = QTDEMUX_STATE_INITIAL; + } else { + /* seek failed, need to buffer */ + demux->offset = old; + GST_DEBUG_OBJECT (demux, "seek failed"); + /* there may be multiple mdat (or alike) buffers */ + /* sanity check */ + if (demux->mdatbuffer) + bs = GST_BUFFER_SIZE (demux->mdatbuffer); + else + bs = 0; + if (size + bs > 10 * (1 << 20)) + goto no_moov; + demux->state = QTDEMUX_STATE_BUFFER_MDAT; + demux->neededbytes = size; + if (!demux->mdatbuffer) + demux->mdatoffset = demux->offset; + } } } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) { GST_ELEMENT_ERROR (demux, STREAM, DECODE, @@ -2999,7 +3047,20 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf) } else { GST_DEBUG_OBJECT (demux, "Carrying on normally"); gst_adapter_flush (demux->adapter, demux->neededbytes); - demux->offset += demux->neededbytes; + + if (demux->first_mdat != -1) { + gboolean res; + + /* we need to seek back */ + res = qtdemux_do_push_seek (demux, demux->first_mdat); + if (res) { + demux->offset = demux->first_mdat; + } else { + GST_DEBUG_OBJECT (demux, "Seek back failed"); + } + } else { + demux->offset += demux->neededbytes; + } demux->neededbytes = 16; demux->state = QTDEMUX_STATE_INITIAL; } diff --git a/gst/qtdemux/qtdemux.h b/gst/qtdemux/qtdemux.h index 107636334..c6982ffe5 100644 --- a/gst/qtdemux/qtdemux.h +++ b/gst/qtdemux/qtdemux.h @@ -86,6 +86,7 @@ struct _GstQTDemux { guint64 offset; /* offset of the mdat atom */ guint64 mdatoffset; + guint64 first_mdat; GstTagList *tag_list; |