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 };