diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2009-09-22 17:42:48 +0200 |
---|---|---|
committer | Wim Taymans <wim@metal.(none)> | 2009-09-28 22:16:53 +0200 |
commit | 3338f91cfeb1bc2fc109766f15d1fe19e2475216 (patch) | |
tree | cd1bc9ba6ea78fa642dce9ff7547e7d1a88f67c7 | |
parent | 1b325945e579cc9ed32953ab1f2d036e61c68de7 (diff) |
avi: fix prev keyframe search and cleanups
-rw-r--r-- | gst/avi/gstavidemux.c | 70 |
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, - ×tamp, &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, |