1 /*************************************************************************** 2 audiocodec_ogg.cpp - description 3 ------------------- 4 begin : Thu May 23 2002 5 copyright : (C) 2002 by mean 6 email : fixounet@free.fr 7 8 Strongly inspired by mplayer ogg vorbis decoder 9 (ripp off should be more appropriate) 10 11 We expect the first packet as extraData. It contains needed info such 12 as frequency/channels etc... 13 14 How to deal with comment and codebook ? 15 Mmmmm 16 17 ***************************************************************************/ 18 19 20 /*************************************************************************** 21 * * 22 * This program is free software; you can redistribute it and/or modify * 23 * it under the terms of the GNU General Public License as published by * 24 * the Free Software Foundation; either version 2 of the License, or * 25 * (at your option) any later version. * 26 * * 27 ***************************************************************************/ 28 #include <vorbis/codec.h> 29 30 #include "ADM_default.h" 31 #include "ADM_ad_plugin.h" 32 #include "ADM_ad_vorbis.h" 33 #include "ADM_coreUtils.h" 34 #include "ADM_audioXiphUtils.h" 35 36 37 /** 38 * \class ADM_vorbis 39 */ 40 class ADM_vorbis : public ADM_Audiocodec 41 { 42 protected: 43 oggVorbis _context; 44 45 public: 46 ADM_vorbis(uint32_t fourcc, WAVHeader *info, uint32_t l, uint8_t *d); 47 virtual ~ADM_vorbis(); 48 virtual uint8_t run(uint8_t *inptr, uint32_t nbIn, float *outptr, uint32_t *nbOut); isCompressed(void)49 virtual uint8_t isCompressed(void) {return 1;} isDecompressable(void)50 virtual uint8_t isDecompressable(void) {return 1;} 51 virtual bool resetAfterSeek(void) ; 52 }; 53 54 // Supported formats + declare our plugin 55 //******************************************************* 56 static ad_supportedFormat Formats[]={ 57 {WAV_OGG_VORBIS,AD_MEDIUM_QUAL}, 58 }; 59 DECLARE_AUDIO_DECODER(ADM_vorbis, // Class 60 0,0,1, // Major, minor,patch 61 Formats, // Supported formats 62 "libVorbis decoder plugin for avidemux (c) Mean\n"); // Desc 63 //******************************************************** 64 65 ~ADM_vorbis()66 ADM_vorbis::~ADM_vorbis() 67 { 68 if(_init) 69 { 70 vorbis_block_clear(&(_context.vblock)); 71 vorbis_info_clear(&(_context.vinfo)); 72 } 73 _init=false; 74 } 75 /** 76 * 77 * @param name 78 * @param pack 79 */ printPacket(const char * name,ogg_packet * pack)80 static void printPacket(const char *name, ogg_packet *pack) 81 { 82 ADM_warning(" sending %s packet of size %d\n",name,pack->bytes); 83 mixDump(pack->packet,pack->bytes); 84 } 85 /** 86 * 87 * @param name 88 * @param error 89 */ printError(const char * name,int error)90 static void printError(const char *name, int error) 91 { 92 ADM_warning(" Error %d when processing %s\n",error,name); 93 94 #define VERR(x) case x: ADM_warning(#x"\n") ;break; 95 96 switch(error) 97 { 98 VERR(OV_EREAD) 99 VERR(OV_EFAULT ) 100 VERR(OV_EIMPL ) 101 VERR(OV_EINVAL ) 102 VERR(OV_ENOTVORBIS ) 103 VERR(OV_EBADHEADER ) 104 VERR(OV_EVERSION ) 105 VERR(OV_ENOTAUDIO ) 106 VERR(OV_EBADPACKET ) 107 VERR(OV_EBADLINK ) 108 VERR(OV_ENOSEEK ) 109 110 default: ADM_warning("Unknown error\n"); 111 break; 112 } 113 114 } 115 /** 116 * 117 * @param fcc 118 * @param info 119 * @param extra 120 * @param extraData 121 */ ADM_vorbis(uint32_t fcc,WAVHeader * info,uint32_t extra,uint8_t * extraData)122 ADM_vorbis::ADM_vorbis(uint32_t fcc, WAVHeader *info, uint32_t extra, uint8_t *extraData) 123 : ADM_Audiocodec(fcc,*info) 124 { 125 ogg_packet packet; 126 vorbis_comment comment; 127 oggVorbis *vrbis; 128 uint8_t *hdr,*cmt,*code; 129 uint32_t size_hdr,size_cmt, size_code; 130 uint32_t *ptr; 131 int error; 132 #define MANAGE_ERROR(st,er) {if(er<0) {printError(st,er); return ;}} 133 _init=0; 134 ADM_info("Trying to initialize vorbis codec with %d bytes of header data\n",(int)extra); 135 136 _init=false; 137 memset(&(_context),0,sizeof(_context)); 138 139 uint8_t *packets[3]; 140 int packetsLen[3]; 141 142 if(!ADMXiph::admExtraData2packets(extraData,extra,packets,packetsLen)) 143 { 144 return ; 145 } 146 147 // init everything 148 vorbis_info_init(&(_context.vinfo)); 149 vorbis_comment_init(&(_context.vcomment)); 150 151 152 // Feed header passed as extraData 153 packet.bytes=packetsLen[0]; 154 packet.packet=packets[0]; 155 packet.b_o_s=1; // yes, it is a new stream 156 printPacket("1st packet",&packet); 157 error=vorbis_synthesis_headerin(&(_context.vinfo),&comment,&packet); 158 MANAGE_ERROR("1st packet",error); 159 // update some info in header this is the only place to get them 160 // especially frequency. 161 /* 162 info->channels=STRUCT->vinfo.channels; 163 info->frequency=STRUCT->vinfo.rate; 164 */ 165 info->byterate=_context.vinfo.bitrate_nominal>>3; 166 167 if(!info->byterate) 168 { 169 ADM_warning("Mmm, no nominal bitrate...\n"); 170 info->byterate=16000; 171 } 172 // now unpack comment 173 packet.bytes=packetsLen[1]; 174 packet.packet=packets[1]; 175 packet.b_o_s=0; // Not new 176 printPacket("2nd packet",&packet); 177 178 error=vorbis_synthesis_headerin(&(_context.vinfo),&comment,&packet); 179 MANAGE_ERROR("2nd packet",error); 180 181 // and codebook 182 packet.bytes=packetsLen[2]; 183 packet.packet=packets[2]; 184 packet.b_o_s=0; // Not new 185 printPacket("3rd packet",&packet); 186 187 error=vorbis_synthesis_headerin(&(_context.vinfo),&comment,&packet); 188 MANAGE_ERROR("3rd packet",error); 189 190 vorbis_comment_clear(&comment); 191 vorbis_synthesis_init(&(_context.vdsp),&(_context.vinfo)); 192 vorbis_block_init(&(_context.vdsp),&(_context.vblock)); 193 ADM_info("Vorbis init successfull\n"); 194 _context.ampscale=1; 195 _init=1; 196 CHANNEL_TYPE *p_ch_type = channelMapping; 197 #define DOIT(y) *(p_ch_type++)=ADM_CH_##y; 198 switch(_context.vinfo.channels) 199 { 200 case 1: 201 case 2: 202 { 203 DOIT(FRONT_LEFT); 204 DOIT(FRONT_RIGHT); 205 break; 206 } 207 default: 208 case 5: 209 { 210 DOIT(FRONT_LEFT); 211 DOIT(FRONT_CENTER); 212 DOIT(FRONT_RIGHT); 213 214 215 DOIT(REAR_LEFT); 216 DOIT(REAR_RIGHT); 217 DOIT(LFE); 218 break; 219 } 220 } 221 } 222 /** 223 * 224 * @param inptr 225 * @param nbIn 226 * @param outptr 227 * @param nbOut 228 * @return 229 */ 230 run(uint8_t * inptr,uint32_t nbIn,float * outptr,uint32_t * nbOut)231 uint8_t ADM_vorbis::run(uint8_t *inptr, uint32_t nbIn, float *outptr, uint32_t *nbOut) 232 { 233 ogg_packet packet; 234 float **sample_pcm; 235 int nb_synth; 236 237 *nbOut=0; 238 if(!_init) return 0; 239 packet.b_o_s=0; 240 packet.e_o_s=0; 241 packet.bytes=nbIn; 242 packet.packet=inptr; 243 packet.granulepos=-1; 244 if(!vorbis_synthesis(&(_context.vblock),&packet)) 245 { 246 vorbis_synthesis_blockin(&(_context.vdsp),&(_context.vblock)); 247 } 248 nb_synth=vorbis_synthesis_pcmout(&(_context.vdsp),&sample_pcm); 249 if(nb_synth<0) 250 { 251 printf("error decoding vorbis %d\n",nb_synth); 252 return 0; 253 } 254 255 for (uint32_t samp = 0; samp < nb_synth; samp++) 256 for (uint8_t chan = 0; chan < _context.vinfo.channels; chan++) 257 *outptr++ = sample_pcm[chan][samp] * _context.ampscale; 258 259 *nbOut = _context.vinfo.channels * nb_synth; 260 261 // Puge them 262 vorbis_synthesis_read(&_context.vdsp,nb_synth); 263 //printf("This round : in %d bytes, out %d bytes synthetized:%d\n",nbIn,*nbOut,nb_synth); 264 return 1; 265 266 } 267 /** 268 \fn resetAfterSeek 269 \brief Try to flush the buffer 270 unsuccessfully :( 271 272 */ resetAfterSeek(void)273 bool ADM_vorbis::resetAfterSeek(void) 274 { 275 float **sample_pcm; 276 ogg_packet packet; 277 278 ADM_info("Vorbis-Resetting\n"); 279 vorbis_synthesis_pcmout(&(_context.vdsp),&sample_pcm); 280 vorbis_synthesis_restart(&(_context.vdsp)); 281 return true; 282 } 283 284 285