00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00067 #include <speex/speex.h>
00068 #include <speex/speex_header.h>
00069 #include <speex/speex_stereo.h>
00070 #include "libavutil/mathematics.h"
00071 #include "libavutil/opt.h"
00072 #include "avcodec.h"
00073 #include "internal.h"
00074
00075 typedef struct {
00076 AVClass *class;
00077 SpeexBits bits;
00078 SpeexHeader header;
00079 void *enc_state;
00080 int frames_per_packet;
00081 float vbr_quality;
00082 int cbr_quality;
00083 int abr;
00084 int pkt_frame_count;
00085 int lookahead;
00086 int64_t next_pts;
00087 int pkt_sample_count;
00088 } LibSpeexEncContext;
00089
00090 static av_cold void print_enc_params(AVCodecContext *avctx,
00091 LibSpeexEncContext *s)
00092 {
00093 const char *mode_str = "unknown";
00094
00095 av_log(avctx, AV_LOG_DEBUG, "channels: %d\n", avctx->channels);
00096 switch (s->header.mode) {
00097 case SPEEX_MODEID_NB: mode_str = "narrowband"; break;
00098 case SPEEX_MODEID_WB: mode_str = "wideband"; break;
00099 case SPEEX_MODEID_UWB: mode_str = "ultra-wideband"; break;
00100 }
00101 av_log(avctx, AV_LOG_DEBUG, "mode: %s\n", mode_str);
00102 if (s->header.vbr) {
00103 av_log(avctx, AV_LOG_DEBUG, "rate control: VBR\n");
00104 av_log(avctx, AV_LOG_DEBUG, " quality: %f\n", s->vbr_quality);
00105 } else if (s->abr) {
00106 av_log(avctx, AV_LOG_DEBUG, "rate control: ABR\n");
00107 av_log(avctx, AV_LOG_DEBUG, " bitrate: %d bps\n", avctx->bit_rate);
00108 } else {
00109 av_log(avctx, AV_LOG_DEBUG, "rate control: CBR\n");
00110 av_log(avctx, AV_LOG_DEBUG, " bitrate: %d bps\n", avctx->bit_rate);
00111 }
00112 av_log(avctx, AV_LOG_DEBUG, "complexity: %d\n",
00113 avctx->compression_level);
00114 av_log(avctx, AV_LOG_DEBUG, "frame size: %d samples\n",
00115 avctx->frame_size);
00116 av_log(avctx, AV_LOG_DEBUG, "frames per packet: %d\n",
00117 s->frames_per_packet);
00118 av_log(avctx, AV_LOG_DEBUG, "packet size: %d\n",
00119 avctx->frame_size * s->frames_per_packet);
00120 }
00121
00122 static av_cold int encode_init(AVCodecContext *avctx)
00123 {
00124 LibSpeexEncContext *s = avctx->priv_data;
00125 const SpeexMode *mode;
00126 uint8_t *header_data;
00127 int header_size;
00128 int32_t complexity;
00129
00130
00131 if (avctx->channels < 1 || avctx->channels > 2) {
00132 av_log(avctx, AV_LOG_ERROR, "Invalid channels (%d). Only stereo and "
00133 "mono are supported\n", avctx->channels);
00134 return AVERROR(EINVAL);
00135 }
00136
00137
00138 switch (avctx->sample_rate) {
00139 case 8000: mode = &speex_nb_mode; break;
00140 case 16000: mode = &speex_wb_mode; break;
00141 case 32000: mode = &speex_uwb_mode; break;
00142 default:
00143 av_log(avctx, AV_LOG_ERROR, "Sample rate of %d Hz is not supported. "
00144 "Resample to 8, 16, or 32 kHz.\n", avctx->sample_rate);
00145 return AVERROR(EINVAL);
00146 }
00147
00148
00149 s->enc_state = speex_encoder_init(mode);
00150 if (!s->enc_state) {
00151 av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex\n");
00152 return -1;
00153 }
00154 speex_init_header(&s->header, avctx->sample_rate, avctx->channels, mode);
00155
00156
00157 if (avctx->flags & CODEC_FLAG_QSCALE) {
00158
00159 s->header.vbr = 1;
00160 speex_encoder_ctl(s->enc_state, SPEEX_SET_VBR, &s->header.vbr);
00161 s->vbr_quality = av_clipf(avctx->global_quality / (float)FF_QP2LAMBDA,
00162 0.0f, 10.0f);
00163 speex_encoder_ctl(s->enc_state, SPEEX_SET_VBR_QUALITY, &s->vbr_quality);
00164 } else {
00165 s->header.bitrate = avctx->bit_rate;
00166 if (avctx->bit_rate > 0) {
00167
00168 if (s->abr) {
00169 speex_encoder_ctl(s->enc_state, SPEEX_SET_ABR,
00170 &s->header.bitrate);
00171 speex_encoder_ctl(s->enc_state, SPEEX_GET_ABR,
00172 &s->header.bitrate);
00173 } else {
00174 speex_encoder_ctl(s->enc_state, SPEEX_SET_BITRATE,
00175 &s->header.bitrate);
00176 speex_encoder_ctl(s->enc_state, SPEEX_GET_BITRATE,
00177 &s->header.bitrate);
00178 }
00179 } else {
00180
00181 speex_encoder_ctl(s->enc_state, SPEEX_SET_QUALITY,
00182 &s->cbr_quality);
00183 speex_encoder_ctl(s->enc_state, SPEEX_GET_BITRATE,
00184 &s->header.bitrate);
00185 }
00186
00187
00188 avctx->bit_rate = s->header.bitrate + (avctx->channels == 2 ? 800 : 0);
00189 }
00190
00191
00192 if (avctx->compression_level > FF_COMPRESSION_DEFAULT) {
00193 complexity = av_clip(avctx->compression_level, 0, 10);
00194 speex_encoder_ctl(s->enc_state, SPEEX_SET_COMPLEXITY, &complexity);
00195 }
00196 speex_encoder_ctl(s->enc_state, SPEEX_GET_COMPLEXITY, &complexity);
00197 avctx->compression_level = complexity;
00198
00199
00200 avctx->frame_size = s->header.frame_size;
00201 s->header.frames_per_packet = s->frames_per_packet;
00202
00203
00204 speex_encoder_ctl(s->enc_state, SPEEX_GET_LOOKAHEAD, &s->lookahead);
00205 s->next_pts = -s->lookahead;
00206
00207
00208
00209
00210 header_data = speex_header_to_packet(&s->header, &header_size);
00211
00212
00213 avctx->extradata = av_malloc(header_size + FF_INPUT_BUFFER_PADDING_SIZE);
00214 avctx->coded_frame = avcodec_alloc_frame();
00215 if (!avctx->extradata || !avctx->coded_frame) {
00216 speex_header_free(header_data);
00217 speex_encoder_destroy(s->enc_state);
00218 av_log(avctx, AV_LOG_ERROR, "memory allocation error\n");
00219 return AVERROR(ENOMEM);
00220 }
00221
00222
00223 memcpy(avctx->extradata, header_data, header_size);
00224 avctx->extradata_size = header_size;
00225 speex_header_free(header_data);
00226
00227
00228 speex_bits_init(&s->bits);
00229
00230 print_enc_params(avctx, s);
00231 return 0;
00232 }
00233
00234 static int encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size,
00235 void *data)
00236 {
00237 LibSpeexEncContext *s = avctx->priv_data;
00238 int16_t *samples = data;
00239
00240 if (data) {
00241
00242 if (avctx->channels == 2)
00243 speex_encode_stereo_int(samples, s->header.frame_size, &s->bits);
00244 speex_encode_int(s->enc_state, samples, &s->bits);
00245 s->pkt_frame_count++;
00246 s->pkt_sample_count += avctx->frame_size;
00247 } else {
00248
00249 if (!s->pkt_frame_count)
00250 return 0;
00251
00252 while (s->pkt_frame_count < s->frames_per_packet) {
00253 speex_bits_pack(&s->bits, 15, 5);
00254 s->pkt_frame_count++;
00255 }
00256 }
00257
00258
00259 if (s->pkt_frame_count == s->frames_per_packet) {
00260 s->pkt_frame_count = 0;
00261 avctx->coded_frame->pts =
00262 av_rescale_q(s->next_pts, (AVRational){ 1, avctx->sample_rate },
00263 avctx->time_base);
00264 s->next_pts += s->pkt_sample_count;
00265 s->pkt_sample_count = 0;
00266 if (buf_size > speex_bits_nbytes(&s->bits)) {
00267 int ret = speex_bits_write(&s->bits, frame, buf_size);
00268 speex_bits_reset(&s->bits);
00269 return ret;
00270 } else {
00271 av_log(avctx, AV_LOG_ERROR, "output buffer too small");
00272 return AVERROR(EINVAL);
00273 }
00274 }
00275 return 0;
00276 }
00277
00278 static av_cold int encode_close(AVCodecContext *avctx)
00279 {
00280 LibSpeexEncContext *s = avctx->priv_data;
00281
00282 speex_bits_destroy(&s->bits);
00283 speex_encoder_destroy(s->enc_state);
00284
00285 av_freep(&avctx->coded_frame);
00286 av_freep(&avctx->extradata);
00287
00288 return 0;
00289 }
00290
00291 #define OFFSET(x) offsetof(LibSpeexEncContext, x)
00292 #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
00293 static const AVOption options[] = {
00294 { "abr", "Use average bit rate", OFFSET(abr), AV_OPT_TYPE_INT, { 0 }, 0, 1, AE },
00295 { "cbr_quality", "Set quality value (0 to 10) for CBR", OFFSET(cbr_quality), AV_OPT_TYPE_INT, { 8 }, 0, 10, AE },
00296 { "frames_per_packet", "Number of frames to encode in each packet", OFFSET(frames_per_packet), AV_OPT_TYPE_INT, { 1 }, 1, 8, AE },
00297 { NULL },
00298 };
00299
00300 static const AVClass class = {
00301 .class_name = "libspeex",
00302 .item_name = av_default_item_name,
00303 .option = options,
00304 .version = LIBAVUTIL_VERSION_INT,
00305 };
00306
00307 static const AVCodecDefault defaults[] = {
00308 { "b", "0" },
00309 { "compression_level", "3" },
00310 { NULL },
00311 };
00312
00313 AVCodec ff_libspeex_encoder = {
00314 .name = "libspeex",
00315 .type = AVMEDIA_TYPE_AUDIO,
00316 .id = CODEC_ID_SPEEX,
00317 .priv_data_size = sizeof(LibSpeexEncContext),
00318 .init = encode_init,
00319 .encode = encode_frame,
00320 .close = encode_close,
00321 .capabilities = CODEC_CAP_DELAY,
00322 .sample_fmts = (const enum SampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE },
00323 .long_name = NULL_IF_CONFIG_SMALL("libspeex Speex"),
00324 .priv_class = &class,
00325 .defaults = defaults,
00326 };