summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--gst/qtdemux/qtdemux.c122
-rw-r--r--win32/common/config.h8
3 files changed, 95 insertions, 47 deletions
diff --git a/ChangeLog b/ChangeLog
index 6cf801d7..1f956df9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-05-31 Julien Moutte <julien@fluendo.com>
+
+ * gst/qtdemux/qtdemux.c: (gst_qtdemux_find_keyframe),
+ (gst_qtdemux_find_segment), (gst_qtdemux_perform_seek),
+ (gst_qtdemux_seek_to_previous_keyframe),
+ (gst_qtdemux_activate_segment), (gst_qtdemux_loop): Make sure we
+ we don't clip the segment's stop using the main segment duration as
+ that could crop quite some video frames. Make reverse playback support
+ more robust and support edit lists. Support seeking to the last frame,
+ and fix reverse looping playback. Add some debugging.
+ * win32/common/config.h: Updated.
+
2008-05-31 Sebastian Dröge <slomo@circular-chaos.org>
* gst/equalizer/gstiirequalizer.c:
diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c
index 5290fb13..6b87dad0 100644
--- a/gst/qtdemux/qtdemux.c
+++ b/gst/qtdemux/qtdemux.c
@@ -528,24 +528,35 @@ static guint32
gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
guint32 index)
{
- if (index >= str->n_samples)
- return str->n_samples;
+ guint32 new_index = index;
+
+ if (index >= str->n_samples) {
+ new_index = str->n_samples;
+ goto beach;
+ }
/* all keyframes, return index */
- if (str->all_keyframe)
- return index;
+ if (str->all_keyframe) {
+ new_index = index;
+ goto beach;
+ }
/* else go back until we have a keyframe */
while (TRUE) {
- if (str->samples[index].keyframe)
+ if (str->samples[new_index].keyframe)
break;
- if (index == 0)
+ if (new_index == 0)
break;
- index--;
+ new_index--;
}
- return index;
+
+beach:
+ GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
+ "gave %u", index, new_index);
+
+ return new_index;
}
/* find the segment for @time_position for @stream
@@ -572,10 +583,19 @@ gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
"looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
- if (segment->time <= time_position && time_position < segment->stop_time) {
- GST_LOG_OBJECT (qtdemux, "segment %d matches", i);
- seg_idx = i;
- break;
+ /* For the last segment we include stop_time in the last segment */
+ if (i < stream->n_segments - 1) {
+ if (segment->time <= time_position && time_position < segment->stop_time) {
+ GST_LOG_OBJECT (qtdemux, "segment %d matches", i);
+ seg_idx = i;
+ break;
+ }
+ } else {
+ if (segment->time <= time_position && time_position <= segment->stop_time) {
+ GST_LOG_OBJECT (qtdemux, "segment %d matches", i);
+ seg_idx = i;
+ break;
+ }
}
}
return seg_idx;
@@ -671,8 +691,6 @@ gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment)
/* find previous keyframe */
kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
- GST_DEBUG_OBJECT (qtdemux, "keyframe at %u", kindex);
-
/* if the keyframe is at a different position, we need to update the
* requiested seek time */
if (index != kindex) {
@@ -1078,16 +1096,17 @@ static GstFlowReturn
gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
{
guint8 n = 0;
- guint32 seg_idx = 0, index = 0, kindex = 0;
- guint64 desired_offset = 0, last_stop = 0, media_start = 0, seg_time = 0;
+ guint32 seg_idx = 0, k_index = 0;
+ guint64 k_pos = 0, last_stop = 0;
QtDemuxSegment *seg = NULL;
- QtDemuxStream *ref_str = NULL, *str = NULL;
+ QtDemuxStream *ref_str = NULL;
/* Now we choose an arbitrary stream, get the previous keyframe timestamp
* and finally align all the other streams on that timestamp with their
* respective keyframes */
for (n = 0; n < qtdemux->n_streams; n++) {
- str = qtdemux->streams[n];
+ QtDemuxStream *str = qtdemux->streams[n];
+
seg_idx = gst_qtdemux_find_segment (qtdemux, str,
qtdemux->segment.last_stop);
@@ -1109,35 +1128,46 @@ gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
}
if (G_UNLIKELY (!ref_str)) {
- GST_WARNING_OBJECT (qtdemux, "couldn't find any stream");
- return GST_FLOW_ERROR;
+ GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
+ goto eos;
}
if (G_UNLIKELY (!ref_str->from_sample)) {
GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
- return GST_FLOW_UNEXPECTED;
+ goto eos;
}
/* So that stream has been playing from from_sample to to_sample. We will
* get the timestamp of the previous sample and search for a keyframe before
* that. For audio streams we do an arbitrary jump in the past (10 samples) */
if (ref_str->subtype == FOURCC_vide) {
- kindex = gst_qtdemux_find_keyframe (qtdemux, ref_str,
+ k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
ref_str->from_sample - 1);
} else {
- kindex = ref_str->from_sample - 10;
+ k_index = ref_str->from_sample - 10;
}
- desired_offset = ref_str->samples[kindex].timestamp;
+
+ /* get current segment for that stream */
+ seg = &ref_str->segments[ref_str->segment_index];
+ /* Crawl back through segments to find the one containing this I frame */
+ while (ref_str->samples[k_index].timestamp < seg->media_start) {
+ GST_DEBUG_OBJECT (qtdemux, "keyframe position is out of segment %u",
+ ref_str->segment_index);
+ if (G_UNLIKELY (!ref_str->segment_index)) {
+ /* Reached first segment, let's consider it's EOS */
+ goto eos;
+ }
+ ref_str->segment_index--;
+ seg = &ref_str->segments[ref_str->segment_index];
+ }
+ /* Calculate time position of the keyframe and where we should stop */
+ k_pos = (ref_str->samples[k_index].timestamp - seg->media_start) + seg->time;
last_stop = ref_str->samples[ref_str->from_sample].timestamp;
- /* Bring that back to global time */
- seg = &ref_str->segments[seg_idx];
- /* Sample global timestamp is timestamp - seg_start + seg_time */
- desired_offset = (desired_offset - seg->media_start) + seg->time;
last_stop = (last_stop - seg->media_start) + seg->time;
GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
"now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
- kindex, GST_TIME_ARGS (desired_offset));
+ k_index, GST_TIME_ARGS (k_pos));
/* Set last_stop with the keyframe timestamp we pushed of that stream */
gst_segment_set_last_stop (&qtdemux->segment, GST_FORMAT_TIME, last_stop);
@@ -1146,14 +1176,16 @@ gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
- return GST_FLOW_UNEXPECTED;
+ goto eos;
}
/* Align them all on this */
for (n = 0; n < qtdemux->n_streams; n++) {
- str = qtdemux->streams[n];
+ guint32 index = 0;
+ guint64 media_start = 0, seg_time = 0;
+ QtDemuxStream *str = qtdemux->streams[n];
- seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_offset);
+ seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
/* segment not found, continue with normal flow */
@@ -1162,7 +1194,7 @@ gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
/* get segment and time in the segment */
seg = &str->segments[seg_idx];
- seg_time = desired_offset - seg->time;
+ seg_time = k_pos - seg->time;
/* get the media time in the segment */
media_start = seg->media_start + seg_time;
@@ -1173,21 +1205,24 @@ gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
GST_TIME_ARGS (media_start), index);
/* find previous keyframe */
- kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
+ k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
/* Remember until where we want to go */
str->to_sample = str->from_sample - 1;
/* Define our time position */
str->time_position =
- (str->samples[kindex].timestamp - seg->media_start) + seg->time;
+ (str->samples[k_index].timestamp - seg->media_start) + seg->time;
/* Now seek back in time */
- gst_qtdemux_move_stream (qtdemux, str, kindex);
+ gst_qtdemux_move_stream (qtdemux, str, k_index);
GST_DEBUG_OBJECT (qtdemux, "keyframe at %u, time position %"
- GST_TIME_FORMAT " playing from sample %u to %u", kindex,
+ GST_TIME_FORMAT " playing from sample %u to %u", k_index,
GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
}
return GST_FLOW_OK;
+
+eos:
+ return GST_FLOW_UNEXPECTED;
}
/* activate the given segment number @seg_idx of @stream at time @offset.
@@ -1235,18 +1270,14 @@ gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
return FALSE;
}
- /* calc media start/stop */
- if (qtdemux->segment.stop == -1)
- stop = segment->media_stop;
- else
- stop = MIN (segment->media_stop, qtdemux->segment.stop);
+ stop = segment->media_stop;
if (qtdemux->segment.rate >= 0) {
start = MIN (segment->media_start + seg_time, stop);
time = offset;
} else {
start = segment->media_start;
stop = MIN (segment->media_start + seg_time, stop);
- time = segment->media_start;
+ time = segment->time;
}
GST_DEBUG_OBJECT (qtdemux, "newsegment %d from %" GST_TIME_FORMAT
@@ -1837,6 +1868,11 @@ pause:
if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
gint64 stop;
+ /* FIXME: I am not sure this is the right fix. If the sinks are
+ * supposed to detect the segment is complete and accumulate
+ * automatically, it does not seem to work here. Need more work */
+ qtdemux->segment_running = TRUE;
+
if ((stop = qtdemux->segment.stop) == -1)
stop = qtdemux->segment.duration;
diff --git a/win32/common/config.h b/win32/common/config.h
index fa1afc4f..8103c7b5 100644
--- a/win32/common/config.h
+++ b/win32/common/config.h
@@ -36,7 +36,7 @@
#define GST_LICENSE "LGPL"
/* package name in plugins */
-#define GST_PACKAGE_NAME "GStreamer Good Plug-ins source release"
+#define GST_PACKAGE_NAME "GStreamer Good Plug-ins CVS/prerelease"
/* package origin */
#define GST_PACKAGE_ORIGIN "Unknown package origin"
@@ -244,13 +244,13 @@
#define PACKAGE_NAME "GStreamer Good Plug-ins"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GStreamer Good Plug-ins 0.10.8"
+#define PACKAGE_STRING "GStreamer Good Plug-ins 0.10.8.1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "gst-plugins-good"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.10.8"
+#define PACKAGE_VERSION "0.10.8.1"
/* Define the plugin directory */
#ifdef _DEBUG
@@ -266,7 +266,7 @@
#undef STDC_HEADERS
/* Version number of package */
-#define VERSION "0.10.8"
+#define VERSION "0.10.8.1"
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */