summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2009-09-22 17:42:48 +0200
committerWim Taymans <wim@metal.(none)>2009-09-28 22:16:53 +0200
commit3338f91cfeb1bc2fc109766f15d1fe19e2475216 (patch)
treecd1bc9ba6ea78fa642dce9ff7547e7d1a88f67c7
parent1b325945e579cc9ed32953ab1f2d036e61c68de7 (diff)
avi: fix prev keyframe search and cleanups
-rw-r--r--gst/avi/gstavidemux.c70
1 files changed, 34 insertions, 36 deletions
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c
index 3233c5bd3..c6ee30bec 100644
--- a/gst/avi/gstavidemux.c
+++ b/gst/avi/gstavidemux.c
@@ -1882,13 +1882,13 @@ gst_avi_demux_index_prev (GstAviDemux * avi, GstAviStream * stream,
GstAviIndexEntry *entry;
guint i;
for (i = last; i > 0; i--) {
entry = &stream->index[i - 1];
if (!keyframe || ENTRY_IS_KEYFRAME (entry)) {
- return i;
+ return i - 1;
}
}
return 0;
}
static guint
@@ -2155,13 +2155,13 @@ gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf)
stream->idx_max);
if (G_UNLIKELY (!stream->index))
goto out_of_mem;
}
GST_LOG_OBJECT (avi,
- "Adding stream %d, index entry %d, kf %d, size %u "
+ "Adding stream %u, index entry %d, kf %d, size %u "
", offset %" G_GUINT64_FORMAT ", total %" G_GUINT64_FORMAT, stream_nr,
stream->idx_n, ENTRY_IS_KEYFRAME (&entry), entry.size, entry.offset,
entry.total);
/* and copy */
stream->index[stream->idx_n++] = entry;
@@ -2200,13 +2200,13 @@ gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf)
}
#ifndef GST_DISABLE_GST_DEBUG
total_idx += stream->idx_n;
total_max += stream->idx_max;
#endif
GST_INFO_OBJECT (avi, "Stream %d, dur %" GST_TIME_FORMAT ", %6u entries, "
- "%5lu keyframes, entry size = %2u, total size = %10u, allocated %10u",
+ "%5u keyframes, entry size = %2u, total size = %10u, allocated %10u",
i, GST_TIME_ARGS (stream->idx_duration), stream->idx_n,
stream->n_keyframes, (guint) sizeof (GstAviIndexEntry),
(guint) (stream->idx_n * sizeof (GstAviIndexEntry)),
(guint) (stream->idx_max * sizeof (GstAviIndexEntry)));
}
#ifndef GST_DISABLE_GST_DEBUG
@@ -3045,30 +3045,29 @@ gst_avi_demux_calculate_durations_from_index (GstAviDemux * avi)
GST_TIME_ARGS (total));
gst_segment_set_duration (&avi->segment, GST_FORMAT_TIME, total);
}
/* returns FALSE if there are no pads to deliver event to,
- * otherwise TRUE (whatever the outcome of event sending) */
+ * otherwise TRUE (whatever the outcome of event sending),
+ * takes ownership of the event. */
static gboolean
gst_avi_demux_push_event (GstAviDemux * avi, GstEvent * event)
{
gboolean result = FALSE;
gint i;
GST_DEBUG_OBJECT (avi, "sending %s event to %d streams",
GST_EVENT_TYPE_NAME (event), avi->num_streams);
- if (avi->num_streams) {
- for (i = 0; i < avi->num_streams; i++) {
- GstAviStream *stream = &avi->stream[i];
+ for (i = 0; i < avi->num_streams; i++) {
+ GstAviStream *stream = &avi->stream[i];
- if (stream->pad) {
- result = TRUE;
- gst_pad_push_event (stream->pad, gst_event_ref (event));
- }
+ if (stream->pad) {
+ result = TRUE;
+ gst_pad_push_event (stream->pad, gst_event_ref (event));
}
}
gst_event_unref (event);
return result;
}
@@ -3732,13 +3731,12 @@ static gboolean
gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
{
GstClockTime seek_time;
gboolean keyframe;
guint i, index;
GstAviStream *stream;
- GstClockTime timestamp, duration;
seek_time = segment->last_stop;
keyframe = !!(segment->flags & GST_SEEK_FLAG_KEY_UNIT);
GST_DEBUG_OBJECT (avi, "seek to: %" GST_TIME_FORMAT
" keyframe seeking:%d", GST_TIME_ARGS (seek_time), keyframe);
@@ -3757,34 +3755,27 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
/* now go to the previous keyframe, this is where we should start
* decoding from. */
index = gst_avi_demux_index_prev (avi, stream, index, TRUE);
GST_DEBUG_OBJECT (avi, "previous keyframe at %u", index);
}
- /* take a look at the final entry */
- gst_avi_demux_get_buffer_info (avi, stream, index,
- &timestamp, &duration, NULL, NULL);
-
- GST_DEBUG_OBJECT (avi,
- "Got keyframe entry %d [ts:%" GST_TIME_FORMAT
- " / duration:%" GST_TIME_FORMAT "]", index,
- GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
+ /* move the main stream to this position */
+ gst_avi_demux_move_stream (avi, stream, segment, index);
if (keyframe) {
/* when seeking to a keyframe, we update the result seek time
* to the time of the keyframe. */
- seek_time = timestamp;
+ seek_time = stream->current_timestamp;
+ GST_DEBUG_OBJECT (avi, "keyframe adjusted to %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (seek_time));
}
/* the seek time is also the last_stop and stream time */
segment->last_stop = seek_time;
segment->time = seek_time;
- /* move the main stream to this position */
- gst_avi_demux_move_stream (avi, stream, segment, index);
-
/* now set DISCONT and align the other streams */
for (i = 0; i < avi->num_streams; i++) {
GstAviStream *ostream;
ostream = &avi->stream[i];
if (ostream == stream)
@@ -3884,17 +3875,19 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event)
}
/* do the seek, seeksegment.last_stop contains the new position, this
* actually never fails. */
gst_avi_demux_do_seek (avi, &seeksegment);
if (flush) {
+ GstEvent *event = gst_event_new_flush_stop ();
gint i;
GST_DEBUG_OBJECT (avi, "sending flush stop");
- gst_avi_demux_push_event (avi, gst_event_new_flush_stop ());
- gst_pad_push_event (avi->sinkpad, gst_event_new_flush_stop ());
+ gst_avi_demux_push_event (avi, gst_event_ref (event));
+ gst_pad_push_event (avi->sinkpad, event);
+
/* reset the last flow and mark discont, FLUSH is always DISCONT */
for (i = 0; i < avi->num_streams; i++) {
avi->stream[i].last_flow = GST_FLOW_OK;
avi->stream[i].discont = TRUE;
}
} else if (avi->segment_running) {
@@ -3925,19 +3918,21 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event)
stop = avi->segment.duration;
/* queue the segment event for the streaming thread. */
if (avi->seek_event)
gst_event_unref (avi->seek_event);
if (avi->segment.rate > 0.0) {
+ /* forwards goes from last_stop to stop */
avi->seek_event = gst_event_new_new_segment (FALSE,
avi->segment.rate, avi->segment.format,
avi->segment.last_stop, stop, avi->segment.time);
} else {
+ /* reverse goes from start to last_stop */
avi->seek_event = gst_event_new_new_segment (FALSE,
avi->segment.rate, avi->segment.format,
- avi->segment.start, avi->segment.last_stop, avi->segment.start);
+ avi->segment.start, avi->segment.last_stop, avi->segment.time);
}
if (!avi->streaming) {
avi->segment_running = TRUE;
gst_pad_start_task (avi->sinkpad, (GstTaskFunction) gst_avi_demux_loop,
avi->sinkpad);
@@ -4207,14 +4202,15 @@ gst_avi_demux_loop_data (GstAviDemux * avi)
}
}
/* correct for index offset */
offset += avi->index_offset + 8;
- GST_LOG ("reading buffer (size=%d) from stream %d at current pos %"
- G_GUINT64_FORMAT " (%llx)", size, stream_num, offset, offset);
+ GST_LOG ("reading buffer (size=%d), stream %d, pos %"
+ G_GUINT64_FORMAT " (%llx), kf %d", size, stream_num, offset,
+ offset, keyframe);
/* pull in the data */
ret = gst_pad_pull_range (avi->sinkpad, offset, size, &buf);
if (ret != GST_FLOW_OK)
goto pull_failed;
@@ -4223,38 +4219,40 @@ gst_avi_demux_loop_data (GstAviDemux * avi)
goto short_buffer;
/* invert the picture if needed */
buf = gst_avi_demux_invert (stream, buf);
/* mark non-keyframes */
- if (!keyframe)
+ if (keyframe)
+ GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+ else
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
GST_BUFFER_TIMESTAMP (buf) = timestamp;
GST_BUFFER_DURATION (buf) = duration;
GST_BUFFER_OFFSET (buf) = out_offset;
GST_BUFFER_OFFSET_END (buf) = out_offset_end;
+ /* mark discont when pending */
+ if (stream->discont) {
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+ stream->discont = FALSE;
+ }
+
gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad));
GST_DEBUG_OBJECT (avi, "Pushing buffer of size %u, ts %"
GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", off %" G_GUINT64_FORMAT
", off_end %" G_GUINT64_FORMAT " on pad %s",
GST_BUFFER_SIZE (buf), GST_TIME_ARGS (timestamp),
GST_TIME_ARGS (duration), GST_BUFFER_OFFSET (buf),
GST_BUFFER_OFFSET_END (buf), GST_PAD_NAME (stream->pad));
/* update current position in the segment */
gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, timestamp);
- /* mark discont when pending */
- if (stream->discont) {
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
- stream->discont = FALSE;
- }
-
ret = gst_pad_push (stream->pad, buf);
/* mark as processed, we increment the frame and byte counters then
* leave the while loop and return the GstFlowReturn */
processed = TRUE;
GST_DEBUG_OBJECT (avi, "Processed buffer %u: %s", stream->current_entry,