00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <libavcodec/avcodec.h>
00020 #include <speex/speex.h>
00021 #include <speex/speex_header.h>
00022 #include <speex/speex_stereo.h>
00023
00024 typedef struct {
00025 SpeexBits bits;
00026 void *enc_state;
00027 SpeexHeader header;
00028 } LibSpeexEncContext;
00029
00030
00031 static av_cold int libspeex_encode_init(AVCodecContext *avctx)
00032 {
00033 LibSpeexEncContext *s = (LibSpeexEncContext*)avctx->priv_data;
00034 const SpeexMode *mode;
00035
00036 if ((avctx->sample_fmt != SAMPLE_FMT_S16 && avctx->sample_fmt != SAMPLE_FMT_FLT) ||
00037 avctx->sample_rate <= 0 ||
00038 avctx->channels <= 0 ||
00039 avctx->channels > 2)
00040 {
00041 av_log(avctx, AV_LOG_ERROR, "Unsupported sample format, rate, or channels for speex");
00042 return -1;
00043 }
00044
00045 if (avctx->sample_rate <= 8000)
00046 mode = &speex_nb_mode;
00047 else if (avctx->sample_rate <= 16000)
00048 mode = &speex_wb_mode;
00049 else
00050 mode = &speex_uwb_mode;
00051
00052 speex_bits_init(&s->bits);
00053 s->enc_state = speex_encoder_init(mode);
00054 if (!s->enc_state)
00055 {
00056 av_log(avctx, AV_LOG_ERROR, "could not initialize speex encoder");
00057 return -1;
00058 }
00059
00060
00061 speex_init_header(&s->header, avctx->sample_rate,
00062 avctx->channels, mode);
00063
00064
00065
00066
00067 if (avctx->flags & CODEC_FLAG_QSCALE) {
00068 spx_int32_t quality = 0;
00069
00070 if (avctx->global_quality > FF_LAMBDA_MAX)
00071 quality = 0;
00072 else
00073 quality = (spx_int32_t)((FF_LAMBDA_MAX-avctx->global_quality)*10.0/FF_LAMBDA_MAX);
00074 speex_encoder_ctl(s->enc_state, SPEEX_SET_QUALITY, &quality);
00075 } else {
00076
00077 if (avctx->bit_rate > 0)
00078 speex_encoder_ctl(s->enc_state, SPEEX_SET_BITRATE, &avctx->bit_rate);
00079
00080 }
00081
00082 speex_encoder_ctl(s->enc_state, SPEEX_GET_BITRATE, &s->header.bitrate);
00083 avctx->bit_rate = s->header.bitrate;
00084
00085
00086 speex_encoder_ctl(s->enc_state, SPEEX_GET_SAMPLING_RATE, &s->header.rate);
00087 avctx->sample_rate = s->header.rate;
00088
00089
00090
00091
00092
00093
00094 speex_encoder_ctl(s->enc_state, SPEEX_GET_FRAME_SIZE, &s->header.frame_size);
00095 s->header.frames_per_packet = 2;
00096 avctx->frame_size = s->header.frame_size*s->header.frames_per_packet;
00097
00098
00099
00100 avctx->extradata = speex_header_to_packet(&s->header, &avctx->extradata_size);
00101 return 0;
00102 }
00103
00104 static av_cold int libspeex_encode_frame(
00105 AVCodecContext *avctx, uint8_t *frame,
00106 int buf_size, void *data)
00107 {
00108 LibSpeexEncContext *s = (LibSpeexEncContext*)avctx->priv_data;
00109 int i = 0;
00110
00111 if (!data)
00112
00113 return 0;
00114
00115 speex_bits_reset(&s->bits);
00116 for(i = 0; i < s->header.frames_per_packet; i++)
00117 {
00118 if (avctx->sample_fmt == SAMPLE_FMT_FLT)
00119 {
00120 if (avctx->channels == 2) {
00121 speex_encode_stereo(
00122 (float*)data+i*s->header.frame_size,
00123 s->header.frame_size,
00124 &s->bits);
00125 }
00126 speex_encode(s->enc_state,
00127 (float*)data+i*s->header.frame_size, &s->bits);
00128 } else {
00129 if (avctx->channels == 2) {
00130 speex_encode_stereo_int(
00131 (spx_int16_t*)data+i*s->header.frame_size,
00132 s->header.frame_size,
00133 &s->bits);
00134 }
00135 speex_encode_int(s->enc_state,
00136 (spx_int16_t*)data+i*s->header.frame_size, &s->bits);
00137 }
00138 }
00139
00140 speex_bits_insert_terminator(&s->bits);
00141
00142 if (buf_size >= speex_bits_nbytes(&s->bits)) {
00143 return speex_bits_write(&s->bits, frame, buf_size);
00144 } else {
00145 av_log(avctx, AV_LOG_ERROR, "output buffer too small");
00146 return -1;
00147 }
00148 }
00149
00150 static av_cold int libspeex_encode_close(AVCodecContext *avctx)
00151 {
00152 LibSpeexEncContext *s = (LibSpeexEncContext*)avctx->priv_data;
00153
00154 speex_bits_destroy(&s->bits);
00155 speex_encoder_destroy(s->enc_state);
00156 s->enc_state = 0;
00157 if (avctx->extradata)
00158 speex_header_free(avctx->extradata);
00159 avctx->extradata = 0;
00160 avctx->extradata_size = 0;
00161
00162 return 0;
00163 }
00164
00165 AVCodec ff_libspeex_encoder = {
00166 "libspeex",
00167 AVMEDIA_TYPE_AUDIO,
00168 CODEC_ID_SPEEX,
00169 sizeof(LibSpeexEncContext),
00170 libspeex_encode_init,
00171 libspeex_encode_frame,
00172 libspeex_encode_close,
00173 0,
00174 .capabilities = CODEC_CAP_DELAY,
00175 .supported_samplerates = (const int[]){8000, 16000, 32000, 0},
00176 .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_FLT,SAMPLE_FMT_NONE},
00177 .long_name = NULL_IF_CONFIG_SMALL("libspeex Speex Encoder"),
00178 };