summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2009-06-09 10:25:34 +0200
committerWim Taymans <wim@metal.(none)>2009-06-09 10:25:34 +0200
commit72e8d9909c75918f9ed48dec4b87562ca70cb27f (patch)
treee4a80b8963c7cd9890853aeea7fad11c9c602db8
parentafeec70effc69dcbcb63b87207428b2715aaa8a1 (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.c67
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 {