From: Andoni Morales Alastruey Date: Fri, 27 Apr 2012 08:19:15 +0000 (+0200) Subject: alsasink: use the iec958 payloader to support non-payloaded input streams X-Git-Tag: RELEASE-0.11.91~18 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c6409806c144ee5070f8d623093dcb3b894ed3d5;p=platform%2Fupstream%2Fgst-plugins-base.git alsasink: use the iec958 payloader to support non-payloaded input streams --- diff --git a/ext/alsa/gstalsa.c b/ext/alsa/gstalsa.c index 19a9ee0..c1529af 100644 --- a/ext/alsa/gstalsa.c +++ b/ext/alsa/gstalsa.c @@ -163,7 +163,7 @@ gst_alsa_detect_formats (GstObject * obj, snd_pcm_hw_params_t * hw_params, s = gst_caps_get_structure (in_caps, i); if (!gst_structure_has_name (s, "audio/x-raw")) { - GST_WARNING_OBJECT (obj, "skipping non-raw format"); + GST_DEBUG_OBJECT (obj, "skipping non-raw format"); continue; } @@ -476,7 +476,7 @@ gst_alsa_probe_supported_formats (GstObject * obj, snd_pcm_t * handle, snd_pcm_t *pcm = gst_alsa_open_iec958_pcm (obj); if (G_LIKELY (pcm)) { - gst_caps_append (caps, gst_caps_new_empty_simple ("audio/x-iec958")); + gst_caps_append (caps, gst_caps_from_string (PASSTHROUGH_CAPS)); snd_pcm_close (pcm); } } diff --git a/ext/alsa/gstalsa.h b/ext/alsa/gstalsa.h index ee813ae..3f4aa87 100644 --- a/ext/alsa/gstalsa.h +++ b/ext/alsa/gstalsa.h @@ -39,6 +39,15 @@ (SND_LIB_MAJOR == (major) && SND_LIB_MINOR == (minor) && \ SND_LIB_SUBMINOR >= (micro))) +#define PASSTHROUGH_CAPS \ + "audio/x-ac3, framed = (boolean) true;" \ + "audio/x-eac3, framed = (boolean) true; " \ + "audio/x-dts, framed = (boolean) true, " \ + "block-size = (int) { 512, 1024, 2048 }; " \ + "audio/mpeg, mpegversion = (int) 1, " \ + "mpegaudioversion = (int) [ 1, 2 ], parsed = (boolean) true;" + + GST_DEBUG_CATEGORY_EXTERN (alsa_debug); #define GST_CAT_DEFAULT alsa_debug diff --git a/ext/alsa/gstalsasink.c b/ext/alsa/gstalsasink.c index 3480712..f07cadd 100644 --- a/ext/alsa/gstalsasink.c +++ b/ext/alsa/gstalsasink.c @@ -51,6 +51,7 @@ #include "gstalsasink.h" #include "gstalsadeviceprobe.h" +#include #include #include "gst/glib-compat-private.h" @@ -81,6 +82,7 @@ static void gst_alsasink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static GstCaps *gst_alsasink_getcaps (GstBaseSink * bsink, GstCaps * filter); +static gboolean gst_alsasink_query (GstBaseSink * bsink, GstQuery * query); static gboolean gst_alsasink_open (GstAudioSink * asink); static gboolean gst_alsasink_prepare (GstAudioSink * asink, @@ -91,6 +93,9 @@ static gint gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length); static guint gst_alsasink_delay (GstAudioSink * asink); static void gst_alsasink_reset (GstAudioSink * asink); +static gboolean gst_alsasink_acceptcaps (GstAlsaSink * alsa, GstCaps * caps); +static GstBuffer *gst_alsasink_payload (GstAudioBaseSink * sink, + GstBuffer * buf); static gint output_ref; /* 0 */ static snd_output_t *output; /* NULL */ @@ -104,7 +109,7 @@ static GstStaticPadTemplate alsasink_sink_factory = "format = (string) " GST_AUDIO_FORMATS_ALL ", " "layout = (string) interleaved, " "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; " - "audio/x-iec958") + PASSTHROUGH_CAPS) ); static void @@ -140,11 +145,13 @@ gst_alsasink_class_init (GstAlsaSinkClass * klass) GObjectClass *gobject_class; GstElementClass *gstelement_class; GstBaseSinkClass *gstbasesink_class; + GstAudioBaseSinkClass *gstbaseaudiosink_class; GstAudioSinkClass *gstaudiosink_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; gstbasesink_class = (GstBaseSinkClass *) klass; + gstbaseaudiosink_class = (GstAudioBaseSinkClass *) klass; gstaudiosink_class = (GstAudioSinkClass *) klass; parent_class = g_type_class_peek_parent (klass); @@ -161,6 +168,9 @@ gst_alsasink_class_init (GstAlsaSinkClass * klass) gst_static_pad_template_get (&alsasink_sink_factory)); gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasink_getcaps); + gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_alsasink_query); + + gstbaseaudiosink_class->payload = GST_DEBUG_FUNCPTR (gst_alsasink_payload); gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_alsasink_open); gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasink_prepare); @@ -312,6 +322,82 @@ gst_alsasink_getcaps (GstBaseSink * bsink, GstCaps * filter) } } +static gboolean +gst_alsasink_acceptcaps (GstAlsaSink * alsa, GstCaps * caps) +{ + GstAudioRingBuffer *rbuf = GST_AUDIO_BASE_SINK (alsa)->ringbuffer; + GstPad *pad = GST_BASE_SINK (alsa)->sinkpad; + GstCaps *pad_caps; + GstStructure *st; + gboolean ret = FALSE; + + GstAudioRingBufferSpec spec = { 0 }; + + pad_caps = gst_pad_query_caps (pad, caps); + if (!pad_caps || gst_caps_is_empty (pad_caps)) { + if (pad_caps) + gst_caps_unref (pad_caps); + ret = FALSE; + goto done; + } + gst_caps_unref (pad_caps); + + /* If we've not got fixed caps, creating a stream might fail, so let's just + * return from here with default acceptcaps behaviour */ + if (!gst_caps_is_fixed (caps)) + goto done; + + if (!gst_audio_ring_buffer_parse_caps (&rbuf->spec, caps)) + goto done; + + /* Make sure input is framed (one frame per buffer) and can be payloaded */ + switch (rbuf->spec.type) { + case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3: + case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3: + case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS: + case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG: + { + gboolean framed = FALSE, parsed = FALSE; + st = gst_caps_get_structure (caps, 0); + + gst_structure_get_boolean (st, "framed", &framed); + gst_structure_get_boolean (st, "parsed", &parsed); + if ((!framed && !parsed) || gst_audio_iec61937_frame_size (&spec) <= 0) + goto done; + } + default:{ + } + } + ret = TRUE; + +done: + return ret; +} + +static gboolean +gst_alsasink_query (GstBaseSink * sink, GstQuery * query) +{ + GstAlsaSink *alsa = GST_ALSA_SINK (sink); + gboolean ret; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_ACCEPT_CAPS: + { + GstCaps *caps; + + gst_query_parse_accept_caps (query, &caps); + ret = gst_alsasink_acceptcaps (alsa, caps); + gst_query_set_accept_caps_result (query, ret); + ret = TRUE; + break; + } + default: + ret = GST_BASE_SINK_CLASS (parent_class)->query (sink, query); + break; + } + return ret; +} + static int set_hwparams (GstAlsaSink * alsa) { @@ -693,7 +779,10 @@ alsasink_parse_spec (GstAlsaSink * alsa, GstAudioRingBufferSpec * spec) case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW: alsa->format = SND_PCM_FORMAT_MU_LAW; break; - case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_IEC958: + case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3: + case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3: + case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS: + case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG: alsa->format = SND_PCM_FORMAT_S16_BE; alsa->iec958 = TRUE; break; @@ -1001,3 +1090,40 @@ prepare_error: return; } } + +static GstBuffer * +gst_alsasink_payload (GstAudioBaseSink * sink, GstBuffer * buf) +{ + GstAlsaSink *alsa; + + alsa = GST_ALSA_SINK (sink); + + if (alsa->iec958) { + GstBuffer *out; + gint framesize; + GstMapInfo iinfo, oinfo; + + framesize = gst_audio_iec61937_frame_size (&sink->ringbuffer->spec); + if (framesize <= 0) + return NULL; + + out = gst_buffer_new_and_alloc (framesize); + + gst_buffer_map (buf, &iinfo, GST_MAP_READ); + gst_buffer_map (out, &oinfo, GST_MAP_WRITE); + + if (!gst_audio_iec61937_payload (iinfo.data, iinfo.size, + oinfo.data, oinfo.size, &sink->ringbuffer->spec)) { + gst_buffer_unref (out); + return NULL; + } + + gst_buffer_unmap (buf, &iinfo); + gst_buffer_unmap (out, &oinfo); + + gst_buffer_copy_into (out, buf, GST_BUFFER_COPY_METADATA, 0, -1); + return out; + } + + return gst_buffer_ref (buf); +}