static int xwd_probe(AVProbeData *p) { const uint8_t *b = p->buf; unsigned width, bpp, bpad, lsize; if ( p->buf_size < XWD_HEADER_SIZE || AV_RB32(b ) < XWD_HEADER_SIZE // header size || AV_RB32(b + 4) != XWD_VERSION // version || AV_RB32(b + 8) != XWD_Z_PIXMAP // format || AV_RB32(b + 12) > 32 || !AV_RB32(b + 12) // depth || AV_RB32(b + 16) == 0 // width || AV_RB32(b + 20) == 0 // height || AV_RB32(b + 28) > 1 // byteorder || AV_RB32(b + 32) & ~56 || av_popcount(AV_RB32(b + 32)) != 1 // bitmap unit || AV_RB32(b + 36) > 1 // bitorder || AV_RB32(b + 40) & ~56 || av_popcount(AV_RB32(b + 40)) != 1 // padding || AV_RB32(b + 44) > 32 || !AV_RB32(b + 44) // bpp || AV_RB32(b + 68) > 256) // colours return 0; width = AV_RB32(b + 16); bpad = AV_RB32(b + 40); bpp = AV_RB32(b + 44); lsize = AV_RB32(b + 48); if (lsize < FFALIGN(width * bpp, bpad) >> 3) return 0; return AVPROBE_SCORE_MAX / 2 + 1; }
int CMixer::Mixing(float* pOutput, int out_samples, BYTE* pInput, int in_samples) { int in_ch = av_popcount(m_in_layout); int out_ch = av_popcount(m_out_layout); float* buf = NULL; if (m_in_avsf != m_in_avsf_used) { // need convert buf = new float[in_samples * in_ch]; convert_to_float(m_in_avsf, (WORD)in_ch, in_samples, pInput, buf); // convert to float pInput = (BYTE*)buf; } // int in_plane_size = in_samples * (av_sample_fmt_is_planar(in_avsf) ? 1 : in_ch) * av_get_bytes_per_sample(in_avsf); int in_plane_size = in_samples * in_ch * av_get_bytes_per_sample(m_in_avsf_used); int out_plane_size = out_samples * out_ch * sizeof(float); out_samples = avresample_convert(m_pAVRCxt, (uint8_t**)&pOutput, in_plane_size, out_samples, (uint8_t**)&pInput, out_plane_size, in_samples); if (buf) { delete [] buf; } if (out_samples < 0) { TRACE(_T("Mixer: avresample_convert failed\n")); return 0; } return out_samples; }
/** * Return the number of channels in an ExSS speaker mask (HD) */ static int dca_exss_mask2count(int mask) { /* count bits that mean speaker pairs twice */ return av_popcount(mask) + av_popcount(mask & (DCA_EXSS_CENTER_LEFT_RIGHT | DCA_EXSS_FRONT_LEFT_RIGHT | DCA_EXSS_FRONT_HIGH_LEFT_RIGHT | DCA_EXSS_WIDE_LEFT_RIGHT | DCA_EXSS_SIDE_LEFT_RIGHT | DCA_EXSS_SIDE_HIGH_LEFT_RIGHT | DCA_EXSS_SIDE_REAR_LEFT_RIGHT | DCA_EXSS_REAR_LEFT_RIGHT | DCA_EXSS_REAR_HIGH_LEFT_RIGHT)); }
void ff_dca_downmix_to_stereo_fixed(DCADSPContext *dcadsp, int32_t **samples, int *coeff_l, int nsamples, int ch_mask) { int pos, spkr, max_spkr = av_log2(ch_mask); int *coeff_r = coeff_l + av_popcount(ch_mask); av_assert0(DCA_HAS_STEREO(ch_mask)); // Scale left and right channels pos = (ch_mask & DCA_SPEAKER_MASK_C); dcadsp->dmix_scale(samples[DCA_SPEAKER_L], coeff_l[pos ], nsamples); dcadsp->dmix_scale(samples[DCA_SPEAKER_R], coeff_r[pos + 1], nsamples); // Downmix remaining channels for (spkr = 0; spkr <= max_spkr; spkr++) { if (!(ch_mask & (1U << spkr))) continue; if (*coeff_l && spkr != DCA_SPEAKER_L) dcadsp->dmix_add(samples[DCA_SPEAKER_L], samples[spkr], *coeff_l, nsamples); if (*coeff_r && spkr != DCA_SPEAKER_R) dcadsp->dmix_add(samples[DCA_SPEAKER_R], samples[spkr], *coeff_r, nsamples); coeff_l++; coeff_r++; } }
void ff_dca_downmix_to_stereo_float(AVFloatDSPContext *fdsp, float **samples, int *coeff_l, int nsamples, int ch_mask) { int pos, spkr, max_spkr = av_log2(ch_mask); int *coeff_r = coeff_l + av_popcount(ch_mask); const float scale = 1.0f / (1 << 15); av_assert0(DCA_HAS_STEREO(ch_mask)); // Scale left and right channels pos = (ch_mask & DCA_SPEAKER_MASK_C); fdsp->vector_fmul_scalar(samples[DCA_SPEAKER_L], samples[DCA_SPEAKER_L], coeff_l[pos ] * scale, nsamples); fdsp->vector_fmul_scalar(samples[DCA_SPEAKER_R], samples[DCA_SPEAKER_R], coeff_r[pos + 1] * scale, nsamples); // Downmix remaining channels for (spkr = 0; spkr <= max_spkr; spkr++) { if (!(ch_mask & (1U << spkr))) continue; if (*coeff_l && spkr != DCA_SPEAKER_L) fdsp->vector_fmac_scalar(samples[DCA_SPEAKER_L], samples[spkr], *coeff_l * scale, nsamples); if (*coeff_r && spkr != DCA_SPEAKER_R) fdsp->vector_fmac_scalar(samples[DCA_SPEAKER_R], samples[spkr], *coeff_r * scale, nsamples); coeff_l++; coeff_r++; } }
DWORD CAC3Encoder::SelectLayout(DWORD layout) { // check supported layouts if (m_pAVCodec && m_pAVCodec->channel_layouts) { for (size_t i = 0; m_pAVCodec->channel_layouts[i] != 0; i++) { if (layout == (DWORD)m_pAVCodec->channel_layouts[i]) { return layout; } } } // select the suitable format int channels = av_popcount(layout & ~AV_CH_LOW_FREQUENCY); // number of channels without lfe DWORD new_layout = layout & AV_CH_LOW_FREQUENCY; if (channels >= 5) { new_layout |= AV_CH_LAYOUT_5POINT0; } else if (channels == 4) { new_layout |= AV_CH_LAYOUT_QUAD; } else if (channels == 3) { new_layout |= AV_CH_LAYOUT_2_1; } else if (channels == 2) { new_layout |= AV_CH_LAYOUT_STEREO; } else if (channels == 1) { new_layout |= AV_CH_LAYOUT_MONO; } return new_layout; }
/** * Skip mixing coefficients of a single mix out configuration (HD) */ static void dca_exss_skip_mix_coeffs(GetBitContext *gb, int channels, int out_ch) { int i; for (i = 0; i < channels; i++) { int mix_map_mask = get_bits(gb, out_ch); int num_coeffs = av_popcount(mix_map_mask); skip_bits_long(gb, num_coeffs * 6); } }
int CMixer::Mixing(float* pOutput, int out_samples, BYTE* pInput, int in_samples) { int in_ch = av_popcount(m_in_layout); int out_ch = av_popcount(m_out_layout); int in_plane_nb = av_sample_fmt_is_planar(m_in_avsf) ? in_ch : 1; int in_plane_size = in_samples * (av_sample_fmt_is_planar(m_in_avsf) ? 1 : in_ch) * av_get_bytes_per_sample(m_in_avsf); static BYTE* ppInput[AVRESAMPLE_MAX_CHANNELS]; for (int i = 0; i < in_plane_nb; i++) { ppInput[i] = pInput + i * in_plane_size; } int out_plane_size = out_samples * out_ch * sizeof(float); out_samples = avresample_convert(m_pAVRCxt, (uint8_t**)&pOutput, out_plane_size, out_samples, ppInput, in_plane_size, in_samples); if (out_samples < 0) { TRACE(_T("Mixer: avresample_convert failed\n")); return 0; } return out_samples; }
bool CAC3Encoder::Init(int sample_rate, DWORD channel_layout) { StreamFinish(); int ret; m_pAVCtx = avcodec_alloc_context3(m_pAVCodec); m_pAVCtx->bit_rate = 640000; m_pAVCtx->sample_fmt = AV_SAMPLE_FMT_FLTP; m_pAVCtx->sample_rate = SelectSamplerate(sample_rate); m_pAVCtx->channel_layout = channel_layout; m_pAVCtx->channels = av_popcount(channel_layout); ret = avcodec_open2(m_pAVCtx, m_pAVCodec, NULL); if (ret < 0) { DbgLog((LOG_TRACE, 3, L"CAC3Encoder::Init() : avcodec_open2() failed")); return false; } m_pFrame = av_frame_alloc(); if (!m_pFrame) { DbgLog((LOG_TRACE, 3, L"CAC3Encoder::Init() : avcodec_alloc_frame() failed")); return false; } m_pFrame->nb_samples = m_pAVCtx->frame_size; m_pFrame->format = m_pAVCtx->sample_fmt; m_pFrame->channel_layout = m_pAVCtx->channel_layout; // the codec gives us the frame size, in samples, // we calculate the size of the samples buffer in bytes m_framesize = m_pAVCtx->frame_size * m_pAVCtx->channels * sizeof(float); m_buffersize = av_samples_get_buffer_size(NULL, m_pAVCtx->channels, m_pAVCtx->frame_size, m_pAVCtx->sample_fmt, 0); m_pSamples = (float*)av_malloc(m_buffersize); if (!m_pSamples) { DbgLog((LOG_TRACE, 3, L"CAC3Encoder::Init() : av_malloc(%d) failed", m_buffersize)); return false; } /* setup the data pointers in the AVFrame */ ret = avcodec_fill_audio_frame(m_pFrame, m_pAVCtx->channels, m_pAVCtx->sample_fmt, (const uint8_t*)m_pSamples, m_buffersize, 0); if (ret < 0) { DbgLog((LOG_TRACE, 3, L"CAC3Encoder::Init() : avcodec_fill_audio_frame() failed")); return false; } return true; }
static int pcx_probe(AVProbeData *p) { const uint8_t *b = p->buf; if ( p->buf_size < 128 || b[0] != 10 || b[1] > 5 || b[2] > 1 || av_popcount(b[3]) != 1 || b[3] > 8 || AV_RL16(&b[4]) > AV_RL16(&b[8]) || AV_RL16(&b[6]) > AV_RL16(&b[10]) || b[64]) return 0; b += 73; while (++b < p->buf + 128) if (*b) return AVPROBE_SCORE_EXTENSION / 4; return AVPROBE_SCORE_EXTENSION + 1; }
static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { AVFrame *frame = data; const uint8_t *buf = avpkt->data; const uint8_t *buf_end; int buf_size = avpkt->size; VmdAudioContext *s = avctx->priv_data; int block_type, silent_chunks, audio_chunks; int ret; uint8_t *output_samples_u8; int16_t *output_samples_s16; if (buf_size < 16) { av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n"); *got_frame_ptr = 0; return buf_size; } block_type = buf[6]; if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) { av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type); return AVERROR(EINVAL); } buf += 16; buf_size -= 16; /* get number of silent chunks */ silent_chunks = 0; if (block_type == BLOCK_TYPE_INITIAL) { uint32_t flags; if (buf_size < 4) { av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); return AVERROR(EINVAL); } flags = AV_RB32(buf); silent_chunks = av_popcount(flags); buf += 4; buf_size -= 4; } else if (block_type == BLOCK_TYPE_SILENCE) { silent_chunks = 1; buf_size = 0; // should already be zero but set it just to be sure } /* ensure output buffer is large enough */ audio_chunks = buf_size / s->chunk_size; /* drop incomplete chunks */ buf_size = audio_chunks * s->chunk_size; /* get output buffer */ frame->nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) / avctx->channels; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; output_samples_u8 = frame->data[0]; output_samples_s16 = (int16_t *)frame->data[0]; /* decode silent chunks */ if (silent_chunks > 0) { int silent_size = avctx->block_align * silent_chunks; av_assert0(avctx->block_align * silent_chunks <= frame->nb_samples * avctx->channels); if (s->out_bps == 2) { memset(output_samples_s16, 0x00, silent_size * 2); output_samples_s16 += silent_size; } else { memset(output_samples_u8, 0x80, silent_size); output_samples_u8 += silent_size; } } /* decode audio chunks */ if (audio_chunks > 0) { buf_end = buf + buf_size; av_assert0((buf_size & (avctx->channels > 1)) == 0); while (buf_end - buf >= s->chunk_size) { if (s->out_bps == 2) { decode_audio_s16(output_samples_s16, buf, s->chunk_size, avctx->channels); output_samples_s16 += avctx->block_align; } else { memcpy(output_samples_u8, buf, s->chunk_size); output_samples_u8 += avctx->block_align; } buf += s->chunk_size; } } *got_frame_ptr = 1; return avpkt->size; }
static int parse_descriptor(DCAExssParser *s, DCAExssAsset *asset) { int i, j, drc_present, descr_size, descr_pos = get_bits_count(&s->gb); // Size of audio asset descriptor in bytes descr_size = get_bits(&s->gb, 9) + 1; // Audio asset identifier asset->asset_index = get_bits(&s->gb, 3); // // Per stream static metadata // if (s->static_fields_present) { // Asset type descriptor presence if (get_bits1(&s->gb)) // Asset type descriptor skip_bits(&s->gb, 4); // Language descriptor presence if (get_bits1(&s->gb)) // Language descriptor skip_bits(&s->gb, 24); // Additional textual information presence if (get_bits1(&s->gb)) { // Byte size of additional text info int text_size = get_bits(&s->gb, 10) + 1; // Sanity check available size if (get_bits_left(&s->gb) < text_size * 8) return AVERROR_INVALIDDATA; // Additional textual information string skip_bits_long(&s->gb, text_size * 8); } // PCM bit resolution asset->pcm_bit_res = get_bits(&s->gb, 5) + 1; // Maximum sample rate asset->max_sample_rate = ff_dca_sampling_freqs[get_bits(&s->gb, 4)]; // Total number of channels asset->nchannels_total = get_bits(&s->gb, 8) + 1; // One to one map channel to speakers if (asset->one_to_one_map_ch_to_spkr = get_bits1(&s->gb)) { int spkr_mask_nbits = 0; int spkr_remap_nsets; int nspeakers[8]; // Embedded stereo flag asset->embedded_stereo = asset->nchannels_total > 2 && get_bits1(&s->gb); // Embedded 6 channels flag asset->embedded_6ch = asset->nchannels_total > 6 && get_bits1(&s->gb); // Speaker mask enabled flag if (asset->spkr_mask_enabled = get_bits1(&s->gb)) { // Number of bits for speaker activity mask spkr_mask_nbits = (get_bits(&s->gb, 2) + 1) << 2; // Loudspeaker activity mask asset->spkr_mask = get_bits(&s->gb, spkr_mask_nbits); } // Number of speaker remapping sets if ((spkr_remap_nsets = get_bits(&s->gb, 3)) && !spkr_mask_nbits) { av_log(s->avctx, AV_LOG_ERROR, "Speaker mask disabled yet there are remapping sets\n"); return AVERROR_INVALIDDATA; } // Standard loudspeaker layout mask for (i = 0; i < spkr_remap_nsets; i++) nspeakers[i] = ff_dca_count_chs_for_mask(get_bits(&s->gb, spkr_mask_nbits)); for (i = 0; i < spkr_remap_nsets; i++) { // Number of channels to be decoded for speaker remapping int nch_for_remaps = get_bits(&s->gb, 5) + 1; for (j = 0; j < nspeakers[i]; j++) { // Decoded channels to output speaker mapping mask int remap_ch_mask = get_bits_long(&s->gb, nch_for_remaps); // Loudspeaker remapping codes skip_bits_long(&s->gb, av_popcount(remap_ch_mask) * 5); } } } else { asset->embedded_stereo = 0; asset->embedded_6ch = 0; asset->spkr_mask_enabled = 0; asset->spkr_mask = 0; // Representation type asset->representation_type = get_bits(&s->gb, 3); } } // // DRC, DNC and mixing metadata // // Dynamic range coefficient presence flag drc_present = get_bits1(&s->gb); // Code for dynamic range coefficient if (drc_present) skip_bits(&s->gb, 8); // Dialog normalization presence flag if (get_bits1(&s->gb)) // Dialog normalization code skip_bits(&s->gb, 5); // DRC for stereo downmix if (drc_present && asset->embedded_stereo) skip_bits(&s->gb, 8); // Mixing metadata presence flag if (s->mix_metadata_enabled && get_bits1(&s->gb)) { int nchannels_dmix; // External mixing flag skip_bits1(&s->gb); // Post mixing / replacement gain adjustment skip_bits(&s->gb, 6); // DRC prior to mixing if (get_bits(&s->gb, 2) == 3) // Custom code for mixing DRC skip_bits(&s->gb, 8); else // Limit for mixing DRC skip_bits(&s->gb, 3); // Scaling type for channels of main audio // Scaling parameters of main audio if (get_bits1(&s->gb)) for (i = 0; i < s->nmixoutconfigs; i++) skip_bits_long(&s->gb, 6 * s->nmixoutchs[i]); else skip_bits_long(&s->gb, 6 * s->nmixoutconfigs); nchannels_dmix = asset->nchannels_total; if (asset->embedded_6ch) nchannels_dmix += 6; if (asset->embedded_stereo) nchannels_dmix += 2; for (i = 0; i < s->nmixoutconfigs; i++) { if (!s->nmixoutchs[i]) { av_log(s->avctx, AV_LOG_ERROR, "Invalid speaker layout mask for mixing configuration\n"); return AVERROR_INVALIDDATA; } for (j = 0; j < nchannels_dmix; j++) { // Mix output mask int mix_map_mask = get_bits(&s->gb, s->nmixoutchs[i]); // Mixing coefficients skip_bits_long(&s->gb, av_popcount(mix_map_mask) * 6); } } } // // Decoder navigation data // // Coding mode for the asset asset->coding_mode = get_bits(&s->gb, 2); // Coding components used in asset switch (asset->coding_mode) { case 0: // Coding mode that may contain multiple coding components asset->extension_mask = get_bits(&s->gb, 12); if (asset->extension_mask & DCA_EXSS_CORE) { // Size of core component in extension substream asset->core_size = get_bits(&s->gb, 14) + 1; // Core sync word present flag if (get_bits1(&s->gb)) // Core sync distance skip_bits(&s->gb, 2); } if (asset->extension_mask & DCA_EXSS_XBR) // Size of XBR extension in extension substream asset->xbr_size = get_bits(&s->gb, 14) + 1; if (asset->extension_mask & DCA_EXSS_XXCH) // Size of XXCH extension in extension substream asset->xxch_size = get_bits(&s->gb, 14) + 1; if (asset->extension_mask & DCA_EXSS_X96) // Size of X96 extension in extension substream asset->x96_size = get_bits(&s->gb, 12) + 1; if (asset->extension_mask & DCA_EXSS_LBR) parse_lbr_parameters(s, asset); if (asset->extension_mask & DCA_EXSS_XLL) parse_xll_parameters(s, asset); if (asset->extension_mask & DCA_EXSS_RSV1) skip_bits(&s->gb, 16); if (asset->extension_mask & DCA_EXSS_RSV2) skip_bits(&s->gb, 16); break; case 1: // Loss-less coding mode without CBR component asset->extension_mask = DCA_EXSS_XLL; parse_xll_parameters(s, asset); break; case 2: // Low bit rate mode asset->extension_mask = DCA_EXSS_LBR; parse_lbr_parameters(s, asset); break; case 3: // Auxiliary coding mode asset->extension_mask = 0; // Size of auxiliary coded data skip_bits(&s->gb, 14); // Auxiliary codec identification skip_bits(&s->gb, 8); // Aux sync word present flag if (get_bits1(&s->gb)) // Aux sync distance skip_bits(&s->gb, 3); break; } if (asset->extension_mask & DCA_EXSS_XLL) // DTS-HD stream ID asset->hd_stream_id = get_bits(&s->gb, 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 (ff_dca_seek_bits(&s->gb, descr_pos + descr_size * 8)) { av_log(s->avctx, AV_LOG_ERROR, "Read past end of EXSS asset descriptor\n"); return AVERROR_INVALIDDATA; } return 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; }
/** * Parse extension substream asset header (HD) */ static int dca_exss_parse_asset_header(DCAContext *s) { int header_pos = get_bits_count(&s->gb); int header_size; int channels = 0; int embedded_stereo = 0; int embedded_6ch = 0; int drc_code_present; int extensions_mask = 0; int i, j; if (get_bits_left(&s->gb) < 16) return AVERROR_INVALIDDATA; /* We will parse just enough to get to the extensions bitmask with which * we can set the profile value. */ header_size = get_bits(&s->gb, 9) + 1; skip_bits(&s->gb, 3); // asset index if (s->static_fields) { if (get_bits1(&s->gb)) skip_bits(&s->gb, 4); // asset type descriptor if (get_bits1(&s->gb)) skip_bits_long(&s->gb, 24); // language descriptor if (get_bits1(&s->gb)) { /* How can one fit 1024 bytes of text here if the maximum value * for the asset header size field above was 512 bytes? */ int text_length = get_bits(&s->gb, 10) + 1; if (get_bits_left(&s->gb) < text_length * 8) return AVERROR_INVALIDDATA; skip_bits_long(&s->gb, text_length * 8); // info text } skip_bits(&s->gb, 5); // bit resolution - 1 skip_bits(&s->gb, 4); // max sample rate code channels = get_bits(&s->gb, 8) + 1; if (get_bits1(&s->gb)) { // 1-to-1 channels to speakers int spkr_remap_sets; int spkr_mask_size = 16; int num_spkrs[7]; if (channels > 2) embedded_stereo = get_bits1(&s->gb); if (channels > 6) embedded_6ch = get_bits1(&s->gb); if (get_bits1(&s->gb)) { spkr_mask_size = (get_bits(&s->gb, 2) + 1) << 2; skip_bits(&s->gb, spkr_mask_size); // spkr activity mask } spkr_remap_sets = get_bits(&s->gb, 3); for (i = 0; i < spkr_remap_sets; i++) { /* std layout mask for each remap set */ num_spkrs[i] = dca_exss_mask2count(get_bits(&s->gb, spkr_mask_size)); } for (i = 0; i < spkr_remap_sets; i++) { int num_dec_ch_remaps = get_bits(&s->gb, 5) + 1; if (get_bits_left(&s->gb) < 0) return AVERROR_INVALIDDATA; for (j = 0; j < num_spkrs[i]; j++) { int remap_dec_ch_mask = get_bits_long(&s->gb, num_dec_ch_remaps); int num_dec_ch = av_popcount(remap_dec_ch_mask); skip_bits_long(&s->gb, num_dec_ch * 5); // remap codes } } } else { skip_bits(&s->gb, 3); // representation type } } drc_code_present = get_bits1(&s->gb); if (drc_code_present) get_bits(&s->gb, 8); // drc code if (get_bits1(&s->gb)) skip_bits(&s->gb, 5); // dialog normalization code if (drc_code_present && embedded_stereo) get_bits(&s->gb, 8); // drc stereo code if (s->mix_metadata && get_bits1(&s->gb)) { skip_bits(&s->gb, 1); // external mix skip_bits(&s->gb, 6); // post mix gain code if (get_bits(&s->gb, 2) != 3) // mixer drc code skip_bits(&s->gb, 3); // drc limit else skip_bits(&s->gb, 8); // custom drc code if (get_bits1(&s->gb)) // channel specific scaling for (i = 0; i < s->num_mix_configs; i++) skip_bits_long(&s->gb, s->mix_config_num_ch[i] * 6); // scale codes else skip_bits_long(&s->gb, s->num_mix_configs * 6); // scale codes for (i = 0; i < s->num_mix_configs; i++) { if (get_bits_left(&s->gb) < 0) return AVERROR_INVALIDDATA; dca_exss_skip_mix_coeffs(&s->gb, channels, s->mix_config_num_ch[i]); if (embedded_6ch) dca_exss_skip_mix_coeffs(&s->gb, 6, s->mix_config_num_ch[i]); if (embedded_stereo) dca_exss_skip_mix_coeffs(&s->gb, 2, s->mix_config_num_ch[i]); } } switch (get_bits(&s->gb, 2)) { case 0: extensions_mask = get_bits(&s->gb, 12); break; case 1: extensions_mask = DCA_EXT_EXSS_XLL; break; case 2: extensions_mask = DCA_EXT_EXSS_LBR; break; case 3: extensions_mask = 0; /* aux coding */ break; } /* not parsed further, we were only interested in the extensions mask */ if (get_bits_left(&s->gb) < 0) return AVERROR_INVALIDDATA; if (get_bits_count(&s->gb) - header_pos > header_size * 8) { av_log(s->avctx, AV_LOG_WARNING, "Asset header size mismatch.\n"); return AVERROR_INVALIDDATA; } skip_bits_long(&s->gb, header_pos + header_size * 8 - get_bits_count(&s->gb)); if (extensions_mask & DCA_EXT_EXSS_XLL) s->profile = FF_PROFILE_DTS_HD_MA; else if (extensions_mask & (DCA_EXT_EXSS_XBR | DCA_EXT_EXSS_X96 | DCA_EXT_EXSS_XXCH)) s->profile = FF_PROFILE_DTS_HD_HRA; if (!(extensions_mask & DCA_EXT_CORE)) av_log(s->avctx, AV_LOG_WARNING, "DTS core detection mismatch.\n"); if ((extensions_mask & DCA_CORE_EXTS) != s->core_ext_mask) av_log(s->avctx, AV_LOG_WARNING, "DTS extensions detection mismatch (%d, %d)\n", extensions_mask & DCA_CORE_EXTS, s->core_ext_mask); return 0; }
void CMixer::Init(AVSampleFormat in_avsf, DWORD in_layout, DWORD out_layout, int in_samplerate, int out_samplerate) { // reset parameters m_in_avsf = AV_SAMPLE_FMT_NONE; m_in_layout = 0; m_out_layout = 0; m_in_samplerate = 0; m_out_samplerate = 0; av_free(m_matrix_dbl); // Close Resample Context avresample_close(m_pAVRCxt); if (in_avsf >= AV_SAMPLE_FMT_U8P && in_avsf <= AV_SAMPLE_FMT_DBLP) { // planar audio is not supported (ffmpeg crashed) m_in_avsf_used = AV_SAMPLE_FMT_FLT; // convert to float } else { m_in_avsf_used = in_avsf; } int ret = 0; // Set options av_opt_set_int(m_pAVRCxt, "in_sample_fmt", m_in_avsf_used, 0); av_opt_set_int(m_pAVRCxt, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); // forced float output av_opt_set_int(m_pAVRCxt, "in_channel_layout", in_layout, 0); av_opt_set_int(m_pAVRCxt, "out_channel_layout", out_layout, 0); av_opt_set_int(m_pAVRCxt, "in_sample_rate", in_samplerate, 0); av_opt_set_int(m_pAVRCxt, "out_sample_rate", out_samplerate, 0); // Open Resample Context ret = avresample_open(m_pAVRCxt); if (ret < 0) { TRACE(_T("Mixer: avresample_open failed\n")); return; } // Create Matrix int in_ch = av_popcount(in_layout); int out_ch = av_popcount(out_layout); m_matrix_dbl = (double*)av_mallocz(in_ch * out_ch * sizeof(*m_matrix_dbl)); // expand stereo if (in_layout == AV_CH_LAYOUT_STEREO && (out_layout == AV_CH_LAYOUT_QUAD || out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1)) { m_matrix_dbl[0] = 1.0; m_matrix_dbl[1] = 0.0; m_matrix_dbl[2] = 0.0; m_matrix_dbl[3] = 1.0; if (out_layout == AV_CH_LAYOUT_QUAD) { m_matrix_dbl[4] = 0.6666; m_matrix_dbl[5] = (-0.2222); m_matrix_dbl[6] = (-0.2222); m_matrix_dbl[7] = 0.6666; } else if (out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1) { m_matrix_dbl[4] = 0.5; m_matrix_dbl[5] = 0.5; m_matrix_dbl[6] = 0.0; m_matrix_dbl[7] = 0.0; m_matrix_dbl[8] = 0.6666; m_matrix_dbl[9] = (-0.2222); m_matrix_dbl[10] = (-0.2222); m_matrix_dbl[11] = 0.6666; if (out_layout == AV_CH_LAYOUT_7POINT1) { m_matrix_dbl[12] = 0.6666; m_matrix_dbl[13] = (-0.2222); m_matrix_dbl[14] = (-0.2222); m_matrix_dbl[15] = 0.6666; } } } else { const double center_mix_level = M_SQRT1_2; const double surround_mix_level = M_SQRT1_2; const double lfe_mix_level = M_SQRT1_2; const int normalize = 0; ret = avresample_build_matrix(in_layout, out_layout, center_mix_level, surround_mix_level, lfe_mix_level, normalize, m_matrix_dbl, in_ch, AV_MATRIX_ENCODING_NONE); if (ret < 0) { TRACE(_T("Mixer: avresample_build_matrix failed\n")); av_free(m_matrix_dbl); return; } } #ifdef _DEBUG CString matrix_str; for (int j = 0; j < out_ch; j++) { matrix_str.AppendFormat(_T("%d:"), j + 1); for (int i = 0; i < in_ch; i++) { double k = m_matrix_dbl[j * in_ch + i]; matrix_str.AppendFormat(_T(" %.4f"), k); } matrix_str += _T("\n"); } TRACE(matrix_str); #endif // Set Matrix on the context ret = avresample_set_matrix(m_pAVRCxt, m_matrix_dbl, in_ch); if (ret < 0) { TRACE(_T("Mixer: avresample_set_matrix failed\n")); av_free(m_matrix_dbl); return; } m_in_avsf = in_avsf; m_in_layout = in_layout; m_out_layout = out_layout; m_in_samplerate = in_samplerate; m_out_samplerate = out_samplerate; }
void CMixer::Init(DWORD out_layout, DWORD in_layout, enum AVSampleFormat in_sf) { avresample_free(&m_pAVRCxt); int ret = 0; // Allocate Resample Context and set options. m_pAVRCxt = avresample_alloc_context(); av_opt_set_int(m_pAVRCxt, "in_channel_layout", in_layout, 0); av_opt_set_int(m_pAVRCxt, "in_sample_fmt", in_sf, 0); av_opt_set_int(m_pAVRCxt, "out_channel_layout", out_layout, 0); av_opt_set_int(m_pAVRCxt, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); // forced float output // Open Resample Context ret = avresample_open(m_pAVRCxt); if (ret < 0) { TRACE(_T("Mixer: avresample_open failed\n")); avresample_free(&m_pAVRCxt); return; } // Create Matrix int in_ch = av_popcount(in_layout); int out_ch = av_popcount(out_layout); double* matrix_dbl = (double*)av_mallocz(in_ch * out_ch * sizeof(*matrix_dbl)); // expand stereo if (in_layout == AV_CH_LAYOUT_STEREO && (out_layout == AV_CH_LAYOUT_QUAD || out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1)) { matrix_dbl[0] = 1.0; matrix_dbl[1] = 0.0; matrix_dbl[2] = 0.0; matrix_dbl[3] = 1.0; if (out_layout == AV_CH_LAYOUT_QUAD) { matrix_dbl[4] = 0.5; matrix_dbl[5] = (-0.5); matrix_dbl[6] = (-0.5); matrix_dbl[7] = 0.5; } else if (out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1) { matrix_dbl[4] = 0.5; matrix_dbl[5] = 0.5; matrix_dbl[6] = 0.0; matrix_dbl[7] = 0.0; matrix_dbl[8] = 0.5; matrix_dbl[9] = (-0.5); matrix_dbl[10] = (-0.5); matrix_dbl[11] = 0.5; if (out_layout == AV_CH_LAYOUT_7POINT1) { matrix_dbl[12] = 0.5; matrix_dbl[13] = (-0.5); matrix_dbl[14] = (-0.5); matrix_dbl[15] = 0.5; } } } else { const double center_mix_level = M_SQRT1_2; const double surround_mix_level = M_SQRT1_2; const double lfe_mix_level = M_SQRT1_2; const int normalize = 0; ret = avresample_build_matrix(in_layout, out_layout, center_mix_level, surround_mix_level, lfe_mix_level, normalize, matrix_dbl, in_ch, AV_MATRIX_ENCODING_NONE); if (ret < 0) { TRACE(_T("Mixer: avresample_build_matrix failed\n")); av_free(matrix_dbl); avresample_free(&m_pAVRCxt); return; } } #ifdef _DEBUG CString matrix_str; for (int j = 0; j < out_ch; j++) { matrix_str.AppendFormat(_T("%d:"), j + 1); for (int i = 0; i < in_ch; i++) { double k = matrix_dbl[j * in_ch + i]; matrix_str.AppendFormat(_T(" %.4f"), k); } matrix_str += _T("\n"); } TRACE(matrix_str); #endif // Set Matrix on the context ret = avresample_set_matrix(m_pAVRCxt, matrix_dbl, in_ch); av_free(matrix_dbl); if (ret < 0) { TRACE(_T("Mixer: avresample_set_matrix failed\n")); avresample_free(&m_pAVRCxt); return; } last_in_layout = in_layout; last_out_layout = out_layout; last_in_sf = in_sf; }
void CMixer::Init(AVSampleFormat in_avsf, DWORD in_layout, DWORD out_layout, float matrix_norm, int in_samplerate, int out_samplerate) { // reset parameters m_in_avsf = AV_SAMPLE_FMT_NONE; m_in_layout = 0; m_out_layout = 0; m_matrix_norm = 0.0f; m_in_samplerate = 0; m_out_samplerate = 0; av_free(m_matrix_dbl); // Close Resample Context avresample_close(m_pAVRCxt); int ret = 0; // Set options av_opt_set_int(m_pAVRCxt, "in_sample_fmt", in_avsf, 0); av_opt_set_int(m_pAVRCxt, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); // forced float output av_opt_set_int(m_pAVRCxt, "in_channel_layout", in_layout, 0); av_opt_set_int(m_pAVRCxt, "out_channel_layout", out_layout, 0); av_opt_set_int(m_pAVRCxt, "in_sample_rate", in_samplerate, 0); av_opt_set_int(m_pAVRCxt, "out_sample_rate", out_samplerate, 0); // Open Resample Context ret = avresample_open(m_pAVRCxt); if (ret < 0) { TRACE(_T("Mixer: avresample_open failed\n")); return; } // Create Matrix int in_ch = av_popcount(in_layout); int out_ch = av_popcount(out_layout); m_matrix_dbl = (double*)av_mallocz(in_ch * out_ch * sizeof(*m_matrix_dbl)); // expand stereo if (in_layout == AV_CH_LAYOUT_STEREO && (out_layout == AV_CH_LAYOUT_QUAD || out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1)) { m_matrix_dbl[0] = 1.0; m_matrix_dbl[1] = 0.0; m_matrix_dbl[2] = 0.0; m_matrix_dbl[3] = 1.0; if (out_layout == AV_CH_LAYOUT_QUAD) { m_matrix_dbl[4] = 0.6666; m_matrix_dbl[5] = (-0.2222); m_matrix_dbl[6] = (-0.2222); m_matrix_dbl[7] = 0.6666; } else if (out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1) { m_matrix_dbl[4] = 0.5; m_matrix_dbl[5] = 0.5; m_matrix_dbl[6] = 0.0; m_matrix_dbl[7] = 0.0; m_matrix_dbl[8] = 0.6666; m_matrix_dbl[9] = (-0.2222); m_matrix_dbl[10] = (-0.2222); m_matrix_dbl[11] = 0.6666; if (out_layout == AV_CH_LAYOUT_7POINT1) { m_matrix_dbl[12] = 0.6666; m_matrix_dbl[13] = (-0.2222); m_matrix_dbl[14] = (-0.2222); m_matrix_dbl[15] = 0.6666; } } } else { const double center_mix_level = M_SQRT1_2; const double surround_mix_level = 1.0; const double lfe_mix_level = 1.0; const int normalize = 0; ret = avresample_build_matrix(in_layout, out_layout, center_mix_level, surround_mix_level, lfe_mix_level, normalize, m_matrix_dbl, in_ch, AV_MATRIX_ENCODING_NONE); if (ret < 0) { TRACE(_T("Mixer: avresample_build_matrix failed\n")); av_free(m_matrix_dbl); return; } // if back channels do not have sound, then divide side channels for the back and side if (out_layout == AV_CH_LAYOUT_7POINT1) { bool back_no_sound = true; for (int i = 0; i < in_ch * 2; i++) { if (m_matrix_dbl[4 * in_ch + i] != 0.0) { back_no_sound = false; } } if (back_no_sound) { for (int i = 0; i < in_ch * 2; i++) { m_matrix_dbl[4 * in_ch + i] = (m_matrix_dbl[6 * in_ch + i] *= M_SQRT1_2); } } } } if (matrix_norm > 0.0f && matrix_norm <= 1.0f) { // 0.0 - normalize off; 1.0 - full normalize matrix double max_peak = 0; for (int j = 0; j < out_ch; j++) { double peak = 0; for (int i = 0; i < in_ch; i++) { peak += fabs(m_matrix_dbl[j * in_ch + i]); } if (peak > max_peak) { max_peak = peak; } } if (max_peak > 1.0) { double g = ((max_peak - 1.0) * (1.0 - matrix_norm) + 1.0) / max_peak; for (int i = 0, n = in_ch * out_ch; i < n; i++) { m_matrix_dbl[i] *= g; } } } #ifdef _DEBUG CString matrix_str = _T("matrix:\n"); for (int j = 0; j < out_ch; j++) { matrix_str.AppendFormat(_T("%d:"), j + 1); for (int i = 0; i < in_ch; i++) { double k = m_matrix_dbl[j * in_ch + i]; matrix_str.AppendFormat(_T(" %.4f"), k); } matrix_str += _T("\n"); } TRACE(matrix_str); #endif // Set Matrix on the context ret = avresample_set_matrix(m_pAVRCxt, m_matrix_dbl, in_ch); if (ret < 0) { TRACE(_T("Mixer: avresample_set_matrix failed\n")); av_free(m_matrix_dbl); return; } m_in_avsf = in_avsf; m_in_layout = in_layout; m_out_layout = out_layout; m_matrix_norm = matrix_norm; m_in_samplerate = in_samplerate; m_out_samplerate = out_samplerate; }