FFmpeg
aptxenc.c
Go to the documentation of this file.
1 /*
2  * Audio Processing Technology codec for Bluetooth (aptX)
3  *
4  * Copyright (C) 2017 Aurelien Jacobs <aurel@gnuage.org>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "aptx.h"
24 
25 /*
26  * Half-band QMF analysis filter realized with a polyphase FIR filter.
27  * Split into 2 subbands and downsample by 2.
28  * So for each pair of samples that goes in, one sample goes out,
29  * split into 2 separate subbands.
30  */
33  const int32_t coeffs[NB_FILTERS][FILTER_TAPS],
34  int shift,
35  int32_t samples[NB_FILTERS],
36  int32_t *low_subband_output,
37  int32_t *high_subband_output)
38 {
40  int i;
41 
42  for (i = 0; i < NB_FILTERS; i++) {
43  aptx_qmf_filter_signal_push(&signal[i], samples[NB_FILTERS-1-i]);
44  subbands[i] = aptx_qmf_convolution(&signal[i], coeffs[i], shift);
45  }
46 
47  *low_subband_output = av_clip_intp2(subbands[0] + subbands[1], 23);
48  *high_subband_output = av_clip_intp2(subbands[0] - subbands[1], 23);
49 }
50 
51 /*
52  * Two stage QMF analysis tree.
53  * Split 4 input samples into 4 subbands and downsample by 4.
54  * So for each group of 4 samples that goes in, one sample goes out,
55  * split into 4 separate subbands.
56  */
58  int32_t samples[4],
59  int32_t subband_samples[4])
60 {
61  int32_t intermediate_samples[4];
62  int i;
63 
64  /* Split 4 input samples into 2 intermediate subbands downsampled to 2 samples */
65  for (i = 0; i < 2; i++)
68  &samples[2*i],
69  &intermediate_samples[0+i],
70  &intermediate_samples[2+i]);
71 
72  /* Split 2 intermediate subband samples into 4 final subbands downsampled to 1 sample */
73  for (i = 0; i < 2; i++)
76  &intermediate_samples[2*i],
77  &subband_samples[2*i+0],
78  &subband_samples[2*i+1]);
79 }
80 
83  const int32_t *intervals, int32_t nb_intervals)
84 {
85  int32_t idx = 0;
86  int i;
87 
88  for (i = nb_intervals >> 1; i > 0; i >>= 1)
89  if (MUL64(factor, intervals[idx + i]) <= ((int64_t)value << 24))
90  idx += i;
91 
92  return idx;
93 }
94 
96  int32_t sample_difference,
98  int32_t quantization_factor,
100 {
101  const int32_t *intervals = tables->quantize_intervals;
102  int32_t quantized_sample, dithered_sample, parity_change;
103  int32_t d, mean, interval, inv, sample_difference_abs;
104  int64_t error;
105 
106  sample_difference_abs = FFABS(sample_difference);
107  sample_difference_abs = FFMIN(sample_difference_abs, (1 << 23) - 1);
108 
109  quantized_sample = aptx_bin_search(sample_difference_abs >> 4,
110  quantization_factor,
111  intervals, tables->tables_size);
112 
113  d = rshift32_clip24(MULH(dither, dither), 7) - (1 << 23);
114  d = rshift64(MUL64(d, tables->quantize_dither_factors[quantized_sample]), 23);
115 
116  intervals += quantized_sample;
117  mean = (intervals[1] + intervals[0]) / 2;
118  interval = (intervals[1] - intervals[0]) * (-(sample_difference < 0) | 1);
119 
120  dithered_sample = rshift64_clip24(MUL64(dither, interval) + ((int64_t)av_clip_intp2(mean + d, 23) << 32), 32);
121  error = ((int64_t)sample_difference_abs << 20) - MUL64(dithered_sample, quantization_factor);
122  quantize->error = FFABS(rshift64(error, 23));
123 
124  parity_change = quantized_sample;
125  if (error < 0)
126  quantized_sample--;
127  else
128  parity_change--;
129 
130  inv = -(sample_difference < 0);
131  quantize->quantized_sample = quantized_sample ^ inv;
132  quantize->quantized_sample_parity_change = parity_change ^ inv;
133 }
134 
136 {
137  int32_t subband_samples[4];
138  int subband;
139  aptx_qmf_tree_analysis(&channel->qmf, samples, subband_samples);
140  ff_aptx_generate_dither(channel);
141  for (subband = 0; subband < NB_SUBBANDS; subband++) {
142  int32_t diff = av_clip_intp2(subband_samples[subband] - channel->prediction[subband].predicted_sample, 23);
143  aptx_quantize_difference(&channel->quantize[subband], diff,
144  channel->dither[subband],
145  channel->invert_quantize[subband].quantization_factor,
146  &ff_aptx_quant_tables[hd][subband]);
147  }
148 }
149 
151 {
152  if (aptx_check_parity(channels, idx)) {
153  int i;
154  Channel *c;
155  static const int map[] = { 1, 2, 0, 3 };
156  Quantize *min = &channels[NB_CHANNELS-1].quantize[map[0]];
157  for (c = &channels[NB_CHANNELS-1]; c >= channels; c--)
158  for (i = 0; i < NB_SUBBANDS; i++)
159  if (c->quantize[map[i]].error < min->error)
160  min = &c->quantize[map[i]];
161 
162  /* Forcing the desired parity is done by offsetting by 1 the quantized
163  * sample from the subband featuring the smallest quantization error. */
165  }
166 }
167 
169 {
171  return (((channel->quantize[3].quantized_sample & 0x06) | parity) << 13)
172  | (((channel->quantize[2].quantized_sample & 0x03) ) << 11)
173  | (((channel->quantize[1].quantized_sample & 0x0F) ) << 7)
174  | (((channel->quantize[0].quantized_sample & 0x7F) ) << 0);
175 }
176 
178 {
180  return (((channel->quantize[3].quantized_sample & 0x01E) | parity) << 19)
181  | (((channel->quantize[2].quantized_sample & 0x00F) ) << 15)
182  | (((channel->quantize[1].quantized_sample & 0x03F) ) << 9)
183  | (((channel->quantize[0].quantized_sample & 0x1FF) ) << 0);
184 }
185 
188  uint8_t *output)
189 {
190  int channel;
191  for (channel = 0; channel < NB_CHANNELS; channel++)
192  aptx_encode_channel(&ctx->channels[channel], samples[channel], ctx->hd);
193 
194  aptx_insert_sync(ctx->channels, &ctx->sync_idx);
195 
196  for (channel = 0; channel < NB_CHANNELS; channel++) {
197  ff_aptx_invert_quantize_and_prediction(&ctx->channels[channel], ctx->hd);
198  if (ctx->hd)
199  AV_WB24(output + 3*channel,
200  aptxhd_pack_codeword(&ctx->channels[channel]));
201  else
202  AV_WB16(output + 2*channel,
203  aptx_pack_codeword(&ctx->channels[channel]));
204  }
205 }
206 
207 static int aptx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
208  const AVFrame *frame, int *got_packet_ptr)
209 {
210  AptXContext *s = avctx->priv_data;
211  int pos, ipos, channel, sample, output_size, ret;
212 
213  if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
214  return ret;
215 
216  output_size = s->block_size * frame->nb_samples/4;
217  if ((ret = ff_alloc_packet2(avctx, avpkt, output_size, 0)) < 0)
218  return ret;
219 
220  for (pos = 0, ipos = 0; pos < output_size; pos += s->block_size, ipos += 4) {
222 
223  for (channel = 0; channel < NB_CHANNELS; channel++)
224  for (sample = 0; sample < 4; sample++)
225  samples[channel][sample] = (int32_t)AV_RN32A(&frame->data[channel][4*(ipos+sample)]) >> 8;
226 
227  aptx_encode_samples(s, samples, avpkt->data + pos);
228  }
229 
230  ff_af_queue_remove(&s->afq, frame->nb_samples, &avpkt->pts, &avpkt->duration);
231  *got_packet_ptr = 1;
232  return 0;
233 }
234 
236 {
237  AptXContext *s = avctx->priv_data;
238  ff_af_queue_close(&s->afq);
239  return 0;
240 }
241 
242 #if CONFIG_APTX_ENCODER
244  .name = "aptx",
245  .long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"),
246  .type = AVMEDIA_TYPE_AUDIO,
247  .id = AV_CODEC_ID_APTX,
248  .priv_data_size = sizeof(AptXContext),
249  .init = ff_aptx_init,
250  .encode2 = aptx_encode_frame,
251  .close = aptx_close,
252  .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME,
253  .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
254  .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0},
255  .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P,
257  .supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0},
258 };
259 #endif
260 
261 #if CONFIG_APTX_HD_ENCODER
263  .name = "aptx_hd",
264  .long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"),
265  .type = AVMEDIA_TYPE_AUDIO,
266  .id = AV_CODEC_ID_APTX_HD,
267  .priv_data_size = sizeof(AptXContext),
268  .init = ff_aptx_init,
269  .encode2 = aptx_encode_frame,
270  .close = aptx_close,
271  .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME,
272  .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
273  .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0},
274  .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P,
276  .supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0},
277 };
278 #endif
#define MUL64(a, b)
Definition: mathops.h:54
Prediction prediction[NB_SUBBANDS]
Definition: aptx.h:91
void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts, int64_t *duration)
Remove frame(s) from the queue.
static int aptx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr)
Definition: aptxenc.c:207
static int shift(int a, int b)
Definition: sonic.c:82
static void aptx_insert_sync(Channel channels[NB_CHANNELS], int32_t *idx)
Definition: aptxenc.c:150
This structure describes decoded (raw) audio or video data.
Definition: frame.h:314
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int block_size
Definition: aptx.h:96
static av_always_inline int32_t aptx_qmf_convolution(FilterSignal *signal, const int32_t coeffs[FILTER_TAPS], int shift)
Definition: aptx.h:177
#define AV_CH_LAYOUT_STEREO
static void error(const char *err)
void ff_aptx_invert_quantize_and_prediction(Channel *channel, int hd)
Definition: aptx.c:496
#define sample
AVCodec.
Definition: codec.h:190
Definition: aptx.h:83
const int32_t * quantize_dither_factors
Definition: aptx.h:105
static void aptx_qmf_tree_analysis(QMFAnalysis *qmf, int32_t samples[4], int32_t subband_samples[4])
Definition: aptxenc.c:57
#define AV_RN32A(p)
Definition: intreadwrite.h:526
static av_always_inline void aptx_qmf_filter_signal_push(FilterSignal *signal, int32_t sample)
Definition: aptx.h:165
static int32_t aptx_quantized_parity(Channel *channel)
Definition: aptx.h:191
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size)
Check AVPacket size and/or allocate data.
Definition: encode.c:33
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
Definition: internal.h:40
uint8_t
#define av_cold
Definition: attributes.h:88
static uint16_t aptx_pack_codeword(Channel *channel)
Definition: aptxenc.c:168
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:381
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:108
Quantize quantize[NB_SUBBANDS]
Definition: aptx.h:89
static const int32_t aptx_qmf_inner_coeffs[NB_FILTERS][FILTER_TAPS]
Definition: aptx.h:150
uint8_t * data
Definition: packet.h:363
static const int32_t aptx_qmf_outer_coeffs[NB_FILTERS][FILTER_TAPS]
Definition: aptx.h:135
int32_t sync_idx
Definition: aptx.h:97
int hd
Definition: aptx.h:95
channels
Definition: aptx.h:33
#define AV_WB16(p, v)
Definition: intreadwrite.h:405
int32_t predicted_sample
Definition: aptx.h:80
void ff_aptx_generate_dither(Channel *channel)
Definition: aptx.c:384
FilterSignal inner_filter_signal[NB_FILTERS][NB_FILTERS]
Definition: aptx.h:57
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:153
static const uint8_t dither[8][8]
Definition: vf_fspp.c:57
unsigned int pos
Definition: spdifenc.c:410
InvertQuantize invert_quantize[NB_SUBBANDS]
Definition: aptx.h:90
const char * name
Name of the codec implementation.
Definition: codec.h:197
int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f)
Add a frame to the queue.
static void aptx_encode_samples(AptXContext *ctx, int32_t samples[NB_CHANNELS][4], uint8_t *output)
Definition: aptxenc.c:186
static uint32_t aptxhd_pack_codeword(Channel *channel)
Definition: aptxenc.c:177
static av_always_inline void aptx_qmf_polyphase_analysis(FilterSignal signal[NB_FILTERS], const int32_t coeffs[NB_FILTERS][FILTER_TAPS], int shift, int32_t samples[NB_FILTERS], int32_t *low_subband_output, int32_t *high_subband_output)
Definition: aptxenc.c:32
av_cold int ff_aptx_init(AVCodecContext *avctx)
Definition: aptx.c:507
#define AV_CODEC_CAP_SMALL_LAST_FRAME
Codec can be fed a final frame with a smaller size.
Definition: codec.h:80
#define FFMIN(a, b)
Definition: common.h:96
signed 32 bits, planar
Definition: samplefmt.h:68
QMFAnalysis qmf
Definition: aptx.h:88
int32_t quantized_sample_parity_change
Definition: aptx.h:62
int32_t quantization_factor
Definition: aptx.h:67
subbands
Definition: aptx.h:39
int32_t
AVFormatContext * ctx
Definition: movenc.c:48
#define AV_WB24(p, d)
Definition: intreadwrite.h:450
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
#define s(width, name)
Definition: cbs_vp9.c:257
mcdeint parity
Definition: vf_mcdeint.c:274
AVCodec ff_aptx_encoder
int32_t error
Definition: aptx.h:63
int32_t quantized_sample
Definition: aptx.h:61
static void aptx_quantize_difference(Quantize *quantize, int32_t sample_difference, int32_t dither, int32_t quantization_factor, ConstTables *tables)
Definition: aptxenc.c:95
AVCodec ff_aptx_hd_encoder
Channel channels[NB_CHANNELS]
Definition: aptx.h:98
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
ConstTables ff_aptx_quant_tables[2][NB_SUBBANDS]
Definition: aptx.c:312
main external API structure.
Definition: avcodec.h:531
AudioFrameQueue afq
Definition: aptx.h:99
static const uint16_t channel_layouts[7]
Definition: dca_lbr.c:113
int tables_size
Definition: aptx.h:107
static int aptx_check_parity(Channel channels[NB_CHANNELS], int32_t *idx)
Definition: aptx.h:204
static const int factor[16]
Definition: vf_pp7.c:75
const VDPAUPixFmtMap * map
Writing a table generator This documentation is preliminary Parts of the API are not good and should be changed Basic concepts A table generator consists of two *_tablegen c and *_tablegen h The h file will provide the variable declarations and initialization code for the tables
Definition: tablegen.txt:8
static av_always_inline int32_t aptx_bin_search(int32_t value, int32_t factor, const int32_t *intervals, int32_t nb_intervals)
Definition: aptxenc.c:82
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:328
FilterSignal outer_filter_signal[NB_FILTERS]
Definition: aptx.h:56
int32_t dither[NB_SUBBANDS]
Definition: aptx.h:86
channel
Use these values when setting the channel map with ebur128_set_channel().
Definition: ebur128.h:39
const int32_t * quantize_intervals
Definition: aptx.h:103
void * priv_data
Definition: avcodec.h:558
static int quantize(CinepakEncContext *s, int h, uint8_t *data[4], int linesize[4], int v1mode, strip_info *info, mb_encoding encoding)
Definition: cinepakenc.c:698
static av_always_inline int diff(const uint32_t a, const uint32_t b)
#define FILTER_TAPS
Definition: aptx.h:48
void ff_af_queue_close(AudioFrameQueue *afq)
Close AudioFrameQueue.
Filter the word “frame” indicates either a video frame or a group of audio samples
#define av_always_inline
Definition: attributes.h:45
Definition: aptx.h:60
float min
static void aptx_encode_channel(Channel *channel, int32_t samples[4], int hd)
Definition: aptxenc.c:135
This structure stores compressed data.
Definition: packet.h:340
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:380
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:356
int i
Definition: input.c:407
static av_cold int aptx_close(AVCodecContext *avctx)
Definition: aptxenc.c:235
#define MULH
Definition: mathops.h:42