Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Copyright (C) 2016 foo86 | ||
3 | * | ||
4 | * This file is part of FFmpeg. | ||
5 | * | ||
6 | * FFmpeg is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public | ||
8 | * License as published by the Free Software Foundation; either | ||
9 | * version 2.1 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * FFmpeg is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License along with FFmpeg; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #include "libavutil/mem.h" | ||
22 | #include "libavutil/opt.h" | ||
23 | #include "libavutil/channel_layout.h" | ||
24 | #include "libavutil/thread.h" | ||
25 | |||
26 | #include "codec_internal.h" | ||
27 | #include "dcadec.h" | ||
28 | #include "dcahuff.h" | ||
29 | #include "dca_syncwords.h" | ||
30 | #include "profiles.h" | ||
31 | |||
32 | #define MIN_PACKET_SIZE 16 | ||
33 | #define MAX_PACKET_SIZE 0x104000 | ||
34 | |||
35 | 2483 | int ff_dca_set_channel_layout(AVCodecContext *avctx, int *ch_remap, int dca_mask) | |
36 | { | ||
37 | static const uint8_t dca2wav_norm[28] = { | ||
38 | 2, 0, 1, 9, 10, 3, 8, 4, 5, 9, 10, 6, 7, 12, | ||
39 | 13, 14, 3, 6, 7, 11, 12, 14, 16, 15, 17, 8, 4, 5, | ||
40 | }; | ||
41 | |||
42 | static const uint8_t dca2wav_wide[28] = { | ||
43 | 2, 0, 1, 4, 5, 3, 8, 4, 5, 9, 10, 6, 7, 12, | ||
44 | 13, 14, 3, 9, 10, 11, 12, 14, 16, 15, 17, 8, 4, 5, | ||
45 | }; | ||
46 | |||
47 | 2483 | DCAContext *s = avctx->priv_data; | |
48 | |||
49 | 2483 | int dca_ch, wav_ch, nchannels = 0; | |
50 | |||
51 | 2483 | av_channel_layout_uninit(&avctx->ch_layout); | |
52 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2483 times.
|
2483 | if (s->output_channel_order == CHANNEL_ORDER_CODED) { |
53 | ✗ | for (dca_ch = 0; dca_ch < DCA_SPEAKER_COUNT; dca_ch++) | |
54 | ✗ | if (dca_mask & (1U << dca_ch)) | |
55 | ✗ | ch_remap[nchannels++] = dca_ch; | |
56 | ✗ | avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; | |
57 | ✗ | avctx->ch_layout.nb_channels = nchannels; | |
58 | } else { | ||
59 | 2483 | int wav_mask = 0; | |
60 | int wav_map[18]; | ||
61 | const uint8_t *dca2wav; | ||
62 |
3/4✓ Branch 0 taken 2483 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1177 times.
✓ Branch 3 taken 1306 times.
|
2483 | if (dca_mask == DCA_SPEAKER_LAYOUT_7POINT0_WIDE || |
63 | dca_mask == DCA_SPEAKER_LAYOUT_7POINT1_WIDE) | ||
64 | 1177 | dca2wav = dca2wav_wide; | |
65 | else | ||
66 | 1306 | dca2wav = dca2wav_norm; | |
67 |
2/2✓ Branch 0 taken 69524 times.
✓ Branch 1 taken 2483 times.
|
72007 | for (dca_ch = 0; dca_ch < 28; dca_ch++) { |
68 |
2/2✓ Branch 0 taken 15431 times.
✓ Branch 1 taken 54093 times.
|
69524 | if (dca_mask & (1 << dca_ch)) { |
69 | 15431 | wav_ch = dca2wav[dca_ch]; | |
70 |
1/2✓ Branch 0 taken 15431 times.
✗ Branch 1 not taken.
|
15431 | if (!(wav_mask & (1 << wav_ch))) { |
71 | 15431 | wav_map[wav_ch] = dca_ch; | |
72 | 15431 | wav_mask |= 1 << wav_ch; | |
73 | } | ||
74 | } | ||
75 | } | ||
76 |
2/2✓ Branch 0 taken 44694 times.
✓ Branch 1 taken 2483 times.
|
47177 | for (wav_ch = 0; wav_ch < 18; wav_ch++) |
77 |
2/2✓ Branch 0 taken 15431 times.
✓ Branch 1 taken 29263 times.
|
44694 | if (wav_mask & (1 << wav_ch)) |
78 | 15431 | ch_remap[nchannels++] = wav_map[wav_ch]; | |
79 | |||
80 | 2483 | av_channel_layout_from_mask(&avctx->ch_layout, wav_mask); | |
81 | } | ||
82 | |||
83 | 2483 | return nchannels; | |
84 | } | ||
85 | |||
86 | 7 | void ff_dca_downmix_to_stereo_fixed(DCADSPContext *dcadsp, int32_t **samples, | |
87 | int *coeff_l, int nsamples, int ch_mask) | ||
88 | { | ||
89 | 7 | int pos, spkr, max_spkr = av_log2(ch_mask); | |
90 | 7 | int *coeff_r = coeff_l + av_popcount(ch_mask); | |
91 | |||
92 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | av_assert0(DCA_HAS_STEREO(ch_mask)); |
93 | |||
94 | // Scale left and right channels | ||
95 | 7 | pos = (ch_mask & DCA_SPEAKER_MASK_C); | |
96 | 7 | dcadsp->dmix_scale(samples[DCA_SPEAKER_L], coeff_l[pos ], nsamples); | |
97 | 7 | dcadsp->dmix_scale(samples[DCA_SPEAKER_R], coeff_r[pos + 1], nsamples); | |
98 | |||
99 | // Downmix remaining channels | ||
100 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 7 times.
|
49 | for (spkr = 0; spkr <= max_spkr; spkr++) { |
101 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | if (!(ch_mask & (1U << spkr))) |
102 | ✗ | continue; | |
103 | |||
104 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 7 times.
|
42 | if (*coeff_l && spkr != DCA_SPEAKER_L) |
105 | 7 | dcadsp->dmix_add(samples[DCA_SPEAKER_L], samples[spkr], | |
106 | *coeff_l, nsamples); | ||
107 | |||
108 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 7 times.
|
42 | if (*coeff_r && spkr != DCA_SPEAKER_R) |
109 | 7 | dcadsp->dmix_add(samples[DCA_SPEAKER_R], samples[spkr], | |
110 | *coeff_r, nsamples); | ||
111 | |||
112 | 42 | coeff_l++; | |
113 | 42 | coeff_r++; | |
114 | } | ||
115 | 7 | } | |
116 | |||
117 | 7 | void ff_dca_downmix_to_stereo_float(AVFloatDSPContext *fdsp, float **samples, | |
118 | int *coeff_l, int nsamples, int ch_mask) | ||
119 | { | ||
120 | 7 | int pos, spkr, max_spkr = av_log2(ch_mask); | |
121 | 7 | int *coeff_r = coeff_l + av_popcount(ch_mask); | |
122 | 7 | const float scale = 1.0f / (1 << 15); | |
123 | |||
124 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | av_assert0(DCA_HAS_STEREO(ch_mask)); |
125 | |||
126 | // Scale left and right channels | ||
127 | 7 | pos = (ch_mask & DCA_SPEAKER_MASK_C); | |
128 | 7 | fdsp->vector_fmul_scalar(samples[DCA_SPEAKER_L], samples[DCA_SPEAKER_L], | |
129 | 7 | coeff_l[pos ] * scale, nsamples); | |
130 | 7 | fdsp->vector_fmul_scalar(samples[DCA_SPEAKER_R], samples[DCA_SPEAKER_R], | |
131 | 7 | coeff_r[pos + 1] * scale, nsamples); | |
132 | |||
133 | // Downmix remaining channels | ||
134 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 7 times.
|
49 | for (spkr = 0; spkr <= max_spkr; spkr++) { |
135 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | if (!(ch_mask & (1U << spkr))) |
136 | ✗ | continue; | |
137 | |||
138 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 7 times.
|
42 | if (*coeff_l && spkr != DCA_SPEAKER_L) |
139 | 7 | fdsp->vector_fmac_scalar(samples[DCA_SPEAKER_L], samples[spkr], | |
140 | 7 | *coeff_l * scale, nsamples); | |
141 | |||
142 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 7 times.
|
42 | if (*coeff_r && spkr != DCA_SPEAKER_R) |
143 | 7 | fdsp->vector_fmac_scalar(samples[DCA_SPEAKER_R], samples[spkr], | |
144 | 7 | *coeff_r * scale, nsamples); | |
145 | |||
146 | 42 | coeff_l++; | |
147 | 42 | coeff_r++; | |
148 | } | ||
149 | 7 | } | |
150 | |||
151 | 2483 | static int dcadec_decode_frame(AVCodecContext *avctx, AVFrame *frame, | |
152 | int *got_frame_ptr, AVPacket *avpkt) | ||
153 | { | ||
154 | 2483 | DCAContext *s = avctx->priv_data; | |
155 | 2483 | const uint8_t *input = avpkt->data; | |
156 | 2483 | int input_size = avpkt->size; | |
157 | 2483 | int i, ret, prev_packet = s->packet; | |
158 | uint32_t mrk; | ||
159 | |||
160 |
2/4✓ Branch 0 taken 2483 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2483 times.
|
2483 | if (input_size < MIN_PACKET_SIZE || input_size > MAX_PACKET_SIZE) { |
161 | ✗ | av_log(avctx, AV_LOG_ERROR, "Invalid packet size\n"); | |
162 | ✗ | return AVERROR_INVALIDDATA; | |
163 | } | ||
164 | |||
165 | // Convert input to BE format | ||
166 | 2483 | mrk = AV_RB32(input); | |
167 |
3/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2471 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
|
2483 | if (mrk != DCA_SYNCWORD_CORE_BE && mrk != DCA_SYNCWORD_SUBSTREAM) { |
168 | ✗ | av_fast_padded_malloc(&s->buffer, &s->buffer_size, input_size); | |
169 | ✗ | if (!s->buffer) | |
170 | ✗ | return AVERROR(ENOMEM); | |
171 | |||
172 | ✗ | for (i = 0, ret = AVERROR_INVALIDDATA; i < input_size - MIN_PACKET_SIZE + 1 && ret < 0; i++) | |
173 | ✗ | ret = avpriv_dca_convert_bitstream(input + i, input_size - i, s->buffer, s->buffer_size); | |
174 | |||
175 | ✗ | if (ret < 0) { | |
176 | ✗ | av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n"); | |
177 | ✗ | return ret; | |
178 | } | ||
179 | |||
180 | ✗ | input = s->buffer; | |
181 | ✗ | input_size = ret; | |
182 | } | ||
183 | |||
184 | 2483 | s->packet = 0; | |
185 | |||
186 | // Parse backward compatible core sub-stream | ||
187 |
2/2✓ Branch 0 taken 2471 times.
✓ Branch 1 taken 12 times.
|
2483 | if (AV_RB32(input) == DCA_SYNCWORD_CORE_BE) { |
188 | int frame_size; | ||
189 | |||
190 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2471 times.
|
2471 | if ((ret = ff_dca_core_parse(&s->core, input, input_size)) < 0) |
191 | ✗ | return ret; | |
192 | |||
193 | 2471 | s->packet |= DCA_PACKET_CORE; | |
194 | |||
195 | // EXXS data must be aligned on 4-byte boundary | ||
196 | 2471 | frame_size = FFALIGN(s->core.frame_size, 4); | |
197 |
2/2✓ Branch 0 taken 1401 times.
✓ Branch 1 taken 1070 times.
|
2471 | if (input_size - 4 > frame_size) { |
198 | 1401 | input += frame_size; | |
199 | 1401 | input_size -= frame_size; | |
200 | } | ||
201 | } | ||
202 | |||
203 |
1/2✓ Branch 0 taken 2483 times.
✗ Branch 1 not taken.
|
2483 | if (!s->core_only) { |
204 | 2483 | DCAExssAsset *asset = NULL; | |
205 | |||
206 | // Parse extension sub-stream (EXSS) | ||
207 |
2/2✓ Branch 0 taken 1413 times.
✓ Branch 1 taken 1070 times.
|
2483 | if (AV_RB32(input) == DCA_SYNCWORD_SUBSTREAM) { |
208 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1413 times.
|
1413 | if ((ret = ff_dca_exss_parse(&s->exss, input, input_size)) < 0) { |
209 | ✗ | if (avctx->err_recognition & AV_EF_EXPLODE) | |
210 | ✗ | return ret; | |
211 | } else { | ||
212 | 1413 | s->packet |= DCA_PACKET_EXSS; | |
213 | 1413 | asset = &s->exss.assets[0]; | |
214 | } | ||
215 | } | ||
216 | |||
217 | // Parse XLL component in EXSS | ||
218 |
4/4✓ Branch 0 taken 1413 times.
✓ Branch 1 taken 1070 times.
✓ Branch 2 taken 1357 times.
✓ Branch 3 taken 56 times.
|
2483 | if (asset && (asset->extension_mask & DCA_EXSS_XLL)) { |
219 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1357 times.
|
1357 | if ((ret = ff_dca_xll_parse(&s->xll, input, asset)) < 0) { |
220 | // Conceal XLL synchronization error | ||
221 | ✗ | if (ret == AVERROR(EAGAIN)) { | |
222 | ✗ | if ((prev_packet & DCA_PACKET_XLL) && (s->packet & DCA_PACKET_CORE)) | |
223 | ✗ | s->packet |= DCA_PACKET_XLL | DCA_PACKET_RECOVERY; | |
224 | ✗ | } else if (ret == AVERROR(ENOMEM) || (avctx->err_recognition & AV_EF_EXPLODE)) | |
225 | ✗ | return ret; | |
226 | } else { | ||
227 | 1357 | s->packet |= DCA_PACKET_XLL; | |
228 | } | ||
229 | } | ||
230 | |||
231 | // Parse LBR component in EXSS | ||
232 |
3/4✓ Branch 0 taken 1413 times.
✓ Branch 1 taken 1070 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1413 times.
|
2483 | if (asset && (asset->extension_mask & DCA_EXSS_LBR)) { |
233 | ✗ | if ((ret = ff_dca_lbr_parse(&s->lbr, input, asset)) < 0) { | |
234 | ✗ | if (ret == AVERROR(ENOMEM) || (avctx->err_recognition & AV_EF_EXPLODE)) | |
235 | ✗ | return ret; | |
236 | } else { | ||
237 | ✗ | s->packet |= DCA_PACKET_LBR; | |
238 | } | ||
239 | } | ||
240 | |||
241 | // Parse core extensions in EXSS or backward compatible core sub-stream | ||
242 |
2/2✓ Branch 0 taken 2471 times.
✓ Branch 1 taken 12 times.
|
2483 | if ((s->packet & DCA_PACKET_CORE) |
243 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2471 times.
|
2471 | && (ret = ff_dca_core_parse_exss(&s->core, input, asset)) < 0) |
244 | ✗ | return ret; | |
245 | } | ||
246 | |||
247 | // Filter the frame | ||
248 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2483 times.
|
2483 | if (s->packet & DCA_PACKET_LBR) { |
249 | ✗ | if ((ret = ff_dca_lbr_filter_frame(&s->lbr, frame)) < 0) | |
250 | ✗ | return ret; | |
251 |
2/2✓ Branch 0 taken 1357 times.
✓ Branch 1 taken 1126 times.
|
2483 | } else if (s->packet & DCA_PACKET_XLL) { |
252 |
2/2✓ Branch 0 taken 1345 times.
✓ Branch 1 taken 12 times.
|
1357 | if (s->packet & DCA_PACKET_CORE) { |
253 | 1345 | int x96_synth = -1; | |
254 | |||
255 | // Enable X96 synthesis if needed | ||
256 |
3/4✓ Branch 0 taken 84 times.
✓ Branch 1 taken 1261 times.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
|
1345 | if (s->xll.chset[0].freq == 96000 && s->core.sample_rate == 48000) |
257 | 84 | x96_synth = 1; | |
258 | |||
259 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1345 times.
|
1345 | if ((ret = ff_dca_core_filter_fixed(&s->core, x96_synth)) < 0) |
260 | ✗ | return ret; | |
261 | |||
262 | // Force lossy downmixed output on the first core frame filtered. | ||
263 | // This prevents audible clicks when seeking and is consistent with | ||
264 | // what reference decoder does when there are multiple channel sets. | ||
265 |
3/4✓ Branch 0 taken 54 times.
✓ Branch 1 taken 1291 times.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
|
1345 | if (!(prev_packet & DCA_PACKET_RESIDUAL) && s->xll.nreschsets > 0 |
266 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 18 times.
|
54 | && s->xll.nchsets > 1) { |
267 | 36 | av_log(avctx, AV_LOG_VERBOSE, "Forcing XLL recovery mode\n"); | |
268 | 36 | s->packet |= DCA_PACKET_RECOVERY; | |
269 | } | ||
270 | |||
271 | // Set 'residual ok' flag for the next frame | ||
272 | 1345 | s->packet |= DCA_PACKET_RESIDUAL; | |
273 | } | ||
274 | |||
275 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1357 times.
|
1357 | if ((ret = ff_dca_xll_filter_frame(&s->xll, frame)) < 0) { |
276 | // Fall back to core unless hard error | ||
277 | ✗ | if (!(s->packet & DCA_PACKET_CORE)) | |
278 | ✗ | return ret; | |
279 | ✗ | if (ret != AVERROR_INVALIDDATA || (avctx->err_recognition & AV_EF_EXPLODE)) | |
280 | ✗ | return ret; | |
281 | ✗ | if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) | |
282 | ✗ | return ret; | |
283 | } | ||
284 |
1/2✓ Branch 0 taken 1126 times.
✗ Branch 1 not taken.
|
1126 | } else if (s->packet & DCA_PACKET_CORE) { |
285 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1126 times.
|
1126 | if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) |
286 | ✗ | return ret; | |
287 |
2/2✓ Branch 0 taken 519 times.
✓ Branch 1 taken 607 times.
|
1126 | if (s->core.filter_mode & DCA_FILTER_MODE_FIXED) |
288 | 519 | s->packet |= DCA_PACKET_RESIDUAL; | |
289 | } else { | ||
290 | ✗ | av_log(avctx, AV_LOG_ERROR, "No valid DCA sub-stream found\n"); | |
291 | ✗ | if (s->core_only) | |
292 | ✗ | av_log(avctx, AV_LOG_WARNING, "Consider disabling 'core_only' option\n"); | |
293 | ✗ | return AVERROR_INVALIDDATA; | |
294 | } | ||
295 | |||
296 | 2483 | *got_frame_ptr = 1; | |
297 | |||
298 | 2483 | return avpkt->size; | |
299 | } | ||
300 | |||
301 | ✗ | static av_cold void dcadec_flush(AVCodecContext *avctx) | |
302 | { | ||
303 | ✗ | DCAContext *s = avctx->priv_data; | |
304 | |||
305 | ✗ | ff_dca_core_flush(&s->core); | |
306 | ✗ | ff_dca_xll_flush(&s->xll); | |
307 | ✗ | ff_dca_lbr_flush(&s->lbr); | |
308 | |||
309 | ✗ | s->packet &= DCA_PACKET_MASK; | |
310 | ✗ | } | |
311 | |||
312 | 99 | static av_cold int dcadec_close(AVCodecContext *avctx) | |
313 | { | ||
314 | 99 | DCAContext *s = avctx->priv_data; | |
315 | |||
316 | 99 | ff_dca_core_close(&s->core); | |
317 | 99 | ff_dca_xll_close(&s->xll); | |
318 | 99 | ff_dca_lbr_close(&s->lbr); | |
319 | |||
320 | 99 | av_freep(&s->buffer); | |
321 | 99 | s->buffer_size = 0; | |
322 | |||
323 | 99 | return 0; | |
324 | } | ||
325 | |||
326 | 54 | static av_cold void dcadec_init_static(void) | |
327 | { | ||
328 | 54 | ff_dca_lbr_init_tables(); | |
329 | 54 | ff_dca_init_vlcs(); | |
330 | 54 | } | |
331 | |||
332 | 99 | static av_cold int dcadec_init(AVCodecContext *avctx) | |
333 | { | ||
334 | static AVOnce init_static_once = AV_ONCE_INIT; | ||
335 | 99 | DCAContext *s = avctx->priv_data; | |
336 | |||
337 | 99 | s->avctx = avctx; | |
338 | 99 | s->core.avctx = avctx; | |
339 | 99 | s->exss.avctx = avctx; | |
340 | 99 | s->xll.avctx = avctx; | |
341 | 99 | s->lbr.avctx = avctx; | |
342 | |||
343 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
|
99 | if (ff_dca_core_init(&s->core) < 0) |
344 | ✗ | return AVERROR(ENOMEM); | |
345 | |||
346 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
|
99 | if (ff_dca_lbr_init(&s->lbr) < 0) |
347 | ✗ | return AVERROR(ENOMEM); | |
348 | |||
349 | 99 | ff_dcadsp_init(&s->dcadsp); | |
350 | 99 | s->core.dcadsp = &s->dcadsp; | |
351 | 99 | s->xll.dcadsp = &s->dcadsp; | |
352 | 99 | s->lbr.dcadsp = &s->dcadsp; | |
353 | |||
354 | 99 | s->crctab = av_crc_get_table(AV_CRC_16_CCITT); | |
355 | |||
356 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 55 times.
|
99 | if (s->downmix_layout.nb_channels) { |
357 |
3/4✓ Branch 1 taken 22 times.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22 times.
|
66 | if (!av_channel_layout_compare(&s->downmix_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO) || |
358 | 22 | !av_channel_layout_compare(&s->downmix_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX)) { | |
359 | 22 | s->request_channel_layout = DCA_SPEAKER_LAYOUT_STEREO; | |
360 | 22 | av_channel_layout_uninit(&avctx->ch_layout); | |
361 | 22 | avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; | |
362 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
|
22 | } else if (!av_channel_layout_compare(&s->downmix_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0)) { |
363 | ✗ | s->request_channel_layout = DCA_SPEAKER_LAYOUT_5POINT0; | |
364 | ✗ | av_channel_layout_uninit(&avctx->ch_layout); | |
365 | ✗ | avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0; | |
366 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | } else if (!av_channel_layout_compare(&s->downmix_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1)) { |
367 | 22 | s->request_channel_layout = DCA_SPEAKER_LAYOUT_5POINT1; | |
368 | 22 | av_channel_layout_uninit(&avctx->ch_layout); | |
369 | 22 | avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1; | |
370 | } | ||
371 | else | ||
372 | ✗ | av_log(avctx, AV_LOG_WARNING, "Invalid downmix layout\n"); | |
373 | } | ||
374 | |||
375 | 99 | ff_thread_once(&init_static_once, dcadec_init_static); | |
376 | |||
377 | 99 | return 0; | |
378 | } | ||
379 | |||
380 | #define OFFSET(x) offsetof(DCAContext, x) | ||
381 | #define PARAM AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM | ||
382 | |||
383 | static const AVOption dcadec_options[] = { | ||
384 | { "core_only", "Decode core only without extensions", OFFSET(core_only), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, PARAM }, | ||
385 | |||
386 | { "channel_order", "Order in which the channels are to be exported", | ||
387 | OFFSET(output_channel_order), AV_OPT_TYPE_INT, | ||
388 | { .i64 = CHANNEL_ORDER_DEFAULT }, 0, 1, PARAM, .unit = "channel_order" }, | ||
389 | { "default", "normal libavcodec channel order", 0, AV_OPT_TYPE_CONST, | ||
390 | { .i64 = CHANNEL_ORDER_DEFAULT }, .flags = PARAM, .unit = "channel_order" }, | ||
391 | { "coded", "order in which the channels are coded in the bitstream", | ||
392 | 0, AV_OPT_TYPE_CONST, { .i64 = CHANNEL_ORDER_CODED }, .flags = PARAM, .unit = "channel_order" }, | ||
393 | |||
394 | { "downmix", "Request a specific channel layout from the decoder", OFFSET(downmix_layout), | ||
395 | AV_OPT_TYPE_CHLAYOUT, {.str = NULL}, .flags = PARAM }, | ||
396 | |||
397 | { NULL } | ||
398 | }; | ||
399 | |||
400 | static const AVClass dcadec_class = { | ||
401 | .class_name = "DCA decoder", | ||
402 | .item_name = av_default_item_name, | ||
403 | .option = dcadec_options, | ||
404 | .version = LIBAVUTIL_VERSION_INT, | ||
405 | .category = AV_CLASS_CATEGORY_DECODER, | ||
406 | }; | ||
407 | |||
408 | const FFCodec ff_dca_decoder = { | ||
409 | .p.name = "dca", | ||
410 | CODEC_LONG_NAME("DCA (DTS Coherent Acoustics)"), | ||
411 | .p.type = AVMEDIA_TYPE_AUDIO, | ||
412 | .p.id = AV_CODEC_ID_DTS, | ||
413 | .priv_data_size = sizeof(DCAContext), | ||
414 | .init = dcadec_init, | ||
415 | FF_CODEC_DECODE_CB(dcadec_decode_frame), | ||
416 | .close = dcadec_close, | ||
417 | .flush = dcadec_flush, | ||
418 | .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, | ||
419 | .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, | ||
420 | AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, | ||
421 | .p.priv_class = &dcadec_class, | ||
422 | .p.profiles = NULL_IF_CONFIG_SMALL(ff_dca_profiles), | ||
423 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, | ||
424 | }; | ||
425 |