• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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