VorbisEncoder.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: VorbisEncoder.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 #include "VorbisEncoder.hpp" 00045 #include "CompressedVideoFrame.hpp" 00046 00047 00048 /***************************************************/ 00049 VorbisEncoder::VorbisEncoder(AudioESInfo *aes, u32 targetBitRate) { 00050 es = aes; 00051 muiTargetBitrate = es->getAvgBandwidth(); 00052 00053 dprintf_full("VorbisEncoder::VorbisEncoder: aes->getAvgBandwidth = %i, targetBitRate = %i\n", 00054 aes->getAvgBandwidth(), targetBitRate); 00055 OGGMuxDemuxIO::initVorbis(aes); 00056 00057 vi = OGGMuxDemuxIO::getVorbisInfo(); 00058 // vorbis_comment* vc; 00059 vd = OGGMuxDemuxIO::getVorbisDspState(); 00060 vb = OGGMuxDemuxIO::getVorbisBlock(); 00061 00062 strcpy(name,"VorbisEncoder-ViTooKi"); 00063 } 00064 00065 00066 /***************************************************/ 00067 void VorbisEncoder::initialize() { 00068 /* 00069 if(initialized) 00070 return; 00071 00072 dprintf_full("VorbisEncoder::initialize() Handle: %p BW: %i bps \n", 00073 mpEncoderHandle, muiTargetBitrate); 00074 00075 es->setAvgBandwidth(muiTargetBitrate); 00076 es->setVOPTimeIncrement(2350); // FIXME: 90000 DIV 38 frames, known by analyzing ffmpeg :( 00077 muiFrameNumber = 0; 00078 inBufSize=0; 00079 initialized = true; 00080 firstFrame = true; 00081 */ 00082 } 00083 00084 00085 /***************************************************/ 00086 VorbisEncoder::~VorbisEncoder() { 00087 // FFMPEGaudioEncoderClose(&mpEncoderHandle); 00088 } 00089 00090 00091 00092 /***************************************************/ 00093 list < Frame * >VorbisEncoder::adapt(Frame * frm) { 00094 CompressedAudioFrame *vorbisFrame = NULL; 00095 list < Frame * >frmList; 00096 u32 iFramesize = 0; 00097 ogg_packet op; 00098 00099 dprintf_full("VorbisEncoder::adapt: frame->AU->size: %i\n%s", frm->getAU()->size, frm->getAU()->toString()); 00100 00101 float** vorbis_buffer; 00102 int sampread = 0, count=0, i=0, j=0; 00103 00104 int Bps = 2; 00105 int channels = 2; 00106 00107 sampread= (frm->getAU()->size) / Bps / channels; // assuming ( 2 Bytes / sample ) ( 2 channels ) 00108 00109 vorbis_buffer=vorbis_analysis_buffer(vd, sampread); 00110 00111 // payload has to be treated as signed char 00112 signed char* payload; 00113 payload = (signed char*)(frm->getAU()->payload); 00114 /* uninterleave samples */ 00115 for(i=0; i<sampread; i++){ 00116 for(j=0; j<channels; j++){ 00117 vorbis_buffer[j][i]= 00118 ((payload[count+1]<<8) | 00119 (0x00ff & (int) payload[count])) 00120 / 32768.f; 00121 count += 2; 00122 } 00123 } 00124 vorbis_analysis_wrote(vd, sampread); 00125 00126 while(vorbis_analysis_blockout(vd, vb) == 1){ 00127 /* analysis, assume we want to use bitrate management */ 00128 vorbis_analysis(vb, NULL); 00129 vorbis_bitrate_addblock(vb); 00130 00131 /* get packtes */ 00132 while(vorbis_bitrate_flushpacket(vd, &op)){ 00133 AU *pAU = new AU(frm->getAU()); 00134 u8* payload = new u8[op.bytes + sizeof(ogg_packet)]; 00135 memcpy(payload, &op, sizeof(ogg_packet)); 00136 memcpy(payload+sizeof(ogg_packet), op.packet, op.bytes); 00137 00138 ((ogg_packet*)payload)->packet = payload + sizeof(ogg_packet); 00139 00140 pAU->size = op.bytes + sizeof(ogg_packet); 00141 pAU->payload = payload; 00142 pAU->cts = muiFrameNumber * es->getVOPTimeIncrement(); 00143 00144 vorbisFrame = new CompressedAudioFrame(Frame::VORBIS_AUDIO); 00145 00146 vorbisFrame->setAU(pAU); 00147 vorbisFrame->setMediaTimeScale(es->getMediaTimeScale()); 00148 00149 frmList.push_back(vorbisFrame); 00150 00151 00152 muiFrameNumber++; 00153 } 00154 } 00155 00156 00157 /* 00158 #define PCM_FRAME_SIZE (1152*2*2) //FIXME: should be read from AVCodecContext->frame_size 00159 00160 if (inBufSize > 0) { // smth was left from last round.... 00161 memcpy(mpInBuf+inBufSize, frm->getAU()->payload, frm->getAU()->size); 00162 dprintf_full("MP3Encoder::adapt %i bytes were left from last round...stored further %i bytes\n",inBufSize,frm->getAU()->size); 00163 inBufSize += frm->getAU()->size; 00164 00165 if (inBufSize >= PCM_FRAME_SIZE) { 00166 iFramesize = FFMPEGaudioEncodeFrame(mpEncoderHandle, (char *)mpInBuf, mpOutBuf); 00167 inBufSize -= PCM_FRAME_SIZE; 00168 assert(inBufSize <= PCM_FRAME_SIZE); //avoid overlapping rest-buffer 00169 memcpy(mpInBuf,mpInBuf+PCM_FRAME_SIZE,inBufSize); //move rest to the front 00170 00171 if (iFramesize > 0) { 00172 AU *pAU = new AU(frm->getAU()); 00173 u8 *payload = new u8[iFramesize]; 00174 memcpy(payload, mpOutBuf, iFramesize); 00175 00176 pAU->size = iFramesize; 00177 pAU->payload = payload; 00178 pAU->cts = muiFrameNumber * es->getVOPTimeIncrement(); 00179 00180 mpgFrame = new CompressedAudioFrame(Frame::MP3_AUDIO); 00181 00182 //mpgFrame->detectFrameType(); 00183 mpgFrame->setAU(pAU); 00184 mpgFrame->setMediaTimeScale(es->getMediaTimeScale()); 00185 frmList.push_back(mpgFrame); 00186 dprintf_full("MP3Encoder::adapt overlapping frame: size %i bytes, %s frameNo %i, CTS %u:\r\n", 00187 pAU->size, Frame::VOPTypeToChar(mpgFrame->getType()), muiFrameNumber, 00188 mpgFrame->getAU()->cts); 00189 muiFrameNumber++; 00190 } else { 00191 dprintf_full("MP3Encoder::adapt ... filling encoder queue: no return data yet.\n"); 00192 } 00193 } else { 00194 dprintf_full("MP3Encoder::adapt ... still harvesting small pcm bits for one full frame...!\n"); 00195 } 00196 } // smth was left from last round.... 00197 else { //inBufSize==0, so store for next round 00198 memcpy(mpInBuf, frm->getAU()->payload, frm->getAU()->size); 00199 inBufSize= frm->getAU()->size; 00200 dprintf_full("MP3Encoder::adapt %i tail-bytes saved for next round...\n",inBufSize); 00201 } 00202 */ 00203 return frmList; 00204 } 00205 00206 00207 /***************************************************/ 00208 list < Frame * >VorbisEncoder::close() { 00209 list < Frame * >frmList; 00210 /* 00211 CompressedAudioFrame *mpgFrame = NULL; 00212 u32 iFramesize; 00213 00214 dprintf_full("MP3Encoder::close ... there are %i bytes left in inBuf, draining....\n",inBufSize); 00215 00216 if (inBufSize > 0) { 00217 //maybe FIXME: for large input frames, maybe more than one PCM_FRAME_SIZE is still in buffer? --> while() needed... 00218 assert(inBufSize <= PCM_FRAME_SIZE); //avoid overlapping rest-buffer 00219 iFramesize = FFMPEGaudioEncodeFrame(mpEncoderHandle, (char *)mpInBuf, mpOutBuf); 00220 00221 do { 00222 if (iFramesize > 0) { 00223 AU *pAU = new AU(); 00224 u8 *payload = new u8[iFramesize]; 00225 memcpy(payload, mpOutBuf, iFramesize); 00226 00227 pAU->size = iFramesize; 00228 pAU->payload = payload; 00229 pAU->cts = muiFrameNumber * es->getVOPTimeIncrement(); 00230 00231 mpgFrame = new CompressedAudioFrame(Frame::MP3_AUDIO); 00232 00233 //mpgFrame->detectFrameType(); 00234 mpgFrame->setAU(pAU); 00235 mpgFrame->setMediaTimeScale(es->getMediaTimeScale()); 00236 frmList.push_back(mpgFrame); 00237 dprintf_full("MP3Encoder::close FINAL frame: size %i bytes, %s frameNo %i, CTS %u:\n", 00238 pAU->size, Frame::VOPTypeToChar(mpgFrame->getType()), muiFrameNumber, 00239 mpgFrame->getAU()->cts); 00240 muiFrameNumber++; 00241 } else { 00242 dprintf_err("MP3Encoder::close ... FINAL pcm samples didnt lead to encoded frame?!?!\n"); 00243 } 00244 iFramesize = FFMPEGaudioEncodeFrame(mpEncoderHandle, NULL, mpOutBuf); 00245 } while (iFramesize > 0); 00246 00247 } else { 00248 dprintf_full("MP3Encoder::close ... nothing left to decode.\n"); 00249 } 00250 00251 */ 00252 return frmList; 00253 } 00254 00255 Adaptor* VorbisEncoder::clone(){ 00256 return NULL; 00257 }