static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration, int *sample_rate, int *framesize) { GetBitContext gb; uint8_t hdr[12 + AV_INPUT_BUFFER_PADDING_SIZE] = { 0 }; int ret, sample_blocks, sr_code; if (buf_size < 12) return AVERROR_INVALIDDATA; if ((ret = avpriv_dca_convert_bitstream(buf, 12, hdr, 12)) < 0) return ret; init_get_bits(&gb, hdr, 96); skip_bits_long(&gb, 39); sample_blocks = get_bits(&gb, 7) + 1; if (sample_blocks < 8) return AVERROR_INVALIDDATA; *duration = 256 * (sample_blocks / 8); *framesize = get_bits(&gb, 14) + 1; if (*framesize < 95) return AVERROR_INVALIDDATA; skip_bits(&gb, 6); sr_code = get_bits(&gb, 4); *sample_rate = avpriv_dca_sample_rates[sr_code]; if (*sample_rate == 0) return AVERROR_INVALIDDATA; return 0; }
static int convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, int max_size) { switch (AV_RB32(src)) { case DCA_SYNCWORD_CORE_BE: case DCA_SYNCWORD_SUBSTREAM: memcpy(dst, src, src_size); return src_size; case DCA_SYNCWORD_CORE_LE: case DCA_SYNCWORD_CORE_14B_BE: case DCA_SYNCWORD_CORE_14B_LE: return avpriv_dca_convert_bitstream(src, src_size, dst, max_size); default: return AVERROR_INVALIDDATA; } }
static int dts_probe(AVProbeData *p) { const uint8_t *buf, *bufp; uint32_t state = -1; int markers[4*16] = {0}; int sum, max, i; int64_t diff = 0; uint8_t hdr[12 + FF_INPUT_BUFFER_PADDING_SIZE] = { 0 }; buf = p->buf + FFMIN(4096, p->buf_size); for(; buf < (p->buf+p->buf_size)-2; buf+=2) { int marker, sample_blocks, sample_rate, sr_code, framesize; int lfe; GetBitContext gb; bufp = buf; state = (state << 16) | bytestream_get_be16(&bufp); if (buf - p->buf >= 4) diff += FFABS(((int16_t)AV_RL16(buf)) - (int16_t)AV_RL16(buf-4)); /* regular bitstream */ if (state == DCA_SYNCWORD_CORE_BE) marker = 0; else if (state == DCA_SYNCWORD_CORE_LE) marker = 1; /* 14 bits big-endian bitstream */ else if (state == DCA_SYNCWORD_CORE_14B_BE && (bytestream_get_be16(&bufp) & 0xFFF0) == 0x07F0) marker = 2; /* 14 bits little-endian bitstream */ else if (state == DCA_SYNCWORD_CORE_14B_LE && (bytestream_get_be16(&bufp) & 0xF0FF) == 0xF007) marker = 3; else continue; if (avpriv_dca_convert_bitstream(buf-2, 12, hdr, 12) < 0) continue; init_get_bits(&gb, hdr, 96); skip_bits_long(&gb, 39); sample_blocks = get_bits(&gb, 7) + 1; if (sample_blocks < 8) continue; framesize = get_bits(&gb, 14) + 1; if (framesize < 95) continue; skip_bits(&gb, 6); sr_code = get_bits(&gb, 4); sample_rate = avpriv_dca_sample_rates[sr_code]; if (sample_rate == 0) continue; get_bits(&gb, 5); if (get_bits(&gb, 1)) continue; skip_bits_long(&gb, 9); lfe = get_bits(&gb, 2); if (lfe > 2) continue; marker += 4* sr_code; markers[marker] ++; } sum = max = 0; for (i=0; i<FF_ARRAY_ELEMS(markers); i++) { sum += markers[i]; if (markers[max] < markers[i]) max = i; } if (markers[max] > 3 && p->buf_size / markers[max] < 32*1024 && markers[max] * 4 > sum * 3 && diff / p->buf_size > 200) return AVPROBE_SCORE_EXTENSION + 1; return 0; }
static int dcadec_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { DCAContext *s = avctx->priv_data; AVFrame *frame = data; uint8_t *input = avpkt->data; int input_size = avpkt->size; int i, ret, prev_packet = s->packet; uint32_t mrk; if (input_size < MIN_PACKET_SIZE || input_size > MAX_PACKET_SIZE) { av_log(avctx, AV_LOG_ERROR, "Invalid packet size\n"); return AVERROR_INVALIDDATA; } // Convert input to BE format mrk = AV_RB32(input); if (mrk != DCA_SYNCWORD_CORE_BE && mrk != DCA_SYNCWORD_SUBSTREAM) { av_fast_padded_malloc(&s->buffer, &s->buffer_size, input_size); if (!s->buffer) return AVERROR(ENOMEM); for (i = 0, ret = AVERROR_INVALIDDATA; i < input_size - MIN_PACKET_SIZE + 1 && ret < 0; i++) ret = avpriv_dca_convert_bitstream(input + i, input_size - i, s->buffer, s->buffer_size); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n"); return ret; } input = s->buffer; input_size = ret; } s->packet = 0; // Parse backward compatible core sub-stream if (AV_RB32(input) == DCA_SYNCWORD_CORE_BE) { int frame_size; if ((ret = ff_dca_core_parse(&s->core, input, input_size)) < 0) return ret; s->packet |= DCA_PACKET_CORE; // EXXS data must be aligned on 4-byte boundary frame_size = FFALIGN(s->core.frame_size, 4); if (input_size - 4 > frame_size) { input += frame_size; input_size -= frame_size; } } if (!s->core_only) { DCAExssAsset *asset = NULL; // Parse extension sub-stream (EXSS) if (AV_RB32(input) == DCA_SYNCWORD_SUBSTREAM) { if ((ret = ff_dca_exss_parse(&s->exss, input, input_size)) < 0) { if (avctx->err_recognition & AV_EF_EXPLODE) return ret; } else { s->packet |= DCA_PACKET_EXSS; asset = &s->exss.assets[0]; } } // Parse XLL component in EXSS if (asset && (asset->extension_mask & DCA_EXSS_XLL)) { if ((ret = ff_dca_xll_parse(&s->xll, input, asset)) < 0) { // Conceal XLL synchronization error if (ret == AVERROR(EAGAIN) && (prev_packet & DCA_PACKET_XLL) && (s->packet & DCA_PACKET_CORE)) s->packet |= DCA_PACKET_XLL | DCA_PACKET_RECOVERY; else if (ret == AVERROR(ENOMEM) || (avctx->err_recognition & AV_EF_EXPLODE)) return ret; } else { s->packet |= DCA_PACKET_XLL; } } // Parse LBR component in EXSS if (asset && (asset->extension_mask & DCA_EXSS_LBR)) { if ((ret = ff_dca_lbr_parse(&s->lbr, input, asset)) < 0) { if (ret == AVERROR(ENOMEM) || (avctx->err_recognition & AV_EF_EXPLODE)) return ret; } else { s->packet |= DCA_PACKET_LBR; } } // Parse core extensions in EXSS or backward compatible core sub-stream if ((s->packet & DCA_PACKET_CORE) && (ret = ff_dca_core_parse_exss(&s->core, input, asset)) < 0) return ret; } // Filter the frame if (s->packet & DCA_PACKET_LBR) { if ((ret = ff_dca_lbr_filter_frame(&s->lbr, frame)) < 0) return ret; } else if (s->packet & DCA_PACKET_XLL) { if (s->packet & DCA_PACKET_CORE) { int x96_synth = -1; // Enable X96 synthesis if needed if (s->xll.chset[0].freq == 96000 && s->core.sample_rate == 48000) x96_synth = 1; if ((ret = ff_dca_core_filter_fixed(&s->core, x96_synth)) < 0) return ret; // Force lossy downmixed output on the first core frame filtered. // This prevents audible clicks when seeking and is consistent with // what reference decoder does when there are multiple channel sets. if (!(prev_packet & DCA_PACKET_RESIDUAL) && s->xll.nreschsets > 0 && s->xll.nchsets > 1) { av_log(avctx, AV_LOG_VERBOSE, "Forcing XLL recovery mode\n"); s->packet |= DCA_PACKET_RECOVERY; } // Set 'residual ok' flag for the next frame s->packet |= DCA_PACKET_RESIDUAL; } if ((ret = ff_dca_xll_filter_frame(&s->xll, frame)) < 0) { // Fall back to core unless hard error if (!(s->packet & DCA_PACKET_CORE)) return ret; if (ret != AVERROR_INVALIDDATA || (avctx->err_recognition & AV_EF_EXPLODE)) return ret; if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) return ret; } } else if (s->packet & DCA_PACKET_CORE) { if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) return ret; if (s->core.filter_mode & DCA_FILTER_MODE_FIXED) s->packet |= DCA_PACKET_RESIDUAL; } else { av_log(avctx, AV_LOG_ERROR, "No valid DCA sub-stream found\n"); if (s->core_only) av_log(avctx, AV_LOG_WARNING, "Consider disabling 'core_only' option\n"); return AVERROR_INVALIDDATA; } *got_frame_ptr = 1; return avpkt->size; }