DCADEC_API int dcadec_frame_parse_header(const uint8_t *data, size_t *size) { struct bitstream bits; uint8_t header[DCADEC_FRAME_HEADER_SIZE]; size_t header_size, frame_size; int ret; if (!data || !size) return -DCADEC_EINVAL; if ((ret = dcadec_frame_convert_bitstream(header, &header_size, data, DCADEC_FRAME_HEADER_SIZE)) < 0) return ret; bits_init(&bits, header, header_size); switch (bits_get(&bits, 32)) { case SYNC_WORD_CORE: { bool normal_frame = bits_get1(&bits); int deficit_samples = bits_get(&bits, 5) + 1; int npcmblocks; if (normal_frame && deficit_samples != 32) return -DCADEC_ENOSYNC; bits_skip1(&bits); npcmblocks = bits_get(&bits, 7) + 1; if ((npcmblocks & 7) && (npcmblocks < 6 || normal_frame)) return -DCADEC_ENOSYNC; frame_size = bits_get(&bits, 14) + 1; if (frame_size < 96) return -DCADEC_ENOSYNC; if (ret & DCADEC_BITSTREAM_BE14) *size = frame_size * 8 / 14 * 2; else *size = frame_size; return DCADEC_FRAME_TYPE_CORE; } case SYNC_WORD_EXSS: { bool wide_hdr; bits_skip(&bits, 10); wide_hdr = bits_get1(&bits); header_size = bits_get(&bits, 8 + 4 * wide_hdr) + 1; if ((header_size & 3) || header_size < DCADEC_FRAME_HEADER_SIZE) return -DCADEC_ENOSYNC; frame_size = bits_get(&bits, 16 + 4 * wide_hdr) + 1; if ((frame_size & 3) || frame_size < header_size) return -DCADEC_ENOSYNC; *size = frame_size; return DCADEC_FRAME_TYPE_EXSS; } default: return -DCADEC_ENOSYNC; } }
static int parse_descriptor(struct exss_asset *asset) { struct exss_parser *exss = asset->parser; int i, j, ret, descr_pos = exss->bits.index; // Size of audio asset descriptor in bytes int descr_size = bits_get(&exss->bits, 9) + 1; // Audio asset identifier asset->asset_index = bits_get(&exss->bits, 3); // // Per stream static metadata // if (exss->static_fields_present) { // Asset type descriptor presence if (bits_get1(&exss->bits)) // Asset type descriptor bits_skip(&exss->bits, 4); // Language descriptor presence if (bits_get1(&exss->bits)) // Language descriptor bits_skip(&exss->bits, 24); // Additional textual information presence if (bits_get1(&exss->bits)) { // Byte size of additional text info int text_size = bits_get(&exss->bits, 10) + 1; // Additional textual information string bits_skip(&exss->bits, text_size * 8); } // PCM bit resolution asset->pcm_bit_res = bits_get(&exss->bits, 5) + 1; // Maximum sample rate asset->max_sample_rate = exss_sample_rates[bits_get(&exss->bits, 4)]; // Total number of channels asset->nchannels_total = bits_get(&exss->bits, 8) + 1; // One to one map channel to speakers asset->one_to_one_map_ch_to_spkr = bits_get1(&exss->bits); if (asset->one_to_one_map_ch_to_spkr) { // Embedded stereo flag if (asset->nchannels_total > 2) asset->embedded_stereo = bits_get1(&exss->bits); // Embedded 6 channels flag if (asset->nchannels_total > 6) asset->embedded_6ch = bits_get1(&exss->bits); // Speaker mask enabled flag asset->spkr_mask_enabled = bits_get1(&exss->bits); int spkr_mask_nbits = 0; if (asset->spkr_mask_enabled) { // Number of bits for speaker activity mask spkr_mask_nbits = (bits_get(&exss->bits, 2) + 1) << 2; // Loudspeaker activity mask asset->spkr_mask = bits_get(&exss->bits, spkr_mask_nbits); } // Number of speaker remapping sets int spkr_remap_nsets = bits_get(&exss->bits, 3); if (spkr_remap_nsets && !spkr_mask_nbits) { exss_err("Speaker mask disabled yet there are remapping sets"); return -DCADEC_EBADDATA; } // Standard loudspeaker layout mask int nspeakers[8]; for (i = 0; i < spkr_remap_nsets; i++) nspeakers[i] = count_chs_for_mask(bits_get(&exss->bits, spkr_mask_nbits)); for (i = 0; i < spkr_remap_nsets; i++) { // Number of channels to be decoded for speaker remapping int nch_for_remaps = bits_get(&exss->bits, 5) + 1; for (j = 0; j < nspeakers[i]; j++) { // Decoded channels to output speaker mapping mask int remap_ch_mask = bits_get(&exss->bits, nch_for_remaps); // Loudspeaker remapping codes int ncodes = dca_popcount(remap_ch_mask); bits_skip(&exss->bits, ncodes * 5); } } } else { asset->embedded_stereo = false; asset->embedded_6ch = false; asset->spkr_mask_enabled = false; asset->spkr_mask = 0; // Representation type asset->representation_type = bits_get(&exss->bits, 3); } } // // DRC, DNC and mixing metadata // // Dynamic range coefficient presence flag bool drc_present = bits_get1(&exss->bits); // Code for dynamic range coefficient if (drc_present) bits_skip(&exss->bits, 8); // Dialog normalization presence flag if (bits_get1(&exss->bits)) // Dialog normalization code bits_skip(&exss->bits, 5); // DRC for stereo downmix if (drc_present && asset->embedded_stereo) bits_skip(&exss->bits, 8); // Mixing metadata presence flag if (exss->mix_metadata_enabled && bits_get1(&exss->bits)) { // External mixing flag bits_skip1(&exss->bits); // Post mixing / replacement gain adjustment bits_skip(&exss->bits, 6); // DRC prior to mixing if (bits_get(&exss->bits, 2) == 3) // Custom code for mixing DRC bits_skip(&exss->bits, 8); else // Limit for mixing DRC bits_skip(&exss->bits, 3); // Scaling type for channels of main audio // Scaling parameters of main audio if (bits_get1(&exss->bits)) for (i = 0; i < exss->nmixoutconfigs; i++) bits_skip(&exss->bits, 6 * exss->nmixoutchs[i]); else bits_skip(&exss->bits, 6 * exss->nmixoutconfigs); int nchannels_dmix = asset->nchannels_total; if (asset->embedded_6ch) nchannels_dmix += 6; if (asset->embedded_stereo) nchannels_dmix += 2; for (i = 0; i < exss->nmixoutconfigs; i++) { for (j = 0; j < nchannels_dmix; j++) { if (!exss->nmixoutchs[i]) { exss_err("Invalid speaker layout mask for mixing configuration"); return -DCADEC_EBADDATA; } // Mix output mask int mix_map_mask = bits_get(&exss->bits, exss->nmixoutchs[i]); // Mixing coefficients int nmixcoefs = dca_popcount(mix_map_mask); bits_skip(&exss->bits, 6 * nmixcoefs); } } } // // Decoder navigation data // // Coding mode for the asset asset->coding_mode = bits_get(&exss->bits, 2); // Coding components used in asset switch (asset->coding_mode) { case 0: // Coding mode that may contain multiple coding components asset->extension_mask = bits_get(&exss->bits, 12); if (asset->extension_mask & EXSS_CORE) { // Size of core component in extension substream asset->core_size = bits_get(&exss->bits, 14) + 1; // Core sync word present flag if (bits_get1(&exss->bits)) // Core sync distance bits_skip(&exss->bits, 2); } if (asset->extension_mask & EXSS_XBR) // Size of XBR extension in extension substream asset->xbr_size = bits_get(&exss->bits, 14) + 1; if (asset->extension_mask & EXSS_XXCH) // Size of XXCH extension in extension substream asset->xxch_size = bits_get(&exss->bits, 14) + 1; if (asset->extension_mask & EXSS_X96) // Size of X96 extension in extension substream asset->x96_size = bits_get(&exss->bits, 12) + 1; if (asset->extension_mask & EXSS_LBR) parse_lbr_parameters(asset); if (asset->extension_mask & EXSS_XLL) parse_xll_parameters(asset); if (asset->extension_mask & EXSS_RSV1) bits_skip(&exss->bits, 16); if (asset->extension_mask & EXSS_RSV2) bits_skip(&exss->bits, 16); break; case 1: // Loss-less coding mode without CBR component asset->extension_mask = EXSS_XLL; parse_xll_parameters(asset); break; case 2: // Low bit rate mode asset->extension_mask = EXSS_LBR; parse_lbr_parameters(asset); break; case 3: // Auxiliary coding mode asset->extension_mask = 0; // Size of auxiliary coded data bits_skip(&exss->bits, 14); // Auxiliary codec identification bits_skip(&exss->bits, 8); // Aux sync word present flag if (bits_get1(&exss->bits)) // Aux sync distance bits_skip(&exss->bits, 3); break; } if (asset->extension_mask & EXSS_XLL) // DTS-HD stream ID asset->hd_stream_id = bits_get(&exss->bits, 3); // One to one mixing flag // Per channel main audio scaling flag // Main audio scaling codes // Decode asset in secondary decoder flag // Revision 2 DRC metadata // Reserved // Zero pad if ((ret = bits_seek(&exss->bits, descr_pos + descr_size * 8)) < 0) exss_err("Read past end of asset descriptor"); return ret; }