diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2009-06-09 10:25:34 +0200 |
---|---|---|
committer | Wim Taymans <wim@metal.(none)> | 2009-06-09 10:25:34 +0200 |
commit | 72e8d9909c75918f9ed48dec4b87562ca70cb27f (patch) | |
tree | e4a80b8963c7cd9890853aeea7fad11c9c602db8 | |
parent | afeec70effc69dcbcb63b87207428b2715aaa8a1 (diff) |
basesink: do proper clipping in steppingframestep
Update the stop position of the segment so that we clip correctly.
After clipping in non-flushing mode, rerender the remainder of the buffer.
-rw-r--r-- | libs/gst/base/gstbasesink.c | 67 |
1 files changed, 44 insertions, 23 deletions
diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index cf9919f69..b4e2c6c13 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -165,6 +165,7 @@ typedef struct guint64 start; /* running_time of the start */ gdouble rate; /* rate of skipping */ gdouble start_rate; /* rate before skipping */ + guint64 start_stop; /* stop position skipping */ gboolean flush; /* if this was a flushing step */ gboolean intermediate; /* if this is an intermediate step */ gboolean need_preroll; /* if we need preroll after this step */ @@ -1482,6 +1483,8 @@ static void start_stepping (GstBaseSink * sink, GstSegment * segment, GstStepInfo * pending, GstStepInfo * current) { + gint64 end; + GST_DEBUG_OBJECT (sink, "update pending step"); GST_OBJECT_LOCK (sink); @@ -1498,6 +1501,15 @@ start_stepping (GstBaseSink * sink, GstSegment * segment, segment->rate *= current->rate; segment->abs_rate = ABS (segment->rate); + if (segment->format == GST_FORMAT_TIME) { + current->start_stop = segment->stop; + end = current->start + current->amount; + segment->stop = gst_segment_to_position (segment, GST_FORMAT_TIME, end); + } + + GST_DEBUG_OBJECT (sink, "segment now %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT, + GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop)); + GST_DEBUG_OBJECT (sink, "step started at running_time %" GST_TIME_FORMAT, GST_TIME_ARGS (current->start)); @@ -1513,8 +1525,7 @@ start_stepping (GstBaseSink * sink, GstSegment * segment, static void stop_stepping (GstBaseSink * sink, GstSegment * segment, - GstStepInfo * current, guint64 cstart, guint64 cstop, gint64 * rstart, - gint64 * rstop) + GstStepInfo * current, gint64 rstart, gint64 rstop) { gint64 stop, position; GstMessage *message; @@ -1522,9 +1533,9 @@ stop_stepping (GstBaseSink * sink, GstSegment * segment, GST_DEBUG_OBJECT (sink, "step complete"); if (segment->rate > 0.0) - stop = *rstart; + stop = rstart; else - stop = *rstop; + stop = rstop; GST_DEBUG_OBJECT (sink, "step stop at running_time %" GST_TIME_FORMAT, GST_TIME_ARGS (stop)); @@ -1537,20 +1548,22 @@ stop_stepping (GstBaseSink * sink, GstSegment * segment, GST_DEBUG_OBJECT (sink, "step elapsed running_time %" GST_TIME_FORMAT, GST_TIME_ARGS (current->duration)); - /* now move the segment to the new running time */ position = current->start + current->duration; - gst_segment_set_running_time (segment, GST_FORMAT_TIME, position); gst_element_set_start_time (GST_ELEMENT_CAST (sink), position); - /* restore the previous rate */ - segment->rate = current->start_rate; - segment->abs_rate = ABS (segment->rate); + /* now move the segment to the new running time */ + gst_segment_set_running_time (segment, GST_FORMAT_TIME, position); if (current->flush) { /* and remove the accumulated time we flushed */ segment->accum = current->start; } + /* restore the previous rate */ + segment->rate = current->start_rate; + segment->abs_rate = ABS (segment->rate); + segment->stop = current->start_stop; + /* the clip segment is used for position report in paused... */ memcpy (sink->abidata.ABI.clip_segment, segment, sizeof (GstSegment)); @@ -1609,7 +1622,8 @@ handle_stepping (GstBaseSink * sink, GstSegment * segment, GST_TIME_ARGS (last - current->start), GST_TIME_ARGS (current->amount)); - if (current->position >= current->amount || last >= end) { + if ((current->flush && current->position >= current->amount) + || last >= end) { GST_DEBUG_OBJECT (sink, "step ended, we need clipping"); step_end = TRUE; if (segment->rate > 0.0) { @@ -1661,7 +1675,8 @@ static gboolean gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj, GstClockTime * rsstart, GstClockTime * rsstop, GstClockTime * rrstart, GstClockTime * rrstop, gboolean * do_sync, - gboolean * stepped, GstSegment * segment, GstStepInfo * step) + gboolean * stepped, GstSegment * segment, GstStepInfo * step, + gboolean * step_end) { GstBaseSinkClass *bclass; GstBuffer *buffer; @@ -1671,15 +1686,12 @@ gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj, GstClockTime sstart, sstop; /* clipped timestamps converted to stream time */ GstFormat format; GstBaseSinkPrivate *priv; - gboolean step_end; priv = basesink->priv; /* start with nothing */ start = stop = -1; - step_end = FALSE; - if (G_UNLIKELY (GST_IS_EVENT (obj))) { GstEvent *event = GST_EVENT_CAST (obj); @@ -1708,7 +1720,7 @@ gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj, GST_DEBUG_OBJECT (basesink, "sync times for EOS %" GST_TIME_FORMAT, GST_TIME_ARGS (rstart)); /* if we are stepping, we end now */ - step_end = step->valid; + *step_end = step->valid; goto eos_done; } default: @@ -1780,7 +1792,7 @@ do_times: rstop = gst_segment_to_running_time (segment, format, cstop); if (G_UNLIKELY (step->valid)) { - if (!(step_end = handle_stepping (basesink, segment, step, &cstart, &cstop, + if (!(*step_end = handle_stepping (basesink, segment, step, &cstart, &cstop, &rstart, &rstop))) { /* step is still busy, we discard data when we are flushing */ *stepped = step->flush; @@ -1793,8 +1805,10 @@ do_times: eos_done: /* done label only called when doing EOS, we also stop stepping then */ - if (step_end) - stop_stepping (basesink, segment, step, cstart, cstop, &rstart, &rstop); + if (*step_end && step->flush) { + stop_stepping (basesink, segment, step, rstart, rstop); + *step_end = FALSE; + } /* save times */ *rsstart = sstart; @@ -2136,7 +2150,7 @@ flushing: */ static GstFlowReturn gst_base_sink_do_sync (GstBaseSink * basesink, GstPad * pad, - GstMiniObject * obj, gboolean * late) + GstMiniObject * obj, gboolean * late, gboolean * step_end) { GstClockTimeDiff jitter; gboolean syncable; @@ -2164,7 +2178,7 @@ do_step: /* get timing information for this object against the render segment */ syncable = gst_base_sink_get_sync_times (basesink, obj, &sstart, &sstop, &rstart, &rstop, &do_sync, &stepped, &basesink->segment, - current); + current, step_end); if (G_UNLIKELY (stepped)) goto step_skipped; @@ -2568,7 +2582,7 @@ gst_base_sink_render_object (GstBaseSink * basesink, GstPad * pad, { GstFlowReturn ret; GstBaseSinkClass *bclass; - gboolean late; + gboolean late, step_end; GstBaseSinkPrivate *priv; @@ -2576,11 +2590,12 @@ gst_base_sink_render_object (GstBaseSink * basesink, GstPad * pad, again: late = FALSE; + step_end = FALSE; ret = GST_FLOW_OK; /* synchronize this object, non syncable objects return OK * immediatly. */ - ret = gst_base_sink_do_sync (basesink, pad, obj, &late); + ret = gst_base_sink_do_sync (basesink, pad, obj, &late, &step_end); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto sync_failed; @@ -2589,7 +2604,7 @@ again: GstBuffer *buf; /* drop late buffers unconditionally, let's hope it's unlikely */ - if (G_UNLIKELY (late)) + if (G_UNLIKELY (late && !step_end)) goto dropped; buf = GST_BUFFER_CAST (obj); @@ -2618,6 +2633,12 @@ again: if (ret == GST_FLOW_STEP) goto again; + if (step_end) { + stop_stepping (basesink, &basesink->segment, &priv->current_step, + priv->current_rstart, priv->current_rstop); + goto again; + } + priv->rendered++; } } else { |