Libav
|
00001 /* 00002 * copyright (c) 2002 Mark Hills <mark@pogo.org.uk> 00003 * 00004 * This file is part of FFmpeg. 00005 * 00006 * FFmpeg is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * FFmpeg is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with FFmpeg; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00027 #include <vorbis/vorbisenc.h> 00028 00029 #include "avcodec.h" 00030 #include "bytestream.h" 00031 00032 #undef NDEBUG 00033 #include <assert.h> 00034 00035 #define OGGVORBIS_FRAME_SIZE 64 00036 00037 #define BUFFER_SIZE (1024*64) 00038 00039 typedef struct OggVorbisContext { 00040 vorbis_info vi ; 00041 vorbis_dsp_state vd ; 00042 vorbis_block vb ; 00043 uint8_t buffer[BUFFER_SIZE]; 00044 int buffer_index; 00045 int eof; 00046 00047 /* decoder */ 00048 vorbis_comment vc ; 00049 ogg_packet op; 00050 } OggVorbisContext ; 00051 00052 00053 static av_cold int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) { 00054 double cfreq; 00055 00056 if(avccontext->flags & CODEC_FLAG_QSCALE) { 00057 /* variable bitrate */ 00058 if(vorbis_encode_setup_vbr(vi, avccontext->channels, 00059 avccontext->sample_rate, 00060 avccontext->global_quality / (float)FF_QP2LAMBDA / 10.0)) 00061 return -1; 00062 } else { 00063 /* constant bitrate */ 00064 if(vorbis_encode_setup_managed(vi, avccontext->channels, 00065 avccontext->sample_rate, -1, avccontext->bit_rate, -1)) 00066 return -1; 00067 00068 #ifdef OGGVORBIS_VBR_BY_ESTIMATE 00069 /* variable bitrate by estimate */ 00070 if(vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE_AVG, NULL)) 00071 return -1; 00072 #endif 00073 } 00074 00075 /* cutoff frequency */ 00076 if(avccontext->cutoff > 0) { 00077 cfreq = avccontext->cutoff / 1000.0; 00078 if(vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &cfreq)) 00079 return -1; 00080 } 00081 00082 return vorbis_encode_setup_init(vi); 00083 } 00084 00085 static av_cold int oggvorbis_encode_init(AVCodecContext *avccontext) { 00086 OggVorbisContext *context = avccontext->priv_data ; 00087 ogg_packet header, header_comm, header_code; 00088 uint8_t *p; 00089 unsigned int offset, len; 00090 00091 vorbis_info_init(&context->vi) ; 00092 if(oggvorbis_init_encoder(&context->vi, avccontext) < 0) { 00093 av_log(avccontext, AV_LOG_ERROR, "oggvorbis_encode_init: init_encoder failed\n") ; 00094 return -1 ; 00095 } 00096 vorbis_analysis_init(&context->vd, &context->vi) ; 00097 vorbis_block_init(&context->vd, &context->vb) ; 00098 00099 vorbis_comment_init(&context->vc); 00100 vorbis_comment_add_tag(&context->vc, "encoder", LIBAVCODEC_IDENT) ; 00101 00102 vorbis_analysis_headerout(&context->vd, &context->vc, &header, 00103 &header_comm, &header_code); 00104 00105 len = header.bytes + header_comm.bytes + header_code.bytes; 00106 avccontext->extradata_size= 64 + len + len/255; 00107 p = avccontext->extradata= av_mallocz(avccontext->extradata_size); 00108 p[0] = 2; 00109 offset = 1; 00110 offset += av_xiphlacing(&p[offset], header.bytes); 00111 offset += av_xiphlacing(&p[offset], header_comm.bytes); 00112 memcpy(&p[offset], header.packet, header.bytes); 00113 offset += header.bytes; 00114 memcpy(&p[offset], header_comm.packet, header_comm.bytes); 00115 offset += header_comm.bytes; 00116 memcpy(&p[offset], header_code.packet, header_code.bytes); 00117 offset += header_code.bytes; 00118 avccontext->extradata_size = offset; 00119 avccontext->extradata= av_realloc(avccontext->extradata, avccontext->extradata_size); 00120 00121 /* vorbis_block_clear(&context->vb); 00122 vorbis_dsp_clear(&context->vd); 00123 vorbis_info_clear(&context->vi);*/ 00124 vorbis_comment_clear(&context->vc); 00125 00126 avccontext->frame_size = OGGVORBIS_FRAME_SIZE ; 00127 00128 avccontext->coded_frame= avcodec_alloc_frame(); 00129 avccontext->coded_frame->key_frame= 1; 00130 00131 return 0 ; 00132 } 00133 00134 00135 static int oggvorbis_encode_frame(AVCodecContext *avccontext, 00136 unsigned char *packets, 00137 int buf_size, void *data) 00138 { 00139 OggVorbisContext *context = avccontext->priv_data ; 00140 ogg_packet op ; 00141 signed short *audio = data ; 00142 int l; 00143 00144 if(data) { 00145 int samples = OGGVORBIS_FRAME_SIZE; 00146 float **buffer ; 00147 00148 buffer = vorbis_analysis_buffer(&context->vd, samples) ; 00149 if(context->vi.channels == 1) { 00150 for(l = 0 ; l < samples ; l++) 00151 buffer[0][l]=audio[l]/32768.f; 00152 } else { 00153 for(l = 0 ; l < samples ; l++){ 00154 buffer[0][l]=audio[l*2]/32768.f; 00155 buffer[1][l]=audio[l*2+1]/32768.f; 00156 } 00157 } 00158 vorbis_analysis_wrote(&context->vd, samples) ; 00159 } else { 00160 if(!context->eof) 00161 vorbis_analysis_wrote(&context->vd, 0) ; 00162 context->eof = 1; 00163 } 00164 00165 while(vorbis_analysis_blockout(&context->vd, &context->vb) == 1) { 00166 vorbis_analysis(&context->vb, NULL); 00167 vorbis_bitrate_addblock(&context->vb) ; 00168 00169 while(vorbis_bitrate_flushpacket(&context->vd, &op)) { 00170 /* i'd love to say the following line is a hack, but sadly it's 00171 * not, apparently the end of stream decision is in libogg. */ 00172 if(op.bytes==1) 00173 continue; 00174 memcpy(context->buffer + context->buffer_index, &op, sizeof(ogg_packet)); 00175 context->buffer_index += sizeof(ogg_packet); 00176 memcpy(context->buffer + context->buffer_index, op.packet, op.bytes); 00177 context->buffer_index += op.bytes; 00178 // av_log(avccontext, AV_LOG_DEBUG, "e%d / %d\n", context->buffer_index, op.bytes); 00179 } 00180 } 00181 00182 l=0; 00183 if(context->buffer_index){ 00184 ogg_packet *op2= (ogg_packet*)context->buffer; 00185 op2->packet = context->buffer + sizeof(ogg_packet); 00186 00187 l= op2->bytes; 00188 avccontext->coded_frame->pts= av_rescale_q(op2->granulepos, (AVRational){1, avccontext->sample_rate}, avccontext->time_base); 00189 //FIXME we should reorder the user supplied pts and not assume that they are spaced by 1/sample_rate 00190 00191 memcpy(packets, op2->packet, l); 00192 context->buffer_index -= l + sizeof(ogg_packet); 00193 memcpy(context->buffer, context->buffer + l + sizeof(ogg_packet), context->buffer_index); 00194 // av_log(avccontext, AV_LOG_DEBUG, "E%d\n", l); 00195 } 00196 00197 return l; 00198 } 00199 00200 00201 static av_cold int oggvorbis_encode_close(AVCodecContext *avccontext) { 00202 OggVorbisContext *context = avccontext->priv_data ; 00203 /* ogg_packet op ; */ 00204 00205 vorbis_analysis_wrote(&context->vd, 0) ; /* notify vorbisenc this is EOF */ 00206 00207 vorbis_block_clear(&context->vb); 00208 vorbis_dsp_clear(&context->vd); 00209 vorbis_info_clear(&context->vi); 00210 00211 av_freep(&avccontext->coded_frame); 00212 av_freep(&avccontext->extradata); 00213 00214 return 0 ; 00215 } 00216 00217 00218 AVCodec libvorbis_encoder = { 00219 "libvorbis", 00220 AVMEDIA_TYPE_AUDIO, 00221 CODEC_ID_VORBIS, 00222 sizeof(OggVorbisContext), 00223 oggvorbis_encode_init, 00224 oggvorbis_encode_frame, 00225 oggvorbis_encode_close, 00226 .capabilities= CODEC_CAP_DELAY, 00227 .sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE}, 00228 .long_name= NULL_IF_CONFIG_SMALL("libvorbis Vorbis"), 00229 } ;