00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 #include <vo-amrwbenc/enc_if.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 
00026 #include "libavutil/avstring.h"
00027 #include "libavutil/internal.h"
00028 #include "libavutil/mem.h"
00029 #include "libavutil/opt.h"
00030 #include "avcodec.h"
00031 #include "internal.h"
00032 
00033 #define MAX_PACKET_SIZE  (1 + (477 + 7) / 8)
00034 
00035 typedef struct AMRWBContext {
00036     AVClass *av_class;
00037     void  *state;
00038     int    mode;
00039     int    last_bitrate;
00040     int    allow_dtx;
00041 } AMRWBContext;
00042 
00043 static const AVOption options[] = {
00044     { "dtx", "Allow DTX (generate comfort noise)", offsetof(AMRWBContext, allow_dtx), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
00045     { NULL }
00046 };
00047 
00048 static const AVClass class = {
00049     "libvo_amrwbenc", av_default_item_name, options, LIBAVUTIL_VERSION_INT
00050 };
00051 
00052 static int get_wb_bitrate_mode(int bitrate, void *log_ctx)
00053 {
00054     
00055     static const int rates[] = {  6600,  8850, 12650, 14250, 15850, 18250,
00056                                  19850, 23050, 23850 };
00057     int i, best = -1, min_diff = 0;
00058     char log_buf[200];
00059 
00060     for (i = 0; i < 9; i++) {
00061         if (rates[i] == bitrate)
00062             return i;
00063         if (best < 0 || abs(rates[i] - bitrate) < min_diff) {
00064             best     = i;
00065             min_diff = abs(rates[i] - bitrate);
00066         }
00067     }
00068     
00069     snprintf(log_buf, sizeof(log_buf), "bitrate not supported: use one of ");
00070     for (i = 0; i < 9; i++)
00071         av_strlcatf(log_buf, sizeof(log_buf), "%.2fk, ", rates[i]    / 1000.f);
00072     av_strlcatf(log_buf, sizeof(log_buf), "using %.2fk", rates[best] / 1000.f);
00073     av_log(log_ctx, AV_LOG_WARNING, "%s\n", log_buf);
00074 
00075     return best;
00076 }
00077 
00078 static av_cold int amr_wb_encode_init(AVCodecContext *avctx)
00079 {
00080     AMRWBContext *s = avctx->priv_data;
00081 
00082     if (avctx->sample_rate != 16000) {
00083         av_log(avctx, AV_LOG_ERROR, "Only 16000Hz sample rate supported\n");
00084         return AVERROR(ENOSYS);
00085     }
00086 
00087     if (avctx->channels != 1) {
00088         av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
00089         return AVERROR(ENOSYS);
00090     }
00091 
00092     s->mode            = get_wb_bitrate_mode(avctx->bit_rate, avctx);
00093     s->last_bitrate    = avctx->bit_rate;
00094 
00095     avctx->frame_size  = 320;
00096     avctx->delay       =  80;
00097 #if FF_API_OLD_ENCODE_AUDIO
00098     avctx->coded_frame = avcodec_alloc_frame();
00099     if (!avctx->coded_frame)
00100         return AVERROR(ENOMEM);
00101 #endif
00102 
00103     s->state     = E_IF_init();
00104 
00105     return 0;
00106 }
00107 
00108 static int amr_wb_encode_close(AVCodecContext *avctx)
00109 {
00110     AMRWBContext *s = avctx->priv_data;
00111 
00112     E_IF_exit(s->state);
00113     av_freep(&avctx->coded_frame);
00114     return 0;
00115 }
00116 
00117 static int amr_wb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
00118                                const AVFrame *frame, int *got_packet_ptr)
00119 {
00120     AMRWBContext *s = avctx->priv_data;
00121     const int16_t *samples = (const int16_t *)frame->data[0];
00122     int size, ret;
00123 
00124     if ((ret = ff_alloc_packet2(avctx, avpkt, MAX_PACKET_SIZE)))
00125         return ret;
00126 
00127     if (s->last_bitrate != avctx->bit_rate) {
00128         s->mode         = get_wb_bitrate_mode(avctx->bit_rate, avctx);
00129         s->last_bitrate = avctx->bit_rate;
00130     }
00131     size = E_IF_encode(s->state, s->mode, samples, avpkt->data, s->allow_dtx);
00132     if (size <= 0 || size > MAX_PACKET_SIZE) {
00133         av_log(avctx, AV_LOG_ERROR, "Error encoding frame\n");
00134         return AVERROR(EINVAL);
00135     }
00136 
00137     if (frame->pts != AV_NOPTS_VALUE)
00138         avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay);
00139 
00140     avpkt->size = size;
00141     *got_packet_ptr = 1;
00142     return 0;
00143 }
00144 
00145 AVCodec ff_libvo_amrwbenc_encoder = {
00146     .name           = "libvo_amrwbenc",
00147     .type           = AVMEDIA_TYPE_AUDIO,
00148     .id             = AV_CODEC_ID_AMR_WB,
00149     .priv_data_size = sizeof(AMRWBContext),
00150     .init           = amr_wb_encode_init,
00151     .encode2        = amr_wb_encode_frame,
00152     .close          = amr_wb_encode_close,
00153     .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
00154                                                      AV_SAMPLE_FMT_NONE },
00155     .long_name      = NULL_IF_CONFIG_SMALL("Android VisualOn AMR-WB "
00156                                            "(Adaptive Multi-Rate Wide-Band)"),
00157     .priv_class     = &class,
00158 };