1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2020 Sanchayan Maity <sanchayan@asymptotic.io>
5
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
10
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <pulsecore/log.h>
25 #include <pulsecore/macro.h>
26 #include <pulsecore/once.h>
27 #include <pulse/sample.h>
28
29 #include <arpa/inet.h>
30
31 #include "a2dp-codecs.h"
32 #include "a2dp-codec-api.h"
33 #include "a2dp-codec-gst.h"
34 #include "rtp.h"
35
can_be_supported(bool for_encoding)36 static bool can_be_supported(bool for_encoding) {
37 GstElementFactory *element_factory;
38
39 if (for_encoding) {
40 element_factory = gst_element_factory_find("openaptxenc");
41 if (element_factory == NULL) {
42 pa_log_info("aptX encoder element `openaptxenc` not found");
43 return false;
44 }
45
46 gst_object_unref(element_factory);
47 } else {
48 element_factory = gst_element_factory_find("openaptxdec");
49 if (element_factory == NULL) {
50 pa_log_info("aptX decoder element `openaptxdec` not found");
51 return false;
52 }
53
54 gst_object_unref(element_factory);
55 }
56
57 return true;
58 }
59
can_accept_capabilities_common(const a2dp_aptx_t * capabilities,uint32_t vendor_id,uint16_t codec_id)60 static bool can_accept_capabilities_common(const a2dp_aptx_t *capabilities, uint32_t vendor_id, uint16_t codec_id) {
61 if (A2DP_GET_VENDOR_ID(capabilities->info) != vendor_id || A2DP_GET_CODEC_ID(capabilities->info) != codec_id)
62 return false;
63
64 if (!(capabilities->frequency & (APTX_SAMPLING_FREQ_16000 | APTX_SAMPLING_FREQ_32000 |
65 APTX_SAMPLING_FREQ_44100 | APTX_SAMPLING_FREQ_48000)))
66 return false;
67
68 if (!(capabilities->channel_mode & APTX_CHANNEL_MODE_STEREO))
69 return false;
70
71 return true;
72 }
73
can_accept_capabilities(const uint8_t * capabilities_buffer,uint8_t capabilities_size,bool for_encoding)74 static bool can_accept_capabilities(const uint8_t *capabilities_buffer, uint8_t capabilities_size, bool for_encoding) {
75 const a2dp_aptx_t *capabilities = (const a2dp_aptx_t *) capabilities_buffer;
76
77 if (capabilities_size != sizeof(*capabilities))
78 return false;
79
80 return can_accept_capabilities_common(capabilities, APTX_VENDOR_ID, APTX_CODEC_ID);
81 }
82
can_accept_capabilities_hd(const uint8_t * capabilities_buffer,uint8_t capabilities_size,bool for_encoding)83 static bool can_accept_capabilities_hd(const uint8_t *capabilities_buffer, uint8_t capabilities_size, bool for_encoding) {
84 const a2dp_aptx_hd_t *capabilities = (const a2dp_aptx_hd_t *) capabilities_buffer;
85
86 if (capabilities_size != sizeof(*capabilities))
87 return false;
88
89 return can_accept_capabilities_common(&capabilities->aptx, APTX_HD_VENDOR_ID, APTX_HD_CODEC_ID);
90 }
91
choose_remote_endpoint(const pa_hashmap * capabilities_hashmap,const pa_sample_spec * default_sample_spec,bool for_encoding)92 static const char *choose_remote_endpoint(const pa_hashmap *capabilities_hashmap, const pa_sample_spec *default_sample_spec, bool for_encoding) {
93 const pa_a2dp_codec_capabilities *a2dp_capabilities;
94 const char *key;
95 void *state;
96
97 /* There is no preference, just choose random valid entry */
98 PA_HASHMAP_FOREACH_KV(key, a2dp_capabilities, capabilities_hashmap, state) {
99 if (can_accept_capabilities(a2dp_capabilities->buffer, a2dp_capabilities->size, for_encoding))
100 return key;
101 }
102
103 return NULL;
104 }
105
choose_remote_endpoint_hd(const pa_hashmap * capabilities_hashmap,const pa_sample_spec * default_sample_spec,bool for_encoding)106 static const char *choose_remote_endpoint_hd(const pa_hashmap *capabilities_hashmap, const pa_sample_spec *default_sample_spec, bool for_encoding) {
107 const pa_a2dp_codec_capabilities *a2dp_capabilities;
108 const char *key;
109 void *state;
110
111 /* There is no preference, just choose random valid entry */
112 PA_HASHMAP_FOREACH_KV(key, a2dp_capabilities, capabilities_hashmap, state) {
113 if (can_accept_capabilities_hd(a2dp_capabilities->buffer, a2dp_capabilities->size, for_encoding))
114 return key;
115 }
116
117 return NULL;
118 }
119
fill_capabilities_common(a2dp_aptx_t * capabilities,uint32_t vendor_id,uint16_t codec_id)120 static void fill_capabilities_common(a2dp_aptx_t *capabilities, uint32_t vendor_id, uint16_t codec_id) {
121 capabilities->info = A2DP_SET_VENDOR_ID_CODEC_ID(vendor_id, codec_id);
122 capabilities->channel_mode = APTX_CHANNEL_MODE_STEREO;
123 capabilities->frequency = APTX_SAMPLING_FREQ_16000 | APTX_SAMPLING_FREQ_32000 |
124 APTX_SAMPLING_FREQ_44100 | APTX_SAMPLING_FREQ_48000;
125 }
126
fill_capabilities(uint8_t capabilities_buffer[MAX_A2DP_CAPS_SIZE])127 static uint8_t fill_capabilities(uint8_t capabilities_buffer[MAX_A2DP_CAPS_SIZE]) {
128 a2dp_aptx_t *capabilities = (a2dp_aptx_t *) capabilities_buffer;
129
130 pa_zero(*capabilities);
131 fill_capabilities_common(capabilities, APTX_VENDOR_ID, APTX_CODEC_ID);
132 return sizeof(*capabilities);
133 }
134
fill_capabilities_hd(uint8_t capabilities_buffer[MAX_A2DP_CAPS_SIZE])135 static uint8_t fill_capabilities_hd(uint8_t capabilities_buffer[MAX_A2DP_CAPS_SIZE]) {
136 a2dp_aptx_hd_t *capabilities = (a2dp_aptx_hd_t *) capabilities_buffer;
137
138 pa_zero(*capabilities);
139 fill_capabilities_common(&capabilities->aptx, APTX_HD_VENDOR_ID, APTX_HD_CODEC_ID);
140 return sizeof(*capabilities);
141 }
142
is_configuration_valid_common(const a2dp_aptx_t * config,uint32_t vendor_id,uint16_t codec_id)143 static bool is_configuration_valid_common(const a2dp_aptx_t *config, uint32_t vendor_id, uint16_t codec_id) {
144 if (A2DP_GET_VENDOR_ID(config->info) != vendor_id || A2DP_GET_CODEC_ID(config->info) != codec_id) {
145 pa_log_error("Invalid vendor codec information in configuration");
146 return false;
147 }
148
149 if (config->frequency != APTX_SAMPLING_FREQ_16000 && config->frequency != APTX_SAMPLING_FREQ_32000 &&
150 config->frequency != APTX_SAMPLING_FREQ_44100 && config->frequency != APTX_SAMPLING_FREQ_48000) {
151 pa_log_error("Invalid sampling frequency in configuration");
152 return false;
153 }
154
155 if (config->channel_mode != APTX_CHANNEL_MODE_STEREO) {
156 pa_log_error("Invalid channel mode in configuration");
157 return false;
158 }
159
160 return true;
161 }
162
is_configuration_valid(const uint8_t * config_buffer,uint8_t config_size)163 static bool is_configuration_valid(const uint8_t *config_buffer, uint8_t config_size) {
164 const a2dp_aptx_t *config = (const a2dp_aptx_t *) config_buffer;
165
166 if (config_size != sizeof(*config)) {
167 pa_log_error("Invalid size of config buffer");
168 return false;
169 }
170
171 return is_configuration_valid_common(config, APTX_VENDOR_ID, APTX_CODEC_ID);
172 }
173
is_configuration_valid_hd(const uint8_t * config_buffer,uint8_t config_size)174 static bool is_configuration_valid_hd(const uint8_t *config_buffer, uint8_t config_size) {
175 const a2dp_aptx_hd_t *config = (const a2dp_aptx_hd_t *) config_buffer;
176
177 if (config_size != sizeof(*config)) {
178 pa_log_error("Invalid size of config buffer");
179 return false;
180 }
181
182 return is_configuration_valid_common(&config->aptx, APTX_HD_VENDOR_ID, APTX_HD_CODEC_ID);
183 }
184
fill_preferred_configuration_common(const pa_sample_spec * default_sample_spec,const a2dp_aptx_t * capabilities,a2dp_aptx_t * config,uint32_t vendor_id,uint16_t codec_id)185 static int fill_preferred_configuration_common(const pa_sample_spec *default_sample_spec, const a2dp_aptx_t *capabilities, a2dp_aptx_t *config, uint32_t vendor_id, uint16_t codec_id) {
186 int i;
187
188 static const struct {
189 uint32_t rate;
190 uint8_t cap;
191 } freq_table[] = {
192 { 16000U, APTX_SAMPLING_FREQ_16000 },
193 { 32000U, APTX_SAMPLING_FREQ_32000 },
194 { 44100U, APTX_SAMPLING_FREQ_44100 },
195 { 48000U, APTX_SAMPLING_FREQ_48000 }
196 };
197
198 if (A2DP_GET_VENDOR_ID(capabilities->info) != vendor_id || A2DP_GET_CODEC_ID(capabilities->info) != codec_id) {
199 pa_log_error("No supported vendor codec information");
200 return -1;
201 }
202
203 config->info = A2DP_SET_VENDOR_ID_CODEC_ID(vendor_id, codec_id);
204
205 if (!(capabilities->channel_mode & APTX_CHANNEL_MODE_STEREO)) {
206 pa_log_error("No supported channel modes");
207 return -1;
208 }
209
210 config->channel_mode = APTX_CHANNEL_MODE_STEREO;
211
212 /* Find the lowest freq that is at least as high as the requested sampling rate */
213 for (i = 0; (unsigned) i < PA_ELEMENTSOF(freq_table); i++) {
214 if (freq_table[i].rate >= default_sample_spec->rate && (capabilities->frequency & freq_table[i].cap)) {
215 config->frequency = freq_table[i].cap;
216 break;
217 }
218 }
219
220 if ((unsigned) i == PA_ELEMENTSOF(freq_table)) {
221 for (--i; i >= 0; i--) {
222 if (capabilities->frequency & freq_table[i].cap) {
223 config->frequency = freq_table[i].cap;
224 break;
225 }
226 }
227
228 if (i < 0) {
229 pa_log_error("Not suitable sample rate");
230 return false;
231 }
232 }
233
234 return 0;
235 }
236
fill_preferred_configuration(const pa_sample_spec * default_sample_spec,const uint8_t * capabilities_buffer,uint8_t capabilities_size,uint8_t config_buffer[MAX_A2DP_CAPS_SIZE])237 static uint8_t fill_preferred_configuration(const pa_sample_spec *default_sample_spec, const uint8_t *capabilities_buffer, uint8_t capabilities_size, uint8_t config_buffer[MAX_A2DP_CAPS_SIZE]) {
238 a2dp_aptx_t *config = (a2dp_aptx_t *) config_buffer;
239 const a2dp_aptx_t *capabilities = (const a2dp_aptx_t *) capabilities_buffer;
240
241 if (capabilities_size != sizeof(*capabilities)) {
242 pa_log_error("Invalid size of capabilities buffer");
243 return 0;
244 }
245
246 pa_zero(*config);
247
248 if (fill_preferred_configuration_common(default_sample_spec, capabilities, config, APTX_VENDOR_ID, APTX_CODEC_ID) < 0)
249 return 0;
250
251 return sizeof(*config);
252 }
253
fill_preferred_configuration_hd(const pa_sample_spec * default_sample_spec,const uint8_t * capabilities_buffer,uint8_t capabilities_size,uint8_t config_buffer[MAX_A2DP_CAPS_SIZE])254 static uint8_t fill_preferred_configuration_hd(const pa_sample_spec *default_sample_spec, const uint8_t *capabilities_buffer, uint8_t capabilities_size, uint8_t config_buffer[MAX_A2DP_CAPS_SIZE]) {
255 a2dp_aptx_hd_t *config = (a2dp_aptx_hd_t *) config_buffer;
256 const a2dp_aptx_hd_t *capabilities = (const a2dp_aptx_hd_t *) capabilities_buffer;
257
258 if (capabilities_size != sizeof(*capabilities)) {
259 pa_log_error("Invalid size of capabilities buffer");
260 return 0;
261 }
262
263 pa_zero(*config);
264
265 if (fill_preferred_configuration_common(default_sample_spec, &capabilities->aptx, &config->aptx, APTX_HD_VENDOR_ID, APTX_HD_CODEC_ID) < 0)
266 return 0;
267
268 return sizeof(*config);
269 }
270
gst_init_aptx(struct gst_info * info,pa_sample_spec * ss,bool for_encoding)271 GstElement *gst_init_aptx(struct gst_info *info, pa_sample_spec *ss, bool for_encoding) {
272 GstElement *bin, *sink, *src, *capsf;
273 GstCaps *caps;
274 GstPad *pad;
275 const char *aptx_codec_media_type;
276
277 ss->format = PA_SAMPLE_S24LE;
278
279 if (info->codec_type == APTX_HD) {
280 switch (info->a2dp_codec_t.aptx_hd_config->aptx.frequency) {
281 case APTX_SAMPLING_FREQ_16000:
282 ss->rate = 16000u;
283 break;
284 case APTX_SAMPLING_FREQ_32000:
285 ss->rate = 32000u;
286 break;
287 case APTX_SAMPLING_FREQ_44100:
288 ss->rate = 44100u;
289 break;
290 case APTX_SAMPLING_FREQ_48000:
291 ss->rate = 48000u;
292 break;
293 default:
294 pa_log_error("aptX HD invalid frequency %d", info->a2dp_codec_t.aptx_hd_config->aptx.frequency);
295 goto fail;
296 }
297
298 switch (info->a2dp_codec_t.aptx_hd_config->aptx.channel_mode) {
299 case APTX_CHANNEL_MODE_STEREO:
300 ss->channels = 2;
301 break;
302 default:
303 pa_log_error("aptX HD invalid channel mode %d", info->a2dp_codec_t.aptx_hd_config->aptx.frequency);
304 goto fail;
305 }
306 } else {
307 switch (info->a2dp_codec_t.aptx_config->frequency) {
308 case APTX_SAMPLING_FREQ_16000:
309 ss->rate = 16000u;
310 break;
311 case APTX_SAMPLING_FREQ_32000:
312 ss->rate = 32000u;
313 break;
314 case APTX_SAMPLING_FREQ_44100:
315 ss->rate = 44100u;
316 break;
317 case APTX_SAMPLING_FREQ_48000:
318 ss->rate = 48000u;
319 break;
320 default:
321 pa_log_error("aptX invalid frequency %d", info->a2dp_codec_t.aptx_config->frequency);
322 goto fail;
323 }
324
325 switch (info->a2dp_codec_t.aptx_config->channel_mode) {
326 case APTX_CHANNEL_MODE_STEREO:
327 ss->channels = 2;
328 break;
329 default:
330 pa_log_error("aptX invalid channel mode %d", info->a2dp_codec_t.aptx_config->frequency);
331 goto fail;
332 }
333 }
334
335 aptx_codec_media_type = info->codec_type == APTX_HD ? "audio/aptx-hd" : "audio/aptx";
336
337 capsf = gst_element_factory_make("capsfilter", "aptx_capsfilter");
338 if (!capsf) {
339 pa_log_error("Could not create aptX capsfilter element");
340 goto fail;
341 }
342
343 caps = gst_caps_new_simple(aptx_codec_media_type,
344 "rate", G_TYPE_INT, (int) ss->rate,
345 "channels", G_TYPE_INT, (int) ss->channels,
346 NULL);
347 g_object_set(capsf, "caps", caps, NULL);
348 gst_caps_unref(caps);
349
350 if (for_encoding) {
351 sink = gst_element_factory_make("openaptxenc", "aptx_encoder");
352 src = capsf;
353
354 if (sink == NULL) {
355 pa_log_error("Could not create aptX encoder element");
356 goto fail_enc_dec;
357 }
358
359 bin = gst_bin_new("aptx_enc_bin");
360 } else {
361 sink = capsf;
362 src = gst_element_factory_make("openaptxdec", "aptx_decoder");
363
364 if (src == NULL) {
365 pa_log_error("Could not create aptX decoder element");
366 goto fail_enc_dec;
367 }
368
369 bin = gst_bin_new("aptx_dec_bin");
370 }
371
372 pa_assert(bin);
373
374 gst_bin_add_many(GST_BIN(bin), sink, src, NULL);
375 pa_assert_se(gst_element_link_many(sink, src, NULL));
376
377 pad = gst_element_get_static_pad(sink, "sink");
378 pa_assert_se(gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad)));
379 gst_object_unref(GST_OBJECT(pad));
380
381 pad = gst_element_get_static_pad(src, "src");
382 pa_assert_se(gst_element_add_pad(bin, gst_ghost_pad_new("src", pad)));
383 gst_object_unref(GST_OBJECT(pad));
384
385 return bin;
386
387 fail_enc_dec:
388 gst_object_unref(GST_OBJECT(capsf));
389
390 fail:
391 pa_log_error("aptX initialisation failed");
392 return NULL;
393 }
394
init_common(enum a2dp_codec_type codec_type,bool for_encoding,bool for_backchannel,const uint8_t * config_buffer,uint8_t config_size,pa_sample_spec * sample_spec,pa_core * core)395 static void *init_common(enum a2dp_codec_type codec_type, bool for_encoding, bool for_backchannel, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *sample_spec, pa_core *core) {
396 GstElement *bin;
397 struct gst_info *info = NULL;
398
399 info = pa_xnew0(struct gst_info, 1);
400 pa_assert(info);
401
402 info->core = core;
403 info->ss = sample_spec;
404
405 if (codec_type == APTX) {
406 info->codec_type = APTX;
407 info->a2dp_codec_t.aptx_config = (const a2dp_aptx_t *) config_buffer;
408 pa_assert(config_size == sizeof(*(info->a2dp_codec_t.aptx_config)));
409 } else if (codec_type == APTX_HD) {
410 info->codec_type = APTX_HD;
411 info->a2dp_codec_t.aptx_hd_config = (const a2dp_aptx_hd_t *) config_buffer;
412 pa_assert(config_size == sizeof(*(info->a2dp_codec_t.aptx_hd_config)));
413 } else
414 pa_assert_not_reached();
415
416 if (!(bin = gst_init_aptx(info, sample_spec, for_encoding)))
417 goto fail;
418
419 if (!gst_codec_init(info, for_encoding, bin))
420 goto fail;
421
422 return info;
423
424 fail:
425 if (info)
426 pa_xfree(info);
427
428 return NULL;
429 }
430
init(bool for_encoding,bool for_backchannel,const uint8_t * config_buffer,uint8_t config_size,pa_sample_spec * sample_spec,pa_core * core)431 static void *init(bool for_encoding, bool for_backchannel, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *sample_spec, pa_core *core) {
432 return init_common(APTX, for_encoding, for_backchannel, config_buffer, config_size, sample_spec, core);
433 }
434
init_hd(bool for_encoding,bool for_backchannel,const uint8_t * config_buffer,uint8_t config_size,pa_sample_spec * sample_spec,pa_core * core)435 static void *init_hd(bool for_encoding, bool for_backchannel, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *sample_spec, pa_core *core) {
436 return init_common(APTX_HD, for_encoding, for_backchannel, config_buffer, config_size, sample_spec, core);
437 }
438
deinit(void * codec_info)439 static void deinit(void *codec_info) {
440 return gst_codec_deinit(codec_info);
441 }
442
reset(void * codec_info)443 static int reset(void *codec_info) {
444 return 0;
445 }
446
reset_hd(void * codec_info)447 static int reset_hd(void *codec_info) {
448 struct gst_info *info = (struct gst_info *) codec_info;
449
450 info->seq_num = 0;
451
452 return 0;
453 }
454
get_block_size(void * codec_info,size_t link_mtu)455 static size_t get_block_size(void *codec_info, size_t link_mtu) {
456 /* aptX compression ratio is 6:1 and we need to process one aptX frame (4 bytes) at once */
457 size_t frame_count = (link_mtu / 4);
458
459 return frame_count * 4 * 6;
460 }
461
get_encoded_block_size(void * codec_info,size_t input_size)462 static size_t get_encoded_block_size(void *codec_info, size_t input_size) {
463 /* input size should be aligned to codec input block size */
464 pa_assert_fp(input_size % (4 * 6) == 0);
465
466 return (input_size / (4 * 6)) * 4;
467 }
468
get_block_size_hd(void * codec_info,size_t link_mtu)469 static size_t get_block_size_hd(void *codec_info, size_t link_mtu) {
470 /* aptX HD compression ratio is 4:1 and we need to process one aptX HD frame (6 bytes) at once, plus aptX HD frames are encapsulated in RTP */
471 size_t rtp_size = sizeof(struct rtp_header);
472 size_t frame_count = (link_mtu - rtp_size) / 6;
473
474 return frame_count * 6 * 4;
475 }
476
get_encoded_block_size_hd(void * codec_info,size_t input_size)477 static size_t get_encoded_block_size_hd(void *codec_info, size_t input_size) {
478 size_t rtp_size = sizeof(struct rtp_header);
479
480 /* input size should be aligned to codec input block size */
481 pa_assert_fp(input_size % (4 * 6) == 0);
482
483 return (input_size / (4 * 6)) * 6 + rtp_size;
484 }
485
reduce_encoder_bitrate(void * codec_info,size_t write_link_mtu)486 static size_t reduce_encoder_bitrate(void *codec_info, size_t write_link_mtu) {
487 return 0;
488 }
489
encode_buffer(void * codec_info,uint32_t timestamp,const uint8_t * input_buffer,size_t input_size,uint8_t * output_buffer,size_t output_size,size_t * processed)490 static size_t encode_buffer(void *codec_info, uint32_t timestamp, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed) {
491 size_t written;
492
493 written = gst_transcode_buffer(codec_info, timestamp, input_buffer, input_size, output_buffer, output_size, processed);
494 if (PA_UNLIKELY(*processed == 0 || *processed != input_size))
495 pa_log_error("aptX encoding error");
496
497 return written;
498 }
499
encode_buffer_hd(void * codec_info,uint32_t timestamp,const uint8_t * input_buffer,size_t input_size,uint8_t * output_buffer,size_t output_size,size_t * processed)500 static size_t encode_buffer_hd(void *codec_info, uint32_t timestamp, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed) {
501 struct gst_info *info = (struct gst_info *) codec_info;
502 struct rtp_header *header;
503 size_t written;
504
505 if (PA_UNLIKELY(output_size < sizeof(*header))) {
506 *processed = 0;
507 return 0;
508 }
509
510 written = encode_buffer(codec_info, timestamp, input_buffer, input_size, output_buffer + sizeof(*header), output_size - sizeof(*header), processed);
511
512 if (PA_LIKELY(written > 0)) {
513 header = (struct rtp_header *) output_buffer;
514 pa_zero(*header);
515 header->v = 2;
516 header->pt = 96;
517 header->sequence_number = htons(info->seq_num++);
518 header->timestamp = htonl(timestamp);
519 header->ssrc = htonl(1);
520 written += sizeof(*header);
521 }
522
523 return written;
524 }
525
decode_buffer(void * codec_info,const uint8_t * input_buffer,size_t input_size,uint8_t * output_buffer,size_t output_size,size_t * processed)526 static size_t decode_buffer(void *codec_info, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed) {
527 size_t written;
528
529 written = gst_transcode_buffer(codec_info, -1, input_buffer, input_size, output_buffer, output_size, processed);
530
531 /* Due to aptX latency, aptx_decode starts filling output buffer after 90 input samples.
532 * If input buffer contains less than 90 samples, aptx_decode returns zero (=no output)
533 * but set *processed to non zero as input samples were processed. So do not check for
534 * return value of aptx_decode, zero is valid. Decoding error is indicating by fact that
535 * not all input samples were processed. */
536 if (PA_UNLIKELY(*processed != input_size))
537 pa_log_error("aptX decoding error");
538
539 return written;
540 }
541
decode_buffer_hd(void * codec_info,const uint8_t * input_buffer,size_t input_size,uint8_t * output_buffer,size_t output_size,size_t * processed)542 static size_t decode_buffer_hd(void *codec_info, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed) {
543 struct rtp_header *header;
544 size_t written;
545
546 if (PA_UNLIKELY(input_size < sizeof(*header))) {
547 *processed = 0;
548 return 0;
549 }
550
551 header = (struct rtp_header *) input_buffer;
552 written = decode_buffer(codec_info, input_buffer + sizeof(*header), input_size - sizeof(*header), output_buffer, output_size, processed);
553 *processed += sizeof(*header);
554 return written;
555 }
556
557 const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_aptx = {
558 .id = { A2DP_CODEC_VENDOR, APTX_VENDOR_ID, APTX_CODEC_ID },
559 .support_backchannel = false,
560 .can_be_supported = can_be_supported,
561 .can_accept_capabilities = can_accept_capabilities,
562 .choose_remote_endpoint = choose_remote_endpoint,
563 .fill_capabilities = fill_capabilities,
564 .is_configuration_valid = is_configuration_valid,
565 .fill_preferred_configuration = fill_preferred_configuration,
566 .bt_codec = {
567 .name = "aptx",
568 .description = "aptX",
569 .init = init,
570 .deinit = deinit,
571 .reset = reset,
572 .get_read_block_size = get_block_size,
573 .get_write_block_size = get_block_size,
574 .get_encoded_block_size = get_encoded_block_size,
575 .reduce_encoder_bitrate = reduce_encoder_bitrate,
576 .encode_buffer = encode_buffer,
577 .decode_buffer = decode_buffer,
578 },
579 };
580
581 const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_aptx_hd = {
582 .id = { A2DP_CODEC_VENDOR, APTX_HD_VENDOR_ID, APTX_HD_CODEC_ID },
583 .support_backchannel = false,
584 .can_be_supported = can_be_supported,
585 .can_accept_capabilities = can_accept_capabilities_hd,
586 .choose_remote_endpoint = choose_remote_endpoint_hd,
587 .fill_capabilities = fill_capabilities_hd,
588 .is_configuration_valid = is_configuration_valid_hd,
589 .fill_preferred_configuration = fill_preferred_configuration_hd,
590 .bt_codec = {
591 .name = "aptx_hd",
592 .description = "aptX HD",
593 .init = init_hd,
594 .deinit = deinit,
595 .reset = reset_hd,
596 .get_read_block_size = get_block_size_hd,
597 .get_write_block_size = get_block_size_hd,
598 .get_encoded_block_size = get_encoded_block_size_hd,
599 .reduce_encoder_bitrate = reduce_encoder_bitrate,
600 .encode_buffer = encode_buffer_hd,
601 .decode_buffer = decode_buffer_hd,
602 },
603 };
604