From ad5caf3ab74dcc2a8761c597ab8bee985026340f Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Wed, 3 Jun 2009 18:50:46 +0000 Subject: [PATCH] AAC ADTS to AudioSpecificConfig bitstream filter Originally committed as revision 19080 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/Makefile | 1 + libavcodec/aac_adtstoasc_bsf.c | 114 +++++++++++++++++++++++++++++++++ libavcodec/allcodecs.c | 1 + 3 files changed, 116 insertions(+) create mode 100644 libavcodec/aac_adtstoasc_bsf.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 14ef9f41a8..cb9e4c4a1e 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -416,6 +416,7 @@ OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o # bitstream filters +OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o aac_parser.o mpeg4audio.o OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o diff --git a/libavcodec/aac_adtstoasc_bsf.c b/libavcodec/aac_adtstoasc_bsf.c new file mode 100644 index 0000000000..e6d51d0533 --- /dev/null +++ b/libavcodec/aac_adtstoasc_bsf.c @@ -0,0 +1,114 @@ +/* + * MPEG-2/4 AAC ADTS to MPEG-4 Audio Specific Configuration bitstream filter + * Copyright (c) 2009 Alex Converse + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "aac_parser.h" +#include "put_bits.h" +#include "get_bits.h" +#include "mpeg4audio.h" +#include "internal.h" + +typedef struct AACBSFContext { + int first_frame_done; +} AACBSFContext; + +/** + * This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4 + * ADTS header and removes the ADTS header. + */ +static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int keyframe) +{ + GetBitContext gb; + PutBitContext pb; + AACADTSHeaderInfo hdr; + + AACBSFContext *ctx = bsfc->priv_data; + + init_get_bits(&gb, buf, AAC_ADTS_HEADER_SIZE*8); + + *poutbuf = (uint8_t*) buf; + *poutbuf_size = buf_size; + + if (avctx->extradata) + if (show_bits(&gb, 12) != 0xfff) + return 0; + + if (ff_aac_parse_header(&gb, &hdr) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error parsing ADTS frame header!\n"); + return -1; + } + + if (!hdr.crc_absent && hdr.num_aac_frames > 1) { + ff_log_missing_feature(avctx, "Multiple RDBs per frame with CRC is", 0); + return -1; + } + + buf += AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent; + buf_size -= AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent; + + if (!ctx->first_frame_done) { + int pce_size = 0; + uint8_t pce_data[MAX_PCE_SIZE]; + if (!hdr.chan_config) { + init_get_bits(&gb, buf, buf_size); + if (get_bits(&gb, 3) != 5) { + ff_log_missing_feature(avctx, "PCE based channel configuration, where the PCE is not the first syntax element is", 0); + return -1; + } + init_put_bits(&pb, pce_data, MAX_PCE_SIZE); + pce_size = ff_copy_pce_data(&pb, &gb)/8; + flush_put_bits(&pb); + buf_size -= get_bits_count(&gb)/8; + buf += get_bits_count(&gb)/8; + } + avctx->extradata_size = 2 + pce_size; + avctx->extradata = av_malloc(avctx->extradata_size); + + init_put_bits(&pb, avctx->extradata, avctx->extradata_size); + put_bits(&pb, 5, hdr.object_type); + put_bits(&pb, 4, hdr.sampling_index); + put_bits(&pb, 4, hdr.chan_config); + put_bits(&pb, 1, 0); //frame length - 1024 samples + put_bits(&pb, 1, 0); //does not depend on core coder + put_bits(&pb, 1, 0); //is not extension + flush_put_bits(&pb); + if (pce_size) { + memcpy(avctx->extradata + 2, pce_data, pce_size); + } + + ctx->first_frame_done = 1; + } + + *poutbuf = (uint8_t*) buf; + *poutbuf_size = buf_size; + + return 0; +} + +AVBitStreamFilter aac_adtstoasc_bsf = { + "aac_adtstoasc", + sizeof(AACBSFContext), + aac_adtstoasc_filter, +}; diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index e8d5d27fa9..7e54d0797c 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -339,6 +339,7 @@ void avcodec_register_all(void) REGISTER_PARSER (VP3, vp3); /* bitstream filters */ + REGISTER_BSF (AAC_ADTSTOASC, aac_adtstoasc); REGISTER_BSF (DUMP_EXTRADATA, dump_extradata); REGISTER_BSF (H264_MP4TOANNEXB, h264_mp4toannexb); REGISTER_BSF (IMX_DUMP_HEADER, imx_dump_header);