Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}