summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2009-11-23 17:46:57 +0100
committerWim Taymans <wim.taymans@collabora.co.uk>2009-11-23 18:06:55 +0100
commita5ca9899aec537e1a03c4c9334f11c4b5520c595 (patch)
tree9021e3d7626e7ad97997b7b80f2c87a769ce1f66
parenta36ed417790256615cca95dfb2e740fc101c4ece (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.c89
-rw-r--r--gst/qtdemux/qtdemux.h1
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;