summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/design/draft-framestep.txt12
-rw-r--r--gst/gstmessage.c29
-rw-r--r--gst/gstmessage.h7
-rw-r--r--libs/gst/base/gstbasesink.c43
-rw-r--r--tests/examples/stepping/framestep1.c4
5 files changed, 62 insertions, 33 deletions
diff --git a/docs/design/draft-framestep.txt b/docs/design/draft-framestep.txt
index 56bceb0b7f..8fe789e00d 100644
--- a/docs/design/draft-framestep.txt
+++ b/docs/design/draft-framestep.txt
@@ -180,13 +180,19 @@ messages
"rate", G_TYPE_DOUBLE
The rate and direction at which the frames were stepped.
- "duration", G_TYPE_UINT64
- The total duration of the stepped units in GST_FORMAT_TIME.
+ "flush", G_TYPE_BOOLEAN
+ If the stepped frames were flushed.
"intermediate", G_TYPE_BOOLEAN
If this is an intermediate step operation that completed.
- The message is emited by the element that performs the step operation.
+ "duration", G_TYPE_UINT64
+ The total duration of the stepped units in GST_FORMAT_TIME.
+
+ The message is emited by the element that performs the step operation. The
+ purpose is to return the duration in GST_FORMAT_TIME of the stepped media. This
+ especially interesting to align other stream in case of stepping frames on the
+ video sink element.
Direction switch
diff --git a/gst/gstmessage.c b/gst/gstmessage.c
index fec9a1992f..4bc185d6a7 100644
--- a/gst/gstmessage.c
+++ b/gst/gstmessage.c
@@ -1641,8 +1641,9 @@ gst_message_get_stream_status_object (GstMessage * message)
* @format: the format of @amount
* @amount: the amount of stepped data
* @rate: the rate of the stepped amount
- * @duration: the duration of the data
+ * @flush: is this an flushing step
* @intermediate: is this an intermediate step
+ * @duration: the duration of the data
*
* This message is posted by elements when they complete a part, when @intermediate set
* to TRUE, or a complete step operation.
@@ -1658,7 +1659,7 @@ gst_message_get_stream_status_object (GstMessage * message)
*/
GstMessage *
gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
- gdouble rate, guint64 duration, gboolean intermediate)
+ gdouble rate, gboolean flush, gboolean intermediate, guint64 duration)
{
GstMessage *message;
GstStructure *structure;
@@ -1667,8 +1668,9 @@ gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
- GST_QUARK (DURATION), G_TYPE_UINT64, duration,
- GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
+ GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
+ GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate,
+ GST_QUARK (DURATION), G_TYPE_UINT64, duration, NULL);
message = gst_message_new_custom (GST_MESSAGE_STEP_DONE, src, structure);
return message;
@@ -1680,8 +1682,9 @@ gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
* @format: result location for the format
* @amount: result location for the amount
* @rate: result location for the rate
- * @duration: result location for the duration
+ * @flush: result location for the flush flag
* @intermediate: result location for the intermediate flag
+ * @duration: result location for the duration
*
* Extract the requested state from the request_state message.
*
@@ -1691,8 +1694,8 @@ gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
*/
void
gst_message_parse_step_done (GstMessage * message, GstFormat * format,
- guint64 * amount, gdouble * rate, guint64 * duration,
- gboolean * intermediate)
+ guint64 * amount, gdouble * rate, gboolean * flush, gboolean * intermediate,
+ guint64 * duration)
{
g_return_if_fail (GST_IS_MESSAGE (message));
g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_DONE);
@@ -1707,12 +1710,16 @@ gst_message_parse_step_done (GstMessage * message, GstFormat * format,
if (rate)
*rate = g_value_get_double (gst_structure_id_get_value (message->structure,
GST_QUARK (RATE)));
- if (duration)
- *duration =
- g_value_get_uint64 (gst_structure_id_get_value (message->structure,
- GST_QUARK (DURATION)));
+ if (flush)
+ *flush =
+ g_value_get_boolean (gst_structure_id_get_value (message->structure,
+ GST_QUARK (FLUSH)));
if (intermediate)
*intermediate =
g_value_get_boolean (gst_structure_id_get_value (message->structure,
GST_QUARK (INTERMEDIATE)));
+ if (duration)
+ *duration =
+ g_value_get_uint64 (gst_structure_id_get_value (message->structure,
+ GST_QUARK (DURATION)));
}
diff --git a/gst/gstmessage.h b/gst/gstmessage.h
index fe55aa5edd..48339b45a2 100644
--- a/gst/gstmessage.h
+++ b/gst/gstmessage.h
@@ -385,10 +385,11 @@ GstMessage * gst_message_new_state_dirty (GstObject * src);
/* STEP_DONE */
GstMessage * gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
- gdouble rate, guint64 duration, gboolean intermediate);
+ gdouble rate, gboolean flush, gboolean intermediate,
+ guint64 duration);
void gst_message_parse_step_done (GstMessage * message, GstFormat *format, guint64 *amount,
- gdouble *rate, guint64 *duration, gboolean *intermediate);
-
+ gdouble *rate, gboolean *flush, gboolean *intermediate,
+ guint64 *duration);
/* CLOCK_PROVIDE */
GstMessage * gst_message_new_clock_provide (GstObject * src, GstClock *clock, gboolean ready);
void gst_message_parse_clock_provide (GstMessage *message, GstClock **clock,
diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c
index 588224aaec..ca1135e997 100644
--- a/libs/gst/base/gstbasesink.c
+++ b/libs/gst/base/gstbasesink.c
@@ -162,6 +162,7 @@ typedef struct
guint64 duration; /* the duration in time of the skipped data */
guint64 start; /* running_time of the start */
gdouble rate; /* rate of 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 */
} GstStepInfo;
@@ -1476,22 +1477,23 @@ static void
start_stepping (GstBaseSink * sink, GstSegment * segment,
GstStepInfo * pending, GstStepInfo * current)
{
- gint64 start;
-
GST_DEBUG_OBJECT (sink, "update pending step");
memcpy (current, pending, sizeof (GstStepInfo));
pending->valid = FALSE;
/* get the running time of the current segment start and remember it */
- start =
- gst_segment_to_running_time (segment, segment->format, segment->start);
+ if (segment->rate > 0.0)
+ current->start =
+ gst_segment_to_running_time (segment, segment->format, segment->start);
+ else
+ current->start =
+ gst_segment_to_running_time (segment, segment->format, segment->stop);
/* set the new rate */
- segment->rate = current->rate;
+ segment->rate = segment->rate * current->rate;
GST_DEBUG_OBJECT (sink, "step started at running_time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (start));
- current->start = start;
+ GST_TIME_ARGS (current->start));
if (current->amount == -1) {
GST_DEBUG_OBJECT (sink, "step amount == -1, stop stepping");
@@ -1517,26 +1519,38 @@ stop_stepping (GstBaseSink * sink, GstSegment * segment,
GST_TIME_FORMAT, GST_TIME_ARGS (*rstart), GST_TIME_ARGS (cstart));
/* configure the duration of the elapsed segment */
- current->duration = *rstart - current->start;
+ if (segment->rate > 0.0)
+ current->duration = *rstart - current->start;
+ else
+ current->duration = *rstop - current->start;
+
GST_DEBUG_OBJECT (sink, "step elapsed running_time %" GST_TIME_FORMAT,
GST_TIME_ARGS (current->duration));
/* update the segment, discarding what was consumed, running time goes
* backwards with the duration of the data we skipped. FIXME, this only works
* in PAUSED. */
- segment->time = gst_segment_to_stream_time (segment, segment->format, cstart);
- segment->start = cstart;
+ if (segment->rate > 0.0) {
+ segment->time =
+ gst_segment_to_stream_time (segment, segment->format, cstart);
+ segment->start = cstart;
+
+ *rstart = current->start;
+ *rstop -= current->duration;
+ } else {
+ segment->stop = cstop;
+ *rstop = current->start;
+ *rstart -= current->duration;
+ }
segment->accum = current->start;
/* the clip segment is used for position report in paused... */
memcpy (sink->abidata.ABI.clip_segment, segment, sizeof (GstSegment));
- *rstart = current->start;
- *rstop -= current->duration;
-
message =
gst_message_new_step_done (GST_OBJECT_CAST (sink), current->format,
- current->amount, current->rate, current->duration, current->intermediate);
+ current->amount, current->rate, current->flush, current->intermediate,
+ current->duration);
gst_message_set_seqnum (message, current->seqnum);
gst_element_post_message (GST_ELEMENT_CAST (sink), message);
@@ -3392,6 +3406,7 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
priv->pending_step.amount = amount;
priv->pending_step.position = 0;
priv->pending_step.rate = rate;
+ priv->pending_step.flush = flush;
priv->pending_step.intermediate = intermediate;
priv->pending_step.valid = TRUE;
diff --git a/tests/examples/stepping/framestep1.c b/tests/examples/stepping/framestep1.c
index 9625f78650..ddf82a2b4f 100644
--- a/tests/examples/stepping/framestep1.c
+++ b/tests/examples/stepping/framestep1.c
@@ -37,11 +37,11 @@ event_loop (GstElement * pipe)
GstFormat format;
guint64 amount;
gdouble rate;
+ gboolean flush, intermediate;
guint64 duration;
- gboolean intermediate;
gst_message_parse_step_done (message, &format, &amount, &rate,
- &duration, &intermediate);
+ &flush, &intermediate, &duration);
if (format == GST_FORMAT_DEFAULT) {
g_message ("step done: %" GST_TIME_FORMAT " skipped in %"