• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavcodec/libvorbis.c

Go to the documentation of this file.
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 "libavutil/opt.h"
00030 #include "avcodec.h"
00031 #include "bytestream.h"
00032 #include "vorbis.h"
00033 #include "libavutil/mathematics.h"
00034 
00035 #undef NDEBUG
00036 #include <assert.h>
00037 
00038 #define OGGVORBIS_FRAME_SIZE 64
00039 
00040 #define BUFFER_SIZE (1024*64)
00041 
00042 typedef struct OggVorbisContext {
00043     AVClass *av_class;
00044     vorbis_info vi ;
00045     vorbis_dsp_state vd ;
00046     vorbis_block vb ;
00047     uint8_t buffer[BUFFER_SIZE];
00048     int buffer_index;
00049     int eof;
00050 
00051     /* decoder */
00052     vorbis_comment vc ;
00053     ogg_packet op;
00054 
00055     double iblock;
00056 } OggVorbisContext ;
00057 
00058 static const AVOption options[]={
00059 {"iblock", "Sets the impulse block bias", offsetof(OggVorbisContext, iblock), FF_OPT_TYPE_DOUBLE, {.dbl = 0}, -15, 0, AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_ENCODING_PARAM},
00060 {NULL}
00061 };
00062 static const AVClass class = { "libvorbis", av_default_item_name, options, LIBAVUTIL_VERSION_INT };
00063 
00064 static av_cold int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) {
00065     OggVorbisContext *context = avccontext->priv_data ;
00066     double cfreq;
00067 
00068     if(avccontext->flags & CODEC_FLAG_QSCALE) {
00069         /* variable bitrate */
00070         if(vorbis_encode_setup_vbr(vi, avccontext->channels,
00071                 avccontext->sample_rate,
00072                 avccontext->global_quality / (float)FF_QP2LAMBDA / 10.0))
00073             return -1;
00074     } else {
00075         int minrate = avccontext->rc_min_rate > 0 ? avccontext->rc_min_rate : -1;
00076         int maxrate = avccontext->rc_min_rate > 0 ? avccontext->rc_max_rate : -1;
00077 
00078         /* constant bitrate */
00079         if(vorbis_encode_setup_managed(vi, avccontext->channels,
00080                 avccontext->sample_rate, minrate, avccontext->bit_rate, maxrate))
00081             return -1;
00082 
00083         /* variable bitrate by estimate, disable slow rate management */
00084         if(minrate == -1 && maxrate == -1)
00085             if(vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE2_SET, NULL))
00086                 return -1;
00087     }
00088 
00089     /* cutoff frequency */
00090     if(avccontext->cutoff > 0) {
00091         cfreq = avccontext->cutoff / 1000.0;
00092         if(vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &cfreq))
00093             return -1;
00094     }
00095 
00096     if(context->iblock){
00097         vorbis_encode_ctl(vi, OV_ECTL_IBLOCK_SET, &context->iblock);
00098     }
00099 
00100     if (avccontext->channels == 3 &&
00101             avccontext->channel_layout != (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) ||
00102         avccontext->channels == 4 &&
00103             avccontext->channel_layout != AV_CH_LAYOUT_2_2 &&
00104             avccontext->channel_layout != AV_CH_LAYOUT_QUAD ||
00105         avccontext->channels == 5 &&
00106             avccontext->channel_layout != AV_CH_LAYOUT_5POINT0 &&
00107             avccontext->channel_layout != AV_CH_LAYOUT_5POINT0_BACK ||
00108         avccontext->channels == 6 &&
00109             avccontext->channel_layout != AV_CH_LAYOUT_5POINT1 &&
00110             avccontext->channel_layout != AV_CH_LAYOUT_5POINT1_BACK ||
00111         avccontext->channels == 7 &&
00112             avccontext->channel_layout != (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) ||
00113         avccontext->channels == 8 &&
00114             avccontext->channel_layout != AV_CH_LAYOUT_7POINT1) {
00115         if (avccontext->channel_layout) {
00116             char name[32];
00117             av_get_channel_layout_string(name, sizeof(name), avccontext->channels,
00118                                          avccontext->channel_layout);
00119             av_log(avccontext, AV_LOG_ERROR, "%s not supported by Vorbis: "
00120                                              "output stream will have incorrect "
00121                                              "channel layout.\n", name);
00122         } else {
00123             av_log(avccontext, AV_LOG_WARNING, "No channel layout specified. The encoder "
00124                                                "will use Vorbis channel layout for "
00125                                                "%d channels.\n", avccontext->channels);
00126         }
00127     }
00128 
00129     return vorbis_encode_setup_init(vi);
00130 }
00131 
00132 /* How many bytes are needed for a buffer of length 'l' */
00133 static int xiph_len(int l) { return (1 + l / 255 + l); }
00134 
00135 static av_cold int oggvorbis_encode_init(AVCodecContext *avccontext) {
00136     OggVorbisContext *context = avccontext->priv_data ;
00137     ogg_packet header, header_comm, header_code;
00138     uint8_t *p;
00139     unsigned int offset;
00140 
00141     vorbis_info_init(&context->vi) ;
00142     if(oggvorbis_init_encoder(&context->vi, avccontext) < 0) {
00143         av_log(avccontext, AV_LOG_ERROR, "oggvorbis_encode_init: init_encoder failed\n") ;
00144         return -1 ;
00145     }
00146     vorbis_analysis_init(&context->vd, &context->vi) ;
00147     vorbis_block_init(&context->vd, &context->vb) ;
00148 
00149     vorbis_comment_init(&context->vc);
00150     vorbis_comment_add_tag(&context->vc, "encoder", LIBAVCODEC_IDENT) ;
00151 
00152     vorbis_analysis_headerout(&context->vd, &context->vc, &header,
00153                                 &header_comm, &header_code);
00154 
00155     avccontext->extradata_size=
00156         1 + xiph_len(header.bytes) + xiph_len(header_comm.bytes) +
00157         header_code.bytes;
00158     p = avccontext->extradata =
00159       av_malloc(avccontext->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
00160     p[0] = 2;
00161     offset = 1;
00162     offset += av_xiphlacing(&p[offset], header.bytes);
00163     offset += av_xiphlacing(&p[offset], header_comm.bytes);
00164     memcpy(&p[offset], header.packet, header.bytes);
00165     offset += header.bytes;
00166     memcpy(&p[offset], header_comm.packet, header_comm.bytes);
00167     offset += header_comm.bytes;
00168     memcpy(&p[offset], header_code.packet, header_code.bytes);
00169     offset += header_code.bytes;
00170     assert(offset == avccontext->extradata_size);
00171 
00172 /*    vorbis_block_clear(&context->vb);
00173     vorbis_dsp_clear(&context->vd);
00174     vorbis_info_clear(&context->vi);*/
00175     vorbis_comment_clear(&context->vc);
00176 
00177     avccontext->frame_size = OGGVORBIS_FRAME_SIZE ;
00178 
00179     avccontext->coded_frame= avcodec_alloc_frame();
00180     avccontext->coded_frame->key_frame= 1;
00181 
00182     return 0 ;
00183 }
00184 
00185 
00186 static int oggvorbis_encode_frame(AVCodecContext *avccontext,
00187                                   unsigned char *packets,
00188                            int buf_size, void *data)
00189 {
00190     OggVorbisContext *context = avccontext->priv_data ;
00191     ogg_packet op ;
00192     signed short *audio = data ;
00193     int l;
00194 
00195     if(data) {
00196         const int samples = avccontext->frame_size;
00197         float **buffer ;
00198         int c, channels = context->vi.channels;
00199 
00200         buffer = vorbis_analysis_buffer(&context->vd, samples) ;
00201         for (c = 0; c < channels; c++) {
00202             int co = (channels > 8) ? c :
00203                 ff_vorbis_encoding_channel_layout_offsets[channels-1][c];
00204             for(l = 0 ; l < samples ; l++)
00205                 buffer[c][l]=audio[l*channels+co]/32768.f;
00206         }
00207         vorbis_analysis_wrote(&context->vd, samples) ;
00208     } else {
00209         if(!context->eof)
00210             vorbis_analysis_wrote(&context->vd, 0) ;
00211         context->eof = 1;
00212     }
00213 
00214     while(vorbis_analysis_blockout(&context->vd, &context->vb) == 1) {
00215         vorbis_analysis(&context->vb, NULL);
00216         vorbis_bitrate_addblock(&context->vb) ;
00217 
00218         while(vorbis_bitrate_flushpacket(&context->vd, &op)) {
00219             /* i'd love to say the following line is a hack, but sadly it's
00220              * not, apparently the end of stream decision is in libogg. */
00221             if(op.bytes==1 && op.e_o_s)
00222                 continue;
00223             if (context->buffer_index + sizeof(ogg_packet) + op.bytes > BUFFER_SIZE) {
00224                 av_log(avccontext, AV_LOG_ERROR, "libvorbis: buffer overflow.");
00225                 return -1;
00226             }
00227             memcpy(context->buffer + context->buffer_index, &op, sizeof(ogg_packet));
00228             context->buffer_index += sizeof(ogg_packet);
00229             memcpy(context->buffer + context->buffer_index, op.packet, op.bytes);
00230             context->buffer_index += op.bytes;
00231 //            av_log(avccontext, AV_LOG_DEBUG, "e%d / %d\n", context->buffer_index, op.bytes);
00232         }
00233     }
00234 
00235     l=0;
00236     if(context->buffer_index){
00237         ogg_packet *op2= (ogg_packet*)context->buffer;
00238         op2->packet = context->buffer + sizeof(ogg_packet);
00239 
00240         l=  op2->bytes;
00241         avccontext->coded_frame->pts= av_rescale_q(op2->granulepos, (AVRational){1, avccontext->sample_rate}, avccontext->time_base);
00242         //FIXME we should reorder the user supplied pts and not assume that they are spaced by 1/sample_rate
00243 
00244         if (l > buf_size) {
00245             av_log(avccontext, AV_LOG_ERROR, "libvorbis: buffer overflow.");
00246             return -1;
00247         }
00248 
00249         memcpy(packets, op2->packet, l);
00250         context->buffer_index -= l + sizeof(ogg_packet);
00251         memmove(context->buffer, context->buffer + l + sizeof(ogg_packet), context->buffer_index);
00252 //        av_log(avccontext, AV_LOG_DEBUG, "E%d\n", l);
00253     }
00254 
00255     return l;
00256 }
00257 
00258 
00259 static av_cold int oggvorbis_encode_close(AVCodecContext *avccontext) {
00260     OggVorbisContext *context = avccontext->priv_data ;
00261 /*  ogg_packet op ; */
00262 
00263     vorbis_analysis_wrote(&context->vd, 0) ; /* notify vorbisenc this is EOF */
00264 
00265     vorbis_block_clear(&context->vb);
00266     vorbis_dsp_clear(&context->vd);
00267     vorbis_info_clear(&context->vi);
00268 
00269     av_freep(&avccontext->coded_frame);
00270     av_freep(&avccontext->extradata);
00271 
00272     return 0 ;
00273 }
00274 
00275 
00276 AVCodec ff_libvorbis_encoder = {
00277     "libvorbis",
00278     AVMEDIA_TYPE_AUDIO,
00279     CODEC_ID_VORBIS,
00280     sizeof(OggVorbisContext),
00281     oggvorbis_encode_init,
00282     oggvorbis_encode_frame,
00283     oggvorbis_encode_close,
00284     .capabilities= CODEC_CAP_DELAY,
00285     .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
00286     .long_name= NULL_IF_CONFIG_SMALL("libvorbis Vorbis"),
00287     .priv_class= &class,
00288 } ;

Generated on Wed Apr 11 2012 07:31:33 for FFmpeg by  doxygen 1.7.1