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);
}
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:
* @dec: a #GstAudioDecoder
@ -1036,7 +1061,6 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf,
GstClockTime ts, next_ts;
gsize size;
GstFlowReturn ret = GST_FLOW_OK;
gboolean needs_reconfigure = FALSE;
/* subclass should not hand us no data */
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);
needs_reconfigure = gst_pad_check_reconfigure (dec->srcpad);
if (buf && 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;
if (buf) {
ret = check_pending_reconfigure (dec);
if (ret == GST_FLOW_FLUSHING || ret == GST_FLOW_NOT_NEGOTIATED)
goto exit;
}
}
if (buf && priv->pending_events) {
send_pending_events (dec);
if (priv->pending_events)
send_pending_events (dec);
}
/* output shoud be whole number of sample frames */
@ -1649,6 +1664,21 @@ gst_audio_decoder_chain_reverse (GstAudioDecoder * dec, GstBuffer * buf)
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
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);
if (G_UNLIKELY (dec->priv->do_caps)) {
GstCaps *caps = gst_pad_get_current_caps (dec->sinkpad);
if (caps) {
if (!gst_audio_decoder_sink_setcaps (dec, caps)) {
gst_caps_unref (caps);
goto not_negotiated;
}
gst_caps_unref (caps);
if (!gst_audio_decoder_do_caps (dec)) {
goto not_negotiated;
}
dec->priv->do_caps = FALSE;
}
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;
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 */
GST_AUDIO_DECODER_STREAM_LOCK (dec);
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;
gst_event_unref (event);
} else {
GstFlowReturn flowret;
/* sub-class doesn't know how to handle empty buffers,
* so just try sending GAP downstream */
send_pending_events (dec);
ret = gst_audio_decoder_push_event (dec, event);
flowret = check_pending_reconfigure (dec);
if (flowret == GST_FLOW_OK) {
send_pending_events (dec);
ret = gst_audio_decoder_push_event (dec, event);
} else {
ret = FALSE;
}
}
return ret;
/* ERRORS */
not_negotiated:
{
GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL),
("decoder not initialized"));
return FALSE;
}
}
static gboolean