blob: c4c054fa5d4f24d312094e63d3aa0bb6b5845987
1 | /* |
2 | * iLBC decoder/encoder stub |
3 | * Copyright (c) 2012 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 <ilbc.h> |
23 | |
24 | #include "libavutil/channel_layout.h" |
25 | #include "libavutil/common.h" |
26 | #include "libavutil/opt.h" |
27 | #include "avcodec.h" |
28 | #include "internal.h" |
29 | |
30 | static int get_mode(AVCodecContext *avctx) |
31 | { |
32 | if (avctx->block_align == 38) |
33 | return 20; |
34 | else if (avctx->block_align == 50) |
35 | return 30; |
36 | else if (avctx->bit_rate > 0) |
37 | return avctx->bit_rate <= 14000 ? 30 : 20; |
38 | else |
39 | return -1; |
40 | } |
41 | |
42 | typedef struct ILBCDecContext { |
43 | const AVClass *class; |
44 | iLBC_Dec_Inst_t decoder; |
45 | int enhance; |
46 | } ILBCDecContext; |
47 | |
48 | static const AVOption ilbc_dec_options[] = { |
49 | { "enhance", "Enhance the decoded audio (adds delay)", offsetof(ILBCDecContext, enhance), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM }, |
50 | { NULL } |
51 | }; |
52 | |
53 | static const AVClass ilbc_dec_class = { |
54 | .class_name = "libilbc", |
55 | .item_name = av_default_item_name, |
56 | .option = ilbc_dec_options, |
57 | .version = LIBAVUTIL_VERSION_INT, |
58 | }; |
59 | |
60 | static av_cold int ilbc_decode_init(AVCodecContext *avctx) |
61 | { |
62 | ILBCDecContext *s = avctx->priv_data; |
63 | int mode; |
64 | |
65 | if ((mode = get_mode(avctx)) < 0) { |
66 | av_log(avctx, AV_LOG_ERROR, "iLBC frame mode not indicated\n"); |
67 | return AVERROR(EINVAL); |
68 | } |
69 | |
70 | WebRtcIlbcfix_InitDecode(&s->decoder, mode, s->enhance); |
71 | |
72 | avctx->channels = 1; |
73 | avctx->channel_layout = AV_CH_LAYOUT_MONO; |
74 | avctx->sample_rate = 8000; |
75 | avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
76 | |
77 | return 0; |
78 | } |
79 | |
80 | static int ilbc_decode_frame(AVCodecContext *avctx, void *data, |
81 | int *got_frame_ptr, AVPacket *avpkt) |
82 | { |
83 | const uint8_t *buf = avpkt->data; |
84 | int buf_size = avpkt->size; |
85 | ILBCDecContext *s = avctx->priv_data; |
86 | AVFrame *frame = data; |
87 | int ret; |
88 | |
89 | if (s->decoder.no_of_bytes > buf_size) { |
90 | av_log(avctx, AV_LOG_ERROR, "iLBC frame too short (%u, should be %u)\n", |
91 | buf_size, s->decoder.no_of_bytes); |
92 | return AVERROR_INVALIDDATA; |
93 | } |
94 | |
95 | frame->nb_samples = s->decoder.blockl; |
96 | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) |
97 | return ret; |
98 | |
99 | WebRtcIlbcfix_DecodeImpl((int16_t *) frame->data[0], (const uint16_t *) buf, &s->decoder, 1); |
100 | |
101 | *got_frame_ptr = 1; |
102 | |
103 | return s->decoder.no_of_bytes; |
104 | } |
105 | |
106 | AVCodec ff_libilbc_decoder = { |
107 | .name = "libilbc", |
108 | .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), |
109 | .type = AVMEDIA_TYPE_AUDIO, |
110 | .id = AV_CODEC_ID_ILBC, |
111 | .priv_data_size = sizeof(ILBCDecContext), |
112 | .init = ilbc_decode_init, |
113 | .decode = ilbc_decode_frame, |
114 | .capabilities = AV_CODEC_CAP_DR1, |
115 | .priv_class = &ilbc_dec_class, |
116 | }; |
117 | |
118 | typedef struct ILBCEncContext { |
119 | const AVClass *class; |
120 | iLBC_Enc_Inst_t encoder; |
121 | int mode; |
122 | } ILBCEncContext; |
123 | |
124 | static const AVOption ilbc_enc_options[] = { |
125 | { "mode", "iLBC mode (20 or 30 ms frames)", offsetof(ILBCEncContext, mode), AV_OPT_TYPE_INT, { .i64 = 20 }, 20, 30, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, |
126 | { NULL } |
127 | }; |
128 | |
129 | static const AVClass ilbc_enc_class = { |
130 | .class_name = "libilbc", |
131 | .item_name = av_default_item_name, |
132 | .option = ilbc_enc_options, |
133 | .version = LIBAVUTIL_VERSION_INT, |
134 | }; |
135 | |
136 | static av_cold int ilbc_encode_init(AVCodecContext *avctx) |
137 | { |
138 | ILBCEncContext *s = avctx->priv_data; |
139 | int mode; |
140 | |
141 | if (avctx->sample_rate != 8000) { |
142 | av_log(avctx, AV_LOG_ERROR, "Only 8000Hz sample rate supported\n"); |
143 | return AVERROR(EINVAL); |
144 | } |
145 | |
146 | if (avctx->channels != 1) { |
147 | av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); |
148 | return AVERROR(EINVAL); |
149 | } |
150 | |
151 | if ((mode = get_mode(avctx)) > 0) |
152 | s->mode = mode; |
153 | else |
154 | s->mode = s->mode != 30 ? 20 : 30; |
155 | WebRtcIlbcfix_InitEncode(&s->encoder, s->mode); |
156 | |
157 | avctx->block_align = s->encoder.no_of_bytes; |
158 | avctx->frame_size = s->encoder.blockl; |
159 | |
160 | return 0; |
161 | } |
162 | |
163 | static int ilbc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, |
164 | const AVFrame *frame, int *got_packet_ptr) |
165 | { |
166 | ILBCEncContext *s = avctx->priv_data; |
167 | int ret; |
168 | |
169 | if ((ret = ff_alloc_packet2(avctx, avpkt, 50, 0)) < 0) |
170 | return ret; |
171 | |
172 | WebRtcIlbcfix_EncodeImpl((uint16_t *) avpkt->data, (const int16_t *) frame->data[0], &s->encoder); |
173 | |
174 | avpkt->size = s->encoder.no_of_bytes; |
175 | *got_packet_ptr = 1; |
176 | return 0; |
177 | } |
178 | |
179 | static const AVCodecDefault ilbc_encode_defaults[] = { |
180 | { "b", "0" }, |
181 | { NULL } |
182 | }; |
183 | |
184 | AVCodec ff_libilbc_encoder = { |
185 | .name = "libilbc", |
186 | .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), |
187 | .type = AVMEDIA_TYPE_AUDIO, |
188 | .id = AV_CODEC_ID_ILBC, |
189 | .priv_data_size = sizeof(ILBCEncContext), |
190 | .init = ilbc_encode_init, |
191 | .encode2 = ilbc_encode_frame, |
192 | .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, |
193 | AV_SAMPLE_FMT_NONE }, |
194 | .defaults = ilbc_encode_defaults, |
195 | .priv_class = &ilbc_enc_class, |
196 | }; |
197 |