From 8992cb1d0d07edc33d274f6d7924ecdf6f83d994 Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Thu, 5 Sep 2013 17:57:22 +0100 Subject: making act segmenter --- ffmpeg/libavcodec/libvo-aacenc.c | 200 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 ffmpeg/libavcodec/libvo-aacenc.c (limited to 'ffmpeg/libavcodec/libvo-aacenc.c') diff --git a/ffmpeg/libavcodec/libvo-aacenc.c b/ffmpeg/libavcodec/libvo-aacenc.c new file mode 100644 index 0000000..4f4cbe7 --- /dev/null +++ b/ffmpeg/libavcodec/libvo-aacenc.c @@ -0,0 +1,200 @@ +/* + * AAC encoder wrapper + * Copyright (c) 2010 Martin Storsjo + * + * 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 +#include + +#include "avcodec.h" +#include "audio_frame_queue.h" +#include "internal.h" +#include "mpeg4audio.h" + +#define FRAME_SIZE 1024 +#define ENC_DELAY 1600 + +typedef struct AACContext { + VO_AUDIO_CODECAPI codec_api; + VO_HANDLE handle; + VO_MEM_OPERATOR mem_operator; + VO_CODEC_INIT_USERDATA user_data; + VO_PBYTE end_buffer; + AudioFrameQueue afq; + int last_frame; + int last_samples; +} AACContext; + + +static int aac_encode_close(AVCodecContext *avctx) +{ + AACContext *s = avctx->priv_data; + + s->codec_api.Uninit(s->handle); + av_freep(&avctx->extradata); + ff_af_queue_close(&s->afq); + av_freep(&s->end_buffer); + + return 0; +} + +static av_cold int aac_encode_init(AVCodecContext *avctx) +{ + AACContext *s = avctx->priv_data; + AACENC_PARAM params = { 0 }; + int index, ret; + + avctx->frame_size = FRAME_SIZE; + avctx->delay = ENC_DELAY; + s->last_frame = 2; + ff_af_queue_init(avctx, &s->afq); + + s->end_buffer = av_mallocz(avctx->frame_size * avctx->channels * 2); + if (!s->end_buffer) { + ret = AVERROR(ENOMEM); + goto error; + } + + voGetAACEncAPI(&s->codec_api); + + s->mem_operator.Alloc = cmnMemAlloc; + s->mem_operator.Copy = cmnMemCopy; + s->mem_operator.Free = cmnMemFree; + s->mem_operator.Set = cmnMemSet; + s->mem_operator.Check = cmnMemCheck; + s->user_data.memflag = VO_IMF_USERMEMOPERATOR; + s->user_data.memData = &s->mem_operator; + s->codec_api.Init(&s->handle, VO_AUDIO_CodingAAC, &s->user_data); + + params.sampleRate = avctx->sample_rate; + params.bitRate = avctx->bit_rate; + params.nChannels = avctx->channels; + params.adtsUsed = !(avctx->flags & CODEC_FLAG_GLOBAL_HEADER); + if (s->codec_api.SetParam(s->handle, VO_PID_AAC_ENCPARAM, ¶ms) + != VO_ERR_NONE) { + av_log(avctx, AV_LOG_ERROR, "Unable to set encoding parameters\n"); + ret = AVERROR(EINVAL); + goto error; + } + + for (index = 0; index < 16; index++) + if (avctx->sample_rate == avpriv_mpeg4audio_sample_rates[index]) + break; + if (index == 16) { + av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate %d\n", + avctx->sample_rate); + ret = AVERROR(ENOSYS); + goto error; + } + if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + avctx->extradata_size = 2; + avctx->extradata = av_mallocz(avctx->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + ret = AVERROR(ENOMEM); + goto error; + } + + avctx->extradata[0] = 0x02 << 3 | index >> 1; + avctx->extradata[1] = (index & 0x01) << 7 | avctx->channels << 3; + } + return 0; +error: + aac_encode_close(avctx); + return ret; +} + +static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + AACContext *s = avctx->priv_data; + VO_CODECBUFFER input = { 0 }, output = { 0 }; + VO_AUDIO_OUTPUTINFO output_info = { { 0 } }; + VO_PBYTE samples; + int ret; + + /* handle end-of-stream small frame and flushing */ + if (!frame) { + if (s->last_frame <= 0) + return 0; + if (s->last_samples > 0 && s->last_samples < ENC_DELAY - FRAME_SIZE) { + s->last_samples = 0; + s->last_frame--; + } + s->last_frame--; + memset(s->end_buffer, 0, 2 * avctx->channels * avctx->frame_size); + samples = s->end_buffer; + } else { + if (frame->nb_samples < avctx->frame_size) { + s->last_samples = frame->nb_samples; + memcpy(s->end_buffer, frame->data[0], 2 * avctx->channels * frame->nb_samples); + samples = s->end_buffer; + } else { + samples = (VO_PBYTE)frame->data[0]; + } + /* add current frame to the queue */ + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) + return ret; + } + + if ((ret = ff_alloc_packet2(avctx, avpkt, FFMAX(8192, 768 * avctx->channels))) < 0) + return ret; + + input.Buffer = samples; + input.Length = 2 * avctx->channels * avctx->frame_size; + output.Buffer = avpkt->data; + output.Length = avpkt->size; + + s->codec_api.SetInputData(s->handle, &input); + if (s->codec_api.GetOutputData(s->handle, &output, &output_info) + != VO_ERR_NONE) { + av_log(avctx, AV_LOG_ERROR, "Unable to encode frame\n"); + return AVERROR(EINVAL); + } + + /* Get the next frame pts/duration */ + ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts, + &avpkt->duration); + + avpkt->size = output.Length; + *got_packet_ptr = 1; + return 0; +} + +/* duplicated from avpriv_mpeg4audio_sample_rates to avoid shared build + * failures */ +static const int mpeg4audio_sample_rates[16] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 7350 +}; + +AVCodec ff_libvo_aacenc_encoder = { + .name = "libvo_aacenc", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AAC, + .priv_data_size = sizeof(AACContext), + .init = aac_encode_init, + .encode2 = aac_encode_frame, + .close = aac_encode_close, + .supported_samplerates = mpeg4audio_sample_rates, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Android VisualOn AAC (Advanced Audio Coding)"), +}; -- cgit v1.2.3