diff options
author | Paul B Mahol <onemda@gmail.com> | 2021-09-30 14:18:22 +0200 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2021-10-03 11:42:15 +0200 |
commit | f282c34c009e3653ec160c3880e64fc1a9300d0e (patch) | |
tree | 0c49a392a4477e8a7dcbd3fb0f5be7bf76162337 /libavcodec/amrwbdec.c | |
parent | e26c4d252faff4f7b1bf3087f609b699f20b47d3 (diff) | |
download | ffmpeg-f282c34c009e3653ec160c3880e64fc1a9300d0e.tar.gz |
avcodec/amr*dec: add multichannel support
Diffstat (limited to 'libavcodec/amrwbdec.c')
-rw-r--r-- | libavcodec/amrwbdec.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/libavcodec/amrwbdec.c b/libavcodec/amrwbdec.c index a6c1d894d7..998dd82791 100644 --- a/libavcodec/amrwbdec.c +++ b/libavcodec/amrwbdec.c @@ -93,21 +93,30 @@ typedef struct AMRWBContext { } AMRWBContext; +typedef struct AMRWBChannelsContext { + AMRWBContext ch[2]; +} AMRWBChannelsContext; + static av_cold int amrwb_decode_init(AVCodecContext *avctx) { - AMRWBContext *ctx = avctx->priv_data; + AMRWBChannelsContext *s = avctx->priv_data; int i; - if (avctx->channels > 1) { - avpriv_report_missing_feature(avctx, "multi-channel AMR"); + if (avctx->channels > 2) { + avpriv_report_missing_feature(avctx, ">2 channel AMR"); return AVERROR_PATCHWELCOME; } - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + if (!avctx->channels) { + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + } if (!avctx->sample_rate) avctx->sample_rate = 16000; - avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + for (int ch = 0; ch < avctx->channels; ch++) { + AMRWBContext *ctx = &s->ch[ch]; av_lfg_init(&ctx->prng, 1); @@ -124,6 +133,7 @@ static av_cold int amrwb_decode_init(AVCodecContext *avctx) ff_acelp_vectors_init(&ctx->acelpv_ctx); ff_celp_filter_init(&ctx->celpf_ctx); ff_celp_math_init(&ctx->celpm_ctx); + } return 0; } @@ -1094,13 +1104,21 @@ static void update_sub_state(AMRWBContext *ctx) static int amrwb_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { - AMRWBContext *ctx = avctx->priv_data; + AMRWBChannelsContext *s = avctx->priv_data; AVFrame *frame = data; - AMRWBFrame *cf = &ctx->frame; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; + int sub, i, ret; + + /* get output buffer */ + frame->nb_samples = 4 * AMRWB_SFR_SIZE_16k; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (int ch = 0; ch < avctx->channels; ch++) { + AMRWBContext *ctx = &s->ch[ch]; + AMRWBFrame *cf = &ctx->frame; int expected_fr_size, header_size; - float *buf_out; float spare_vector[AMRWB_SFR_SIZE]; // extra stack space to hold result from anti-sparseness processing float fixed_gain_factor; // fixed gain correction factor (gamma) float *synth_fixed_vector; // pointer to the fixed vector that synthesis should use @@ -1110,13 +1128,7 @@ static int amrwb_decode_frame(AVCodecContext *avctx, void *data, float hb_exc[AMRWB_SFR_SIZE_16k]; // excitation for the high frequency band float hb_samples[AMRWB_SFR_SIZE_16k]; // filtered high-band samples from synthesis float hb_gain; - int sub, i, ret; - - /* get output buffer */ - frame->nb_samples = 4 * AMRWB_SFR_SIZE_16k; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - buf_out = (float *)frame->data[0]; + float *buf_out = (float *)frame->extended_data[ch]; header_size = decode_mime_header(ctx, buf); expected_fr_size = ((cf_sizes_wb[ctx->fr_cur_mode] + 7) >> 3) + 1; @@ -1127,9 +1139,10 @@ static int amrwb_decode_frame(AVCodecContext *avctx, void *data, if (ctx->fr_cur_mode == NO_DATA || !ctx->fr_quality) { /* The specification suggests a "random signal" and "a muting technique" to "gradually decrease the output level". */ - av_samples_set_silence(&frame->data[0], 0, frame->nb_samples, 1, AV_SAMPLE_FMT_FLT); - *got_frame_ptr = 1; - return expected_fr_size; + av_samples_set_silence(&frame->extended_data[ch], 0, frame->nb_samples, 1, AV_SAMPLE_FMT_FLT); + buf += expected_fr_size; + buf_size -= expected_fr_size; + continue; } if (ctx->fr_cur_mode > MODE_SID) { av_log(avctx, AV_LOG_ERROR, @@ -1270,9 +1283,13 @@ static int amrwb_decode_frame(AVCodecContext *avctx, void *data, memcpy(ctx->isp_sub4_past, ctx->isp[3], LP_ORDER * sizeof(ctx->isp[3][0])); memcpy(ctx->isf_past_final, ctx->isf_cur, LP_ORDER * sizeof(float)); + buf += expected_fr_size; + buf_size -= expected_fr_size; + } + *got_frame_ptr = 1; - return expected_fr_size; + return avpkt->size; } const AVCodec ff_amrwb_decoder = { @@ -1280,7 +1297,7 @@ const AVCodec ff_amrwb_decoder = { .long_name = NULL_IF_CONFIG_SMALL("AMR-WB (Adaptive Multi-Rate WideBand)"), .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_AMR_WB, - .priv_data_size = sizeof(AMRWBContext), + .priv_data_size = sizeof(AMRWBChannelsContext), .init = amrwb_decode_init, .decode = amrwb_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, |