VorbisDecoder.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: VorbisDecoder.cpp * 00006 * * 00007 * * 00008 * * 00009 * ITEC institute of the University of Klagenfurt (Austria) * 00010 * http://www.itec.uni-klu.ac.at * 00011 * * 00012 * * 00013 * For more information visit the ViTooKi homepage: * 00014 * http://ViTooKi.sourceforge.net * 00015 * vitooki-user@lists.sourceforge.net * 00016 * vitooki-devel@lists.sourceforge.net * 00017 * * 00018 * This file is part of ViTooKi, a free video toolkit. * 00019 * ViTooKi is free software; you can redistribute it and/or * 00020 * modify it under the terms of the GNU General Public License * 00021 * as published by the Free Software Foundation; either version 2 * 00022 * of the License, or (at your option) any later version. * 00023 * * 00024 * This program is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU General Public License * 00030 * along with this program; if not, write to the Free Software * 00031 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * 00032 * MA 02111-1307, USA. * 00033 * * 00034 ***********************************************************************/ 00035 00036 /*********************************************************************** 00037 * * 00038 * REVISION HISTORY: * 00039 * * 00040 * * 00041 * * 00042 ***********************************************************************/ 00043 00044 00056 #ifdef ENABLE_OGG 00057 00058 #include "VorbisDecoder.hpp" 00059 00060 vorbis_info *vi; 00061 vorbis_block *vb; 00062 00063 VorbisDecoder::VorbisDecoder(AudioESInfo* es) { 00064 this->es = es; 00065 strcpy(name,"VorbisDecoder"); 00066 FrameCount = 0; 00067 Status = 0; 00068 initialized = false; 00069 lastTS=0; 00070 // inputBuffer = new unsigned char[MAD_INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD]; 00071 } 00072 00073 00074 VorbisDecoder::~VorbisDecoder() { 00075 if (initialized) { 00076 } 00077 delete [] inputBuffer; 00078 } 00079 00080 int audiobuf_fill = 0; 00081 int audiobuf_ready = 0; 00082 double audiotime; 00083 ogg_int16_t *audiobuf; 00084 ogg_int64_t *audiobuf_granulepos=0; 00085 00086 void VorbisDecoder::initialize() { 00087 /* First the structures used by libvorbis must be initialized. */ 00088 00089 OGGHandler *ogh = OGGContainerFile::getOGGHandler(); 00090 OGGStreamInfo *tmp = ogh->osi; 00091 dprintf_full("VorbisDecoder::initialize()\n"); 00092 00093 vd = new vorbis_dsp_state; 00094 vb = new vorbis_block; 00095 00096 if(tmp){ 00097 do{ 00098 // in the VorbisDecoder we only seek for VORBIS streams 00099 if(tmp->getStreamType() == OGG_VORBIS){ 00100 dprintf_full("VorbisDecoder::initialize(): FOUND OGG_VORBIS\n"); 00101 osi = tmp; 00102 break; 00103 } 00104 tmp = tmp->getNext(); 00105 }while(tmp); 00106 } 00107 if(!osi){ 00108 dprintf_err("VorbisDecoder::initialize(): no stream in OGG-file found... ABORTING!\n"); 00109 exit(1); 00110 } 00111 00112 vi = (vorbis_info*)osi->getCodecInfo(); 00113 00114 vorbis_synthesis_init(vd, vi); 00115 vorbis_block_init(vd, vb); 00116 00117 initialized=true; 00118 numInFrames = 0; 00119 } 00120 00121 00122 int samplesprocessed = 0; 00123 00124 /***************************************************************/ 00125 list < Frame * > VorbisDecoder::adapt(Frame * frm) { 00126 OGGContainerFile::oggMutexLock("VorbisDecoder"); 00127 list < Frame * >tmp; 00128 u32 thisCTS; 00129 int thisSec; 00130 AU *au = frm->getAU(); 00131 00132 ogg_packet *op = (ogg_packet*)au->payload; 00133 00134 double start_dtime, now_dtime; 00135 struct timeval now_tv; 00136 gettimeofday(&now_tv,NULL); 00137 start_dtime = now_tv.tv_sec + now_tv.tv_usec/1000000.0; 00138 00139 dprintf_full("VorbisDecoder::adapt: got Frame %p, AU %p, cts %u!\n",frm, frm->getAU(), frm->getAU()->cts); 00140 00141 //initialize decoder 00142 if (!initialized) { 00143 initialize(); 00144 } 00145 00146 if (frm->getAU() == NULL){ 00147 dprintf_full("VorbisDecoder::adapt: frm->getAU() was NULL!!\n"); 00148 OGGContainerFile::oggMutexRelease("VorbisDecoder"); 00149 return tmp; 00150 } 00151 00152 thisCTS = au->cts; 00153 thisSec = (int)floor((double)thisCTS / es->getMediaTimeScale()); 00154 dprintf_full("VorbisDecoder::adapt: frame %i (size %i) CTS %i, VOP increment %i, samplerate %i Hz, Channels: %i, thisSec: %i, op->bytes: %li\n", 00155 numInFrames, 00156 au->size, 00157 thisCTS, 00158 es->getVOPTimeIncrement(), 00159 es->getSampleRate(), 00160 es->getAudioChannels(), 00161 thisSec, 00162 op->bytes); 00163 00164 numInFrames++; 00165 00166 int samples; 00167 float **pcm; 00168 int i,j; 00169 AU *dAU = new AU(); 00170 UncompressedAudioFrame *uaf; 00171 // check if all OK 00172 // and submit Ogg-Packet to Vorbis Synthesis 00173 { 00174 if(vorbis_synthesis(vb, op) == 0) 00175 vorbis_synthesis_blockin(vd,vb); 00176 00177 samples = vorbis_synthesis_pcmout(vd, &pcm); 00178 } 00179 00180 // if we have pcmdata... copy 00181 if(samples > 0) { 00182 samplesprocessed += samples; 00183 00184 // dAU->payload ist u8 00185 // ein Sample hat 16 bits --> * 2 00186 // stereo --> * 2 00187 // mono --> * 1 00188 int convsize = samples * 2 * vi->channels; 00189 int clipflag = 0; 00190 00191 dAU->size = convsize; 00192 dAU->payload = new u8[convsize]; 00193 00194 ogg_int16_t* ptr = (ogg_int16_t*)(dAU->payload); 00195 00196 // convsize/2 weil pro durchlauf beide channels berechnet werden 00197 for (i = 0; i < convsize/2/vi->channels; i++) { 00198 for (j = 0; j < vi->channels; j++) { 00199 int val = (int)rint(pcm[j][i]*32767.f); 00200 if(val > 32767){ clipflag = 1; val = 32767; } 00201 if(val < -32768){ clipflag = 1; val = -32768; } 00202 00203 //*(ptr++)=val; 00204 *(ptr++) = (ogg_int16_t)val; 00205 } 00206 } 00207 00208 if(clipflag) 00209 dprintf_full("VorbisDecoder::adapt: Clipping in frame %ld\n",(long)vd->sequence); 00210 00211 vorbis_synthesis_read(vd, samples); 00212 00213 if(vd->granulepos > 0) 00214 audiotime = vd->granulepos;// - samples + i; 00215 else 00216 audiotime += i; 00217 00218 // realtime = audiotime / rate / 2 / vi->channels 00219 // dAU->cts = (long)((audiotime/(vi->rate))*90000.0); 00220 //dAU->cts = (int)((samplesprocessed-samples)*90000.0/es->getSampleRate()); 00221 dAU->cts = (int)((audiotime-i)*90000.0/es->getSampleRate()); 00222 dAU->dts = dAU->cts; 00223 00224 //FIXME: dirty hack by Mike 00225 //after some audio frames, start to adjust variable frame sizes to the average 00226 if (numInFrames > 100){ 00227 dprintf_full("VorbisDecoder::adapt: setVOPTimeIncrement(%li) <- %i / %li * 90.000\n", 00228 (long)(((float)samples/(float)vi->rate)*90000.0), 00229 samples, 00230 vi->rate); 00231 es->setVOPTimeIncrement( 00232 (long)(((float)samples/(float)vi->rate)*90000.0)); 00233 } 00234 // es->setVOPTimeIncrement(dAU->cts/numInFrames); 00235 00236 dprintf_full("VorbisDecoder::adapt: aud_timestamp: %f, aud_gran: %li (%li), cts: %u, VOPInc %i, samples: %i (%i), samplesprocessed: %i, numinframes: %i\n", 00237 dAU->cts/90000.0, 00238 (long) audiotime, (long)vd->granulepos, 00239 dAU->cts, 00240 es->getVOPTimeIncrement(), 00241 samples,i, 00242 samplesprocessed, 00243 numInFrames); 00244 00245 00246 uaf = new UncompressedAudioFrame(Frame::RAW_AUDIO); 00247 uaf->setAU(dAU); 00248 tmp.push_back(uaf); 00249 00250 } 00251 00252 //FIXME: assert(isAudioFrame) 00253 gettimeofday(&now_tv,NULL); 00254 now_dtime = now_tv.tv_sec + now_tv.tv_usec/1000000.0; 00255 dprintf_full("VorbisDecoder::adapt(): worked for %2.0f msecs\n", 00256 (now_dtime-start_dtime)*1000.0); 00257 00258 if(au){ 00259 /******************************************************************** 00260 * somehow the ogg_packet struct has already been cleared. 00261 * there is no memory leak! but don't ask why... 00262 * so i only set payload to NULL, so that AccessUnit doesn't try to 00263 * delete payload. 00264 */ 00265 // printf("payload -> %p\n",au->payload); 00266 // au->payload=NULL; 00267 } 00268 00269 OGGContainerFile::oggMutexRelease("VorbisDecoder"); 00270 00271 return tmp; 00272 } 00273 00274 #endif