Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members
VITMuxDemuxIO.cpp
00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: VITMuxDemuxIO.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 "VITMuxDemuxIO.hpp" 00045 #include "VideoESInfo.hpp" 00046 #include "AudioESInfo.hpp" 00047 #include "../container/VITContainerFile.hpp" 00048 00049 00050 VITMuxDemuxIO::VITMuxDemuxIO(ByteStream *stream) : MuxDemuxIO(stream) { 00051 } 00052 00053 00054 VITMuxDemuxIO::~VITMuxDemuxIO() { 00055 } 00056 00058 int VITMuxDemuxIO::writeFrame(Frame * frm, ESInfo *out_es) { 00059 00060 if (state != OPEN) 00061 this->open(); 00062 00063 if (state != OPEN || readOnly) { 00064 dprintf_err("VITMuxDemuxIO::writeFrame: Stream not open (for writing?)!\n"); 00065 return 0; 00066 } 00067 00068 if (firstFrame) { //write Container Header to stream 00069 firstFrame=false; 00070 00071 //FOURCC 00072 char fourcc[5]; 00073 strcpy(fourcc,"VIT "); 00074 stream->write( fourcc,4); //only write first 4 bytes, ignore \0 00075 00076 //version number 00077 u32 version = VIT_VERSION_NUMBER; 00078 stream->write( &version, sizeof(version)); 00079 00080 //number of following (muxed) tracks 00081 u32 numTracks = getNumberOfConnectedBufferedIO(); 00082 stream->write( &numTracks, sizeof(numTracks)); 00083 00084 00085 //write list of streamID and CODEC_ID 00086 map < int, BufferedIO* >::iterator currIO; 00087 for(currIO=ioList.begin(); currIO != ioList.end(); currIO++) { 00088 ESInfo *esi = currIO->second->getESInfo(); 00089 00090 VITTrackInfo ti; 00091 memset(&ti,0,sizeof(ti)); //get it empty 00092 00093 ti.streamID = currIO->first; 00094 ti.codecID = esi->getCodecID(); 00095 ti.kbps = esi->getAvgBandwidth() / 1024; 00096 ti.vopinc = esi->getVOPTimeIncrement(); 00097 00098 if (esi->isVisualStream()) { 00099 ti.streamType = VIT_VIDEO; 00100 ti.esi.vi.fps = (u32)ceil(((VideoESInfo*)esi)->getFPS()); 00101 ti.esi.vi.width = (u32)((VideoESInfo*)esi)->getWidth(); 00102 ti.esi.vi.height = (u32)((VideoESInfo*)esi)->getHeight(); 00103 ti.esi.vi.aspectRatio = (float)((VideoESInfo*)esi)->getAspectRatio(); 00104 00105 } else if (esi->isAudioStream()) { 00106 ti.streamType = VIT_AUDIO; 00107 ti.esi.ai.sampleRate = ((AudioESInfo*)esi)->getSampleRate(); 00108 ti.esi.ai.channels = ((AudioESInfo*)esi)->getAudioChannels(); 00109 //copy first two characters 00110 ti.esi.ai.language[1] = ((AudioESInfo*)esi)->getLanguage()[1]; 00111 ti.esi.ai.language[2] = ((AudioESInfo*)esi)->getLanguage()[2]; 00112 } 00113 00114 dprintf_full("VITMuxDemuxIO::writeFrame: Header with streamID %i CodecID %i StreamType %i\n", 00115 ti.streamID, ti.codecID, ti.streamType); 00116 stream->write(&ti, sizeof(ti)); 00117 } 00118 00119 00120 } 00121 00122 dprintf_full("VITMuxDemuxIO::writeFrame: writing frame CTS %i size %i from track %lli to container\n", 00123 frm->getAU()->cts, frm->getAU()->size, out_es->getStreamId()); 00124 00125 00126 VITFrameInfo fi; 00127 //FIXME: litte/big endian awareness is missing!! 00128 fi.streamID = (u32)out_es->getStreamId(); 00129 fi.cts = frm->getAU()->cts; 00130 fi.size = frm->getAU()->size; 00131 stream->write( &fi, sizeof(fi)); 00132 00133 // save the frame 00134 int i = stream->write(frm->getAU()->payload, frm->getAU()->size); 00135 00136 00137 00138 framesSeen++; 00139 00140 #ifdef _POSIX_PRIORITY_SCHEDULING 00141 sched_yield(); //this is necessary to give parallel getFrames a chance 00142 #endif 00143 00144 return (i == (signed)frm->getAU()->size); 00145 } 00146 00147 00148 00149 00150 00155 Frame *VITMuxDemuxIO::getFrame() { 00156 if (firstFrame && (state != OPEN)) { 00157 dprintf_err("VITMuxDemuxIO::getFrame: opening\n"); 00158 this->open(); 00159 } 00160 00161 if (state != OPEN || !readOnly) { 00162 dprintf_err("VITMuxDemuxIO::getFrame: Stream not open (for reading?) or EOF!\n"); 00163 return 0; 00164 } 00165 00166 if (firstFrame) { //write Container Header to stream 00167 00168 //HEADER parsing is not necessary, since the stream is still open from VITContainerFile! 00169 00170 /* 00171 //jump over already parsed header and do some sanity checks 00172 //FOURCC 00173 char fourcc[5]; 00174 stream->read( fourcc,4); //only read first 4 bytes, add \0 00175 fourcc[4] = '\0'; 00176 if (strcmp(fourcc,"VIT ") != 0) { 00177 dprintf_err("VITMuxDemuxIO::getFrame: stream %s is no ViTooKi VIT container file!\n",stream->getUrl()); 00178 close(true); 00179 return NULL; 00180 } 00181 00182 //version number 00183 u32 version; 00184 stream->read( &version, sizeof(version)); 00185 if (version != VIT_VERSION_NUMBER) { 00186 dprintf_err("VITMuxDemuxIO::getFrame: VIT file %s has wrong version number %i (expected %i)!\n", 00187 stream->getUrl(),version,VIT_VERSION_NUMBER); 00188 close(true); 00189 return NULL; 00190 } 00191 00192 //number of following (muxed) tracks 00193 u32 numTracks; 00194 stream->read( &numTracks, sizeof(numTracks)); 00195 dprintf_full("VITMuxDemuxIO::getFrame: VIT file contains %i elementary streams\n",numTracks); 00196 00197 00198 //jump over list of tracks 00199 for (u32 curr=0; curr < numTracks; curr++) { 00200 00201 VITTrackInfo ti; 00202 stream->read(&ti, sizeof(ti)); 00203 dprintf_full("VITMuxDemuxIO:getFrame Header withstreamID %i CodecID %i StreamType %i\n", 00204 ti.streamID, ti.codecID, ti.streamType); 00205 } 00206 */ 00207 00208 firstFrame=false; 00209 } 00210 00211 //parse frame header and then payload 00212 //FIXME: litte/big endian awareness is missing!! 00213 VITFrameInfo fi; 00214 int ret; 00215 Frame *frm = NULL; 00216 00217 ret = stream->read( &fi, sizeof(fi)); 00218 00219 if (ret == sizeof(fi)) { 00220 // read the real frame 00221 AU *au = new AU(); 00222 Frame::FrameType type = Frame::NN_VOP; 00223 00224 au->size = fi.size; 00225 au->payload = new u8[fi.size]; 00226 au->cts = fi.cts; 00227 au->dts = au->cts; 00228 00229 //get the payload 00230 ret = stream->read(au->payload, fi.size); 00231 00232 00233 //NOTE: some things (duration, codecID, ...) have to be set in processFrame(), 00234 //since here there are no ESs known yet.... 00235 au->sampleFlags = 0; 00236 au->err = SA_OK; 00237 00238 00239 frm = new Frame(type); 00240 frm->setStreamID(fi.streamID); //give the mapping for the right BufferedIO/ESInfo 00241 // later in processReadFrame.. 00242 frm->setAU(au); 00243 00244 00245 framesSeen++; 00246 currentFrameNumber++; 00247 dprintf_full("VITMuxDemuxIO::getFrame: stream offset %llu, CTS %i,size %i, streamID %i\n", 00248 stream->tell(), fi.cts, fi.size, fi.streamID); 00249 } 00250 00251 00252 if (ret == -1) { 00253 #ifndef WINCE 00254 dprintf_err("VitMuxDemuxIO::getFrame failed to read full frame: ferror %i\n",ret); 00255 perror("VitMuxDemuxIO::getFrame failed to read full frame"); 00256 #endif 00257 state = STREAMERR; 00258 return NULL; 00259 } 00260 else if (ret == 0) { 00261 dprintf_full("VITMuxDemuxIO::getFrame: STREAMEOF reached\n"); 00262 state = STREAMEOF; 00263 return NULL; 00264 } 00265 00266 00267 00268 #ifdef _POSIX_PRIORITY_SCHEDULING 00269 sched_yield(); //this is necessary to give parallel getFrames a chance 00270 #endif 00271 00272 return frm; 00273 }