Exemple #1
0
static int parse_dmix_coeffs(struct xll_chset *chs)
{
    struct xll_decoder *xll = chs->decoder;
    int m, n;

    if (chs->primary_chset) {
        m = dmix_primary_nch[chs->dmix_type];
        n = chs->nchannels;
    } else {
        m = chs->dmix_m;
        n = chs->nchannels + 2; // Two extra columns for scales
    }

    // Reallocate downmix coefficients matrix
    if (ta_zalloc_fast(xll->chset, &chs->dmix_coeff, m * n, sizeof(int)) < 0)
        return -DCADEC_ENOMEM;

    if (chs->primary_chset) {
        chs->dmix_scale = NULL;
        chs->dmix_scale_inv = NULL;
    } else {
        chs->dmix_scale = chs->dmix_coeff + m * chs->nchannels;
        chs->dmix_scale_inv = chs->dmix_coeff + m * (chs->nchannels + 1);
    }

    int *coeff_ptr = chs->dmix_coeff;
    for (int i = 0; i < m; i++) {
        int scale_inv = 0;

        // Downmix scale
        // Only for non-primary channel sets
        if (!chs->primary_chset) {
            int code = bits_get(&xll->bits, 9);
            int sign = (code >> 8) - 1; code &= 0xff;
            if (code > 0) {
                unsigned int index = code - 1;
                enforce(index >= 40 && index < dca_countof(dmix_table), "Invalid downmix scale index");
                int scale = dmix_table[index];
                scale_inv = dmix_table_inv[index - 40];
                chs->dmix_scale[i] = (scale ^ sign) - sign;
                chs->dmix_scale_inv[i] = (scale_inv ^ sign) - sign;
            } else {
                chs->dmix_scale[i] = 0;
                chs->dmix_scale_inv[i] = 0;
            }
        }

        // Downmix coefficients
        for (int j = 0; j < chs->nchannels; j++) {
            int code = bits_get(&xll->bits, 9);
            int sign = (code >> 8) - 1; code &= 0xff;
            if (code > 0) {
                unsigned int index = code - 1;
                enforce(index < dca_countof(dmix_table), "Invalid downmix coefficient index");
                int coeff = dmix_table[index];
                if (!chs->primary_chset)
                    // Multiply by |InvDmixScale| to get |UndoDmixScale|
                    coeff = mul16(scale_inv, coeff);
                // Convert sign
                *coeff_ptr++ = (coeff ^ sign) - sign;
            } else {
                *coeff_ptr++ = 0;
            }
        }
    }
Exemple #2
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;
}
Exemple #3
0
static int parse_dmix_coeffs(struct xll_chset *chs)
{
    struct xll_decoder *xll = chs->decoder;
    int m, n;

    if (chs->primary_chset) {
        m = dmix_primary_nch[chs->dmix_type];
        n = chs->nchannels;
    } else {
        m = chs->dmix_m;
        n = chs->nchannels + 2; // Two extra columns for scales
    }

    // Reallocate downmix coefficients buffer
    if (ta_zalloc_fast(xll->chset, &chs->dmix_coeff, m * n * 2, sizeof(int)) < 0)
        return -DCADEC_ENOMEM;

    // Setup buffer pointers for current and previous frame
    bool valid = (chs->dmix_coeffs_signature == XLL_DMIX_SIGNATURE(chs));
    chs->dmix_coeff_cur = chs->dmix_coeff + m * n * chs->dmix_coeffs_parity;
    chs->dmix_coeff_pre = chs->dmix_coeff + m * n * (chs->dmix_coeffs_parity ^ valid);

    if (chs->primary_chset) {
        chs->dmix_scale_cur = chs->dmix_scale_pre = NULL;
        chs->dmix_scale_inv_cur = chs->dmix_scale_inv_pre = NULL;
    } else {
        chs->dmix_scale_cur = chs->dmix_coeff_cur + m * chs->nchannels;
        chs->dmix_scale_pre = chs->dmix_coeff_pre + m * chs->nchannels;
        chs->dmix_scale_inv_cur = chs->dmix_coeff_cur + m * (chs->nchannels + 1);
        chs->dmix_scale_inv_pre = chs->dmix_coeff_pre + m * (chs->nchannels + 1);
    }

    int *coeff_ptr = chs->dmix_coeff_cur;
    for (int i = 0; i < m; i++) {
        int scale_inv = 0;

        // Downmix scale
        // Only for non-primary channel sets
        if (!chs->primary_chset) {
            int code = bits_get(&xll->bits, 9);
            int sign = (code >> 8) - 1; code &= 0xff;
            if (code > 0) {
                unsigned int index = code - 1;
                if (index < 40 || index >= dca_countof(dmix_table)) {
                    xll_err("Invalid downmix scale index");
                    return -DCADEC_EBADDATA;
                }
                int scale = dmix_table[index];
                scale_inv = dmix_table_inv[index - 40];
                chs->dmix_scale_cur[i] = (scale ^ sign) - sign;
                chs->dmix_scale_inv_cur[i] = (scale_inv ^ sign) - sign;
            } else {
                chs->dmix_scale_cur[i] = 0;
                chs->dmix_scale_inv_cur[i] = 0;
            }
        }

        // Downmix coefficients
        for (int j = 0; j < chs->nchannels; j++) {
            int code = bits_get(&xll->bits, 9);
            int sign = (code >> 8) - 1; code &= 0xff;
            if (code > 0) {
                unsigned int index = code - 1;
                if (index >= dca_countof(dmix_table)) {
                    xll_err("Invalid downmix coefficient index");
                    return -DCADEC_EBADDATA;
                }
                int coeff = dmix_table[index];
                if (!chs->primary_chset)
                    // Multiply by |InvDmixScale| to get |UndoDmixScale|
                    coeff = mul16(scale_inv, coeff);
                // Convert sign
                *coeff_ptr++ = (coeff ^ sign) - sign;
            } else {
                *coeff_ptr++ = 0;
            }
        }
    }