• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "a2dp_vendor_aptx_hd_encoder"
18 
19 #include "a2dp_vendor_aptx_hd_encoder.h"
20 
21 #include <dlfcn.h>
22 #include <inttypes.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include "a2dp_vendor.h"
27 #include "a2dp_vendor_aptx_hd.h"
28 #include "bt_common.h"
29 #include "common/time_util.h"
30 #include "osi/include/log.h"
31 #include "osi/include/osi.h"
32 
33 //
34 // Encoder for aptX-HD Source Codec
35 //
36 
37 //
38 // The aptX-HD encoder shared library, and the functions to use
39 //
40 static const char* APTX_HD_ENCODER_LIB_NAME = "libaptXHD_encoder.so";
41 static void* aptx_hd_encoder_lib_handle = NULL;
42 
43 static const char* APTX_HD_ENCODER_INIT_NAME = "aptxhdbtenc_init";
44 typedef int (*tAPTX_HD_ENCODER_INIT)(void* state, short endian);
45 
46 static const char* APTX_HD_ENCODER_ENCODE_STEREO_NAME =
47     "aptxhdbtenc_encodestereo";
48 typedef int (*tAPTX_HD_ENCODER_ENCODE_STEREO)(void* state, void* pcmL,
49                                               void* pcmR, void* buffer);
50 
51 static const char* APTX_HD_ENCODER_SIZEOF_PARAMS_NAME = "SizeofAptxhdbtenc";
52 typedef int (*tAPTX_HD_ENCODER_SIZEOF_PARAMS)(void);
53 
54 static tAPTX_HD_ENCODER_INIT aptx_hd_encoder_init_func;
55 static tAPTX_HD_ENCODER_ENCODE_STEREO aptx_hd_encoder_encode_stereo_func;
56 static tAPTX_HD_ENCODER_SIZEOF_PARAMS aptx_hd_encoder_sizeof_params_func;
57 
58 // offset
59 #if (BTA_AV_CO_CP_SCMS_T == TRUE)
60 #define A2DP_APTX_HD_OFFSET (AVDT_MEDIA_OFFSET + 1)
61 #else
62 #define A2DP_APTX_HD_OFFSET AVDT_MEDIA_OFFSET
63 #endif
64 
65 #define A2DP_APTX_HD_MAX_PCM_BYTES_PER_READ 4096
66 
67 typedef struct {
68   uint64_t sleep_time_ns;
69   uint32_t pcm_reads;
70   uint32_t pcm_bytes_per_read;
71   uint32_t aptx_hd_bytes;
72   uint32_t frame_size_counter;
73 } tAPTX_HD_FRAMING_PARAMS;
74 
75 typedef struct {
76   uint64_t session_start_us;
77 
78   size_t media_read_total_expected_packets;
79   size_t media_read_total_expected_reads_count;
80   size_t media_read_total_expected_read_bytes;
81 
82   size_t media_read_total_dropped_packets;
83   size_t media_read_total_actual_reads_count;
84   size_t media_read_total_actual_read_bytes;
85 } a2dp_aptx_hd_encoder_stats_t;
86 
87 typedef struct {
88   a2dp_source_read_callback_t read_callback;
89   a2dp_source_enqueue_callback_t enqueue_callback;
90 
91   bool use_SCMS_T;
92   bool is_peer_edr;          // True if the peer device supports EDR
93   bool peer_supports_3mbps;  // True if the peer device supports 3Mbps EDR
94   uint16_t peer_mtu;         // MTU of the A2DP peer
95   uint32_t timestamp;        // Timestamp for the A2DP frames
96 
97   tA2DP_FEEDING_PARAMS feeding_params;
98   tAPTX_HD_FRAMING_PARAMS framing_params;
99   void* aptx_hd_encoder_state;
100   a2dp_aptx_hd_encoder_stats_t stats;
101 } tA2DP_APTX_HD_ENCODER_CB;
102 
103 static tA2DP_APTX_HD_ENCODER_CB a2dp_aptx_hd_encoder_cb;
104 
105 static void a2dp_vendor_aptx_hd_encoder_update(
106     uint16_t peer_mtu, A2dpCodecConfig* a2dp_codec_config,
107     bool* p_restart_input, bool* p_restart_output, bool* p_config_updated);
108 static void aptx_hd_init_framing_params(
109     tAPTX_HD_FRAMING_PARAMS* framing_params);
110 static void aptx_hd_update_framing_params(
111     tAPTX_HD_FRAMING_PARAMS* framing_params);
112 static size_t aptx_hd_encode_24bit(tAPTX_HD_FRAMING_PARAMS* framing_params,
113                                    size_t* data_out_index, uint32_t* data32_in,
114                                    uint8_t* data_out);
115 
A2DP_VendorLoadEncoderAptxHd(void)116 bool A2DP_VendorLoadEncoderAptxHd(void) {
117   if (aptx_hd_encoder_lib_handle != NULL) return true;  // Already loaded
118 
119   // Open the encoder library
120   aptx_hd_encoder_lib_handle = dlopen(APTX_HD_ENCODER_LIB_NAME, RTLD_NOW);
121   if (aptx_hd_encoder_lib_handle == NULL) {
122     LOG_ERROR(LOG_TAG, "%s: cannot open aptX-HD encoder library %s: %s",
123               __func__, APTX_HD_ENCODER_LIB_NAME, dlerror());
124     return false;
125   }
126 
127   aptx_hd_encoder_init_func = (tAPTX_HD_ENCODER_INIT)dlsym(
128       aptx_hd_encoder_lib_handle, APTX_HD_ENCODER_INIT_NAME);
129   if (aptx_hd_encoder_init_func == NULL) {
130     LOG_ERROR(LOG_TAG,
131               "%s: cannot find function '%s' in the encoder library: %s",
132               __func__, APTX_HD_ENCODER_INIT_NAME, dlerror());
133     A2DP_VendorUnloadEncoderAptxHd();
134     return false;
135   }
136 
137   aptx_hd_encoder_encode_stereo_func = (tAPTX_HD_ENCODER_ENCODE_STEREO)dlsym(
138       aptx_hd_encoder_lib_handle, APTX_HD_ENCODER_ENCODE_STEREO_NAME);
139   if (aptx_hd_encoder_encode_stereo_func == NULL) {
140     LOG_ERROR(LOG_TAG,
141               "%s: cannot find function '%s' in the encoder library: %s",
142               __func__, APTX_HD_ENCODER_ENCODE_STEREO_NAME, dlerror());
143     A2DP_VendorUnloadEncoderAptxHd();
144     return false;
145   }
146 
147   aptx_hd_encoder_sizeof_params_func = (tAPTX_HD_ENCODER_SIZEOF_PARAMS)dlsym(
148       aptx_hd_encoder_lib_handle, APTX_HD_ENCODER_SIZEOF_PARAMS_NAME);
149   if (aptx_hd_encoder_sizeof_params_func == NULL) {
150     LOG_ERROR(LOG_TAG,
151               "%s: cannot find function '%s' in the encoder library: %s",
152               __func__, APTX_HD_ENCODER_SIZEOF_PARAMS_NAME, dlerror());
153     A2DP_VendorUnloadEncoderAptxHd();
154     return false;
155   }
156 
157   return true;
158 }
159 
A2DP_VendorUnloadEncoderAptxHd(void)160 void A2DP_VendorUnloadEncoderAptxHd(void) {
161   aptx_hd_encoder_init_func = NULL;
162   aptx_hd_encoder_encode_stereo_func = NULL;
163   aptx_hd_encoder_sizeof_params_func = NULL;
164 
165   if (aptx_hd_encoder_lib_handle != NULL) {
166     dlclose(aptx_hd_encoder_lib_handle);
167     aptx_hd_encoder_lib_handle = NULL;
168   }
169 }
170 
a2dp_vendor_aptx_hd_encoder_init(const tA2DP_ENCODER_INIT_PEER_PARAMS * p_peer_params,A2dpCodecConfig * a2dp_codec_config,a2dp_source_read_callback_t read_callback,a2dp_source_enqueue_callback_t enqueue_callback)171 void a2dp_vendor_aptx_hd_encoder_init(
172     const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
173     A2dpCodecConfig* a2dp_codec_config,
174     a2dp_source_read_callback_t read_callback,
175     a2dp_source_enqueue_callback_t enqueue_callback) {
176   memset(&a2dp_aptx_hd_encoder_cb, 0, sizeof(a2dp_aptx_hd_encoder_cb));
177 
178   a2dp_aptx_hd_encoder_cb.stats.session_start_us =
179       bluetooth::common::time_get_os_boottime_us();
180 
181   a2dp_aptx_hd_encoder_cb.read_callback = read_callback;
182   a2dp_aptx_hd_encoder_cb.enqueue_callback = enqueue_callback;
183   a2dp_aptx_hd_encoder_cb.is_peer_edr = p_peer_params->is_peer_edr;
184   a2dp_aptx_hd_encoder_cb.peer_supports_3mbps =
185       p_peer_params->peer_supports_3mbps;
186   a2dp_aptx_hd_encoder_cb.peer_mtu = p_peer_params->peer_mtu;
187   a2dp_aptx_hd_encoder_cb.timestamp = 0;
188 
189   /* aptX-HD encoder config */
190   a2dp_aptx_hd_encoder_cb.use_SCMS_T = false;  // TODO: should be a parameter
191 #if (BTA_AV_CO_CP_SCMS_T == TRUE)
192   a2dp_aptx_hd_encoder_cb.use_SCMS_T = true;
193 #endif
194 
195   a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state =
196       osi_malloc(aptx_hd_encoder_sizeof_params_func());
197   if (a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state != NULL) {
198     aptx_hd_encoder_init_func(a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state, 0);
199   } else {
200     LOG_ERROR(LOG_TAG, "%s: Cannot allocate aptX-HD encoder state", __func__);
201     // TODO: Return an error?
202   }
203 
204   // NOTE: Ignore the restart_input / restart_output flags - this initization
205   // happens when the connection is (re)started.
206   bool restart_input = false;
207   bool restart_output = false;
208   bool config_updated = false;
209   a2dp_vendor_aptx_hd_encoder_update(a2dp_aptx_hd_encoder_cb.peer_mtu,
210                                      a2dp_codec_config, &restart_input,
211                                      &restart_output, &config_updated);
212 }
213 
updateEncoderUserConfig(const tA2DP_ENCODER_INIT_PEER_PARAMS * p_peer_params,bool * p_restart_input,bool * p_restart_output,bool * p_config_updated)214 bool A2dpCodecConfigAptxHd::updateEncoderUserConfig(
215     const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params, bool* p_restart_input,
216     bool* p_restart_output, bool* p_config_updated) {
217   a2dp_aptx_hd_encoder_cb.is_peer_edr = p_peer_params->is_peer_edr;
218   a2dp_aptx_hd_encoder_cb.peer_supports_3mbps =
219       p_peer_params->peer_supports_3mbps;
220   a2dp_aptx_hd_encoder_cb.peer_mtu = p_peer_params->peer_mtu;
221   a2dp_aptx_hd_encoder_cb.timestamp = 0;
222 
223   if (a2dp_aptx_hd_encoder_cb.peer_mtu == 0) {
224     LOG_ERROR(LOG_TAG,
225               "%s: Cannot update the codec encoder for %s: "
226               "invalid peer MTU",
227               __func__, name().c_str());
228     return false;
229   }
230 
231   a2dp_vendor_aptx_hd_encoder_update(a2dp_aptx_hd_encoder_cb.peer_mtu, this,
232                                      p_restart_input, p_restart_output,
233                                      p_config_updated);
234   return true;
235 }
236 
237 // Update the A2DP aptX-HD encoder.
238 // |peer_mtu| is the peer MTU.
239 // |a2dp_codec_config| is the A2DP codec to use for the update.
a2dp_vendor_aptx_hd_encoder_update(uint16_t peer_mtu,A2dpCodecConfig * a2dp_codec_config,bool * p_restart_input,bool * p_restart_output,bool * p_config_updated)240 static void a2dp_vendor_aptx_hd_encoder_update(
241     uint16_t peer_mtu, A2dpCodecConfig* a2dp_codec_config,
242     bool* p_restart_input, bool* p_restart_output, bool* p_config_updated) {
243   uint8_t codec_info[AVDT_CODEC_SIZE];
244 
245   *p_restart_input = false;
246   *p_restart_output = false;
247   *p_config_updated = false;
248   if (!a2dp_codec_config->copyOutOtaCodecConfig(codec_info)) {
249     LOG_ERROR(LOG_TAG,
250               "%s: Cannot update the codec encoder for %s: "
251               "invalid codec config",
252               __func__, a2dp_codec_config->name().c_str());
253     return;
254   }
255   const uint8_t* p_codec_info = codec_info;
256 
257   // The feeding parameters
258   tA2DP_FEEDING_PARAMS* p_feeding_params =
259       &a2dp_aptx_hd_encoder_cb.feeding_params;
260   p_feeding_params->sample_rate =
261       A2DP_VendorGetTrackSampleRateAptxHd(p_codec_info);
262   p_feeding_params->bits_per_sample =
263       a2dp_codec_config->getAudioBitsPerSample();
264   p_feeding_params->channel_count =
265       A2DP_VendorGetTrackChannelCountAptxHd(p_codec_info);
266   LOG_DEBUG(LOG_TAG, "%s: sample_rate=%u bits_per_sample=%u channel_count=%u",
267             __func__, p_feeding_params->sample_rate,
268             p_feeding_params->bits_per_sample, p_feeding_params->channel_count);
269   a2dp_vendor_aptx_hd_feeding_reset();
270 }
271 
a2dp_vendor_aptx_hd_encoder_cleanup(void)272 void a2dp_vendor_aptx_hd_encoder_cleanup(void) {
273   osi_free(a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state);
274   memset(&a2dp_aptx_hd_encoder_cb, 0, sizeof(a2dp_aptx_hd_encoder_cb));
275 }
276 
277 //
278 // Initialize the framing parameters, and set those that don't change
279 // while streaming (e.g., 'sleep_time_ns').
280 //
aptx_hd_init_framing_params(tAPTX_HD_FRAMING_PARAMS * framing_params)281 static void aptx_hd_init_framing_params(
282     tAPTX_HD_FRAMING_PARAMS* framing_params) {
283   framing_params->sleep_time_ns = 0;
284   framing_params->pcm_reads = 0;
285   framing_params->pcm_bytes_per_read = 0;
286   framing_params->aptx_hd_bytes = 0;
287   framing_params->frame_size_counter = 0;
288 
289   framing_params->sleep_time_ns = 9000000;
290 
291   LOG_DEBUG(LOG_TAG, "%s: sleep_time_ns = %" PRIu64, __func__,
292             framing_params->sleep_time_ns);
293 }
294 
295 //
296 // Set frame size and transmission interval needed to stream the required
297 // sample rate using 2-DH5 packets for aptX and 2-DH3 packets for aptX-LL.
298 // With SCMS-T enabled we need to reserve room for extra headers added later.
299 // Packets are always sent at equals time intervals but to achieve the
300 // required sample rate, the frame size needs to change on occasion.
301 //
302 // Also need to specify how many of the required PCM samples are read at a
303 // time:
304 //     aptx_bytes = pcm_reads * pcm_bytes_per_read / 4
305 // and
306 //     number of aptX samples produced = pcm_bytes_per_read / 16
307 //
aptx_hd_update_framing_params(tAPTX_HD_FRAMING_PARAMS * framing_params)308 static void aptx_hd_update_framing_params(
309     tAPTX_HD_FRAMING_PARAMS* framing_params) {
310   if (a2dp_aptx_hd_encoder_cb.feeding_params.sample_rate == 48000) {
311     framing_params->aptx_hd_bytes = 648;
312     framing_params->pcm_bytes_per_read = 24;
313     framing_params->pcm_reads = 108;
314   } else {
315     // Assume the sample rate is 44100
316 
317     //
318     // Total of 80 iterations:
319     // - Iteration 80: packet size 648, with 108 reads of 24 PCM bytes
320     // - Iterations 20, 40, 60: packet size 612, with 102 reads of 24 PCM bytes
321     // - All other iterations: packet size 594, with 99 reads of 24 PCM bytes
322     //
323     if (framing_params->frame_size_counter + 1 == 80) {
324       framing_params->aptx_hd_bytes = 648;
325       framing_params->pcm_bytes_per_read = 24;
326       framing_params->pcm_reads = 108;
327     } else if (((framing_params->frame_size_counter + 1) % 20) == 0) {
328       framing_params->aptx_hd_bytes = 612;
329       framing_params->pcm_bytes_per_read = 24;
330       framing_params->pcm_reads = 102;
331     } else {
332       framing_params->aptx_hd_bytes = 594;
333       framing_params->pcm_bytes_per_read = 24;
334       framing_params->pcm_reads = 99;
335     }
336     framing_params->frame_size_counter++;
337     if (framing_params->frame_size_counter == 80)
338       framing_params->frame_size_counter = 0;
339   }
340 
341   LOG_VERBOSE(LOG_TAG,
342               "%s: sleep_time_ns = %" PRIu64
343               " aptx_hd_bytes = %u "
344               "pcm_bytes_per_read = %u pcm_reads = %u frame_size_counter = %u",
345               __func__, framing_params->sleep_time_ns,
346               framing_params->aptx_hd_bytes, framing_params->pcm_bytes_per_read,
347               framing_params->pcm_reads, framing_params->frame_size_counter);
348 }
349 
a2dp_vendor_aptx_hd_feeding_reset(void)350 void a2dp_vendor_aptx_hd_feeding_reset(void) {
351   aptx_hd_init_framing_params(&a2dp_aptx_hd_encoder_cb.framing_params);
352 }
353 
a2dp_vendor_aptx_hd_feeding_flush(void)354 void a2dp_vendor_aptx_hd_feeding_flush(void) {
355   aptx_hd_init_framing_params(&a2dp_aptx_hd_encoder_cb.framing_params);
356 }
357 
a2dp_vendor_aptx_hd_get_encoder_interval_ms(void)358 uint64_t a2dp_vendor_aptx_hd_get_encoder_interval_ms(void) {
359   return a2dp_aptx_hd_encoder_cb.framing_params.sleep_time_ns / (1000 * 1000);
360 }
361 
a2dp_vendor_aptx_hd_send_frames(uint64_t timestamp_us)362 void a2dp_vendor_aptx_hd_send_frames(uint64_t timestamp_us) {
363   tAPTX_HD_FRAMING_PARAMS* framing_params =
364       &a2dp_aptx_hd_encoder_cb.framing_params;
365 
366   // Prepare the packet to send
367   BT_HDR* p_buf = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
368   p_buf->offset = A2DP_APTX_HD_OFFSET;
369   p_buf->len = 0;
370   p_buf->layer_specific = 0;
371 
372   uint8_t* encoded_ptr = (uint8_t*)(p_buf + 1);
373   encoded_ptr += p_buf->offset;
374 
375   aptx_hd_update_framing_params(framing_params);
376 
377   //
378   // Read the PCM data and encode it
379   //
380   uint32_t
381       read_buffer32[A2DP_APTX_HD_MAX_PCM_BYTES_PER_READ / sizeof(uint32_t)];
382   uint32_t expected_read_bytes =
383       framing_params->pcm_reads * framing_params->pcm_bytes_per_read;
384   size_t encoded_ptr_index = 0;
385   size_t pcm_bytes_encoded = 0;
386   uint32_t bytes_read = 0;
387 
388   a2dp_aptx_hd_encoder_cb.stats.media_read_total_expected_packets++;
389   a2dp_aptx_hd_encoder_cb.stats.media_read_total_expected_reads_count++;
390   a2dp_aptx_hd_encoder_cb.stats.media_read_total_expected_read_bytes +=
391       expected_read_bytes;
392 
393   LOG_VERBOSE(LOG_TAG, "%s: PCM read of size %u", __func__,
394               expected_read_bytes);
395   bytes_read = a2dp_aptx_hd_encoder_cb.read_callback((uint8_t*)read_buffer32,
396                                                      expected_read_bytes);
397   a2dp_aptx_hd_encoder_cb.stats.media_read_total_actual_read_bytes +=
398       bytes_read;
399   if (bytes_read < expected_read_bytes) {
400     LOG_WARN(LOG_TAG,
401              "%s: underflow at PCM reading: read %u bytes instead of %u",
402              __func__, bytes_read, expected_read_bytes);
403     a2dp_aptx_hd_encoder_cb.stats.media_read_total_dropped_packets++;
404     osi_free(p_buf);
405     return;
406   }
407   a2dp_aptx_hd_encoder_cb.stats.media_read_total_actual_reads_count++;
408 
409   for (uint32_t reads = 0, offset = 0; reads < framing_params->pcm_reads;
410        reads++, offset +=
411                 framing_params->pcm_bytes_per_read / sizeof(uint32_t)) {
412     pcm_bytes_encoded +=
413         aptx_hd_encode_24bit(framing_params, &encoded_ptr_index,
414                              read_buffer32 + offset, encoded_ptr);
415   }
416 
417   // Compute the number of encoded bytes
418   const int COMPRESSION_RATIO = 4;
419   size_t encoded_bytes = pcm_bytes_encoded / COMPRESSION_RATIO;
420   p_buf->len += encoded_bytes;
421   LOG_VERBOSE(LOG_TAG, "%s: encoded %zu PCM bytes to %zu", __func__,
422               pcm_bytes_encoded, encoded_bytes);
423 
424   // Update the RTP timestamp
425   *((uint32_t*)(p_buf + 1)) = a2dp_aptx_hd_encoder_cb.timestamp;
426   const uint8_t BYTES_PER_FRAME = 3;
427   uint32_t rtp_timestamp =
428       (pcm_bytes_encoded /
429        a2dp_aptx_hd_encoder_cb.feeding_params.channel_count) /
430       BYTES_PER_FRAME;
431   a2dp_aptx_hd_encoder_cb.timestamp += rtp_timestamp;
432 
433   if (p_buf->len > 0) {
434     a2dp_aptx_hd_encoder_cb.enqueue_callback(p_buf, 1, bytes_read);
435   } else {
436     a2dp_aptx_hd_encoder_cb.stats.media_read_total_dropped_packets++;
437     osi_free(p_buf);
438   }
439 }
440 
aptx_hd_encode_24bit(tAPTX_HD_FRAMING_PARAMS * framing_params,size_t * data_out_index,uint32_t * data32_in,uint8_t * data_out)441 static size_t aptx_hd_encode_24bit(tAPTX_HD_FRAMING_PARAMS* framing_params,
442                                    size_t* data_out_index, uint32_t* data32_in,
443                                    uint8_t* data_out) {
444   size_t pcm_bytes_encoded = 0;
445   const uint8_t* p = (const uint8_t*)(data32_in);
446 
447   for (size_t aptx_hd_samples = 0;
448        aptx_hd_samples < framing_params->pcm_bytes_per_read / 24;
449        aptx_hd_samples++) {
450     uint32_t pcmL[4];
451     uint32_t pcmR[4];
452     uint32_t encoded_sample[2];
453 
454     // Expand from AUDIO_FORMAT_PCM_24_BIT_PACKED data (3 bytes per sample)
455     // into AUDIO_FORMAT_PCM_8_24_BIT (4 bytes per sample).
456     for (size_t i = 0; i < 4; i++) {
457       pcmL[i] = ((p[0] << 0) | (p[1] << 8) | (((int8_t)p[2]) << 16));
458       p += 3;
459       pcmR[i] = ((p[0] << 0) | (p[1] << 8) | (((int8_t)p[2]) << 16));
460       p += 3;
461     }
462 
463     aptx_hd_encoder_encode_stereo_func(
464         a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state, &pcmL, &pcmR,
465         &encoded_sample);
466 
467     uint8_t* encoded_ptr = (uint8_t*)&encoded_sample[0];
468     data_out[*data_out_index + 0] = *(encoded_ptr + 2);
469     data_out[*data_out_index + 1] = *(encoded_ptr + 1);
470     data_out[*data_out_index + 2] = *(encoded_ptr + 0);
471     data_out[*data_out_index + 3] = *(encoded_ptr + 6);
472     data_out[*data_out_index + 4] = *(encoded_ptr + 5);
473     data_out[*data_out_index + 5] = *(encoded_ptr + 4);
474 
475     pcm_bytes_encoded += 24;
476     *data_out_index += 6;
477   }
478 
479   return pcm_bytes_encoded;
480 }
481 
encoderIntervalMs() const482 uint64_t A2dpCodecConfigAptxHd::encoderIntervalMs() const {
483   return a2dp_vendor_aptx_hd_get_encoder_interval_ms();
484 }
485 
getEffectiveMtu() const486 int A2dpCodecConfigAptxHd::getEffectiveMtu() const {
487   return a2dp_aptx_hd_encoder_cb.peer_mtu;
488 }
489 
debug_codec_dump(int fd)490 void A2dpCodecConfigAptxHd::debug_codec_dump(int fd) {
491   a2dp_aptx_hd_encoder_stats_t* stats = &a2dp_aptx_hd_encoder_cb.stats;
492 
493   A2dpCodecConfig::debug_codec_dump(fd);
494 
495   dprintf(fd,
496           "  Packet counts (expected/dropped)                        : %zu / "
497           "%zu\n",
498           stats->media_read_total_expected_packets,
499           stats->media_read_total_dropped_packets);
500 
501   dprintf(fd,
502           "  PCM read counts (expected/actual)                       : %zu / "
503           "%zu\n",
504           stats->media_read_total_expected_reads_count,
505           stats->media_read_total_actual_reads_count);
506 
507   dprintf(fd,
508           "  PCM read bytes (expected/actual)                        : %zu / "
509           "%zu\n",
510           stats->media_read_total_expected_read_bytes,
511           stats->media_read_total_actual_read_bytes);
512 }
513