[pulseaudio-discuss] [PATCH v2 1/2] Modular API for Bluetooth A2DP codec

Tanu Kaskinen tanuk at iki.fi
Mon Sep 17 12:02:18 UTC 2018


(I sent my review both to you and to the list, but you replied only
privately - probably not on purpose. I'll send this mail only to the
list.)

On Thu, 2018-09-13 at 10:54 +0200, Pali Rohár wrote:
> On Tuesday 04 September 2018 11:44:10 Tanu Kaskinen wrote:
> > Using libopenaptx directly
> > doesn't prevent us from switching to GStreamer later if someone writes
> > the code.
> 
> Yes, that is truth.
> 
> > Another point that was raised that the codec choice shouldn't be bound
> > to the card profile. I tend to agree with that. There are situations
> > where module-bluetooth-policy or the user only wants to switch from HSP
> > to A2DP and not care about the codec. You asked how the codec should be
> > negotiated or switched by the user if it's not bound to the profile.
> > Regarding negotiation, we can add a hook that module-bluetooth-policy
> > can use to make the codec decision (if module-bluetooth-policy isn't
> > loaded, SBC seems like a sensible default).
> > 
> > Is there a need for the user to be able to choose the codec? Shouldn't
> > we always automatically pick the highest-quality one?
> 
> What is "highest-quality" codec? How you would compare e.g. our SBC
> implementation which can dynamically change bitpool and therefore
> quality?
> 
> Also how you can compare... has SBC higher quality as MPEG1? Or has aptX
> HD higher quality as MPEG/AAC?

Fair point.

> Until now everybody said that aptX "is better" then SBC. But today it
> does not look like it is truth.
> 
> Also if you have MP3 files on disk, then the best quality which you can
> achieve is to passthru it without any reencoding. In other cases AAC can
> be better.

Passthrough is a separate thing. If someone implements passthrough
support for bluetooth and a client requests it, we should always switch
to the requested codec regardless of other user preferences.

> So answer to this question depends on lot of things and either user
> itself or user's application would better it.
> 
> > I'm not against
> > adding the functionality, it would be useful for testing if nothing
> > else. It just doesn't seem very important.
> > 
> > We could have a "preferred-a2dp-codec" option in bluetooth.conf (that
> > file doesn't exist, but can be added). A per-card option would be
> > possible too, as would be having both a global option that could be
> > overridden with a per-card option.
> 
> Preferred codec is not helpful. The only mandatory codec is SBC, all
> other are optional. And basically every manufactor supports different
> set of codecs. So at least some kind of list or partially ordered set of
> codec is needed.

Sure, a priority list can better capture the user preferences, but
surely a "preferred codec" option is better than nothing. A priority
list of codecs isn't an obvious ultimate solution either, since some
codecs have adjustable parameters that can affect the codec preference
ranking. For example, someone's preference might be:

SBC (high bitrate)
aptX
SBC (medium bitrate)

It's not clear to me how fine-grained control is optimal. A solution
that allows specifying a priority list with an arbitrary number of
codec parameters would obviously be sufficient, but it's unlikely we
want that complex system.

Real use cases are needed. I can't provide any, since I don't use
bluetooth (and if I did, I probably wouldn't bother with the codec
settings at all - SBC and aptX seem both good enough for me). Now that
you found out that aptX isn't that great after all, do you have
personal use for aptX either?

> > For runtime configuration, we can add a command to set the codec
> > preference. This should be done with the message API that Georg Chini
> > has been working on (not yet finished). There's then need for saving
> > the choice too. We can either introduce a new database for bluetooth
> > stuff, or we can add some API to module-card-restore so that other
> > modules (module-bluetooth-discover in this case) can save arbitrary
> > parameters for cards.
> > 
> > I recall there was some lack of relevant APIs in bluetoothd for
> > choosing the codec from PulseAudio. Can you remind me, what are the
> > limitations, and how did you plan to deal with them?
> 
> Currently when bluetooth headset initialize connection, it is up to
> headset which codec would choose. I did some testing and my headset
> choose codec (sbc vs aptx) just randomly.
> 
> When bluez initialize connection, then it prefer codecs in order in
> which pulseaudio did dbus endpoint registration. Order is global and
> hardcoded in source code.
> 
> Once connection is established there is no way to change codec. bluez
> does not provide API for it.
> 
> So everything which you wrote above would apply only when pulseaudio
> starts a2dp connection, not headset.
> 
> And I think it is very bad if we cannot achieve stable codec selection.

So what do you propose? If your point was that my suggestions result in
unstable codec selection, I don't see how your original proposal of
having a separate card profile for each codec (or potentially each set
of codec parameters) makes the situation better.

> > Comments on the code below. This review was done over several days,
> > sorry for any inconsistencies or strange repetition (I noticed I
> > explain some things multiple times).
> 
> Currently I do not have much time to work on this. So just few comments
> below.
> 
> > > @@ -888,10 +889,21 @@ finish:
> > >  static void register_endpoint(pa_bluetooth_discovery *y, const char *path, const char *endpoint, const char *uuid) {
> > >      DBusMessage *m;
> > >      DBusMessageIter i, d;
> > > -    uint8_t codec = 0;
> > > +    uint8_t capabilities[1024];
> > > +    size_t capabilities_size;
> > > +    uint8_t codec_id;
> > > +    const pa_a2dp_codec_t *codec;
> > > +
> > > +    codec = pa_a2dp_endpoint_to_a2dp_codec(endpoint);
> > 
> > I think it would be better to change the function parameters so that
> > instead of an endpoint path the function would take a codec id.
> 
> What do you mean by codec id? Do you mean A2DP codec id? If yes, then it
> would not work, as every non-sbc and non-mpeg codec has codec is 0xFF.
> Codec itself is then determined by passed capabilities.

I thought we could use the id from the A2DP spec, but apparently not. I
propose having our own separate codec enumeration then that provides
the necessary ids.

> > There
> > would be a function called get_a2dp_codec() that would take the codec
> > id as a parameter and return the codec struct. The endpoint path could
> > be added to the codec struct.
> > 
> > Shuffling things around like this wouldn't have huge benefits, I just
> > find looking up the codec based on the id neater than based on the
> > endpoint path.
> > 
> > I hope you don't have a problem with that suggestion, but if you do and
> > you want to keep using pa_a2dp_endpoint_to_a2dp_codec(), then the
> > function should be made static (it's not used outside bluez5-utils.c)
> > and the pa_ prefix should be dropped, since functions that aren't
> > exported through headers should not use the pa_ prefix according to our
> > coding style.
> > > +    sbc_info->min_bitpool = config->min_bitpool;
> > > +    sbc_info->max_bitpool = config->max_bitpool;
> > > +
> > > +    /* Set minimum bitpool for source to get the maximum possible block_size */
> > > +    sbc_info->sbc.bitpool = is_a2dp_sink ? sbc_info->max_bitpool : sbc_info->min_bitpool;
> > 
> > Do you understand the logic here?
> 
> I have not looked deeply at this code. So I'm not fully sure. I just
> moved existing code into new file.

Ok, so this remains a mystery to all of us.

-- 
Tanu

https://www.patreon.com/tanuk
https://liberapay.com/tanuk



More information about the pulseaudio-discuss mailing list