libopencore-amr, libvo-amrwbenc: Only check the bitrate when changed
[ffmpeg.git] / libavcodec / libvo-amrwbenc.c
1 /*
2  * AMR Audio encoder stub
3  * Copyright (c) 2003 the ffmpeg project
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; 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-amrwbenc/enc_if.h>
23
24 #include "avcodec.h"
25 #include "libavutil/avstring.h"
26
27 typedef struct AMRWBContext {
28     void  *state;
29     int    mode;
30     int    last_bitrate;
31     int    allow_dtx;
32 } AMRWBContext;
33
34 static int get_wb_bitrate_mode(int bitrate, void *log_ctx)
35 {
36     /* make the correspondance between bitrate and mode */
37     static const int rates[] = {  6600,  8850, 12650, 14250, 15850, 18250,
38                                  19850, 23050, 23850 };
39     int i, best = -1, min_diff = 0;
40     char log_buf[200];
41
42     for (i = 0; i < 9; i++) {
43         if (rates[i] == bitrate)
44             return i;
45         if (best < 0 || abs(rates[i] - bitrate) < min_diff) {
46             best     = i;
47             min_diff = abs(rates[i] - bitrate);
48         }
49     }
50     /* no bitrate matching exactly, log a warning */
51     snprintf(log_buf, sizeof(log_buf), "bitrate not supported: use one of ");
52     for (i = 0; i < 9; i++)
53         av_strlcatf(log_buf, sizeof(log_buf), "%.2fk, ", rates[i]    / 1000.f);
54     av_strlcatf(log_buf, sizeof(log_buf), "using %.2fk", rates[best] / 1000.f);
55     av_log(log_ctx, AV_LOG_WARNING, "%s\n", log_buf);
56
57     return best;
58 }
59
60 static av_cold int amr_wb_encode_init(AVCodecContext *avctx)
61 {
62     AMRWBContext *s = avctx->priv_data;
63
64     if (avctx->sample_rate != 16000) {
65         av_log(avctx, AV_LOG_ERROR, "Only 16000Hz sample rate supported\n");
66         return AVERROR(ENOSYS);
67     }
68
69     if (avctx->channels != 1) {
70         av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
71         return AVERROR(ENOSYS);
72     }
73
74     s->mode            = get_wb_bitrate_mode(avctx->bit_rate, avctx);
75     s->last_bitrate    = avctx->bit_rate;
76
77     avctx->frame_size  = 320;
78     avctx->coded_frame = avcodec_alloc_frame();
79
80     s->state     = E_IF_init();
81     s->allow_dtx = 0;
82
83     return 0;
84 }
85
86 static int amr_wb_encode_close(AVCodecContext *avctx)
87 {
88     AMRWBContext *s = avctx->priv_data;
89
90     E_IF_exit(s->state);
91     av_freep(&avctx->coded_frame);
92     return 0;
93 }
94
95 static int amr_wb_encode_frame(AVCodecContext *avctx,
96                                unsigned char *frame/*out*/,
97                                int buf_size, void *data/*in*/)
98 {
99     AMRWBContext *s = avctx->priv_data;
100     int size;
101
102     if (s->last_bitrate != avctx->bit_rate) {
103         s->mode         = get_wb_bitrate_mode(avctx->bit_rate, avctx);
104         s->last_bitrate = avctx->bit_rate;
105     }
106     size = E_IF_encode(s->state, s->mode, data, frame, s->allow_dtx);
107     return size;
108 }
109
110 AVCodec ff_libvo_amrwbenc_encoder = {
111     "libvo_amrwbenc",
112     CODEC_TYPE_AUDIO,
113     CODEC_ID_AMR_WB,
114     sizeof(AMRWBContext),
115     amr_wb_encode_init,
116     amr_wb_encode_frame,
117     amr_wb_encode_close,
118     NULL,
119     .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
120     .long_name = NULL_IF_CONFIG_SMALL("Android VisualOn Adaptive Multi-Rate "
121                                       "(AMR) Wide-Band"),
122 };
123