audiodecoder: make sure caps is set before forwarding gap event

Before trying to generate a default fixated caps when handling a gap
event, make sure that the same strategy that is used when handling
a buffer has been attempted. Otherwise audiodecoder will ignore
upstream caps settings such as rate and channels and will likely
end with a caps with channels=1 and rate=1.

https://bugzilla.gnome.org/show_bug.cgi?id=722144
This commit is contained in:
Thiago Santos 2014-01-13 20:44:23 -03:00
parent bbbd9f7d49
commit 8cf8332b91

View file

@ -1007,6 +1007,31 @@ send_pending_events (GstAudioDecoder * dec)
g_list_free (pending_events); g_list_free (pending_events);
} }
static GstFlowReturn
check_pending_reconfigure (GstAudioDecoder * dec)
{
GstFlowReturn ret = GST_FLOW_OK;
GstAudioDecoderContext *ctx;
gboolean needs_reconfigure;
ctx = &dec->priv->ctx;
needs_reconfigure = gst_pad_check_reconfigure (dec->srcpad);
if (G_UNLIKELY (ctx->output_format_changed ||
(GST_AUDIO_INFO_IS_VALID (&ctx->info)
&& needs_reconfigure))) {
if (!gst_audio_decoder_negotiate_unlocked (dec)) {
gst_pad_mark_reconfigure (dec->srcpad);
if (GST_PAD_IS_FLUSHING (dec->srcpad))
ret = GST_FLOW_FLUSHING;
else
ret = GST_FLOW_NOT_NEGOTIATED;
}
}
return ret;
}
/** /**
* gst_audio_decoder_finish_frame: * gst_audio_decoder_finish_frame:
* @dec: a #GstAudioDecoder * @dec: a #GstAudioDecoder
@ -1036,7 +1061,6 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf,
GstClockTime ts, next_ts; GstClockTime ts, next_ts;
gsize size; gsize size;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
gboolean needs_reconfigure = FALSE;
/* subclass should not hand us no data */ /* subclass should not hand us no data */
g_return_val_if_fail (buf == NULL || gst_buffer_get_size (buf) > 0, g_return_val_if_fail (buf == NULL || gst_buffer_get_size (buf) > 0,
@ -1059,22 +1083,13 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf,
GST_AUDIO_DECODER_STREAM_LOCK (dec); GST_AUDIO_DECODER_STREAM_LOCK (dec);
needs_reconfigure = gst_pad_check_reconfigure (dec->srcpad); if (buf) {
if (buf && G_UNLIKELY (ctx->output_format_changed || ret = check_pending_reconfigure (dec);
(GST_AUDIO_INFO_IS_VALID (&ctx->info) if (ret == GST_FLOW_FLUSHING || ret == GST_FLOW_NOT_NEGOTIATED)
&& needs_reconfigure))) {
if (!gst_audio_decoder_negotiate_unlocked (dec)) {
gst_pad_mark_reconfigure (dec->srcpad);
if (GST_PAD_IS_FLUSHING (dec->srcpad))
ret = GST_FLOW_FLUSHING;
else
ret = GST_FLOW_NOT_NEGOTIATED;
goto exit; goto exit;
}
}
if (buf && priv->pending_events) { if (priv->pending_events)
send_pending_events (dec); send_pending_events (dec);
} }
/* output shoud be whole number of sample frames */ /* output shoud be whole number of sample frames */
@ -1649,6 +1664,21 @@ gst_audio_decoder_chain_reverse (GstAudioDecoder * dec, GstBuffer * buf)
return result; return result;
} }
static gboolean
gst_audio_decoder_do_caps (GstAudioDecoder * dec)
{
GstCaps *caps = gst_pad_get_current_caps (dec->sinkpad);
if (caps) {
if (!gst_audio_decoder_sink_setcaps (dec, caps)) {
gst_caps_unref (caps);
return FALSE;
}
gst_caps_unref (caps);
}
dec->priv->do_caps = FALSE;
return TRUE;
}
static GstFlowReturn static GstFlowReturn
gst_audio_decoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) gst_audio_decoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{ {
@ -1658,15 +1688,9 @@ gst_audio_decoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
dec = GST_AUDIO_DECODER (parent); dec = GST_AUDIO_DECODER (parent);
if (G_UNLIKELY (dec->priv->do_caps)) { if (G_UNLIKELY (dec->priv->do_caps)) {
GstCaps *caps = gst_pad_get_current_caps (dec->sinkpad); if (!gst_audio_decoder_do_caps (dec)) {
if (caps) { goto not_negotiated;
if (!gst_audio_decoder_sink_setcaps (dec, caps)) {
gst_caps_unref (caps);
goto not_negotiated;
}
gst_caps_unref (caps);
} }
dec->priv->do_caps = FALSE;
} }
if (G_UNLIKELY (!gst_pad_has_current_caps (pad) && dec->priv->needs_format)) if (G_UNLIKELY (!gst_pad_has_current_caps (pad) && dec->priv->needs_format))
@ -1769,6 +1793,13 @@ gst_audio_decoder_handle_gap (GstAudioDecoder * dec, GstEvent * event)
gboolean ret; gboolean ret;
GstClockTime timestamp, duration; GstClockTime timestamp, duration;
/* Check if there is a caps pending to be pushed */
if (G_UNLIKELY (dec->priv->do_caps)) {
if (!gst_audio_decoder_do_caps (dec)) {
goto not_negotiated;
}
}
/* Ensure we have caps first */ /* Ensure we have caps first */
GST_AUDIO_DECODER_STREAM_LOCK (dec); GST_AUDIO_DECODER_STREAM_LOCK (dec);
if (!GST_AUDIO_INFO_IS_VALID (&dec->priv->ctx.info)) { if (!GST_AUDIO_INFO_IS_VALID (&dec->priv->ctx.info)) {
@ -1804,12 +1835,27 @@ gst_audio_decoder_handle_gap (GstAudioDecoder * dec, GstEvent * event)
ret = TRUE; ret = TRUE;
gst_event_unref (event); gst_event_unref (event);
} else { } else {
GstFlowReturn flowret;
/* sub-class doesn't know how to handle empty buffers, /* sub-class doesn't know how to handle empty buffers,
* so just try sending GAP downstream */ * so just try sending GAP downstream */
send_pending_events (dec); flowret = check_pending_reconfigure (dec);
ret = gst_audio_decoder_push_event (dec, event); if (flowret == GST_FLOW_OK) {
send_pending_events (dec);
ret = gst_audio_decoder_push_event (dec, event);
} else {
ret = FALSE;
}
} }
return ret; return ret;
/* ERRORS */
not_negotiated:
{
GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL),
("decoder not initialized"));
return FALSE;
}
} }
static gboolean static gboolean