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 f218b984cc
commit 589c455ccb
5 changed files with 41 additions and 14 deletions

View file

@ -465,7 +465,7 @@ gst_aacparse_detect_stream (GstAacParse * aacparse,
aacparse->channels = ((data[2] & 0x01) << 2) | ((data[3] & 0xc0) >> 6); aacparse->channels = ((data[2] & 0x01) << 2) | ((data[3] & 0xc0) >> 6);
gst_base_parse_set_frame_props (GST_BASE_PARSE (aacparse), gst_base_parse_set_frame_props (GST_BASE_PARSE (aacparse),
aacparse->sample_rate, 1024); aacparse->sample_rate, 1024, 2, 2);
GST_DEBUG ("ADTS: samplerate %d, channels %d, objtype %d", GST_DEBUG ("ADTS: samplerate %d, channels %d, objtype %d",
aacparse->sample_rate, aacparse->channels, aacparse->object_type); aacparse->sample_rate, aacparse->channels, aacparse->object_type);

View file

@ -465,7 +465,7 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf)
ac3parse->sample_rate = rate; ac3parse->sample_rate = rate;
ac3parse->channels = chans; ac3parse->channels = chans;
gst_base_parse_set_frame_props (parse, rate, 256 * blocks); gst_base_parse_set_frame_props (parse, rate, 256 * blocks, 2, 2);
} }
return GST_FLOW_OK; return GST_FLOW_OK;

View file

@ -237,7 +237,7 @@ gst_amrparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
} }
amrparse->need_header = FALSE; amrparse->need_header = FALSE;
gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1); gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
gst_amrparse_set_src_caps (amrparse); gst_amrparse_set_src_caps (amrparse);
return TRUE; return TRUE;
} }
@ -306,7 +306,7 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse,
if (dsize >= AMR_MIME_HEADER_SIZE && if (dsize >= AMR_MIME_HEADER_SIZE &&
gst_amrparse_parse_header (amrparse, data, skipsize)) { gst_amrparse_parse_header (amrparse, data, skipsize)) {
amrparse->need_header = FALSE; amrparse->need_header = FALSE;
gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1); gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
} else { } else {
GST_WARNING ("media doesn't look like a AMR format"); GST_WARNING ("media doesn't look like a AMR format");
} }

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);