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
00024 #include "avcodec.h"
00025 #include "libavutil/avstring.h"
00026 #include "libavutil/opt.h"
00027
00028 typedef struct AMRWBContext {
00029 AVClass *av_class;
00030 void *state;
00031 int mode;
00032 int last_bitrate;
00033 int allow_dtx;
00034 } AMRWBContext;
00035
00036 static const AVOption options[] = {
00037 { "dtx", "Allow DTX (generate comfort noise)", offsetof(AMRWBContext, allow_dtx), FF_OPT_TYPE_INT, 0, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
00038 { NULL }
00039 };
00040
00041 static const AVClass class = {
00042 "libvo_amrwbenc", av_default_item_name, options, LIBAVUTIL_VERSION_INT
00043 };
00044
00045 static int get_wb_bitrate_mode(int bitrate, void *log_ctx)
00046 {
00047
00048 static const int rates[] = { 6600, 8850, 12650, 14250, 15850, 18250,
00049 19850, 23050, 23850 };
00050 int i, best = -1, min_diff = 0;
00051 char log_buf[200];
00052
00053 for (i = 0; i < 9; i++) {
00054 if (rates[i] == bitrate)
00055 return i;
00056 if (best < 0 || abs(rates[i] - bitrate) < min_diff) {
00057 best = i;
00058 min_diff = abs(rates[i] - bitrate);
00059 }
00060 }
00061
00062 snprintf(log_buf, sizeof(log_buf), "bitrate not supported: use one of ");
00063 for (i = 0; i < 9; i++)
00064 av_strlcatf(log_buf, sizeof(log_buf), "%.2fk, ", rates[i] / 1000.f);
00065 av_strlcatf(log_buf, sizeof(log_buf), "using %.2fk", rates[best] / 1000.f);
00066 av_log(log_ctx, AV_LOG_WARNING, "%s\n", log_buf);
00067
00068 return best;
00069 }
00070
00071 static av_cold int amr_wb_encode_init(AVCodecContext *avctx)
00072 {
00073 AMRWBContext *s = avctx->priv_data;
00074
00075 if (avctx->sample_rate != 16000) {
00076 av_log(avctx, AV_LOG_ERROR, "Only 16000Hz sample rate supported\n");
00077 return AVERROR(ENOSYS);
00078 }
00079
00080 if (avctx->channels != 1) {
00081 av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
00082 return AVERROR(ENOSYS);
00083 }
00084
00085 s->mode = get_wb_bitrate_mode(avctx->bit_rate, avctx);
00086 s->last_bitrate = avctx->bit_rate;
00087
00088 avctx->frame_size = 320;
00089 avctx->coded_frame = avcodec_alloc_frame();
00090
00091 s->state = E_IF_init();
00092
00093 return 0;
00094 }
00095
00096 static int amr_wb_encode_close(AVCodecContext *avctx)
00097 {
00098 AMRWBContext *s = avctx->priv_data;
00099
00100 E_IF_exit(s->state);
00101 av_freep(&avctx->coded_frame);
00102 return 0;
00103 }
00104
00105 static int amr_wb_encode_frame(AVCodecContext *avctx,
00106 unsigned char *frame,
00107 int buf_size, void *data)
00108 {
00109 AMRWBContext *s = avctx->priv_data;
00110 int size;
00111
00112 if (s->last_bitrate != avctx->bit_rate) {
00113 s->mode = get_wb_bitrate_mode(avctx->bit_rate, avctx);
00114 s->last_bitrate = avctx->bit_rate;
00115 }
00116 size = E_IF_encode(s->state, s->mode, data, frame, s->allow_dtx);
00117 return size;
00118 }
00119
00120 AVCodec ff_libvo_amrwbenc_encoder = {
00121 "libvo_amrwbenc",
00122 AVMEDIA_TYPE_AUDIO,
00123 CODEC_ID_AMR_WB,
00124 sizeof(AMRWBContext),
00125 amr_wb_encode_init,
00126 amr_wb_encode_frame,
00127 amr_wb_encode_close,
00128 NULL,
00129 .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
00130 .long_name = NULL_IF_CONFIG_SMALL("Android VisualOn Adaptive Multi-Rate "
00131 "(AMR) Wide-Band"),
00132 .priv_class = &class,
00133 };
00134