baseparse: use _set_frame_props to configure frame lead_in and lead_out

... provided a corresponding decoder with sufficient leading and following
frames to carry out full decoding for a particular segment.
This commit is contained in:
Mark Nauwelaerts 2010-09-22 15:07:09 +02:00 committed by Tim-Philipp Müller
parent 668ad3836a
commit 038821d30e
2 changed files with 37 additions and 10 deletions

View file

@ -219,6 +219,8 @@ struct _GstBaseParsePrivate
guint fps_num, fps_den; guint fps_num, fps_den;
guint update_interval; guint update_interval;
guint bitrate; guint bitrate;
guint lead_in, lead_out;
GstClockTime lead_in_ts, lead_out_ts;
GstBaseParseSeekable seekable; GstBaseParseSeekable seekable;
gboolean discont; gboolean discont;
@ -478,6 +480,8 @@ gst_base_parse_reset (GstBaseParse * parse)
parse->priv->update_interval = 50; parse->priv->update_interval = 50;
parse->priv->fps_num = parse->priv->fps_den = 0; parse->priv->fps_num = parse->priv->fps_den = 0;
parse->priv->frame_duration = GST_CLOCK_TIME_NONE; parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
parse->priv->lead_in = parse->priv->lead_out = 0;
parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
parse->priv->seekable = GST_BASE_PARSE_SEEK_DEFAULT; parse->priv->seekable = GST_BASE_PARSE_SEEK_DEFAULT;
parse->priv->bitrate = 0; parse->priv->bitrate = 0;
parse->priv->framecount = 0; parse->priv->framecount = 0;
@ -1475,14 +1479,15 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
if (ret == GST_BASE_PARSE_FLOW_CLIP) { if (ret == GST_BASE_PARSE_FLOW_CLIP) {
if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
GST_BUFFER_TIMESTAMP (buffer) > parse->segment.stop) { GST_BUFFER_TIMESTAMP (buffer) >
parse->segment.stop + parse->priv->lead_out_ts) {
GST_LOG_OBJECT (parse, "Dropped frame, after segment"); GST_LOG_OBJECT (parse, "Dropped frame, after segment");
ret = GST_FLOW_UNEXPECTED; ret = GST_FLOW_UNEXPECTED;
} else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
GST_BUFFER_DURATION_IS_VALID (buffer) && GST_BUFFER_DURATION_IS_VALID (buffer) &&
GST_CLOCK_TIME_IS_VALID (parse->segment.start) && GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) +
< parse->segment.start) { parse->priv->lead_in_ts < parse->segment.start) {
GST_LOG_OBJECT (parse, "Dropped frame, before segment"); GST_LOG_OBJECT (parse, "Dropped frame, before segment");
ret = GST_BASE_PARSE_FLOW_DROPPED; ret = GST_BASE_PARSE_FLOW_DROPPED;
} else { } else {
@ -2205,13 +2210,18 @@ gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough)
* @parse: the #GstBaseParse to set * @parse: the #GstBaseParse to set
* @fps_num: frames per second (numerator). * @fps_num: frames per second (numerator).
* @fps_den: frames per second (denominator). * @fps_den: frames per second (denominator).
* @lead_in: frames needed before a segment for subsequent decode
* @lead_out: frames needed after a segment
* *
* If frames per second is configured, parser can take care of buffer duration * If frames per second is configured, parser can take care of buffer duration
* and timestamping. * and timestamping. When performing segment clipping, or seeking to a specific
* location, a corresponding decoder might need an initial @lead_in and a
* following @lead_out number of frames to ensure the desired segment is
* entirely filled upon decoding.
*/ */
void void
gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
guint fps_den) guint fps_den, guint lead_in, guint lead_out)
{ {
g_return_if_fail (parse != NULL); g_return_if_fail (parse != NULL);
@ -2223,13 +2233,24 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
fps_num, fps_den); fps_num, fps_den);
fps_num = fps_den = 0; fps_num = fps_den = 0;
parse->priv->frame_duration = GST_CLOCK_TIME_NONE; parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
parse->priv->lead_in = parse->priv->lead_out = 0;
parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
} else { } else {
parse->priv->frame_duration = parse->priv->frame_duration =
gst_util_uint64_scale (GST_SECOND, parse->priv->fps_den, gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
parse->priv->fps_num); parse->priv->lead_in = lead_in;
parse->priv->lead_out = lead_out;
parse->priv->lead_in_ts =
gst_util_uint64_scale (GST_SECOND, fps_den * lead_in, fps_num);
parse->priv->lead_out_ts =
gst_util_uint64_scale (GST_SECOND, fps_den * lead_out, fps_num);
} }
GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms", GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms",
fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND); fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND);
GST_LOG_OBJECT (parse, "set lead in: %d frames = %" G_GUINT64_FORMAT " ms, "
"lead out: %d frames = %" G_GUINT64_FORMAT " ms",
lead_in, parse->priv->lead_in_ts / GST_MSECOND,
lead_out, parse->priv->lead_out_ts / GST_MSECOND);
GST_BASE_PARSE_UNLOCK (parse); GST_BASE_PARSE_UNLOCK (parse);
} }
@ -2598,8 +2619,14 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
accurate = TRUE; accurate = TRUE;
} }
if (accurate) { if (accurate) {
seekpos = gst_base_parse_find_offset (parse, seeksegment.last_stop, TRUE, GstClockTime startpos = seeksegment.last_stop;
&start_ts);
/* accurate requested, so ... seek a bit before target */
if (startpos < parse->priv->lead_in_ts)
startpos = 0;
else
startpos -= parse->priv->lead_in_ts;
seekpos = gst_base_parse_find_offset (parse, startpos, TRUE, &start_ts);
seekstop = gst_base_parse_find_offset (parse, seeksegment.stop, FALSE, seekstop = gst_base_parse_find_offset (parse, seeksegment.stop, FALSE,
NULL); NULL);
} else { } else {

View file

@ -294,7 +294,7 @@ void gst_base_parse_set_min_frame_size (GstBaseParse *parse,
void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough); void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough);
void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
guint fps_den); guint fps_den, guint lead_in, guint lead_out);
gboolean gst_base_parse_get_sync (GstBaseParse * parse); gboolean gst_base_parse_get_sync (GstBaseParse * parse);