mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
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:
parent
13f85c8f11
commit
36165d8d44
5 changed files with 41 additions and 14 deletions
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue