2 * Copyright (C) 2014 Tieto Poland
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include "audio-msg.h"
25 #include "hal-audio.h"
27 #include "profiles/audio/a2dp-codecs.h"
29 #define APTX_SO_NAME "libbt-aptx.so"
37 static const a2dp_aptx_t aptx_presets[] = {
40 .vendor_id = APTX_VENDOR_ID,
41 .codec_id = APTX_CODEC_ID,
43 .frequency = APTX_SAMPLING_FREQ_44100 |
44 APTX_SAMPLING_FREQ_48000,
45 .channel_mode = APTX_CHANNEL_MODE_STEREO,
49 .vendor_id = APTX_VENDOR_ID,
50 .codec_id = APTX_CODEC_ID,
52 .frequency = APTX_SAMPLING_FREQ_48000,
53 .channel_mode = APTX_CHANNEL_MODE_STEREO,
57 .vendor_id = APTX_VENDOR_ID,
58 .codec_id = APTX_CODEC_ID,
60 .frequency = APTX_SAMPLING_FREQ_44100,
61 .channel_mode = APTX_CHANNEL_MODE_STEREO,
65 static void *aptx_handle;
66 static int aptx_btencsize;
67 static int (*aptx_init)(void *, short);
68 static int (*aptx_encode)(void *, void *, void *, void *);
70 static bool aptx_load(void)
72 const char * (*aptx_version)(void);
73 const char * (*aptx_build)(void);
74 int (*aptx_sizeofenc)(void);
76 aptx_handle = dlopen(APTX_SO_NAME, RTLD_LAZY);
78 error("APTX: failed to open library %s (%s)", APTX_SO_NAME,
83 aptx_version = dlsym(aptx_handle, "aptxbtenc_version");
84 aptx_build = dlsym(aptx_handle, "aptxbtenc_build");
86 if (aptx_version && aptx_build)
87 info("APTX: using library version %s build %s", aptx_version(),
90 warn("APTX: cannot retrieve library version");
92 aptx_sizeofenc = dlsym(aptx_handle, "SizeofAptxbtenc");
93 aptx_init = dlsym(aptx_handle, "aptxbtenc_init");
94 aptx_encode = dlsym(aptx_handle, "aptxbtenc_encodestereo");
95 if (!aptx_sizeofenc || !aptx_init || !aptx_encode) {
96 error("APTX: failed initialize library");
101 aptx_btencsize = aptx_sizeofenc();
103 info("APTX: codec library initialized (size=%d)", aptx_btencsize);
108 static void aptx_unload(void)
113 dlclose(aptx_handle);
117 static int aptx_get_presets(struct audio_preset *preset, size_t *len)
122 uint8_t *ptr = (uint8_t *) preset;
123 size_t preset_size = sizeof(*preset) + sizeof(a2dp_aptx_t);
127 count = sizeof(aptx_presets) / sizeof(aptx_presets[0]);
129 for (i = 0; i < count; i++) {
130 preset = (struct audio_preset *) ptr;
132 if (new_len + preset_size > *len)
135 preset->len = sizeof(a2dp_aptx_t);
136 memcpy(preset->data, &aptx_presets[i], preset->len);
138 new_len += preset_size;
147 static bool aptx_codec_init(struct audio_preset *preset, uint16_t payload_len,
150 struct aptx_data *aptx_data;
154 if (preset->len != sizeof(a2dp_aptx_t)) {
155 error("APTX: preset size mismatch");
159 aptx_data = malloc(sizeof(*aptx_data));
163 memset(aptx_data, 0, sizeof(*aptx_data));
164 memcpy(&aptx_data->aptx, preset->data, preset->len);
166 aptx_data->enc = calloc(1, aptx_btencsize);
167 if (!aptx_data->enc) {
168 error("APTX: failed to create encoder");
173 /* 1 = big-endian, this is what devices are using */
174 aptx_init(aptx_data->enc, 1);
176 *codec_data = aptx_data;
181 static bool aptx_cleanup(void *codec_data)
183 struct aptx_data *aptx_data = (struct aptx_data *) codec_data;
185 free(aptx_data->enc);
191 static bool aptx_get_config(void *codec_data, struct audio_input_config *config)
193 struct aptx_data *aptx_data = (struct aptx_data *) codec_data;
195 config->rate = aptx_data->aptx.frequency & APTX_SAMPLING_FREQ_48000 ?
197 config->channels = AUDIO_CHANNEL_OUT_STEREO;
198 config->format = AUDIO_FORMAT_PCM_16_BIT;
203 static size_t aptx_get_buffer_size(void *codec_data)
205 /* TODO: return actual value */
209 static size_t aptx_get_mediapacket_duration(void *codec_data)
211 /* TODO: return actual value */
215 static ssize_t aptx_encode_mediapacket(void *codec_data, const uint8_t *buffer,
216 size_t len, struct media_packet *mp,
217 size_t mp_data_len, size_t *written)
219 struct aptx_data *aptx_data = (struct aptx_data *) codec_data;
220 const int16_t *ptr = (const void *) buffer;
222 size_t bytes_out = 0;
224 while ((len - bytes_in) >= 16 && (mp_data_len - bytes_out) >= 4) {
225 int pcm_l[4], pcm_r[4];
228 for (i = 0; i < 4; i++) {
234 aptx_encode(aptx_data->enc, pcm_l, pcm_r, &mp->data[bytes_out]);
240 *written = bytes_out;
245 static bool aptx_update_qos(void *codec_data, uint8_t op)
248 * aptX has constant bitrate of 352kbps (with constant 4:1 compression
249 * ratio) thus QoS is not possible here.
255 static const struct audio_codec codec = {
256 .type = A2DP_CODEC_VENDOR,
260 .unload = aptx_unload,
262 .get_presets = aptx_get_presets,
264 .init = aptx_codec_init,
265 .cleanup = aptx_cleanup,
266 .get_config = aptx_get_config,
267 .get_buffer_size = aptx_get_buffer_size,
268 .get_mediapacket_duration = aptx_get_mediapacket_duration,
269 .encode_mediapacket = aptx_encode_mediapacket,
270 .update_qos = aptx_update_qos,
273 const struct audio_codec *codec_aptx(void)