ContainerDemux.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: ContainerDemux.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 "ContainerDemux.hpp" 00045 #include "ContainerInfo.hpp" 00046 #include "Adaptor.hpp" 00047 #include "DataChannel.hpp" 00048 #include "io/IOCreator.hpp" 00049 #include "io/MPGStreamIO.hpp" 00050 #include "io/DevNull.hpp" 00051 #include "DataSink.hpp" 00052 00053 00060 ContainerInfo *ContainerDemux::demultiplex(ContainerInfo * &mp4Info, const char* outputDir, 00061 const Adaptor * visualAdaptor, 00062 bool omitHeader, bool deleteMP4, 00063 bool visualizeAdaptation) { 00064 ContainerInfo * mp4New = mp4Info->clone(); 00065 ContainerDemux::demultiplexAndUpdateIO(mp4New, outputDir, visualAdaptor, omitHeader, 00066 deleteMP4, visualizeAdaptation); 00067 return mp4New; 00068 } 00069 00070 00075 void ContainerDemux::demultiplexAndUpdateIO(ContainerInfo * &mp4Info, 00076 const char* outputDir, 00077 const Adaptor * visualAdaptor, 00078 bool omitHeader, bool deleteMP4, 00079 bool visualizeAdaptation) { 00080 00081 list < ESInfo * > *es = mp4Info->getESList(); 00082 assert(es && es->size() > 0); 00083 list < ESInfo * >::iterator li = es->begin(); 00084 DataChannel **dc = new DataChannel *[es->size()]; 00085 for (int i = 0; i < (int) es->size(); i++) { 00086 // for each ES create a DataChannel, MP4IO will be used for reading 00087 dc[i] = new DataChannel(IOCreator::createInput((*li), false), (*li)); 00088 00089 char *out = dc[i]->enableCaching(omitHeader,outputDir); 00090 00091 (*li)->setInput(out); 00092 00093 delete[] out; 00094 00095 if ((*li)->isVisualStream() && visualAdaptor != NULL) { 00096 Adaptor* at=((Adaptor*)visualAdaptor)->clone(); 00097 at->setESInfo(*li); 00098 dc[i]->setAdaptor(at); 00099 } 00100 00101 if (visualizeAdaptation && (*li)->isVisualStream()) { 00102 dc[i]->visualizeCaching(); 00103 } 00104 00105 ++li; 00106 } 00107 00108 // rewind the iterator 00109 li = es->begin(); 00110 for (int j = 0; j < (int) es->size(); j++) { 00111 // start & wait for each thread to finish 00112 // -> ISOMP4 lib is not thread safe 00113 dc[j]->start(); 00114 if(dc[j]->running()) 00115 dc[j]->wait(); 00116 /* the stream may have contained empty frames, 00117 * so update the duration to avoid inconsistent 00118 * ESInfo::frameStatistics 00119 */ 00120 ESInfo *ess = (ESInfo *) dc[j]->getESInfo(); 00121 u32 essFrames = ess->getNumberOfMediaSamples(); 00122 u32 readFrames = dc[j]->getInput()->getCurrentFrameNumber(); 00123 if (readFrames != essFrames) { 00124 dprintf_full("ContainerDemux::demultiplexAndUpdateIO() stream %d: read %u frames, correcting ESInfo (was %u)\n", 00125 j, readFrames, essFrames); 00126 ess->setDuration((u64) readFrames * (u64) ess->getVOPTimeIncrement()); 00127 } 00128 ess->setCompleteState(true); 00129 delete dc[j]; 00130 } 00131 delete[] dc; 00132 // now delete the mp4file 00133 if (deleteMP4) { 00134 dprintf_full("ISOMP4ContainerFile::demultiplexAndUpdateIO: Deleting ISOMP4ContainerFile\r\n"); 00135 FILE *fp = fopen(mp4Info->getLocalFile(), "w"); 00136 00137 if (fp) { 00138 fclose(fp); 00139 remove(mp4Info->getLocalFile()); 00140 } 00141 } 00142 } 00143 00144 00145 void ContainerDemux::adaptESInfo(ESInfo* es, const char* outputFile, Adaptor* adaptor, u32 startFrame, u32 endFrame, bool omitHeader, bool visualize) { 00146 assert(es); 00147 00148 DataChannel* dc = ContainerDemux::createDataChannel(es,outputFile,adaptor,startFrame,endFrame,omitHeader,visualize); 00149 if(!dc) 00150 return; 00151 00152 dc->start(); 00153 if(dc->running()) 00154 { 00155 dc->wait(); 00156 } 00157 delete dc; 00158 00159 } 00160 00161 00164 void ContainerDemux::adaptESInfo(ESInfo* es, const char* outputFile, Adaptor* adaptor, 00165 double startSecond, double endSecond, bool omitHeader, bool visualize) { 00166 assert(es); 00167 u32 startFrame=es->getFrameNumber(startSecond); 00168 u32 endFrame=4294967295u; //2^32-1 00169 if(endSecond > 0.0) 00170 endFrame=es->getFrameNumber(endSecond); 00171 ContainerDemux::adaptESInfo(es,outputFile,adaptor,(u32)startFrame,(u32)endFrame,omitHeader,visualize); 00172 } 00173 00174 00176 DataChannel* ContainerDemux::createDataChannel(ESInfo* es, const char* outputFile, 00177 Adaptor* adaptor, u32 startFrame, u32 endFrame, 00178 bool omitHeader, bool visualize) { 00179 assert(es); 00180 if(!es) // for release build where all asserts vanish 00181 return NULL; 00182 00183 IO* input = IOCreator::createInput(es, false); 00184 00185 input->setToClosestIFrame(startFrame); 00186 input->setEndFrameNumber(endFrame); 00187 IO* output=NULL; 00188 if(outputFile) 00189 output = new MPGStreamIO(es, outputFile, true, omitHeader); 00190 else 00191 output = new DevNull(); 00192 00193 DataSink* datasink = new DataSink(0, output, "127.0.0.1", 0, NULL); 00194 DataChannel* dc = new DataChannel(input, es); 00195 if(visualize) 00196 dc->visualizeCaching(); 00197 dc->setAdaptor(adaptor); 00198 dc->insert(datasink); 00199 dc->play(0, 0.0); 00200 return dc; 00201 }