mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
stepping: more stepping improvements
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.
This commit is contained in:
parent
23b772664b
commit
25067558dc
7 changed files with 119 additions and 53 deletions
|
@ -170,6 +170,39 @@ events
|
|||
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:
|
||||
|
||||
|
@ -191,6 +224,9 @@ messages
|
|||
"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
|
||||
|
|
|
@ -1645,6 +1645,7 @@ gst_message_get_stream_status_object (GstMessage * message)
|
|||
* @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.
|
||||
|
@ -1660,7 +1661,8 @@ gst_message_get_stream_status_object (GstMessage * message)
|
|||
*/
|
||||
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;
|
||||
|
@ -1671,7 +1673,8 @@ gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
|
|||
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;
|
||||
|
@ -1686,6 +1689,7 @@ gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
|
|||
* @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.
|
||||
*
|
||||
|
@ -1696,56 +1700,52 @@ 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, 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);
|
||||
}
|
||||
|
|
|
@ -399,10 +399,10 @@ GstMessage * gst_message_new_state_dirty (GstObject * src);
|
|||
/* 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,
|
||||
|
@ -466,8 +466,12 @@ GstMessage * gst_message_new_request_state (GstObject * src, GstState state
|
|||
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,
|
||||
|
|
|
@ -47,7 +47,7 @@ static const gchar *_quark_strings[] = {
|
|||
"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];
|
||||
|
|
|
@ -116,8 +116,9 @@ typedef enum _GstQuarkId
|
|||
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];
|
||||
|
|
|
@ -1495,7 +1495,9 @@ start_stepping (GstBaseSink * sink, GstSegment * segment,
|
|||
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);
|
||||
|
||||
|
@ -1518,16 +1520,28 @@ start_stepping (GstBaseSink * sink, GstSegment * segment,
|
|||
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));
|
||||
|
@ -1544,7 +1558,7 @@ start_stepping (GstBaseSink * sink, GstSegment * segment,
|
|||
|
||||
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;
|
||||
|
@ -1596,7 +1610,7 @@ stop_stepping (GstBaseSink * sink, GstSegment * segment,
|
|||
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);
|
||||
|
||||
|
@ -1711,6 +1725,7 @@ gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj,
|
|||
GstClockTime sstart, sstop; /* clipped timestamps converted to stream time */
|
||||
GstFormat format;
|
||||
GstBaseSinkPrivate *priv;
|
||||
gboolean eos;
|
||||
|
||||
priv = basesink->priv;
|
||||
|
||||
|
@ -1746,6 +1761,7 @@ gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj,
|
|||
GST_TIME_ARGS (rstart));
|
||||
/* if we are stepping, we end now */
|
||||
*step_end = step->valid;
|
||||
eos = TRUE;
|
||||
goto eos_done;
|
||||
}
|
||||
default:
|
||||
|
@ -1759,6 +1775,8 @@ gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj,
|
|||
}
|
||||
}
|
||||
|
||||
eos = FALSE;
|
||||
|
||||
/* else do buffer sync code */
|
||||
buffer = GST_BUFFER_CAST (obj);
|
||||
|
||||
|
@ -1799,6 +1817,7 @@ gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * 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;
|
||||
|
@ -1841,10 +1860,10 @@ do_times:
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -2326,6 +2345,7 @@ flushing:
|
|||
preroll_failed:
|
||||
{
|
||||
GST_DEBUG_OBJECT (basesink, "preroll failed");
|
||||
*step_end = FALSE;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -2674,6 +2694,9 @@ again:
|
|||
if (ret == GST_FLOW_STEP)
|
||||
goto again;
|
||||
|
||||
if (G_UNLIKELY (basesink->flushing))
|
||||
goto flushing;
|
||||
|
||||
priv->rendered++;
|
||||
}
|
||||
} else {
|
||||
|
@ -2739,7 +2762,7 @@ done:
|
|||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -3550,8 +3573,9 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
|
|||
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) {
|
||||
|
|
|
@ -39,9 +39,10 @@ event_loop (GstElement * pipe)
|
|||
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 %"
|
||||
|
|
Loading…
Reference in a new issue