summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Swain <robert.swain@collabora.co.uk>2009-11-14 15:52:09 +0100
committerRobert Swain <robert.swain@collabora.co.uk>2009-11-20 15:11:59 +0100
commit42ef98a9d5eb1415e62e9ebf97f26d55ebc3b0aa (patch)
treed629d07307c792e3f34229e6ac17cf1996b082e0
parent4fa0bcb2b1af177620ea61698fb4121235b1b7f7 (diff)
qtdemux: Parse per sample rather than all at once but build complete index when
seeking
m---------common0
-rw-r--r--gst/qtdemux/qtdemux.c90
2 files changed, 76 insertions, 14 deletions
diff --git a/common b/common
-Subproject 53a2485bb2a648f38767a310caebe1b2679f0ce
+Subproject 0702fe19e974bc4461b5cfeb5db0e80de00a84d
diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c
index 98d86c77..10993d9a 100644
--- a/gst/qtdemux/qtdemux.c
+++ b/gst/qtdemux/qtdemux.c
@@ -386,6 +386,8 @@ static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
gchar ** codec_name);
+static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
+ QtDemuxStream * stream, guint32 n);
GType
gst_qtdemux_get_type (void)
@@ -732,7 +734,8 @@ find_func (QtDemuxSample * s1, guint64 * media_time, gpointer user_data)
return -1;
}
-/* find the index of the sample that includes the data for @media_time
+/* find the index of the sample that includes the data for @media_time using a
+ * binary search
*
* Returns the index of the sample.
*/
@@ -755,6 +758,37 @@ gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
return index;
}
+/* find the index of the sample that includes the data for @media_time using a
+ * linear search
+ *
+ * Returns the index of the sample.
+ */
+static guint32
+gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
+ guint64 media_time)
+{
+ QtDemuxSample *result = str->samples;
+ guint32 index = 0;
+
+ if (media_time == result->timestamp)
+ return index;
+
+ result++;
+ while (index < str->n_samples - 1) {
+ if (index + 1 > str->stbl_index
+ && !qtdemux_parse_samples (qtdemux, str, index + 1)) {
+ GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
+ return -1;
+ }
+ if (media_time < result->timestamp)
+ break;
+ index++;
+ result++;
+ }
+
+ return index;
+}
+
/* find the index of the keyframe needed to decode the sample at @index
* of stream @str.
*
@@ -1218,9 +1252,21 @@ 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->pullbased) {
res = gst_qtdemux_do_seek (qtdemux, pad, event);
} else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams) {
@@ -1963,19 +2009,24 @@ gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
/* and move to the keyframe before the indicated media time of the
* segment */
if (qtdemux->segment.rate >= 0) {
- index = gst_qtdemux_find_index (qtdemux, stream, start);
+ index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
stream->to_sample = stream->n_samples;
GST_DEBUG_OBJECT (qtdemux, "moving data pointer to %" GST_TIME_FORMAT
", index: %u, pts %" GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
GST_TIME_ARGS (stream->samples[index].timestamp));
} else {
- index = gst_qtdemux_find_index (qtdemux, stream, stop);
+ index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
stream->to_sample = index;
GST_DEBUG_OBJECT (qtdemux, "moving data pointer to %" GST_TIME_FORMAT
", index: %u, pts %" GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
GST_TIME_ARGS (stream->samples[index].timestamp));
}
+ /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
+ * encountered an error and printed a message so we return appropriately */
+ if (index == -1)
+ return FALSE;
+
/* we're at the right spot */
if (index == stream->sample_index) {
GST_DEBUG_OBJECT (qtdemux, "we are at the right index");
@@ -2055,12 +2106,24 @@ gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
/* now get the info for the sample we're at */
sample = &stream->samples[stream->sample_index];
+ if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
+ GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
+ stream->sample_index);
+ return FALSE;
+ }
+
*timestamp = sample->timestamp + sample->pts_offset;
*offset = sample->offset;
*size = sample->size;
*duration = sample->duration;
*keyframe = stream->all_keyframe || sample->keyframe;
+ /* update dummy segment duration */
+ if (stream->sample_index == stream->n_samples - 1 && stream->n_segments == 1) {
+ stream->segments[0].duration = stream->segments[0].stop_time =
+ stream->segments[0].media_stop = *timestamp + *duration;
+ }
+
return TRUE;
/* special cases */
@@ -2102,6 +2165,12 @@ gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
/* get next sample */
sample = &stream->samples[stream->sample_index];
+ if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
+ GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
+ stream->sample_index);
+ return;
+ }
+
/* see if we are past the segment */
if (G_UNLIKELY (sample->timestamp >= segment->media_stop))
goto next_segment;
@@ -4361,19 +4430,12 @@ done:
/* no segments, create one to play the complete trak */
if (stream->n_segments == 0) {
- GstClockTime stream_duration = 0;
+ GstClockTime stream_duration =
+ gst_util_uint64_scale (stream->duration, GST_SECOND, stream->timescale);
if (stream->segments == NULL)
stream->segments = g_new (QtDemuxSegment, 1);
- /* samples know best */
- if (stream->n_samples > 0) {
- stream_duration =
- stream->samples[stream->n_samples - 1].timestamp +
- stream->samples[stream->n_samples - 1].pts_offset +
- stream->samples[stream->n_samples - 1].duration;
- }
-
stream->segments[0].time = 0;
stream->segments[0].stop_time = stream_duration;
stream->segments[0].duration = stream_duration;
@@ -5325,8 +5387,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
/* collect sample information */
- if (!qtdemux_stbl_init (qtdemux, stream, stbl) ||
- !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
+ if (!qtdemux_stbl_init (qtdemux, stream, stbl)
+ || !qtdemux_parse_samples (qtdemux, stream, 0))
goto samples_failed;
/* configure segments */