static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration, int *sample_rate) { GetBitContext gb; uint8_t hdr[12 + FF_INPUT_BUFFER_PADDING_SIZE] = { 0 }; int ret, sample_blocks, sr_code; if (buf_size < 12) return AVERROR_INVALIDDATA; if ((ret = ff_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); skip_bits(&gb, 20); sr_code = get_bits(&gb, 4); *sample_rate = avpriv_dca_sample_rates[sr_code]; if (*sample_rate == 0) return AVERROR_INVALIDDATA; return 0; }
int parse_dts_header(DTSParserContext *pContext, DTSHeader *pHeader, uint8_t *pBuffer, unsigned uSize) { if(!pContext) return -1; if(!pHeader) return -1; unsigned ExtDescriptor = 0, ExtCoding = 0; uint8_t dts_buffer[32 + FF_INPUT_BUFFER_PADDING_SIZE] = {0}; int ret = ff_dca_convert_bitstream(pBuffer, uSize, dts_buffer, 32); bool is16be = (AV_RB32(pBuffer) == DCA_MARKER_RAW_BE); /* Parse Core Header */ if (ret >= 0) { pHeader->HasCore = 1; GetBitContext *gb = pContext->gb; init_get_bits(gb, dts_buffer, 32 << 3); skip_bits_long(gb, 32); /* Sync code */ skip_bits1(gb); /* Frame type */ pHeader->SamplesPerBlock = get_bits(gb, 5) + 1; /* Samples deficit */ pHeader->CRCPresent = get_bits1(gb); /* CRC present */ pHeader->Blocks = get_bits(gb, 7) + 1; /* Number of Blocks */ pHeader->FrameSize = get_bits(gb, 14) + 1; /* Primary (core) Frame Size */ pHeader->ChannelLayout = get_bits(gb, 6); /* Channel configuration */ unsigned sample_index = get_bits(gb, 4); /* Sample frequency index */ pHeader->SampleRate = avpriv_dca_sample_rates[sample_index]; unsigned bitrate_index = get_bits(gb, 5); /* Bitrate index */ pHeader->Bitrate = dca_bit_rates[bitrate_index]; skip_bits1(gb); /* Down mix */ skip_bits1(gb); /* Dynamic range */ skip_bits1(gb); /* Time stamp */ skip_bits1(gb); /* Auxiliary data */ skip_bits1(gb); /* HDCD */ ExtDescriptor = get_bits(gb, 3); /* External descriptor */ ExtCoding = get_bits1(gb); /* Extended coding */ skip_bits1(gb); /* ASPF */ pHeader->LFE = get_bits(gb, 2); /* LFE */ skip_bits1(gb); /* Predictor History */ if(pHeader->CRCPresent) skip_bits(gb, 16); /* CRC */ skip_bits1(gb); /* Multirate Interpolator */ skip_bits(gb, 4); /* Encoder Software Revision */ skip_bits(gb, 2); /* Copy history */ pHeader->ES = get_bits1(gb); /* ES */ skip_bits(gb, 2); /* PCMR (source PCM resolution) */ skip_bits1(gb); /* SUMF (Front Sum/Difference Flag) */ skip_bits1(gb); /* SUMS (Surround Sum/Difference Flag) */ skip_bits(gb, 4); /* Dialog Normalization Parameter or Unspecified (dependent on encoder version) */ // Check some basic validity if (uSize < pHeader->FrameSize) return -1; } else { pHeader->HasCore = 0; } if (pHeader->HasCore && !is16be) return 0; // DTS-HD parsing const uint8_t *pHD = nullptr; if (pHeader->HasCore) { // If we have a core, only search after the normal buffer if (uSize > (pHeader->FrameSize + 4)) { // at least 4 bytes extra, could probably insert a minimal size of a HD header, but so what pHD = find_marker32_position(pBuffer + pHeader->FrameSize, uSize - pHeader->FrameSize, DCA_HD_MARKER); } } else { pHD = find_marker32_position(pBuffer, uSize, DCA_HD_MARKER); } if (pHD) { pHeader->IsHD = 1; size_t remaining = uSize - (pHD - pBuffer); parse_dts_hd_header(pContext, pHeader, pHD, (unsigned)remaining); const uint8_t *pXChHD = find_marker32_position(pHD, remaining, DCA_XCH_MARKER); if (pXChHD) { size_t remaining = uSize - (pXChHD - pBuffer); parse_dts_xch_hd_header(pContext, pHeader, pXChHD, (unsigned)remaining); } const uint8_t *pXXChHD = find_marker32_position(pHD, remaining, DCA_XXCH_MARKER); if (pXXChHD) { size_t remaining = uSize - (pXXChHD - pBuffer); parse_dts_xxch_hd_header(pContext, pHeader, pXXChHD, (unsigned)remaining); } } // Handle DTS extensions if (ExtCoding) { size_t coreSize = pHD ? (pHD - pBuffer) : uSize; if (ExtDescriptor == 0 || ExtDescriptor == 3) { const uint8_t *pXCh = find_marker32_position(pBuffer, coreSize, DCA_XCH_MARKER); if (pXCh) { size_t remaining = coreSize - (pXCh - pBuffer); parse_dts_xch_header(pContext, pHeader, pXCh, (unsigned)remaining); } } if (ExtDescriptor == 6) { const uint8_t *pXXCh = find_marker32_position(pBuffer, coreSize, DCA_XXCH_MARKER); if (pXXCh) { size_t remaining = coreSize - (pXXCh - pBuffer); parse_dts_xxch_header(pContext, pHeader, pXXCh, (unsigned)remaining); } } } return 0; }