summaryrefslogtreecommitdiff
path: root/gst-libs/gst/audio/gstaudiodecoder.c
diff options
context:
space:
mode:
authorJan Schmidt <jan@centricular.com>2013-12-26 23:21:45 +1100
committerJan Schmidt <jan@centricular.com>2013-12-27 04:04:45 +1100
commitc24a1254c9f1f73e23a1471ce9dd08f513618c8b (patch)
treec68e0e95c92fd70529d191e33ac3bd0750a8e829 /gst-libs/gst/audio/gstaudiodecoder.c
parent01c7fb11ba17bd70bd00ab5c2db6639ea9da3458 (diff)
audiodecoder: Choose a default initial caps before sending GAP
If there are no caps from the audio decoder when handling a GAP event - as when one is received right at the start on a DVD without initial audio - then choose any default caps for downstream and then send the GAP, so the audio sink has a configured format in which to start the ringbuffer. Also, make the audio sink reject a GAP without caps with a clearer error message. Fixes bug https://bugzilla.gnome.org/show_bug.cgi?id=603921
Diffstat (limited to 'gst-libs/gst/audio/gstaudiodecoder.c')
-rw-r--r--gst-libs/gst/audio/gstaudiodecoder.c114
1 files changed, 82 insertions, 32 deletions
diff --git a/gst-libs/gst/audio/gstaudiodecoder.c b/gst-libs/gst/audio/gstaudiodecoder.c
index c8068716e..7bd338f17 100644
--- a/gst-libs/gst/audio/gstaudiodecoder.c
+++ b/gst-libs/gst/audio/gstaudiodecoder.c
@@ -1732,6 +1732,86 @@ gst_audio_decoder_do_byte (GstAudioDecoder * dec)
1732 dec->priv->ctx.info.rate <= dec->priv->samples_out; 1732 dec->priv->ctx.info.rate <= dec->priv->samples_out;
1733} 1733}
1734 1734
1735/* Must be called holding the GST_AUDIO_DECODER_STREAM_LOCK */
1736static gboolean
1737gst_audio_decoder_negotiate_default_caps (GstAudioDecoder * dec)
1738{
1739 GstCaps *caps;
1740
1741 caps = gst_pad_get_current_caps (dec->srcpad);
1742 if (caps && !gst_audio_info_from_caps (&dec->priv->ctx.info, caps))
1743 return FALSE;
1744
1745 caps = gst_pad_get_allowed_caps (dec->srcpad);
1746 if (!caps || gst_caps_is_empty (caps) || gst_caps_is_any (caps))
1747 return FALSE;
1748
1749 caps = gst_caps_fixate (caps);
1750 if (!caps || !gst_audio_info_from_caps (&dec->priv->ctx.info, caps))
1751 return FALSE;
1752
1753 GST_INFO_OBJECT (dec,
1754 "Chose default caps %" GST_PTR_FORMAT " for initial gap", caps);
1755 gst_caps_unref (caps);
1756
1757 if (!gst_audio_decoder_negotiate_unlocked (dec)) {
1758 GST_INFO_OBJECT (dec, "Failed to negotiate default caps for initial gap");
1759 gst_pad_mark_reconfigure (dec->srcpad);
1760 return FALSE;
1761 }
1762
1763 return TRUE;
1764}
1765
1766static gboolean
1767gst_audio_decoder_handle_gap (GstAudioDecoder * dec, GstEvent * event)
1768{
1769 gboolean ret;
1770 GstClockTime timestamp, duration;
1771
1772 /* Ensure we have caps first */
1773 GST_AUDIO_DECODER_STREAM_LOCK (dec);
1774 if (!GST_AUDIO_INFO_IS_VALID (&dec->priv->ctx.info)) {
1775 if (!gst_audio_decoder_negotiate_default_caps (dec)) {
1776 GST_ELEMENT_ERROR (dec, STREAM, FORMAT, (NULL),
1777 ("Decoder output not negotiated before GAP event."));
1778 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
1779 return FALSE;
1780 }
1781 }
1782 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
1783
1784 gst_event_parse_gap (event, &timestamp, &duration);
1785
1786 /* time progressed without data, see if we can fill the gap with
1787 * some concealment data */
1788 GST_DEBUG_OBJECT (dec,
1789 "gap event: plc %d, do_plc %d, position %" GST_TIME_FORMAT
1790 " duration %" GST_TIME_FORMAT,
1791 dec->priv->plc, dec->priv->ctx.do_plc,
1792 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
1793
1794 if (dec->priv->plc && dec->priv->ctx.do_plc && dec->input_segment.rate > 0.0) {
1795 GstAudioDecoderClass *klass = GST_AUDIO_DECODER_GET_CLASS (dec);
1796 GstBuffer *buf;
1797
1798 /* hand subclass empty frame with duration that needs covering */
1799 buf = gst_buffer_new ();
1800 GST_BUFFER_TIMESTAMP (buf) = timestamp;
1801 GST_BUFFER_DURATION (buf) = duration;
1802 /* best effort, not much error handling */
1803 gst_audio_decoder_handle_frame (dec, klass, buf);
1804 ret = TRUE;
1805 gst_event_unref (event);
1806 } else {
1807 /* sub-class doesn't know how to handle empty buffers,
1808 * so just try sending GAP downstream */
1809 send_pending_events (dec);
1810 ret = gst_audio_decoder_push_event (dec, event);
1811 }
1812 return ret;
1813}
1814
1735static gboolean 1815static gboolean
1736gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event) 1816gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event)
1737{ 1817{
@@ -1819,39 +1899,9 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event)
1819 ret = TRUE; 1899 ret = TRUE;
1820 break; 1900 break;
1821 } 1901 }
1822 case GST_EVENT_GAP:{ 1902 case GST_EVENT_GAP:
1823 GstClockTime timestamp, duration; 1903 ret = gst_audio_decoder_handle_gap (dec, event);
1824 gst_event_parse_gap (event, &timestamp, &duration);
1825
1826 /* time progressed without data, see if we can fill the gap with
1827 * some concealment data */
1828 GST_DEBUG_OBJECT (dec,
1829 "gap event: plc %d, do_plc %d, position %" GST_TIME_FORMAT
1830 " duration %" GST_TIME_FORMAT,
1831 dec->priv->plc, dec->priv->ctx.do_plc,
1832 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
1833 if (dec->priv->plc && dec->priv->ctx.do_plc &&
1834 dec->input_segment.rate > 0.0) {
1835 GstAudioDecoderClass *klass;
1836 GstBuffer *buf;
1837
1838 klass = GST_AUDIO_DECODER_GET_CLASS (dec);
1839 /* hand subclass empty frame with duration that needs covering */
1840 buf = gst_buffer_new ();
1841 GST_BUFFER_TIMESTAMP (buf) = timestamp;
1842 GST_BUFFER_DURATION (buf) = duration;
1843 /* best effort, not much error handling */
1844 gst_audio_decoder_handle_frame (dec, klass, buf);
1845 ret = TRUE;
1846 gst_event_unref (event);
1847 } else {
1848 /* FIXME: sub-class doesn't know how to handle empty buffers,
1849 * so just try sending GAP downstream */
1850 send_pending_events (dec);
1851 ret = gst_audio_decoder_push_event (dec, event);
1852 }
1853 break; 1904 break;
1854 }
1855 case GST_EVENT_FLUSH_STOP: 1905 case GST_EVENT_FLUSH_STOP:
1856 GST_AUDIO_DECODER_STREAM_LOCK (dec); 1906 GST_AUDIO_DECODER_STREAM_LOCK (dec);
1857 /* prepare for fresh start */ 1907 /* prepare for fresh start */