* which can be provided to GstBaseParse to enable it to cater for
* buffer time metadata (which will be taken from upstream as much as possible).
* Internally keeping track of frames and respective
- * sizes that have been pushed provides GstBaseParse which a bytes per frame
+ * sizes that have been pushed provides GstBaseParse with a bytes per frame
* rate. A default @convert (used if not overriden) will then use these
* rates to perform obvious conversions. These rates are also used to update
* (estimated) duration at regular frame intervals.
+ * If no (fixed) frames per second rate applies, default conversion will be
+ * based on (estimated) bytes per second (but no default buffer metadata
+ * can be provided in this case).
* </para></listitem>
* </itemizedlist>
*
gint64 duration;
GstFormat duration_fmt;
+ gint64 estimated_duration;
guint min_frame_size;
gboolean passthrough;
guint64 framecount;
guint64 bytecount;
+ guint64 acc_duration;
GList *pending_events;
gint64 src_value, GstFormat dest_format, gint64 * dest_value)
{
gboolean ret = FALSE;
+ guint64 bytes, duration;
- if (src_format == dest_format) {
+ if (G_UNLIKELY (src_format == dest_format)) {
*dest_value = src_value;
return TRUE;
}
- /* need data and frame info (having num means den also ok) */
- if (!parse->priv->framecount || !parse->priv->fps_num)
+ if (G_UNLIKELY (src_value == -1)) {
+ *dest_value = -1;
+ return TRUE;
+ }
+
+ /* need at least some frames */
+ if (!parse->priv->framecount)
+ return FALSE;
+
+ /* either frame info (having num means den also ok) or use average bitrate */
+ if (parse->priv->fps_num) {
+ duration = parse->priv->framecount * parse->priv->fps_den * 1000;
+ bytes = parse->priv->bytecount * parse->priv->fps_num;
+ } else {
+ duration = parse->priv->acc_duration / GST_MSECOND;
+ bytes = parse->priv->bytecount;
+ }
+
+ if (G_UNLIKELY (!duration || !bytes))
return FALSE;
if (src_format == GST_FORMAT_BYTES) {
/* BYTES -> TIME conversion */
GST_DEBUG_OBJECT (parse, "converting bytes -> time");
- *dest_value = gst_util_uint64_scale (src_value,
- parse->priv->framecount * parse->priv->fps_den * 1000,
- parse->priv->bytecount * parse->priv->fps_num);
+ *dest_value = gst_util_uint64_scale (src_value, duration, bytes);
*dest_value *= GST_MSECOND;
GST_DEBUG_OBJECT (parse, "conversion result: %" G_GINT64_FORMAT " ms",
*dest_value / GST_MSECOND);
} else if (src_format == GST_FORMAT_TIME) {
GST_DEBUG_OBJECT (parse, "converting time -> bytes");
if (dest_format == GST_FORMAT_BYTES) {
- *dest_value = gst_util_uint64_scale (src_value / GST_MSECOND,
- parse->priv->fps_num * parse->priv->bytecount,
- parse->priv->fps_den * 1000 * parse->priv->framecount);
+ *dest_value = gst_util_uint64_scale (src_value / GST_MSECOND, bytes,
+ duration);
GST_DEBUG_OBJECT (parse,
"time %" G_GINT64_FORMAT " ms in bytes = %" G_GINT64_FORMAT,
src_value / GST_MSECOND, *dest_value);
ret = TRUE;
}
} else if (src_format == GST_FORMAT_DEFAULT) {
+ /* DEFAULT == frame-based */
if (dest_format == GST_FORMAT_TIME) {
- /* DEFAULT == frame-based */
- *dest_value = gst_util_uint64_scale (src_value,
- GST_SECOND * parse->priv->fps_den, parse->priv->fps_num);
- ret = TRUE;
+ if (parse->priv->fps_den) {
+ *dest_value = gst_util_uint64_scale (src_value,
+ GST_SECOND * parse->priv->fps_den, parse->priv->fps_num);
+ ret = TRUE;
+ }
} else if (dest_format == GST_FORMAT_BYTES) {
}
}
{
GstPad *peer;
GstBaseParse *parse;
+ GstBaseParseClass *klass;
parse = GST_BASE_PARSE (aacparse);
+ klass = GST_BASE_PARSE_GET_CLASS (parse);
- /* need frame info */
- if (!parse->priv->fps_den || !parse->priv->fps_num) {
+ /* must be able to convert */
+ if (!klass->convert)
return;
- }
-
- /* Cannot estimate duration. No data has been passed to us yet */
- if (!parse->priv->framecount || !parse->priv->bytecount) {
- return;
- }
peer = gst_pad_get_peer (parse->sinkpad);
if (peer) {
GstFormat pformat = GST_FORMAT_BYTES;
gboolean qres = FALSE;
- gint64 ptot;
+ gint64 ptot, dest_value;
qres = gst_pad_query_duration (peer, &pformat, &ptot);
gst_object_unref (GST_OBJECT (peer));
if (qres) {
- gst_base_parse_set_duration (parse, GST_FORMAT_TIME,
- gst_util_uint64_scale (ptot,
- parse->priv->framecount * parse->priv->fps_den * GST_SECOND,
- parse->priv->bytecount * parse->priv->fps_num));
+ if (klass->convert (parse, pformat, ptot, GST_FORMAT_TIME, &dest_value))
+ parse->priv->estimated_duration = dest_value;
}
}
}
/* update stats */
parse->priv->bytecount += GST_BUFFER_SIZE (buffer);
- parse->priv->framecount +=
- !GST_BUFFER_FLAG_IS_SET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME);
+ if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME)) {
+ parse->priv->framecount++;
+ if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
+ parse->priv->acc_duration += GST_BUFFER_DURATION (buffer);
+ }
+ }
GST_BUFFER_FLAG_UNSET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME);
if (parse->priv->update_interval &&
(parse->priv->framecount % parse->priv->update_interval) == 0)
parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
parse->priv->framecount = 0;
parse->priv->bytecount = 0;
+ parse->priv->acc_duration = 0;
+ parse->priv->estimated_duration = -1;
parse->priv->next_ts = 0;
parse->priv->passthrough = FALSE;
} else if (parse->priv->duration != -1) {
res = klass->convert (parse, parse->priv->duration_fmt,
parse->priv->duration, format, &dest_value);
+ } else if (parse->priv->estimated_duration != -1) {
+ dest_value = parse->priv->estimated_duration;
+ res = TRUE;
}
g_mutex_unlock (parse->parse_lock);