diff options
author | Lynne <dev@lynne.ee> | 2024-03-16 23:34:46 +0100 |
---|---|---|
committer | Lynne <dev@lynne.ee> | 2024-04-23 08:31:39 +0200 |
commit | ce740618d194e6c8523466ba15be2d662da37105 (patch) | |
tree | ebf6e6809f3277426be16510b5cf0467b1005612 /libavcodec/aacdec.c | |
parent | e93793bf3cf15968c34b0e7bf0c677fad3032f5d (diff) | |
download | ffmpeg-ce740618d194e6c8523466ba15be2d662da37105.tar.gz |
aacdec: move LATM decode functions into a separate file
Diffstat (limited to 'libavcodec/aacdec.c')
-rw-r--r-- | libavcodec/aacdec.c | 315 |
1 files changed, 1 insertions, 314 deletions
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index 1e7bdb6416..bf1b1c29c7 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -65,296 +65,7 @@ #include "aacdec_template.c" -#define LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word - -struct LATMContext { - AACDecContext aac_ctx; ///< containing AACContext - int initialized; ///< initialized after a valid extradata was seen - - // parser data - int audio_mux_version_A; ///< LATM syntax version - int frame_length_type; ///< 0/1 variable/fixed frame length - int frame_length; ///< frame length for fixed frame length -}; - -static inline uint32_t latm_get_value(GetBitContext *b) -{ - int length = get_bits(b, 2); - - return get_bits_long(b, (length+1)*8); -} - -static int latm_decode_audio_specific_config(struct LATMContext *latmctx, - GetBitContext *gb, int asclen) -{ - AACDecContext *ac = &latmctx->aac_ctx; - AVCodecContext *avctx = ac->avctx; - MPEG4AudioConfig m4ac = { 0 }; - GetBitContext gbc; - int config_start_bit = get_bits_count(gb); - int sync_extension = 0; - int bits_consumed, esize, i; - - if (asclen > 0) { - sync_extension = 1; - asclen = FFMIN(asclen, get_bits_left(gb)); - init_get_bits(&gbc, gb->buffer, config_start_bit + asclen); - skip_bits_long(&gbc, config_start_bit); - } else if (asclen == 0) { - gbc = *gb; - } else { - return AVERROR_INVALIDDATA; - } - - if (get_bits_left(gb) <= 0) - return AVERROR_INVALIDDATA; - - bits_consumed = decode_audio_specific_config_gb(NULL, avctx, &m4ac, - &gbc, config_start_bit, - sync_extension); - - if (bits_consumed < config_start_bit) - return AVERROR_INVALIDDATA; - bits_consumed -= config_start_bit; - - if (asclen == 0) - asclen = bits_consumed; - - if (!latmctx->initialized || - ac->oc[1].m4ac.sample_rate != m4ac.sample_rate || - ac->oc[1].m4ac.chan_config != m4ac.chan_config) { - - if (latmctx->initialized) { - av_log(avctx, AV_LOG_INFO, "audio config changed (sample_rate=%d, chan_config=%d)\n", m4ac.sample_rate, m4ac.chan_config); - } else { - av_log(avctx, AV_LOG_DEBUG, "initializing latmctx\n"); - } - latmctx->initialized = 0; - - esize = (asclen + 7) / 8; - - if (avctx->extradata_size < esize) { - av_free(avctx->extradata); - avctx->extradata = av_malloc(esize + AV_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) - return AVERROR(ENOMEM); - } - - avctx->extradata_size = esize; - gbc = *gb; - for (i = 0; i < esize; i++) { - avctx->extradata[i] = get_bits(&gbc, 8); - } - memset(avctx->extradata+esize, 0, AV_INPUT_BUFFER_PADDING_SIZE); - } - skip_bits_long(gb, asclen); - - return 0; -} - -static int read_stream_mux_config(struct LATMContext *latmctx, - GetBitContext *gb) -{ - int ret, audio_mux_version = get_bits(gb, 1); - - latmctx->audio_mux_version_A = 0; - if (audio_mux_version) - latmctx->audio_mux_version_A = get_bits(gb, 1); - - if (!latmctx->audio_mux_version_A) { - - if (audio_mux_version) - latm_get_value(gb); // taraFullness - - skip_bits(gb, 1); // allStreamSameTimeFraming - skip_bits(gb, 6); // numSubFrames - // numPrograms - if (get_bits(gb, 4)) { // numPrograms - avpriv_request_sample(latmctx->aac_ctx.avctx, "Multiple programs"); - return AVERROR_PATCHWELCOME; - } - - // for each program (which there is only one in DVB) - - // for each layer (which there is only one in DVB) - if (get_bits(gb, 3)) { // numLayer - avpriv_request_sample(latmctx->aac_ctx.avctx, "Multiple layers"); - return AVERROR_PATCHWELCOME; - } - - // for all but first stream: use_same_config = get_bits(gb, 1); - if (!audio_mux_version) { - if ((ret = latm_decode_audio_specific_config(latmctx, gb, 0)) < 0) - return ret; - } else { - int ascLen = latm_get_value(gb); - if ((ret = latm_decode_audio_specific_config(latmctx, gb, ascLen)) < 0) - return ret; - } - - latmctx->frame_length_type = get_bits(gb, 3); - switch (latmctx->frame_length_type) { - case 0: - skip_bits(gb, 8); // latmBufferFullness - break; - case 1: - latmctx->frame_length = get_bits(gb, 9); - break; - case 3: - case 4: - case 5: - skip_bits(gb, 6); // CELP frame length table index - break; - case 6: - case 7: - skip_bits(gb, 1); // HVXC frame length table index - break; - } - - if (get_bits(gb, 1)) { // other data - if (audio_mux_version) { - latm_get_value(gb); // other_data_bits - } else { - int esc; - do { - if (get_bits_left(gb) < 9) - return AVERROR_INVALIDDATA; - esc = get_bits(gb, 1); - skip_bits(gb, 8); - } while (esc); - } - } - - if (get_bits(gb, 1)) // crc present - skip_bits(gb, 8); // config_crc - } - - return 0; -} - -static int read_payload_length_info(struct LATMContext *ctx, GetBitContext *gb) -{ - uint8_t tmp; - - if (ctx->frame_length_type == 0) { - int mux_slot_length = 0; - do { - if (get_bits_left(gb) < 8) - return AVERROR_INVALIDDATA; - tmp = get_bits(gb, 8); - mux_slot_length += tmp; - } while (tmp == 255); - return mux_slot_length; - } else if (ctx->frame_length_type == 1) { - return ctx->frame_length; - } else if (ctx->frame_length_type == 3 || - ctx->frame_length_type == 5 || - ctx->frame_length_type == 7) { - skip_bits(gb, 2); // mux_slot_length_coded - } - return 0; -} - -static int read_audio_mux_element(struct LATMContext *latmctx, - GetBitContext *gb) -{ - int err; - uint8_t use_same_mux = get_bits(gb, 1); - if (!use_same_mux) { - if ((err = read_stream_mux_config(latmctx, gb)) < 0) - return err; - } else if (!latmctx->aac_ctx.avctx->extradata) { - av_log(latmctx->aac_ctx.avctx, AV_LOG_DEBUG, - "no decoder config found\n"); - return 1; - } - if (latmctx->audio_mux_version_A == 0) { - int mux_slot_length_bytes = read_payload_length_info(latmctx, gb); - if (mux_slot_length_bytes < 0 || mux_slot_length_bytes * 8LL > get_bits_left(gb)) { - av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR, "incomplete frame\n"); - return AVERROR_INVALIDDATA; - } else if (mux_slot_length_bytes * 8 + 256 < get_bits_left(gb)) { - av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR, - "frame length mismatch %d << %d\n", - mux_slot_length_bytes * 8, get_bits_left(gb)); - return AVERROR_INVALIDDATA; - } - } - return 0; -} - - -static int latm_decode_frame(AVCodecContext *avctx, AVFrame *out, - int *got_frame_ptr, AVPacket *avpkt) -{ - struct LATMContext *latmctx = avctx->priv_data; - int muxlength, err; - GetBitContext gb; - - if ((err = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0) - return err; - - // check for LOAS sync word - if (get_bits(&gb, 11) != LOAS_SYNC_WORD) - return AVERROR_INVALIDDATA; - - muxlength = get_bits(&gb, 13) + 3; - // not enough data, the parser should have sorted this out - if (muxlength > avpkt->size) - return AVERROR_INVALIDDATA; - - if ((err = read_audio_mux_element(latmctx, &gb))) - return (err < 0) ? err : avpkt->size; - - if (!latmctx->initialized) { - if (!avctx->extradata) { - *got_frame_ptr = 0; - return avpkt->size; - } else { - push_output_configuration(&latmctx->aac_ctx); - if ((err = decode_audio_specific_config( - &latmctx->aac_ctx, avctx, &latmctx->aac_ctx.oc[1].m4ac, - avctx->extradata, avctx->extradata_size*8LL, 1)) < 0) { - pop_output_configuration(&latmctx->aac_ctx); - return err; - } - latmctx->initialized = 1; - } - } - - if (show_bits(&gb, 12) == 0xfff) { - av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR, - "ADTS header detected, probably as result of configuration " - "misparsing\n"); - return AVERROR_INVALIDDATA; - } - - switch (latmctx->aac_ctx.oc[1].m4ac.object_type) { - case AOT_ER_AAC_LC: - case AOT_ER_AAC_LTP: - case AOT_ER_AAC_LD: - case AOT_ER_AAC_ELD: - err = aac_decode_er_frame(avctx, out, got_frame_ptr, &gb); - break; - default: - err = aac_decode_frame_int(avctx, out, got_frame_ptr, &gb, avpkt); - } - if (err < 0) - return err; - - return muxlength; -} - -static av_cold int latm_decode_init(AVCodecContext *avctx) -{ - struct LATMContext *latmctx = avctx->priv_data; - int ret = aac_decode_init(avctx); - - if (avctx->extradata_size > 0) - latmctx->initialized = !ret; - - return ret; -} +#include "libavcodec/aac/aacdec_latm.h" const FFCodec ff_aac_decoder = { .p.name = "aac", @@ -376,30 +87,6 @@ const FFCodec ff_aac_decoder = { .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), }; -/* - Note: This decoder filter is intended to decode LATM streams transferred - in MPEG transport streams which only contain one program. - To do a more complex LATM demuxing a separate LATM demuxer should be used. -*/ -const FFCodec ff_aac_latm_decoder = { - .p.name = "aac_latm", - CODEC_LONG_NAME("AAC LATM (Advanced Audio Coding LATM syntax)"), - .p.type = AVMEDIA_TYPE_AUDIO, - .p.id = AV_CODEC_ID_AAC_LATM, - .priv_data_size = sizeof(struct LATMContext), - .init = latm_decode_init, - .close = ff_aac_decode_close, - FF_CODEC_DECODE_CB(latm_decode_frame), - .p.sample_fmts = (const enum AVSampleFormat[]) { - AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE - }, - .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .p.ch_layouts = ff_aac_ch_layout, - .flush = flush, - .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), -}; - const FFCodec ff_aac_fixed_decoder = { .p.name = "aac_fixed", CODEC_LONG_NAME("AAC (Advanced Audio Coding)"), |