1/* 2 * copyright (c) 2002 Mark Hills <mark@pogo.org.uk> 3 * 4 * This file is part of Libav. 5 * 6 * Libav is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * Libav is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with Libav; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21/** 22 * @file 23 * Ogg Vorbis codec support via libvorbisenc. 24 * @author Mark Hills <mark@pogo.org.uk> 25 */ 26 27#include <vorbis/vorbisenc.h> 28 29#include "libavutil/opt.h" 30#include "avcodec.h" 31#include "bytestream.h" 32#include "internal.h" 33#include "vorbis.h" 34#include "libavutil/mathematics.h" 35 36#undef NDEBUG 37#include <assert.h> 38 39#define OGGVORBIS_FRAME_SIZE 64 40 41#define BUFFER_SIZE (1024 * 64) 42 43typedef struct OggVorbisContext { 44 AVClass *av_class; 45 vorbis_info vi; 46 vorbis_dsp_state vd; 47 vorbis_block vb; 48 uint8_t buffer[BUFFER_SIZE]; 49 int buffer_index; 50 int eof; 51 52 /* decoder */ 53 vorbis_comment vc; 54 ogg_packet op; 55 56 double iblock; 57} OggVorbisContext; 58 59static const AVOption options[] = { 60 { "iblock", "Sets the impulse block bias", offsetof(OggVorbisContext, iblock), AV_OPT_TYPE_DOUBLE, { .dbl = 0 }, -15, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, 61 { NULL } 62}; 63 64static const AVCodecDefault defaults[] = { 65 { "b", "0" }, 66 { NULL }, 67}; 68 69static const AVClass class = { "libvorbis", av_default_item_name, options, LIBAVUTIL_VERSION_INT }; 70 71static av_cold int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) 72{ 73 OggVorbisContext *context = avccontext->priv_data; 74 double cfreq; 75 76 if (avccontext->flags & CODEC_FLAG_QSCALE || !avccontext->bit_rate) { 77 /* variable bitrate 78 * NOTE: we use the oggenc range of -1 to 10 for global_quality for 79 * user convenience, but libvorbis uses -0.1 to 1.0. 80 */ 81 float q = avccontext->global_quality / (float)FF_QP2LAMBDA; 82 /* default to 3 if the user did not set quality or bitrate */ 83 if (!(avccontext->flags & CODEC_FLAG_QSCALE)) 84 q = 3.0; 85 if (vorbis_encode_setup_vbr(vi, avccontext->channels, 86 avccontext->sample_rate, 87 q / 10.0)) 88 return -1; 89 } else { 90 int minrate = avccontext->rc_min_rate > 0 ? avccontext->rc_min_rate : -1; 91 int maxrate = avccontext->rc_max_rate > 0 ? avccontext->rc_max_rate : -1; 92 93 /* constant bitrate */ 94 if (vorbis_encode_setup_managed(vi, avccontext->channels, 95 avccontext->sample_rate, maxrate, 96 avccontext->bit_rate, minrate)) 97 return -1; 98 99 /* variable bitrate by estimate, disable slow rate management */ 100 if (minrate == -1 && maxrate == -1) 101 if (vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE2_SET, NULL)) 102 return -1; 103 } 104 105 /* cutoff frequency */ 106 if (avccontext->cutoff > 0) { 107 cfreq = avccontext->cutoff / 1000.0; 108 if (vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &cfreq)) 109 return -1; 110 } 111 112 if (context->iblock) { 113 vorbis_encode_ctl(vi, OV_ECTL_IBLOCK_SET, &context->iblock); 114 } 115 116 return vorbis_encode_setup_init(vi); 117} 118 119/* How many bytes are needed for a buffer of length 'l' */ 120static int xiph_len(int l) 121{ 122 return 1 + l / 255 + l; 123} 124 125static av_cold int oggvorbis_encode_init(AVCodecContext *avccontext) 126{ 127 OggVorbisContext *context = avccontext->priv_data; 128 ogg_packet header, header_comm, header_code; 129 uint8_t *p; 130 unsigned int offset; 131 132 vorbis_info_init(&context->vi); 133 if (oggvorbis_init_encoder(&context->vi, avccontext) < 0) { 134 av_log(avccontext, AV_LOG_ERROR, "oggvorbis_encode_init: init_encoder failed\n"); 135 return -1; 136 } 137 vorbis_analysis_init(&context->vd, &context->vi); 138 vorbis_block_init(&context->vd, &context->vb); 139 140 vorbis_comment_init(&context->vc); 141 vorbis_comment_add_tag(&context->vc, "encoder", LIBAVCODEC_IDENT); 142 143 vorbis_analysis_headerout(&context->vd, &context->vc, &header, 144 &header_comm, &header_code); 145 146 avccontext->extradata_size = 147 1 + xiph_len(header.bytes) + xiph_len(header_comm.bytes) + 148 header_code.bytes; 149 p = avccontext->extradata = 150 av_malloc(avccontext->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); 151 p[0] = 2; 152 offset = 1; 153 offset += av_xiphlacing(&p[offset], header.bytes); 154 offset += av_xiphlacing(&p[offset], header_comm.bytes); 155 memcpy(&p[offset], header.packet, header.bytes); 156 offset += header.bytes; 157 memcpy(&p[offset], header_comm.packet, header_comm.bytes); 158 offset += header_comm.bytes; 159 memcpy(&p[offset], header_code.packet, header_code.bytes); 160 offset += header_code.bytes; 161 assert(offset == avccontext->extradata_size); 162 163#if 0 164 vorbis_block_clear(&context->vb); 165 vorbis_dsp_clear(&context->vd); 166 vorbis_info_clear(&context->vi); 167#endif 168 vorbis_comment_clear(&context->vc); 169 170 avccontext->frame_size = OGGVORBIS_FRAME_SIZE; 171 172 avccontext->coded_frame = avcodec_alloc_frame(); 173 avccontext->coded_frame->key_frame = 1; 174 175 return 0; 176} 177 178static int oggvorbis_encode_frame(AVCodecContext *avccontext, 179 unsigned char *packets, 180 int buf_size, void *data) 181{ 182 OggVorbisContext *context = avccontext->priv_data; 183 ogg_packet op; 184 signed short *audio = data; 185 int l; 186 187 if (data) { 188 const int samples = avccontext->frame_size; 189 float **buffer; 190 int c, channels = context->vi.channels; 191 192 buffer = vorbis_analysis_buffer(&context->vd, samples); 193 for (c = 0; c < channels; c++) { 194 int co = (channels > 8) ? c : 195 ff_vorbis_encoding_channel_layout_offsets[channels - 1][c]; 196 for (l = 0; l < samples; l++) 197 buffer[c][l] = audio[l * channels + co] / 32768.f; 198 } 199 vorbis_analysis_wrote(&context->vd, samples); 200 } else { 201 if (!context->eof) 202 vorbis_analysis_wrote(&context->vd, 0); 203 context->eof = 1; 204 } 205 206 while (vorbis_analysis_blockout(&context->vd, &context->vb) == 1) { 207 vorbis_analysis(&context->vb, NULL); 208 vorbis_bitrate_addblock(&context->vb); 209 210 while (vorbis_bitrate_flushpacket(&context->vd, &op)) { 211 /* i'd love to say the following line is a hack, but sadly it's 212 * not, apparently the end of stream decision is in libogg. */ 213 if (op.bytes == 1 && op.e_o_s) 214 continue; 215 if (context->buffer_index + sizeof(ogg_packet) + op.bytes > BUFFER_SIZE) { 216 av_log(avccontext, AV_LOG_ERROR, "libvorbis: buffer overflow."); 217 return -1; 218 } 219 memcpy(context->buffer + context->buffer_index, &op, sizeof(ogg_packet)); 220 context->buffer_index += sizeof(ogg_packet); 221 memcpy(context->buffer + context->buffer_index, op.packet, op.bytes); 222 context->buffer_index += op.bytes; 223// av_log(avccontext, AV_LOG_DEBUG, "e%d / %d\n", context->buffer_index, op.bytes); 224 } 225 } 226 227 l = 0; 228 if (context->buffer_index) { 229 ogg_packet *op2 = (ogg_packet *)context->buffer; 230 op2->packet = context->buffer + sizeof(ogg_packet); 231 232 l = op2->bytes; 233 avccontext->coded_frame->pts = av_rescale_q(op2->granulepos, (AVRational) { 1, avccontext->sample_rate }, avccontext->time_base); 234 //FIXME we should reorder the user supplied pts and not assume that they are spaced by 1/sample_rate 235 236 if (l > buf_size) { 237 av_log(avccontext, AV_LOG_ERROR, "libvorbis: buffer overflow."); 238 return -1; 239 } 240 241 memcpy(packets, op2->packet, l); 242 context->buffer_index -= l + sizeof(ogg_packet); 243 memmove(context->buffer, context->buffer + l + sizeof(ogg_packet), context->buffer_index); 244// av_log(avccontext, AV_LOG_DEBUG, "E%d\n", l); 245 } 246 247 return l; 248} 249 250static av_cold int oggvorbis_encode_close(AVCodecContext *avccontext) 251{ 252 OggVorbisContext *context = avccontext->priv_data; 253/* ogg_packet op ; */ 254 255 vorbis_analysis_wrote(&context->vd, 0); /* notify vorbisenc this is EOF */ 256 257 vorbis_block_clear(&context->vb); 258 vorbis_dsp_clear(&context->vd); 259 vorbis_info_clear(&context->vi); 260 261 av_freep(&avccontext->coded_frame); 262 av_freep(&avccontext->extradata); 263 264 return 0; 265} 266 267AVCodec ff_libvorbis_encoder = { 268 .name = "libvorbis", 269 .type = AVMEDIA_TYPE_AUDIO, 270 .id = CODEC_ID_VORBIS, 271 .priv_data_size = sizeof(OggVorbisContext), 272 .init = oggvorbis_encode_init, 273 .encode = oggvorbis_encode_frame, 274 .close = oggvorbis_encode_close, 275 .capabilities = CODEC_CAP_DELAY, 276 .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, 277 .long_name = NULL_IF_CONFIG_SMALL("libvorbis Vorbis"), 278 .priv_class = &class, 279 .defaults = defaults, 280}; 281