Update design doc with step-start docs.
Add eos field to step done message
when stepping in reverse, update the segment time field.
Flush out the current step when we are flushing.
messages
--------
+ A GST_MESSAGE_STEP_START is created. It contains the following fields.
+
+ "active"
+ If the step was queued or activated.
+
+ "format", GST_TYPE_FORMAT
+ The format of the step units that queued/activated.
+
+ "amount", G_TYPE_UINT64
+ The amount of units that were queued/activated.
+
+ "rate", G_TYPE_DOUBLE
+ The rate and direction at which the frames were queued/activated.
+
+ "flush", G_TYPE_BOOLEAN
+ If the queued/activated frames will be flushed.
+
+ "intermediate", G_TYPE_BOOLEAN
+ If this is an intermediate step operation that queued/activated.
+
+ The STEP_START message is emited 2 times:
+
+ * first when an element received the STEP event and queued it. The "active"
+ field will be FALSE in this case.
+
+ * second when the step operation started in the streaming thread. The "active"
+ field is TRUE in this case. After this message is emited, the application
+ can queue a new step operation.
+
+ The purpose of this message is to find out how many elements participate in the
+ step operation and to queue new step operations at the earliest possible
+ moment.
+
A new GST_MESSAGE_STEP_DONE message is created. It contains the following
fields:
"duration", G_TYPE_UINT64
The total duration of the stepped units in GST_FORMAT_TIME.
+ "eos", G_TYPE_BOOLEAN
+ The step ended because of EOS.
+
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
* @flush: is this an flushing step
* @intermediate: is this an intermediate step
* @duration: the duration of the data
+ * @eos: the step caused EOS
*
* This message is posted by elements when they complete a part, when @intermediate set
* to TRUE, or a complete step operation.
*/
GstMessage *
gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
- gdouble rate, gboolean flush, gboolean intermediate, guint64 duration)
+ gdouble rate, gboolean flush, gboolean intermediate, guint64 duration,
+ gboolean eos)
{
GstMessage *message;
GstStructure *structure;
GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate,
- GST_QUARK (DURATION), G_TYPE_UINT64, duration, NULL);
+ GST_QUARK (DURATION), G_TYPE_UINT64, duration,
+ GST_QUARK (EOS), G_TYPE_BOOLEAN, eos, NULL);
message = gst_message_new_custom (GST_MESSAGE_STEP_DONE, src, structure);
return message;
* @flush: result location for the flush flag
* @intermediate: result location for the intermediate flag
* @duration: result location for the duration
+ * @eos: result location for the EOS flag
*
* Extract the requested state from the request_state message.
*
void
gst_message_parse_step_done (GstMessage * message, GstFormat * format,
guint64 * amount, gdouble * rate, gboolean * flush, gboolean * intermediate,
- guint64 * duration)
+ guint64 * duration, gboolean * eos)
{
g_return_if_fail (GST_IS_MESSAGE (message));
g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_DONE);
- if (format)
- *format = g_value_get_enum (gst_structure_id_get_value (message->structure,
- GST_QUARK (FORMAT)));
- if (amount)
- *amount =
- g_value_get_uint64 (gst_structure_id_get_value (message->structure,
- GST_QUARK (AMOUNT)));
- if (rate)
- *rate = g_value_get_double (gst_structure_id_get_value (message->structure,
- GST_QUARK (RATE)));
- 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)));
+ gst_structure_id_get (message->structure,
+ GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+ GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
+ GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+ GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
+ GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate,
+ GST_QUARK (EOS), G_TYPE_BOOLEAN, eos, NULL);
}
GstMessage *
-gst_message_new_step_start (GstObject * src, gboolean active)
+gst_message_new_step_start (GstObject * src, gboolean active, GstFormat format,
+ guint64 amount, gdouble rate, gboolean flush, gboolean intermediate)
{
GstMessage *message;
GstStructure *structure;
structure = gst_structure_id_new (GST_QUARK (MESSAGE_STEP_START),
- GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active, NULL);
+ GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active,
+ GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+ GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
+ GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+ GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
+ GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
message = gst_message_new_custom (GST_MESSAGE_STEP_START, src, structure);
return message;
}
void
-gst_message_parse_step_start (GstMessage * message, gboolean * active)
+gst_message_parse_step_start (GstMessage * message, gboolean * active,
+ GstFormat * format, guint64 * amount, gdouble * rate, gboolean * flush,
+ gboolean * intermediate)
{
g_return_if_fail (GST_IS_MESSAGE (message));
g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_START);
- if (active)
- *active =
- g_value_get_boolean (gst_structure_id_get_value (message->structure,
- GST_QUARK (ACTIVE)));
+ gst_structure_id_get (message->structure,
+ GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active,
+ GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
+ GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
+ GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
+ GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
+ GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
}
/* STEP_DONE */
GstMessage * gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
gdouble rate, gboolean flush, gboolean intermediate,
- guint64 duration);
+ guint64 duration, gboolean eos);
void gst_message_parse_step_done (GstMessage * message, GstFormat *format, guint64 *amount,
gdouble *rate, gboolean *flush, gboolean *intermediate,
- guint64 *duration);
+ guint64 *duration, gboolean *eos);
/* CLOCK_PROVIDE */
GstMessage * gst_message_new_clock_provide (GstObject * src, GstClock *clock, gboolean ready);
void gst_message_parse_clock_provide (GstMessage *message, GstClock **clock,
void gst_message_parse_request_state (GstMessage * message, GstState *state);
/* STEP_START */
-GstMessage * gst_message_new_step_start (GstObject * src, gboolean active);
-void gst_message_parse_step_start (GstMessage * message, gboolean *active);
+GstMessage * gst_message_new_step_start (GstObject * src, gboolean active, GstFormat format,
+ guint64 amount, gdouble rate, gboolean flush,
+ gboolean intermediate);
+void gst_message_parse_step_start (GstMessage * message, gboolean *active, GstFormat *format,
+ guint64 *amount, gdouble *rate, gboolean *flush,
+ gboolean *intermediate);
/* custom messages */
GstMessage * gst_message_new_custom (GstMessageType type,
"GstQueryPosition", "GstQueryDuration", "GstQueryLatency", "GstQueryConvert",
"GstQuerySegment", "GstQuerySeeking", "GstQueryFormats", "GstQueryBuffering",
"GstQueryURI", "GstEventStep", "GstMessageStepDone", "amount", "flush",
- "intermediate", "GstMessageStepStart", "active"
+ "intermediate", "GstMessageStepStart", "active", "eos"
};
GQuark _priv_gst_quark_table[GST_QUARK_MAX];
GST_QUARK_INTERMEDIATE = 87,
GST_QUARK_MESSAGE_STEP_START = 88,
GST_QUARK_ACTIVE = 89,
+ GST_QUARK_EOS = 90,
- GST_QUARK_MAX = 90
+ GST_QUARK_MAX = 91
} GstQuarkId;
extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
GST_OBJECT_UNLOCK (sink);
/* post message first */
- message = gst_message_new_step_start (GST_OBJECT (sink), TRUE);
+ message =
+ gst_message_new_step_start (GST_OBJECT (sink), TRUE, current->format,
+ current->amount, current->rate, current->flush, current->intermediate);
gst_message_set_seqnum (message, current->seqnum);
gst_element_post_message (GST_ELEMENT (sink), message);
end = current->start + current->amount;
if (!current->flush) {
/* update the segment clipping regions for non-flushing seeks */
- if (segment->rate > 0.0)
+ if (segment->rate > 0.0) {
segment->stop = gst_segment_to_position (segment, GST_FORMAT_TIME, end);
- else
- segment->start =
- gst_segment_to_position (segment, GST_FORMAT_TIME, end);
+ segment->last_stop = segment->stop;
+ } else {
+ gint64 position;
+
+ position = gst_segment_to_position (segment, GST_FORMAT_TIME, end);
+ segment->time = position;
+ segment->start = position;
+ segment->last_stop = position;
+ }
}
}
- 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,
+ "segment now rate %lf, applied rate %lf, "
+ "format GST_FORMAT_TIME, "
+ "%" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT
+ ", time %" GST_TIME_FORMAT ", accum %" GST_TIME_FORMAT,
+ segment->rate, segment->applied_rate, GST_TIME_ARGS (segment->start),
+ GST_TIME_ARGS (segment->stop), GST_TIME_ARGS (segment->time),
+ GST_TIME_ARGS (segment->accum));
GST_DEBUG_OBJECT (sink, "step started at running_time %" GST_TIME_FORMAT,
GST_TIME_ARGS (current->start));
static void
stop_stepping (GstBaseSink * sink, GstSegment * segment,
- GstStepInfo * current, gint64 rstart, gint64 rstop)
+ GstStepInfo * current, gint64 rstart, gint64 rstop, gboolean eos)
{
gint64 stop, position;
GstMessage *message;
message =
gst_message_new_step_done (GST_OBJECT_CAST (sink), current->format,
current->amount, current->rate, current->flush, current->intermediate,
- current->duration);
+ current->duration, eos);
gst_message_set_seqnum (message, current->seqnum);
gst_element_post_message (GST_ELEMENT_CAST (sink), message);
GstClockTime sstart, sstop; /* clipped timestamps converted to stream time */
GstFormat format;
GstBaseSinkPrivate *priv;
+ gboolean eos;
priv = basesink->priv;
GST_TIME_ARGS (rstart));
/* if we are stepping, we end now */
*step_end = step->valid;
+ eos = TRUE;
goto eos_done;
}
default:
}
}
+ eos = FALSE;
+
/* else do buffer sync code */
buffer = GST_BUFFER_CAST (obj);
if (G_UNLIKELY (!gst_segment_clip (segment, GST_FORMAT_TIME,
(gint64) start, (gint64) stop, &cstart, &cstop))) {
if (step->valid) {
+ GST_DEBUG_OBJECT (basesink, "step out of segment");
/* when we are stepping, pretend we're at the end of the segment */
if (segment->rate > 0.0) {
cstart = segment->stop;
sstop = gst_segment_to_stream_time (segment, format, cstop);
eos_done:
- /* done label only called when doing EOS, we also stop stepping then */
+ /* eos_done label only called when doing EOS, we also stop stepping then */
if (*step_end && step->flush) {
GST_DEBUG_OBJECT (basesink, "flushing step ended");
- stop_stepping (basesink, segment, step, rstart, rstop);
+ stop_stepping (basesink, segment, step, rstart, rstop, eos);
*step_end = FALSE;
}
preroll_failed:
{
GST_DEBUG_OBJECT (basesink, "preroll failed");
+ *step_end = FALSE;
return ret;
}
}
if (ret == GST_FLOW_STEP)
goto again;
+ if (G_UNLIKELY (basesink->flushing))
+ goto flushing;
+
priv->rendered++;
}
} else {
/* the step ended, check if we need to activate a new step */
GST_DEBUG_OBJECT (basesink, "step ended");
stop_stepping (basesink, &basesink->segment, &priv->current_step,
- priv->current_rstart, priv->current_rstop);
+ priv->current_rstart, priv->current_rstop, basesink->eos);
goto again;
}
current = &priv->current_step;
/* post message first */
- message = gst_message_new_step_start (GST_OBJECT (sink), FALSE);
- gst_message_set_seqnum (message, current->seqnum);
+ message = gst_message_new_step_start (GST_OBJECT (sink), FALSE, format,
+ amount, rate, flush, intermediate);
+ gst_message_set_seqnum (message, seqnum);
gst_element_post_message (GST_ELEMENT (sink), message);
if (flush) {
gdouble rate;
gboolean flush, intermediate;
guint64 duration;
+ gboolean eos;
gst_message_parse_step_done (message, &format, &amount, &rate,
- &flush, &intermediate, &duration);
+ &flush, &intermediate, &duration, &eos);
if (format == GST_FORMAT_DEFAULT) {
g_message ("step done: %" GST_TIME_FORMAT " skipped in %"