Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * AAC encoder wrapper
  3.  * Copyright (c) 2010 Martin Storsjo
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. #include <vo-aacenc/voAAC.h>
  23. #include <vo-aacenc/cmnMemory.h>
  24.  
  25. #include "avcodec.h"
  26. #include "audio_frame_queue.h"
  27. #include "internal.h"
  28. #include "mpeg4audio.h"
  29.  
  30. #define FRAME_SIZE 1024
  31. #define ENC_DELAY  1600
  32.  
  33. typedef struct AACContext {
  34.     VO_AUDIO_CODECAPI codec_api;
  35.     VO_HANDLE handle;
  36.     VO_MEM_OPERATOR mem_operator;
  37.     VO_CODEC_INIT_USERDATA user_data;
  38.     VO_PBYTE end_buffer;
  39.     AudioFrameQueue afq;
  40.     int last_frame;
  41.     int last_samples;
  42. } AACContext;
  43.  
  44.  
  45. static int aac_encode_close(AVCodecContext *avctx)
  46. {
  47.     AACContext *s = avctx->priv_data;
  48.  
  49.     s->codec_api.Uninit(s->handle);
  50.     av_freep(&avctx->extradata);
  51.     ff_af_queue_close(&s->afq);
  52.     av_freep(&s->end_buffer);
  53.  
  54.     return 0;
  55. }
  56.  
  57. static av_cold int aac_encode_init(AVCodecContext *avctx)
  58. {
  59.     AACContext *s = avctx->priv_data;
  60.     AACENC_PARAM params = { 0 };
  61.     int index, ret;
  62.  
  63.     avctx->frame_size = FRAME_SIZE;
  64.     avctx->delay      = ENC_DELAY;
  65.     s->last_frame     = 2;
  66.     ff_af_queue_init(avctx, &s->afq);
  67.  
  68.     s->end_buffer = av_mallocz(avctx->frame_size * avctx->channels * 2);
  69.     if (!s->end_buffer) {
  70.         ret = AVERROR(ENOMEM);
  71.         goto error;
  72.     }
  73.  
  74.     voGetAACEncAPI(&s->codec_api);
  75.  
  76.     s->mem_operator.Alloc = cmnMemAlloc;
  77.     s->mem_operator.Copy = cmnMemCopy;
  78.     s->mem_operator.Free = cmnMemFree;
  79.     s->mem_operator.Set = cmnMemSet;
  80.     s->mem_operator.Check = cmnMemCheck;
  81.     s->user_data.memflag = VO_IMF_USERMEMOPERATOR;
  82.     s->user_data.memData = &s->mem_operator;
  83.     s->codec_api.Init(&s->handle, VO_AUDIO_CodingAAC, &s->user_data);
  84.  
  85.     params.sampleRate = avctx->sample_rate;
  86.     params.bitRate    = avctx->bit_rate;
  87.     params.nChannels  = avctx->channels;
  88.     params.adtsUsed   = !(avctx->flags & CODEC_FLAG_GLOBAL_HEADER);
  89.     if (s->codec_api.SetParam(s->handle, VO_PID_AAC_ENCPARAM, &params)
  90.         != VO_ERR_NONE) {
  91.         av_log(avctx, AV_LOG_ERROR, "Unable to set encoding parameters\n");
  92.         ret = AVERROR(EINVAL);
  93.         goto error;
  94.     }
  95.  
  96.     for (index = 0; index < 16; index++)
  97.         if (avctx->sample_rate == avpriv_mpeg4audio_sample_rates[index])
  98.             break;
  99.     if (index == 16) {
  100.         av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate %d\n",
  101.                                     avctx->sample_rate);
  102.         ret = AVERROR(ENOSYS);
  103.         goto error;
  104.     }
  105.     if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
  106.         avctx->extradata_size = 2;
  107.         avctx->extradata      = av_mallocz(avctx->extradata_size +
  108.                                            FF_INPUT_BUFFER_PADDING_SIZE);
  109.         if (!avctx->extradata) {
  110.             ret = AVERROR(ENOMEM);
  111.             goto error;
  112.         }
  113.  
  114.         avctx->extradata[0] = 0x02 << 3 | index >> 1;
  115.         avctx->extradata[1] = (index & 0x01) << 7 | avctx->channels << 3;
  116.     }
  117.     return 0;
  118. error:
  119.     aac_encode_close(avctx);
  120.     return ret;
  121. }
  122.  
  123. static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
  124.                             const AVFrame *frame, int *got_packet_ptr)
  125. {
  126.     AACContext *s = avctx->priv_data;
  127.     VO_CODECBUFFER input = { 0 }, output = { 0 };
  128.     VO_AUDIO_OUTPUTINFO output_info = { { 0 } };
  129.     VO_PBYTE samples;
  130.     int ret;
  131.  
  132.     /* handle end-of-stream small frame and flushing */
  133.     if (!frame) {
  134.         if (s->last_frame <= 0)
  135.             return 0;
  136.         if (s->last_samples > 0 && s->last_samples < ENC_DELAY - FRAME_SIZE) {
  137.             s->last_samples = 0;
  138.             s->last_frame--;
  139.         }
  140.         s->last_frame--;
  141.         memset(s->end_buffer, 0, 2 * avctx->channels * avctx->frame_size);
  142.         samples = s->end_buffer;
  143.     } else {
  144.         if (frame->nb_samples < avctx->frame_size) {
  145.             s->last_samples = frame->nb_samples;
  146.             memcpy(s->end_buffer, frame->data[0], 2 * avctx->channels * frame->nb_samples);
  147.             samples = s->end_buffer;
  148.         } else {
  149.             samples = (VO_PBYTE)frame->data[0];
  150.         }
  151.         /* add current frame to the queue */
  152.         if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
  153.             return ret;
  154.     }
  155.  
  156.     if ((ret = ff_alloc_packet2(avctx, avpkt, FFMAX(8192, 768 * avctx->channels))) < 0)
  157.         return ret;
  158.  
  159.     input.Buffer  = samples;
  160.     input.Length  = 2 * avctx->channels * avctx->frame_size;
  161.     output.Buffer = avpkt->data;
  162.     output.Length = avpkt->size;
  163.  
  164.     s->codec_api.SetInputData(s->handle, &input);
  165.     if (s->codec_api.GetOutputData(s->handle, &output, &output_info)
  166.         != VO_ERR_NONE) {
  167.         av_log(avctx, AV_LOG_ERROR, "Unable to encode frame\n");
  168.         return AVERROR(EINVAL);
  169.     }
  170.  
  171.     /* Get the next frame pts/duration */
  172.     ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
  173.                        &avpkt->duration);
  174.  
  175.     avpkt->size = output.Length;
  176.     *got_packet_ptr = 1;
  177.     return 0;
  178. }
  179.  
  180. /* duplicated from avpriv_mpeg4audio_sample_rates to avoid shared build
  181.  * failures */
  182. static const int mpeg4audio_sample_rates[16] = {
  183.     96000, 88200, 64000, 48000, 44100, 32000,
  184.     24000, 22050, 16000, 12000, 11025, 8000, 7350
  185. };
  186.  
  187. AVCodec ff_libvo_aacenc_encoder = {
  188.     .name           = "libvo_aacenc",
  189.     .long_name      = NULL_IF_CONFIG_SMALL("Android VisualOn AAC (Advanced Audio Coding)"),
  190.     .type           = AVMEDIA_TYPE_AUDIO,
  191.     .id             = AV_CODEC_ID_AAC,
  192.     .priv_data_size = sizeof(AACContext),
  193.     .init           = aac_encode_init,
  194.     .encode2        = aac_encode_frame,
  195.     .close          = aac_encode_close,
  196.     .supported_samplerates = mpeg4audio_sample_rates,
  197.     .capabilities   = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY,
  198.     .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
  199.                                                      AV_SAMPLE_FMT_NONE },
  200. };
  201.