2024-02-02 20:08:28

by Pauli Virtanen

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

Support parsing Opus (Google) A2DP vendor codec capabilities.
---
monitor/a2dp.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)

diff --git a/monitor/a2dp.c b/monitor/a2dp.c
index f6e99ab26..d26b679bc 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,27 @@ 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);
+ print_value_bits(BASE_INDENT + 2, cap, opus_g_frequency_table);
+
+ print_field("%*cFrame Duration: 0x%02x", BASE_INDENT + 2, ' ', cap);
+ print_value_bits(BASE_INDENT + 2, cap, opus_g_duration_table);
+
+ print_field("%*cChannel Mode: 0x%02x", BASE_INDENT + 2, ' ', cap);
+ print_value_bits(BASE_INDENT + 2, cap, opus_g_channels_table);
+
+ return true;
+}
+
static bool codec_vendor_cap(uint8_t losc, struct l2cap_frame *frame)
{
uint32_t vendor_id = 0;
--
2.43.0



2024-02-02 20:08:35

by Pauli Virtanen

[permalink] [raw]
Subject: [PATCH BlueZ 2/2] client/player: parse Google's Opus A2DP vendor codec capabilities

Support parsing Opus (Google) A2DP vendor codec capabilities.
---
client/player.c | 32 ++++++++++++++++++++++++++++++++
profiles/audio/a2dp-codecs.h | 17 +++++++++++++++++
2 files changed, 49 insertions(+)

diff --git a/client/player.c b/client/player.c
index 623519209..10a3d3f18 100644
--- a/client/player.c
+++ b/client/player.c
@@ -2462,6 +2462,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;
@@ -2499,6 +2529,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;
--
2.43.0


2024-02-02 21:43:55

by bluez.test.bot

[permalink] [raw]
Subject: RE: [BlueZ,1/2] monitor: parse Google's Opus A2DP vendor codec capabilities

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=822659

---Test result---

Test Summary:
CheckPatch FAIL 1.95 seconds
GitLint PASS 0.57 seconds
BuildEll PASS 23.97 seconds
BluezMake PASS 722.72 seconds
MakeCheck PASS 11.75 seconds
MakeDistcheck PASS 161.55 seconds
CheckValgrind PASS 224.79 seconds
CheckSmatch PASS 326.14 seconds
bluezmakeextell PASS 106.22 seconds
IncrementalBuild PASS 1328.51 seconds
ScanBuild PASS 976.90 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,2/2] client/player: parse Google's Opus A2DP vendor codec capabilities
WARNING:NEW_TYPEDEFS: do not add new typedefs
#180: FILE: profiles/audio/a2dp-codecs.h:436:
+typedef struct {

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#183: FILE: profiles/audio/a2dp-codecs.h:439:
+} __attribute__ ((packed)) a2dp_opus_g_t;

/github/workspace/src/src/13543351.patch total: 0 errors, 2 warnings, 70 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/src/13543351.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.




---
Regards,
Linux Bluetooth

2024-02-05 15:31:41

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ 1/2] monitor: parse Google's Opus A2DP vendor codec capabilities

Hi Pauli,

On Fri, Feb 2, 2024 at 3:08 PM Pauli Virtanen <[email protected]> wrote:
>
> Support parsing Opus (Google) A2DP vendor codec capabilities.

Add a sample output.

> ---
> monitor/a2dp.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 44 insertions(+)
>
> diff --git a/monitor/a2dp.c b/monitor/a2dp.c
> index f6e99ab26..d26b679bc 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

Hmm, is this vendor-specific to Google? Don't we have it defined as an
optional codec nowadays?


> 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,27 @@ 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);
> + print_value_bits(BASE_INDENT + 2, cap, opus_g_frequency_table);
> +
> + print_field("%*cFrame Duration: 0x%02x", BASE_INDENT + 2, ' ', cap);
> + print_value_bits(BASE_INDENT + 2, cap, opus_g_duration_table);
> +
> + print_field("%*cChannel Mode: 0x%02x", BASE_INDENT + 2, ' ', cap);
> + print_value_bits(BASE_INDENT + 2, cap, opus_g_channels_table);
> +
> + return true;
> +}
> +
> static bool codec_vendor_cap(uint8_t losc, struct l2cap_frame *frame)
> {
> uint32_t vendor_id = 0;
> --
> 2.43.0
>
>


--
Luiz Augusto von Dentz