[PATCH BlueZ v2 1/2] monitor: parse Google's Opus A2DP vendor codec capabilities

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Support parsing Opus (Google) A2DP vendor codec capabilities.
AOSP & Google Pixel Buds Pro has this implemented.

> ACL Data RX: Handle 256 flags 0x02 dlen 21       #419 [hci0] 26.905032
      Channel: 65 len 17 [PSM 25 mode Basic (0x00)] {chan 4}
      AVDTP: Get All Capabilities (0x0c) Response Accept (0x02) type 0x00 label 3 nosp 0
        Service Category: Media Transport (0x01)
        Service Category: Media Codec (0x07)
          Media Type: Audio (0x00)
          Media Codec: Non-A2DP (0xff)
            Vendor ID: Google (0x000000e0)
            Vendor Specific Codec ID: Opus (Google) (0x0001)
              Frequency: 0x80
                48000
              Frame Duration: 0x18
                10 ms
                20 ms
              Channel Mode: 0x07
                Mono
                Stereo
                Dual Mono
              Reserved: 0x60
        Service Category: Delay Reporting (0x08)
---

Notes:
    As far as I know, Opus is in no Bluetooth standard, only vendor codec.

 monitor/a2dp.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/monitor/a2dp.c b/monitor/a2dp.c
index f6e99ab26..ae88f565e 100644
--- a/monitor/a2dp.c
+++ b/monitor/a2dp.c
@@ -47,6 +47,8 @@
 #define APTX_HD_CODEC_ID	0x0024
 #define LDAC_VENDOR_ID		0x0000012d
 #define LDAC_CODEC_ID		0x00aa
+#define OPUS_G_VENDOR_ID	0x000000e0
+#define OPUS_G_CODEC_ID		0x0001
 
 struct bit_desc {
 	uint8_t bit_num;
@@ -201,6 +203,24 @@ static const struct bit_desc faststream_source_frequency_table[] = {
 	{ }
 };
 
+static const struct bit_desc opus_g_frequency_table[] = {
+	{  7, "48000" },
+	{ }
+};
+
+static const struct bit_desc opus_g_duration_table[] = {
+	{  3, "10 ms" },
+	{  4, "20 ms" },
+	{ }
+};
+
+static const struct bit_desc opus_g_channels_table[] = {
+	{  0, "Mono" },
+	{  1, "Stereo" },
+	{  2, "Dual Mono" },
+	{ }
+};
+
 static void print_value_bits(uint8_t indent, uint32_t value,
 						const struct bit_desc *table)
 {
@@ -244,6 +264,7 @@ static bool codec_vendor_aptx_ll_cfg(uint8_t losc, struct l2cap_frame *frame);
 static bool codec_vendor_aptx_hd_cap(uint8_t losc, struct l2cap_frame *frame);
 static bool codec_vendor_aptx_hd_cfg(uint8_t losc, struct l2cap_frame *frame);
 static bool codec_vendor_ldac(uint8_t losc, struct l2cap_frame *frame);
+static bool codec_vendor_opus_g(uint8_t losc, struct l2cap_frame *frame);
 
 static const struct vndcodec vndcodecs[] = {
 	{ APTX_VENDOR_ID, APTX_CODEC_ID, "aptX",
@@ -256,6 +277,8 @@ static const struct vndcodec vndcodecs[] = {
 	  codec_vendor_aptx_hd_cap, codec_vendor_aptx_hd_cfg },
 	{ LDAC_VENDOR_ID, LDAC_CODEC_ID, "LDAC",
 	  codec_vendor_ldac, codec_vendor_ldac },
+	{ OPUS_G_VENDOR_ID, OPUS_G_CODEC_ID, "Opus (Google)",
+	  codec_vendor_opus_g, codec_vendor_opus_g },
 	{ }
 };
 
@@ -685,6 +708,31 @@ static bool codec_vendor_ldac(uint8_t losc, struct l2cap_frame *frame)
 	return true;
 }
 
+static bool codec_vendor_opus_g(uint8_t losc, struct l2cap_frame *frame)
+{
+	uint8_t cap = 0;
+
+	if (losc != 1)
+		return false;
+
+	l2cap_frame_get_u8(frame, &cap);
+
+	print_field("%*cFrequency: 0x%02x", BASE_INDENT + 2, ' ', cap & 0x80);
+	print_value_bits(BASE_INDENT + 2, cap, opus_g_frequency_table);
+
+	print_field("%*cFrame Duration: 0x%02x", BASE_INDENT + 2, ' ',
+								cap & 0x18);
+	print_value_bits(BASE_INDENT + 2, cap, opus_g_duration_table);
+
+	print_field("%*cChannel Mode: 0x%02x", BASE_INDENT + 2, ' ',
+								cap & 0x07);
+	print_value_bits(BASE_INDENT + 2, cap, opus_g_channels_table);
+
+	print_field("%*cReserved: 0x%02x", BASE_INDENT + 2, ' ', cap & 0x60);
+
+	return true;
+}
+
 static bool codec_vendor_cap(uint8_t losc, struct l2cap_frame *frame)
 {
 	uint32_t vendor_id = 0;
-- 
2.43.0





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux