Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members
ESInfo.cpp
00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: ESInfo.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 "ESInfo.hpp" 00045 #ifndef WINCE 00046 #include <iostream> 00047 #endif 00048 #include "ContainerInfo.hpp" 00049 #include "BitField.hpp" 00050 #include "ReferenceCounter.hpp" 00051 00052 #include "container/ffMP4ContainerFile.hpp" 00053 #include "container/ISOMP4ContainerFile.hpp" 00054 00055 00056 #include "net/SDP.hpp" 00057 00058 ESInfo::ESInfo(u64 streamid, u32 streamtype, ContainerInfo * vob, u32 timeIncrement, 00059 u8 * encodeddecconf, u32 objtype, 00060 u32 bufsize, u32 avgBand, u32 maxBand, 00061 u32 timeScale, u64 dur, u32 size, bool comp, 00062 CodecID codecID, float stQuality) { 00063 dprintf_full("ESInfo::ESInfo created with duration %llu timeIncrement %u avgBW %u kbps\n", 00064 dur, timeIncrement,avgBand/1024); 00065 assert(timeScale>0); // otherwise div zero Bugs are possible 00066 description[0]='\0'; 00067 frameStatistic=NULL; 00068 decConfUpdated=false; 00069 input = NULL; 00070 streamId = streamid; 00071 vo = vob; 00072 encodedDecoderConfig = encodeddecconf; 00073 objectType = objtype; 00074 streamType = streamtype; 00075 bufferSize = bufsize; 00076 00077 avgBandwidth = avgBand; 00078 maxBandwidth = maxBand; 00079 mediaTimeScale = timeScale; 00080 duration = dur; 00081 mediaSize = size; 00082 vopTimeIncrement=timeIncrement; 00083 complete=comp; 00084 existingClones=NULL; 00085 usageCounter=new ReferenceCounter(); 00086 codec_id = codecID; 00087 quality = stQuality; 00088 generateDescriptionText(); 00089 } 00090 00091 00092 ESInfo::~ESInfo() { 00093 dprintf_full("ESInfo::~ESInfo(): input %s streamId %llu\n", (input?input:"NULL"), streamId); 00094 if (input) 00095 delete[] input; 00096 00097 if (encodedDecoderConfig) 00098 delete[] encodedDecoderConfig; 00099 00100 if(frameStatistic) 00101 delete frameStatistic; 00102 00103 if(existingClones && existingClones->decreaseAndDeactivateWhenUsage(0)) { 00104 delete existingClones; 00105 existingClones=NULL; 00106 } 00107 if(usageCounter) { 00108 delete usageCounter; 00109 usageCounter=NULL; 00110 } 00111 } 00112 00113 00114 00115 void ESInfo::setEncodedDecoderConfig(u8 * enc) { 00116 if (encodedDecoderConfig) 00117 delete encodedDecoderConfig; 00118 encodedDecoderConfig = enc; 00119 00120 decConfUpdated=true; 00121 } 00122 00123 00126 void ESInfo::setDecoderConfig(const u8 * dec, int size) { 00127 u8* dummy = new u8[size * 2 + 1]; 00128 SDP::encodeDecoderConfig(dummy, dec, size); 00129 setEncodedDecoderConfig(dummy); 00130 } 00131 00132 00136 void ESInfo::setInput(const char *inp) { 00137 dprintf_full("ESInfo::setInput: old input %s new input %s\n",(input?input:"NULL"),(inp?inp:"NULL")); 00138 if (!inp) 00139 return; 00140 if (input) 00141 delete[] input; 00142 input = new char[strlen(inp) + 1]; 00143 strcpy(input, inp); 00144 char* tmp=input; 00145 #ifdef WIN32 00146 while(tmp=strchr(tmp,'/')) { 00147 *tmp='\\'; 00148 tmp++; 00149 } 00150 #else 00151 while((tmp=strchr(tmp,'\\')) != NULL) { 00152 *tmp='/'; 00153 tmp++; 00154 } 00155 #endif 00156 } 00157 00158 u32 ESInfo::getHeaders(u8 **pHeaders) const 00159 { 00160 if (!encodedDecoderConfig) { 00161 dprintf_err("ESInfo::getHeaders No decoder Config found\n"); 00162 return 0; 00163 } 00164 assert( (*pHeaders) == NULL); 00165 int size = strlen((char *) encodedDecoderConfig); 00166 if (size < 1) { 00167 dprintf_err("ESInfo::getHeaders %llu: Failed to get EncodedDecoderConfig, got %s\n", 00168 streamId, encodedDecoderConfig); 00169 return 0; 00170 } 00171 00172 u8 *decConf = new u8[size / 2 + 1]; 00173 SDP::decodeDecoderConfig(decConf, encodedDecoderConfig, size); 00174 // problem: decoderConfig is some extended Header 00175 // we have some leading bytes, and then we have 00 00 01h, the start of the header 00176 // so search for this hex value 00177 int i = 0; 00178 u32 data = 65535; 00179 u32 offset = 0; 00180 // generic streams have different headers 00181 if (!isVisualStream() && !isAudioStream()) { 00182 i = size / 2; // do not change them 00183 } 00184 00185 while (i < size / 2 - 1 && (data & 0x00FFFFFF) != 1) { 00186 data <<= 8; 00187 data += decConf[i]; 00188 i++; 00189 } 00190 if ((data & 0x00FFFFFF) == 1) { // we read 2 zeros followed by a 1 00191 // found the header 00192 dprintf_full("ESInfo::getHeaders: Found header in decconf %x\n", data); 00193 // then set offset to point to the first 0 00194 // i points after the 1 -> header is 00 00 01 xx-> reduce by 3 00195 // 00 01 02 03 00 00 01 xx -> i=7 -> i=4 00196 offset = i - sizeof(data) + 1; 00197 } 00198 00199 *pHeaders= new u8[size / 2 - offset+1]; 00200 memcpy(*pHeaders, (decConf + offset), size / 2 - offset); 00201 (*pHeaders)[size / 2 - offset] = 0; 00202 dprintf_full 00203 ("ESInfo::getHeaders: Offset is %i, header size is %i first 4 bytes are %x %x %x %x\n", 00204 offset, (size/2-offset),decConf[offset], decConf[offset + 1], decConf[offset + 2], 00205 decConf[offset + 3]); 00206 00207 delete[] decConf; 00208 return size / 2 - offset; 00209 }; 00210 00214 u32 ESInfo::getFrameNumber(double timeInSeconds, bool upround) const { 00215 // Example: 2.5 seconds, framerate is 25 00216 // the result is 25*2.5=37 00217 u32 result; 00218 if (upround) 00219 result=(u32)ceil(timeInSeconds*((double)mediaTimeScale)/((double)vopTimeIncrement)); 00220 else 00221 result=(u32)floor(timeInSeconds*((double)mediaTimeScale)/((double)vopTimeIncrement)); 00222 dprintf_full("ESInfo::getFrameNumber(%f) == No %i (rounded %s)\r\n",timeInSeconds,result,upround?"up":"down"); 00223 return result; 00224 }; 00225 00226 /* calculate media time in seconds from frame number */ 00227 double ESInfo::getMediaTime(u32 frameNo) const 00228 { 00229 if (!mediaTimeScale) { 00230 dprintf_err("ESInfo::getMediaTime(frameNo = %u) ERROR: mediaTimeScale is 0!\n", frameNo); 00231 return 0.0; 00232 } 00233 return (double) frameNo * (double) vopTimeIncrement / (double) mediaTimeScale; 00234 } 00235 00237 bool ESInfo::enableFrameStatistic() 00238 { 00239 dprintf_full("ESInfo::enableFrameStatistic\n"); 00240 if(frameStatistic==NULL) { 00241 frameStatistic=new BitField(getNumberOfMediaSamples(),false); 00242 return true; 00243 } 00244 return false; 00245 }; 00246 00247 /* frees an existing frame statistics object */ 00248 void ESInfo::disableFrameStatistic() 00249 { 00250 dprintf_full("ESInfo::disableFrameStatistic\n"); 00251 if(frameStatistic) { 00252 delete frameStatistic; 00253 frameStatistic=NULL; 00254 } 00255 }; 00256 00257 BitField* ESInfo::getFrameStatistic() 00258 { 00259 return frameStatistic; 00260 } 00261 00262 void ESInfo::setFrameStatistic(BitField* b) 00263 { 00264 if(frameStatistic) 00265 delete frameStatistic; 00266 frameStatistic=b; 00267 }; 00268 00269 void ESInfo::setDuration(u64 uiDuration) 00270 { 00271 duration = uiDuration; 00272 if(frameStatistic) { 00273 BitField* b=frameStatistic; 00274 frameStatistic=b->createWithNewSize(getNumberOfMediaSamples(),false); 00275 delete b; 00276 } 00277 } 00278 00280 void ESInfo::setVOPTimeIncrement(u32 ticks) { 00281 assert(ticks>0); 00282 vopTimeIncrement = ticks; 00283 dprintf_full("ESInfo (0x%p)::setVOPTimeIncrement to %u (duration %llu) mediaTimeScale is %u ticks\n", 00284 this, ticks, duration, getMediaTimeScale()); 00285 if(frameStatistic) { 00286 BitField* b=frameStatistic; 00287 frameStatistic=b->createWithNewSize(getNumberOfMediaSamples(),false); 00288 delete b; 00289 } 00290 }; 00291 00292 bool ESInfo::getCompleteState() const { 00293 if(this->frameStatistic) 00294 return frameStatistic->isAllSet(); 00295 return complete; 00296 }; 00297 00298 00299 00300 void ESInfo::setCloneCounter( ReferenceCounter* &ref) 00301 { 00302 if(existingClones && existingClones->decreaseAndDeactivateWhenUsage(0)) { 00303 delete existingClones; 00304 existingClones=NULL; 00305 } 00306 else if(existingClones && existingClones->getUsage()>0) { 00307 existingClones->decrease(); 00308 } 00309 existingClones=ref; 00310 }; 00311 00312 00313 00314 00318 u32 ESInfo::getCurrentDemuxedMediaSize() const 00319 { 00320 if(!input) 00321 return 0; 00322 FILE* fp=fopen(this->input,"rb"); 00323 u32 res=0; 00324 if(fp) { 00325 fseek(fp,0,SEEK_END); 00326 long l=ftell(fp); 00327 fclose(fp); 00328 if(l>0) 00329 res=(u32)l; 00330 } 00331 return res; 00332 }; 00333 00335 bool ESInfo::destroy() 00336 { 00337 bool ret=false; 00338 if(input) { 00339 #ifndef WINCE 00340 ret=(remove(input)==0); 00341 #else 00342 ret=(DeleteFile((LPCTSTR)input)!=0); 00343 #endif 00344 //hack to remove possible hint files 00345 char* tmp=new char[strlen(input)+6]; 00346 strcpy(tmp,input); 00347 strcat(tmp,".hint"); 00348 #ifndef WINCE 00349 remove(tmp); 00350 #else 00351 DeleteFile((LPCTSTR)tmp); 00352 #endif 00353 00354 delete[] tmp; 00355 delete[] input; 00356 input=NULL; 00357 disableFrameStatistic(); 00358 enableFrameStatistic(); 00359 } 00360 return ret; 00361 } 00362