mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-27 03:23:16 +00:00
bluez: avdtpsink: Add support for LDAC to avdtpsink
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1621>
This commit is contained in:
parent
a576814553
commit
ef3085c743
4 changed files with 146 additions and 10 deletions
|
@ -2332,7 +2332,7 @@
|
|||
"long-name": "Bluetooth AVDTP sink",
|
||||
"pad-templates": {
|
||||
"sink": {
|
||||
"caps": "application/x-rtp:\n media: audio\n payload: [ 96, 127 ]\n clock-rate: { (int)16000, (int)32000, (int)44100, (int)48000 }\n encoding-name: SBC\napplication/x-rtp:\n media: audio\n payload: 14\n clock-rate: 90000\napplication/x-rtp:\n media: audio\n payload: [ 96, 127 ]\n clock-rate: 90000\n encoding-name: MPA\n",
|
||||
"caps": "application/x-rtp:\n media: audio\n payload: [ 96, 127 ]\n clock-rate: { (int)16000, (int)32000, (int)44100, (int)48000 }\n encoding-name: SBC\napplication/x-rtp:\n media: audio\n payload: 14\n clock-rate: 90000\napplication/x-rtp:\n media: audio\n payload: [ 96, 127 ]\n clock-rate: 90000\n encoding-name: MPA\napplication/x-rtp:\n media: audio\n payload: [ 96, 127 ]\n clock-rate: { (int)44100, (int)48000, (int)88200, (int)96000 }\n encoding-name: X-GST-LDAC\n",
|
||||
"direction": "sink",
|
||||
"presence": "always"
|
||||
}
|
||||
|
|
|
@ -111,6 +111,26 @@
|
|||
#define AAC_CHANNELS_1 0x02
|
||||
#define AAC_CHANNELS_2 0x01
|
||||
|
||||
#define SONY_VENDOR_ID 0x0000012d
|
||||
#define LDAC_CODEC_ID 0x00aa
|
||||
|
||||
#define LDAC_SAMPLING_FREQ_44100 0x20
|
||||
#define LDAC_SAMPLING_FREQ_48000 0x10
|
||||
#define LDAC_SAMPLING_FREQ_88200 0x08
|
||||
#define LDAC_SAMPLING_FREQ_96000 0x04
|
||||
|
||||
#define LDAC_CHANNEL_MODE_MONO 0x04
|
||||
#define LDAC_CHANNEL_MODE_DUAL 0x02
|
||||
#define LDAC_CHANNEL_MODE_STEREO 0x01
|
||||
|
||||
#define A2DP_GET_VENDOR_ID(a) ( \
|
||||
(((uint32_t)(a).vendor_id[0]) << 0) | \
|
||||
(((uint32_t)(a).vendor_id[1]) << 8) | \
|
||||
(((uint32_t)(a).vendor_id[2]) << 16) | \
|
||||
(((uint32_t)(a).vendor_id[3]) << 24) \
|
||||
)
|
||||
#define A2DP_GET_CODEC_ID(a) ((a).codec_id[0] | (((uint16_t)(a).codec_id[1]) << 8))
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
|
||||
typedef struct {
|
||||
|
@ -182,4 +202,10 @@ typedef struct {
|
|||
uint8_t codec_id[2];
|
||||
} __attribute__ ((packed)) a2dp_vendor_codec_t;
|
||||
|
||||
typedef struct {
|
||||
a2dp_vendor_codec_t info;
|
||||
uint8_t frequency;
|
||||
uint8_t channel_mode;
|
||||
} __attribute__ ((packed)) a2dp_ldac_t;
|
||||
|
||||
#endif /* #define __GST_BLUEZ_A2DP_CODECS_H_INCLUDED__ */
|
||||
|
|
|
@ -74,21 +74,22 @@ static GstStaticPadTemplate avdtp_sink_factory =
|
|||
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-rtp, "
|
||||
"media = (string) \"audio\","
|
||||
"payload = (int) "
|
||||
GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
|
||||
"clock-rate = (int) { 16000, 32000, "
|
||||
"44100, 48000 }, "
|
||||
"payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
|
||||
"clock-rate = (int) { 16000, 32000, 44100, 48000 }, "
|
||||
"encoding-name = (string) \"SBC\"; "
|
||||
"application/x-rtp, "
|
||||
"media = (string) \"audio\", "
|
||||
"payload = (int) "
|
||||
GST_RTP_PAYLOAD_MPA_STRING ", "
|
||||
"payload = (int) " GST_RTP_PAYLOAD_MPA_STRING ", "
|
||||
"clock-rate = (int) 90000; "
|
||||
"application/x-rtp, "
|
||||
"media = (string) \"audio\", "
|
||||
"payload = (int) "
|
||||
GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
|
||||
"clock-rate = (int) 90000, " "encoding-name = (string) \"MPA\""));
|
||||
"payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
|
||||
"clock-rate = (int) 90000, " "encoding-name = (string) \"MPA\"; "
|
||||
"application/x-rtp, "
|
||||
"media = (string) \"audio\", "
|
||||
"payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
|
||||
"clock-rate = (int) { 44100, 48000, 88200, 96000 }, "
|
||||
"encoding-name = (string) \"X-GST-LDAC\""));
|
||||
|
||||
static gboolean
|
||||
gst_avdtp_sink_stop (GstBaseSink * basesink)
|
||||
|
|
|
@ -690,6 +690,112 @@ gst_avdtp_util_parse_aac_raw (void *config)
|
|||
return structure;
|
||||
}
|
||||
|
||||
static GstStructure *
|
||||
gst_avdtp_util_parse_ldac_raw (void *config)
|
||||
{
|
||||
/* We assume the vendor/codec ID have been verified already */
|
||||
a2dp_ldac_t *ldac = (a2dp_ldac_t *) config;
|
||||
GstStructure *structure;
|
||||
GValue value = G_VALUE_INIT;
|
||||
GValue list = G_VALUE_INIT;
|
||||
gboolean mono, stereo;
|
||||
|
||||
structure = gst_structure_new_empty ("audio/x-ldac");
|
||||
|
||||
g_value_init (&list, GST_TYPE_LIST);
|
||||
g_value_init (&value, G_TYPE_INT);
|
||||
|
||||
/* rate */
|
||||
if (ldac->frequency & LDAC_SAMPLING_FREQ_44100) {
|
||||
g_value_set_int (&value, 44100);
|
||||
gst_value_list_prepend_value (&list, &value);
|
||||
}
|
||||
if (ldac->frequency & LDAC_SAMPLING_FREQ_48000) {
|
||||
g_value_set_int (&value, 48000);
|
||||
gst_value_list_prepend_value (&list, &value);
|
||||
}
|
||||
if (ldac->frequency & LDAC_SAMPLING_FREQ_88200) {
|
||||
g_value_set_int (&value, 88200);
|
||||
gst_value_list_prepend_value (&list, &value);
|
||||
}
|
||||
if (ldac->frequency & LDAC_SAMPLING_FREQ_96000) {
|
||||
g_value_set_int (&value, 96000);
|
||||
gst_value_list_prepend_value (&list, &value);
|
||||
}
|
||||
|
||||
if (gst_value_list_get_size (&list) == 1)
|
||||
gst_structure_set_value (structure, "rate", &value);
|
||||
else
|
||||
gst_structure_set_value (structure, "rate", &list);
|
||||
|
||||
g_value_unset (&value);
|
||||
g_value_reset (&list);
|
||||
|
||||
/* channels */
|
||||
mono = FALSE;
|
||||
stereo = FALSE;
|
||||
if (ldac->channel_mode & LDAC_CHANNEL_MODE_MONO)
|
||||
mono = TRUE;
|
||||
if ((ldac->channel_mode & LDAC_CHANNEL_MODE_STEREO) ||
|
||||
(ldac->channel_mode & LDAC_CHANNEL_MODE_DUAL))
|
||||
stereo = TRUE;
|
||||
|
||||
if (mono && stereo) {
|
||||
g_value_init (&value, GST_TYPE_INT_RANGE);
|
||||
gst_value_set_int_range (&value, 1, 2);
|
||||
} else {
|
||||
g_value_init (&value, G_TYPE_INT);
|
||||
if (mono)
|
||||
g_value_set_int (&value, 1);
|
||||
else if (stereo)
|
||||
g_value_set_int (&value, 2);
|
||||
else {
|
||||
GST_ERROR ("Unexpected number of channels");
|
||||
g_value_set_int (&value, 0);
|
||||
}
|
||||
}
|
||||
gst_structure_set_value (structure, "channels", &value);
|
||||
|
||||
g_value_unset (&value);
|
||||
g_value_init (&value, G_TYPE_STRING);
|
||||
|
||||
/* channel mode */
|
||||
if (ldac->channel_mode & LDAC_CHANNEL_MODE_MONO) {
|
||||
g_value_set_static_string (&value, "mono");
|
||||
gst_value_list_prepend_value (&list, &value);
|
||||
}
|
||||
if (ldac->channel_mode & LDAC_CHANNEL_MODE_STEREO) {
|
||||
g_value_set_static_string (&value, "stereo");
|
||||
gst_value_list_prepend_value (&list, &value);
|
||||
}
|
||||
if (ldac->channel_mode & LDAC_CHANNEL_MODE_DUAL) {
|
||||
g_value_set_static_string (&value, "dual");
|
||||
gst_value_list_prepend_value (&list, &value);
|
||||
}
|
||||
|
||||
if (gst_value_list_get_size (&list) == 1)
|
||||
gst_structure_set_value (structure, "channel-mode", &value);
|
||||
else
|
||||
gst_structure_take_value (structure, "channel-mode", &list);
|
||||
|
||||
g_value_unset (&value);
|
||||
g_value_unset (&list);
|
||||
|
||||
return structure;
|
||||
}
|
||||
|
||||
static GstStructure *
|
||||
gst_avdtp_util_parse_vendor_raw (void *config)
|
||||
{
|
||||
a2dp_vendor_codec_t *vendor = (a2dp_vendor_codec_t *) config;
|
||||
|
||||
if (A2DP_GET_VENDOR_ID (*vendor) == SONY_VENDOR_ID &&
|
||||
A2DP_GET_CODEC_ID (*vendor) == LDAC_CODEC_ID)
|
||||
return gst_avdtp_util_parse_ldac_raw (config);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GstCaps *
|
||||
gst_avdtp_connection_get_caps (GstAvdtpConnection * conn)
|
||||
{
|
||||
|
@ -709,6 +815,9 @@ gst_avdtp_connection_get_caps (GstAvdtpConnection * conn)
|
|||
case A2DP_CODEC_MPEG24:
|
||||
structure = gst_avdtp_util_parse_aac_raw (conn->data.config);
|
||||
break;
|
||||
case A2DP_CODEC_VENDOR:
|
||||
structure = gst_avdtp_util_parse_vendor_raw (conn->data.config);
|
||||
break;
|
||||
default:
|
||||
GST_ERROR ("Unsupported configuration");
|
||||
return NULL;
|
||||
|
|
Loading…
Reference in a new issue