RawStreamIO.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: RawStreamIO.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 "RawStreamIO.hpp" 00045 #include "Frame.hpp" 00046 #include "ESInfo.hpp" 00047 #include "IO.hpp" 00048 #include "BitField.hpp" 00049 #ifndef WINCE 00050 #include <errno.h> 00051 #endif 00052 #ifndef WIN32 00053 #include <sys/file.h> 00054 #endif 00055 00056 RawStreamIO::RawStreamIO(ESInfo * esi, const char *file, bool write) : IO() { 00057 if (!file) 00058 url = NULL; 00059 else { 00060 url = new char[strlen(file) + 1]; 00061 strcpy(url, file); 00062 } 00063 writeOnly = write; 00064 lastCTSSeen=0; 00065 io = NULL; 00066 es = esi; 00067 atFileStart = true; 00068 state = CLOSED; 00069 currentFrameNumber=0; 00070 frameSize = 0; 00071 } 00072 00073 00074 RawStreamIO::~RawStreamIO() { 00075 if (state != CLOSED) 00076 close(); 00077 if (io) { 00078 #ifndef WIN32 00079 int val = flock(fileno(io),LOCK_UN); 00080 if (val == -1) 00081 perror("RawStreamIO::destructor flock out-file"); 00082 #endif 00083 fclose(io); 00084 io=NULL; 00085 } 00086 if (url) 00087 delete[] url; 00088 } 00089 00093 bool RawStreamIO::open() { 00094 if(!url) 00095 return false; 00096 dprintf_full("RawStreamIO::open() Trying to open %s\r\n", url); 00097 if(state==OPEN) 00098 return true; 00099 00100 bool ret = false; 00101 atFileStart = true; 00102 state = OPENING; 00103 lastCTSSeen=0; 00104 char *name = new char[512]; 00105 strcpy(name,url); 00106 strcat(name,".hint"); 00107 00108 if (writeOnly) { 00109 // we want to write to a local file 00110 // reset statistic 00111 dprintf_full("RawStreamIO::open(): resetting Statistic to %u dur %u ticks %u\n",es->getNumberOfMediaSamples(),(unsigned)es->getDuration(),es->getVOPTimeIncrement()); 00112 es->disableFrameStatistic(); 00113 es->enableFrameStatistic(); 00114 io=fopen(url,"wb"); 00115 ret = (io!=NULL); 00116 if (ret==true) { 00117 #ifndef WIN32 00118 int val = flock(fileno(io),LOCK_EX | LOCK_NB); 00119 if (val == -1) 00120 perror("RawStreamIO::open flock out-file"); 00121 ret = ((val == 0) || (errno == ENOLCK)); //eg. NFS might not support flocks 00122 if (errno == EWOULDBLOCK) { 00123 dprintf_err("RawStreamIO::open(): FATAL: lock on %s is held by other process! \n", url); 00124 ::exit(1); 00125 } 00126 #endif 00127 ; 00128 } 00129 } else { 00130 // we want to read from a local file 00131 io=fopen(url,"rb"); 00132 ret = (io!=NULL); 00133 } 00134 00135 if (ret) 00136 state = OPEN; 00137 else 00138 state = CLOSED; 00139 currentFrameNumber=0; 00140 framesSeen=0; 00141 delete [] name; 00142 return ret; 00143 } 00144 00145 00146 bool RawStreamIO::close(bool immediate) { 00147 state = CLOSING; 00148 if (io) { 00149 fclose(io); 00150 io=NULL; 00151 } 00152 state = CLOSED; 00153 // this->es->setDuration(lastCTSSeen+es->getVOPTimeIncrement()); 00154 return true; 00155 } 00156 00157 00159 int RawStreamIO::writeFrame(Frame * frm, ESInfo *out_es) { 00160 dprintf_full("RawStreamIO::writeFrame %p\n",frm); 00161 // drop frames we have already written!! 00162 if ( (lastCTSSeen >= (signed)frm->getAU()->cts) && (lastCTSSeen != 0) ) { 00163 dprintf_small("RawStreamIO::writeFrame WARNING: CTS %u already seen (lastCTSSeen %li) still writing to file!\n", 00164 frm->getAU()->cts,lastCTSSeen); 00165 } else 00166 lastCTSSeen = frm->getAU()->cts; 00167 00168 if (!writeOnly || state != OPEN) { 00169 dprintf_small("RawStreamIO::writeFrame esID %llu Warning: Output is readonly or not open\n", es->getStreamId()); 00170 return -1; 00171 } 00172 if (frm->getAU()->size == 0) { 00173 dprintf_small("RawStreamIO::writeFrame esID %llu: Cannot write zero sized frames\n", es->getStreamId()); 00174 return 0; 00175 } 00176 00177 dprintf_full("RawStreamIO::writeFrame: Saving %i bytes of CTS %i\n", 00178 frm->getAU()->size, frm->getAU()->cts); 00179 // save the frame 00180 int i = fwrite(frm->getAU()->payload,sizeof(char), frm->getAU()->size , io); 00181 00182 00183 framesSeen++; 00184 es->getFrameStatistic()->setBit(frm->getAU()->cts/es->getVOPTimeIncrement()); 00185 00186 #ifdef _POSIX_PRIORITY_SCHEDULING 00187 sched_yield(); //this is necessary to give parallel getFrames a chance 00188 #endif 00189 00190 return ((signed)frm->getAU()->size == i); 00191 } 00192 00193 00194 void RawStreamIO::setFrameSize(u32 size) { 00195 frameSize = size; 00196 } 00197 00198 00203 Frame *RawStreamIO::getFrame() { 00204 if (writeOnly || state != OPEN) 00205 return NULL; 00206 00207 if (frameSize == 0) { 00208 dprintf_err("RawStreamIO::getFrame() has no frameSize, so use \"setFrameSize\" first!\n"); 00209 ::exit(1); 00210 } 00211 00212 if (atFileStart) { 00213 atFileStart = false; 00214 // return NULL; 00215 } 00216 // now read the frame 00217 // first check hintfile 00218 AU *au = new AU(); 00219 Frame *frm = NULL; 00220 Frame::FrameType type = Frame::NN_VOP; 00221 00222 au->size = frameSize; 00223 au->payload = new u8[frameSize]; 00224 if (fread(au->payload,1,frameSize,io) < frameSize) { 00225 if (ferror(io)) { 00226 #ifndef WINCE 00227 perror("RawStreamIO::getFrame failed to read full frame"); 00228 #endif 00229 state = STREAMERR; 00230 } 00231 else 00232 state = STREAMEOF; 00233 return NULL; 00234 } 00235 au->cts = framesSeen * es->getVOPTimeIncrement(); 00236 au->dts = au->cts; 00237 au->duration = es->getDuration(); 00238 au->sampleFlags = 0; 00239 au->err = SA_OK; 00240 00241 frm = new Frame(type); 00242 frm->setAU(au); 00243 frm->setMediaTimeScale(es->getMediaTimeScale()); 00244 framesSeen++; 00245 currentFrameNumber++; 00246 dprintf_full("RawStreamIO::getFrame: file offset %li cts %i dts %i\r\n",ftell(io),au->cts,au->dts); 00247 00248 #ifdef _POSIX_PRIORITY_SCHEDULING 00249 sched_yield(); //this is necessary to give parallel getFrames a chance 00250 #endif 00251 00252 return frm; 00253 } 00254 00255 00256 bool RawStreamIO::setToFrameNumber(u32 frameNumber) { 00257 // check if valid 00258 // e.g.: writeOnly streams can not be seeked 00259 if(writeOnly || !io) { 00260 dprintf_full("RawStreamIO::setToFrameNumber(u32 %i) failed: not WriteClass or no Input IO\n",frameNumber); 00261 return false; 00262 } 00263 00264 dprintf_full("RawStreamIO::setToFrameNumber(u32 %i)\r\n",frameNumber); 00265 fseek(io,frameSize * frameNumber,SEEK_SET); 00266 currentFrameNumber=frameNumber; 00267 00268 if (frameNumber == 0) 00269 atFileStart = true; 00270 return true; 00271 } 00272 00273 00274 bool RawStreamIO::destroy() { 00275 // if we have a network connection we have got nothing to delete 00276 // so return true 00277 00278 if (!io) 00279 return true; 00280 00281 close(); 00282 #ifndef WINCE 00283 bool err = (remove(url) == 0); 00284 #else 00285 bool err = (DeleteFile((LPCTSTR)url) != 0); 00286 #endif 00287 00288 return err; 00289 }