aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/aacdec.c
diff options
context:
space:
mode:
authorLynne <dev@lynne.ee>2024-03-16 23:34:46 +0100
committerLynne <dev@lynne.ee>2024-04-23 08:31:39 +0200
commitce740618d194e6c8523466ba15be2d662da37105 (patch)
treeebf6e6809f3277426be16510b5cf0467b1005612 /libavcodec/aacdec.c
parente93793bf3cf15968c34b0e7bf0c677fad3032f5d (diff)
downloadffmpeg-ce740618d194e6c8523466ba15be2d662da37105.tar.gz
aacdec: move LATM decode functions into a separate file
Diffstat (limited to 'libavcodec/aacdec.c')
-rw-r--r--libavcodec/aacdec.c315
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)"),