summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2009-12-18 13:54:46 +0100
committerWim Taymans <wim.taymans@collabora.co.uk>2010-01-05 15:51:43 +0100
commit86021857c5450aeb65cf817434cb9a76c58cca6d (patch)
tree04becd1ab820d49d13beb94c16092ebcdadf94d5
parent3b643817be2a1a58660d470e86935cee66149b81 (diff)
qtdemux: make seeking in push mode work
Move sample position checks into qtdemux_parse_samples where we can protect it with a lock. Refactor and make an qtdemux_ensure_index function. Rename qtdemux_do_push_seek to qtdemux_seek_offset in order to avoid confusion with gst_qtdemux_do_push_seek.
-rw-r--r--gst/qtdemux/qtdemux.c69
1 files changed, 50 insertions, 19 deletions
diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c
index 9b9178cce..a607752b5 100644
--- a/gst/qtdemux/qtdemux.c
+++ b/gst/qtdemux/qtdemux.c
@@ -776,8 +776,7 @@ gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
result++;
while (index < str->n_samples - 1) {
- if (index + 1 > str->stbl_index
- && !qtdemux_parse_samples (qtdemux, str, index + 1))
+ if (!qtdemux_parse_samples (qtdemux, str, index + 1))
goto parse_failed;
if (media_time < result->timestamp)
@@ -1026,6 +1025,7 @@ gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
gst_event_parse_seek (event, &rate, &format, &flags,
&cur_type, &cur, &stop_type, &stop);
+ /* FIXME, always play to the end */
stop = -1;
/* only forward streaming and seeking is possible */
@@ -1048,6 +1048,7 @@ gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
"start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
stop);
+
/* BYTE seek event */
event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
stop_type, stop);
@@ -1253,25 +1254,39 @@ no_format:
}
static gboolean
+qtdemux_ensure_index (GstQTDemux * qtdemux)
+{
+ guint i;
+
+ /* Build complete index */
+ for (i = 0; i < qtdemux->n_streams; i++) {
+ if (!qtdemux_parse_samples (qtdemux, qtdemux->streams[i],
+ qtdemux->streams[i]->n_samples - 1))
+ goto parse_error;
+ }
+ return TRUE;
+
+ /* ERRORS */
+parse_error:
+ {
+ GST_LOG_OBJECT (qtdemux,
+ "Building complete index of stream %u for seeking failed!", i);
+ return FALSE;
+ }
+}
+
+static gboolean
gst_qtdemux_handle_src_event (GstPad * pad, GstEvent * event)
{
gboolean res = TRUE;
GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
- guint i;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK:
/* Build complete index for seeking */
- for (i = 0; i < qtdemux->n_streams; i++) {
- if (!qtdemux_parse_samples (qtdemux, qtdemux->streams[i],
- qtdemux->streams[i]->n_samples - 1)) {
- GST_LOG_OBJECT (qtdemux,
- "Building complete index of stream %u for seeking failed!", i);
- res = FALSE;
- gst_event_unref (event);
- break;
- }
- }
+ if (!qtdemux_ensure_index (qtdemux))
+ goto index_failed;
+
if (qtdemux->pullbased) {
res = gst_qtdemux_do_seek (qtdemux, pad, event);
} else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams) {
@@ -1296,6 +1311,14 @@ gst_qtdemux_handle_src_event (GstPad * pad, GstEvent * event)
gst_object_unref (qtdemux);
return res;
+
+ /* ERRORS */
+index_failed:
+ {
+ GST_ERROR_OBJECT (qtdemux, "Index failed");
+ gst_event_unref (event);
+ return FALSE;
+ }
}
/* stream/index return sample that is min/max w.r.t. byte position,
@@ -2820,8 +2843,7 @@ next_entry_size (GstQTDemux * demux)
continue;
}
- if ((stream->sample_index > stream->stbl_index)
- && !qtdemux_parse_samples (demux, stream, stream->sample_index)) {
+ if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
stream->sample_index);
return -1;
@@ -2872,7 +2894,7 @@ gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
}
static gboolean
-qtdemux_do_push_seek (GstQTDemux * demux, guint64 offset)
+qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
{
GstEvent *event;
gboolean res = 0;
@@ -2957,7 +2979,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
target = old + size;
/* try to jump over the atom with a seek */
- res = qtdemux_do_push_seek (demux, target);
+ res = qtdemux_seek_offset (demux, target);
if (res) {
GST_DEBUG_OBJECT (demux, "seek success");
@@ -3063,7 +3085,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
gboolean res;
/* we need to seek back */
- res = qtdemux_do_push_seek (demux, demux->first_mdat);
+ res = qtdemux_seek_offset (demux, demux->first_mdat);
if (res) {
demux->offset = demux->first_mdat;
} else {
@@ -4117,6 +4139,9 @@ corrupt_file:
/* collect samples from the next sample to be parsed up to sample @n for @stream
* by reading the info from @stbl
+ *
+ * This code can be executed from both the streaming thread and the seeking
+ * thread so it takes the object lock to protect itself
*/
static gboolean
qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
@@ -4127,6 +4152,7 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
if (n >= stream->n_samples)
goto out_of_samples;
+ GST_OBJECT_LOCK (qtdemux);
if (n <= stream->stbl_index)
goto already_parsed;
@@ -4390,6 +4416,7 @@ ctts:
}
done:
stream->stbl_index = n;
+ GST_OBJECT_UNLOCK (qtdemux);
return TRUE;
@@ -4399,6 +4426,7 @@ already_parsed:
GST_LOG_OBJECT (qtdemux,
"Tried to parse up to sample %u but this sample has already been parsed",
n);
+ GST_OBJECT_UNLOCK (qtdemux);
return TRUE;
}
/* ERRORS */
@@ -4407,12 +4435,15 @@ out_of_samples:
GST_LOG_OBJECT (qtdemux,
"Tried to parse up to sample %u but there are only %u samples", n + 1,
stream->n_samples);
- goto corrupt_file;
+ GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
+ (_("This file is corrupt and cannot be played.")), (NULL));
+ return FALSE;
}
corrupt_file:
{
GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
(_("This file is corrupt and cannot be played.")), (NULL));
+ GST_OBJECT_UNLOCK (qtdemux);
return FALSE;
}
}