mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 00:31:13 +00:00
alsasink: use the iec958 payloader to support non-payloaded input streams
This commit is contained in:
parent
b7b123964b
commit
c6409806c1
3 changed files with 139 additions and 4 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "gstalsasink.h"
|
||||
#include "gstalsadeviceprobe.h"
|
||||
|
||||
#include <gst/audio/gstaudioiec61937.h>
|
||||
#include <gst/gst-i18n-plugin.h>
|
||||
#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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue