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