int exss_parse(struct exss_parser *exss, uint8_t *data, int size) { int i, j, ret; bits_init(&exss->bits, data, size); // Extension substream sync word bits_skip(&exss->bits, 32); // User defined bits bits_skip(&exss->bits, 8); // Extension substream index exss->exss_index = bits_get(&exss->bits, 2); // Flag indicating short or long header size bool wide_hdr = bits_get1(&exss->bits); // Extension substream header length int header_size = bits_get(&exss->bits, 8 + 4 * wide_hdr) + 1; // Check CRC if ((ret = bits_check_crc(&exss->bits, 32 + 8, header_size * 8)) < 0) { exss_err("Invalid EXSS header checksum"); return ret; } exss->exss_size_nbits = 16 + 4 * wide_hdr; // Number of bytes of extension substream exss->exss_size = bits_get(&exss->bits, exss->exss_size_nbits) + 1; if (exss->exss_size > size) { exss_err("Packet too short for EXSS frame"); return -DCADEC_EBADDATA; } // Per stream static fields presence flag exss->static_fields_present = bits_get1(&exss->bits); if (exss->static_fields_present) { // Reference clock code bits_skip(&exss->bits, 2); // Extension substream frame duration bits_skip(&exss->bits, 3); // Timecode presence flag if (bits_get1(&exss->bits)) { // Timecode data bits_skip(&exss->bits, 32); bits_skip(&exss->bits, 4); } // Number of defined audio presentations exss->npresents = bits_get(&exss->bits, 3) + 1; // Number of audio assets in extension substream exss->nassets = bits_get(&exss->bits, 3) + 1; // Reject unsupported features for now if (exss->npresents > 1 || exss->nassets > 1) { exss_err_once("Multiple audio presentations " "and/or assets are not supported"); return -DCADEC_ENOSUP; } // Active extension substream mask for audio presentation int active_exss_mask[8]; for (i = 0; i < exss->npresents; i++) active_exss_mask[i] = bits_get(&exss->bits, exss->exss_index + 1); // Active audio asset mask for (i = 0; i < exss->npresents; i++) for (j = 0; j <= exss->exss_index; j++) if (active_exss_mask[i] & (1 << j)) bits_skip(&exss->bits, 8); // Mixing metadata enable flag exss->mix_metadata_enabled = bits_get1(&exss->bits); if (exss->mix_metadata_enabled) { // Mixing metadata adjustment level bits_skip(&exss->bits, 2); // Number of bits for mixer output speaker activity mask int spkr_mask_nbits = (bits_get(&exss->bits, 2) + 1) << 2; // Number of mixing configurations exss->nmixoutconfigs = bits_get(&exss->bits, 2) + 1; // Speaker layout mask for mixer output channels for (i = 0; i < exss->nmixoutconfigs; i++) exss->nmixoutchs[i] = count_chs_for_mask(bits_get(&exss->bits, spkr_mask_nbits)); } } else { exss->npresents = 1; exss->nassets = 1; } // Reallocate assets if (ta_zalloc_fast(exss, &exss->assets, exss->nassets, sizeof(struct exss_asset)) < 0) return -DCADEC_ENOMEM; // Size of encoded asset data in bytes int offset = header_size; for (i = 0; i < exss->nassets; i++) { exss->assets[i].asset_offset = offset; exss->assets[i].asset_size = bits_get(&exss->bits, exss->exss_size_nbits) + 1; offset += exss->assets[i].asset_size; if (offset > exss->exss_size) { exss_err("Asset out of bounds"); return -DCADEC_EBADDATA; } } // Audio asset descriptor for (i = 0; i < exss->nassets; i++) { exss->assets[i].parser = exss; if ((ret = parse_descriptor(&exss->assets[i])) < 0) return ret; if ((ret = set_exss_offsets(&exss->assets[i])) < 0) { exss_err("Invalid extension size in asset descriptor"); return ret; } } // Backward compatible core present // Backward compatible core substream index // Backward compatible core asset index // Reserved // Byte align // CRC16 of extension substream header if ((ret = bits_seek(&exss->bits, header_size * 8)) < 0) exss_err("Read past end of EXSS header"); return ret; }
int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size) { int i, ret, offset, wide_hdr, header_size; if ((ret = init_get_bits8(&s->gb, data, size)) < 0) return ret; // Extension substream sync word skip_bits_long(&s->gb, 32); // User defined bits skip_bits(&s->gb, 8); // Extension substream index s->exss_index = get_bits(&s->gb, 2); // Flag indicating short or long header size wide_hdr = get_bits1(&s->gb); // Extension substream header length header_size = get_bits(&s->gb, 8 + 4 * wide_hdr) + 1; // Check CRC if (ff_dca_check_crc(s->avctx, &s->gb, 32 + 8, header_size * 8)) { av_log(s->avctx, AV_LOG_ERROR, "Invalid EXSS header checksum\n"); return AVERROR_INVALIDDATA; } s->exss_size_nbits = 16 + 4 * wide_hdr; // Number of bytes of extension substream s->exss_size = get_bits(&s->gb, s->exss_size_nbits) + 1; if (s->exss_size > size) { av_log(s->avctx, AV_LOG_ERROR, "Packet too short for EXSS frame\n"); return AVERROR_INVALIDDATA; } // Per stream static fields presence flag if (s->static_fields_present = get_bits1(&s->gb)) { int active_exss_mask[8]; // Reference clock code skip_bits(&s->gb, 2); // Extension substream frame duration skip_bits(&s->gb, 3); // Timecode presence flag if (get_bits1(&s->gb)) // Timecode data skip_bits_long(&s->gb, 36); // Number of defined audio presentations s->npresents = get_bits(&s->gb, 3) + 1; if (s->npresents > 1) { avpriv_request_sample(s->avctx, "%d audio presentations", s->npresents); return AVERROR_PATCHWELCOME; } // Number of audio assets in extension substream s->nassets = get_bits(&s->gb, 3) + 1; if (s->nassets > 1) { avpriv_request_sample(s->avctx, "%d audio assets", s->nassets); return AVERROR_PATCHWELCOME; } // Active extension substream mask for audio presentation for (i = 0; i < s->npresents; i++) active_exss_mask[i] = get_bits(&s->gb, s->exss_index + 1); // Active audio asset mask for (i = 0; i < s->npresents; i++) skip_bits_long(&s->gb, av_popcount(active_exss_mask[i]) * 8); // Mixing metadata enable flag if (s->mix_metadata_enabled = get_bits1(&s->gb)) { int spkr_mask_nbits; // Mixing metadata adjustment level skip_bits(&s->gb, 2); // Number of bits for mixer output speaker activity mask spkr_mask_nbits = (get_bits(&s->gb, 2) + 1) << 2; // Number of mixing configurations s->nmixoutconfigs = get_bits(&s->gb, 2) + 1; // Speaker layout mask for mixer output channels for (i = 0; i < s->nmixoutconfigs; i++) s->nmixoutchs[i] = ff_dca_count_chs_for_mask(get_bits(&s->gb, spkr_mask_nbits)); } } else { s->npresents = 1; s->nassets = 1; } // Size of encoded asset data in bytes offset = header_size; for (i = 0; i < s->nassets; i++) { s->assets[i].asset_offset = offset; s->assets[i].asset_size = get_bits(&s->gb, s->exss_size_nbits) + 1; offset += s->assets[i].asset_size; if (offset > s->exss_size) { av_log(s->avctx, AV_LOG_ERROR, "EXSS asset out of bounds\n"); return AVERROR_INVALIDDATA; } } // Audio asset descriptor for (i = 0; i < s->nassets; i++) { if ((ret = parse_descriptor(s, &s->assets[i])) < 0) return ret; if ((ret = set_exss_offsets(&s->assets[i])) < 0) { av_log(s->avctx, AV_LOG_ERROR, "Invalid extension size in EXSS asset descriptor\n"); return ret; } } // Backward compatible core present // Backward compatible core substream index // Backward compatible core asset index // Reserved // Byte align // CRC16 of extension substream header if (ff_dca_seek_bits(&s->gb, header_size * 8)) { av_log(s->avctx, AV_LOG_ERROR, "Read past end of EXSS header\n"); return AVERROR_INVALIDDATA; } return 0; }