summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Moutte <julien@moutte.net>2008-05-31 15:30:41 +0000
committerJulien Moutte <julien@moutte.net>2008-05-31 15:30:41 +0000
commitc39a49245f5f742865cb3b87e28e3c16fbfef76d (patch)
tree4d89a1e1eeb948ac807528d55b315a06cf0e7e08
parentf6ef43bbd7eea5d8f42a56211eadfd215cb0780e (diff)
gst/qtdemux/qtdemux.c: Make sure we we don't clip the segment's stop using the main segment duration as that could cr...
Original commit message from CVS: 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.
-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). */