GstAudioDecoder *dec;
GstFlowReturn ret;
- dec = GST_AUDIO_DECODER (GST_PAD_PARENT (pad));
+ dec = GST_AUDIO_DECODER (parent);
- if (G_UNLIKELY (!GST_PAD_CAPS (pad) && dec->priv->needs_format))
++ if (G_UNLIKELY (!gst_pad_has_current_caps (pad) && dec->priv->needs_format))
+ goto not_negotiated;
+
GST_LOG_OBJECT (dec,
- "received buffer of size %d with ts %" GST_TIME_FORMAT
- ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
+ "received buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
+ ", duration %" GST_TIME_FORMAT, gst_buffer_get_size (buffer),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
}
}
- if (need) {
+ priv->got_data = FALSE;
+ if (G_LIKELY (need)) {
- buf = gst_buffer_new ();
- GST_BUFFER_DATA (buf) = (guint8 *)
- gst_adapter_peek (priv->adapter, priv->offset + need) + priv->offset;
- GST_BUFFER_SIZE (buf) = need;
+ const guint8 *data;
+
+ data = gst_adapter_map (priv->adapter, priv->offset + need);
+ buf =
+ gst_buffer_new_wrapped_full ((gpointer) data, NULL, priv->offset,
+ need);
+ } else if (!priv->drainable) {
+ GST_DEBUG_OBJECT (enc, "non-drainable and no more data");
+ goto finish;
}
GST_LOG_OBJECT (enc, "providing subclass with %d bytes at offset %d",
priv->offset += need;
priv->samples_in += need / ctx->info.bpf;
- priv->got_data = FALSE;
- ret = klass->handle_frame (enc, buf);
+ /* subclass might not want to be bothered with leftover data,
+ * so take care of that here if so, otherwise pass along */
+ if (G_UNLIKELY (priv->force && priv->hard_min && buf)) {
+ GST_DEBUG_OBJECT (enc, "bypassing subclass with leftover");
+ ret = gst_audio_encoder_finish_frame (enc, NULL, -1);
+ } else {
+ ret = klass->handle_frame (enc, buf);
+ }
- if (G_LIKELY (buf))
+ if (G_LIKELY (buf)) {
gst_buffer_unref (buf);
+ gst_adapter_unmap (priv->adapter);
+ }
+ finish:
/* no data to feed, no leftover provided, then bail out */
if (G_UNLIKELY (!buf && !priv->got_data)) {
priv->drained = TRUE;
GST_DEBUG ("Attempting to query duration");
- if (gst_element_query_duration (pipeline, &format, &dur)) {
- if (format == GST_FORMAT_TIME) {
- GST_DEBUG ("Got duration %" GST_TIME_FORMAT, GST_TIME_ARGS (dur));
- dc->priv->current_info->duration = (guint64) dur;
- }
+ if (gst_element_query_duration (pipeline, GST_FORMAT_TIME, &dur)) {
+ GST_DEBUG ("Got duration %" GST_TIME_FORMAT, GST_TIME_ARGS (dur));
+ dc->priv->current_info->duration = (guint64) dur;
+ } else {
+ GstStateChangeReturn sret;
+
+ /* Some parsers may not even return a rough estimate right away, e.g.
+ * because they've only processed a single frame so far, so if we
+ * didn't get a duration the first time, spin a bit and try again.
+ * Ugly, but still better than making parsers or other elements return
+ * completely bogus values. We need some API extensions to solve this
+ * better. */
+ GST_INFO ("No duration yet, try a bit harder..");
+ sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ if (sret != GST_STATE_CHANGE_FAILURE) {
+ int i;
+
+ for (i = 0; i < 2; ++i) {
+ g_usleep (G_USEC_PER_SEC / 20);
- if (gst_element_query_duration (pipeline, &format, &dur) &&
- format == GST_FORMAT_TIME && dur > 0) {
++ if (gst_element_query_duration (pipeline, GST_FORMAT_TIME, &dur)
++ && dur > 0) {
+ GST_DEBUG ("Got duration %" GST_TIME_FORMAT, GST_TIME_ARGS (dur));
+ dc->priv->current_info->duration = (guint64) dur;
+ break;
+ }
+ }
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ }
}
if (dc->priv->seeking_query) {