diff mbox series

[BlueZ,v2,2/2] client/player: parse Google's Opus A2DP vendor codec capabilities

Message ID 85bd33f548fd177b392f067d54ad3922a0db6cec.1707152569.git.pav@iki.fi
State New
Headers show
Series [BlueZ,v2,1/2] monitor: parse Google's Opus A2DP vendor codec capabilities | expand

Commit Message

Pauli Virtanen Feb. 5, 2024, 5:03 p.m. UTC
Support parsing Opus (Google) A2DP vendor codec capabilities.

Transport /org/bluez/hci0/dev_B8_7B_D4_32_44_15/sep3/fd2
        UUID: 0000110a-0000-1000-8000-00805f9b34fb
        Codec: 0xff (255)
        Media Codec: Vendor Specific A2DP Codec
        Vendor ID 0x000000e0
        Vendor Specific Codec ID 0x0001
        Vendor Specific Data: 0x92
                Vendor Specific Value (Opus [Google])
                Frequencies: 48kHz
                Channel modes: Stereo
                Frame durations: 20 ms
        Device: /org/bluez/hci0/dev_B8_7B_D4_32_44_15
        State: idle
        Delay: 0x0898 (2200)
        Volume: 0x001e (30)
        Endpoint: /org/bluez/hci0/dev_B8_7B_D4_32_44_15/sep3
---
 client/player.c              | 32 ++++++++++++++++++++++++++++++++
 profiles/audio/a2dp-codecs.h | 17 +++++++++++++++++
 2 files changed, 49 insertions(+)
diff mbox series

Patch

diff --git a/client/player.c b/client/player.c
index b43b4b867..a40bf66e3 100644
--- a/client/player.c
+++ b/client/player.c
@@ -2471,6 +2471,36 @@  static void print_ldac(a2dp_ldac_t *ldac, uint8_t size)
 	bt_shell_printf("\n");
 }
 
+static void print_opus_g(a2dp_opus_g_t *opus, uint8_t size)
+{
+	bt_shell_printf("\t\tVendor Specific Value (Opus [Google])");
+
+	if (size < sizeof(*opus)) {
+		bt_shell_printf(" (broken)\n");
+		return;
+	}
+
+	bt_shell_printf("\n\t\tFrequencies: ");
+	if (opus->data & OPUS_G_FREQUENCY_48000)
+		bt_shell_printf("48kHz ");
+
+	bt_shell_printf("\n\t\tChannel modes: ");
+	if (opus->data & OPUS_G_CHANNELS_MONO)
+		bt_shell_printf("Mono ");
+	if (opus->data & OPUS_G_CHANNELS_STEREO)
+		bt_shell_printf("Stereo ");
+	if (opus->data & OPUS_G_CHANNELS_DUAL)
+		bt_shell_printf("Dual Mono ");
+
+	bt_shell_printf("\n\t\tFrame durations: ");
+	if (opus->data & OPUS_G_DURATION_100)
+		bt_shell_printf("10 ms ");
+	if (opus->data & OPUS_G_DURATION_200)
+		bt_shell_printf("20 ms ");
+
+	bt_shell_printf("\n");
+}
+
 static void print_vendor(a2dp_vendor_codec_t *vendor, uint8_t size)
 {
 	uint32_t vendor_id;
@@ -2508,6 +2538,8 @@  static void print_vendor(a2dp_vendor_codec_t *vendor, uint8_t size)
 		print_aptx_hd((void *) vendor, size);
 	else if (vendor_id == LDAC_VENDOR_ID && codec_id == LDAC_CODEC_ID)
 		print_ldac((void *) vendor, size);
+	else if (vendor_id == OPUS_G_VENDOR_ID && codec_id == OPUS_G_CODEC_ID)
+		print_opus_g((void *) vendor, size);
 }
 
 static void print_mpeg24(a2dp_aac_t *aac, uint8_t size)
diff --git a/profiles/audio/a2dp-codecs.h b/profiles/audio/a2dp-codecs.h
index 6f5670947..38b9038f8 100644
--- a/profiles/audio/a2dp-codecs.h
+++ b/profiles/audio/a2dp-codecs.h
@@ -250,6 +250,18 @@ 
 #define LDAC_CHANNEL_MODE_DUAL		0x02
 #define LDAC_CHANNEL_MODE_STEREO	0x01
 
+#define OPUS_G_VENDOR_ID		0x000000e0
+#define OPUS_G_CODEC_ID			0x0001
+
+#define OPUS_G_FREQUENCY_48000		0x80
+
+#define OPUS_G_DURATION_100		0x08
+#define OPUS_G_DURATION_200		0x10
+
+#define OPUS_G_CHANNELS_MONO		0x01
+#define OPUS_G_CHANNELS_STEREO		0x02
+#define OPUS_G_CHANNELS_DUAL		0x04
+
 typedef struct {
 	uint8_t vendor_id4;
 	uint8_t vendor_id3;
@@ -420,3 +432,8 @@  typedef struct {
 	uint8_t reserved2;
 	uint8_t reserved3;
 } __attribute__ ((packed)) a2dp_aptx_hd_t;
+
+typedef struct {
+	a2dp_vendor_codec_t info;
+	uint8_t data;
+} __attribute__ ((packed)) a2dp_opus_g_t;