BufferedIO.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: BufferedIO.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 "BufferedIO.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 BufferedIO::BufferedIO(ESInfo * esi, MuxDemuxIO *muxio, bool write) : IO() { 00057 writeOnly = write; 00058 lastCTSSeen=0; 00059 es = esi; 00060 this->muxio = muxio; 00061 muxio->addBufferedIO(es->getStreamId(), this); 00062 00063 atFileStart = true; 00064 state = CLOSED; 00065 currentFrameNumber=0; 00066 } 00067 00068 00069 BufferedIO::~BufferedIO() { 00070 if (state != CLOSED) 00071 close(); 00072 } 00073 00077 bool BufferedIO::open() { 00078 bool ret = false; 00079 atFileStart = true; 00080 state = OPENING; 00081 lastCTSSeen=0; 00082 00083 if (writeOnly) { 00084 // reset statistic 00085 dprintf_full("BufferedIO::open(): resetting Statistic to %u dur %lli ticks %u\n",es->getNumberOfMediaSamples(), 00086 es->getDuration(), es->getVOPTimeIncrement()); 00087 es->disableFrameStatistic(); 00088 es->enableFrameStatistic(); 00089 } 00090 00091 ret = muxio->open(); 00092 00093 if (ret) 00094 state = OPEN; 00095 else 00096 state = CLOSED; 00097 00098 currentFrameNumber=0; 00099 framesSeen=0; 00100 00101 return ret; 00102 } 00103 00104 00105 bool BufferedIO::close(bool immediate) { 00106 dprintf_full("BufferedIO::close ES-ID %lli, immediate=%i, %i frames left in buffer\n",es->getStreamId(), immediate, buffer.size()); 00107 00108 if (state == CLOSED) 00109 return true; 00110 00111 state = CLOSING; 00112 if (!immediate) 00113 while(!buffer.empty()) { //wait until MuxDemuxIO got everything... 00114 dprintf_full("BufferedIO::close ES-ID %lli, %i frames left in buffer\n",es->getStreamId(), buffer.size()); 00115 //if (muxio->getNumberOfConnectedBufferedIO() == 1) //we are the last one, so poll empty 00116 muxio->processFrame(); 00117 // else 00118 //sleep(1); 00119 } 00120 else 00121 buffer.clear(); 00122 00123 muxio->removeBufferedIO(es->getStreamId(), this); 00124 state = CLOSED; 00125 return true; 00126 } 00127 00128 00130 int BufferedIO::writeFrame(Frame * frm, ESInfo *out_es) { 00131 00132 dprintf_full("BufferedIO::writeFrame %p, AU %p, ES-ID %lli\n",frm, frm->getAU(),es->getStreamId()); 00133 // drop frames we have already written!! 00134 if ( (lastCTSSeen >= (signed)frm->getAU()->cts) && (lastCTSSeen != 0) ) { 00135 dprintf_small("BufferedIO::writeFrame WARNING: CTS %u already seen (lastCTSSeen %li) still writing to file!\n", 00136 frm->getAU()->cts,lastCTSSeen); 00137 } else 00138 lastCTSSeen = frm->getAU()->cts; 00139 00140 if (!writeOnly || state != OPEN) { 00141 dprintf_small("BufferedIO::writeFrame esID %llu Warning: Output is readonly or not open\n", es->getStreamId()); 00142 return -1; 00143 } 00144 if (frm->getAU()->size == 0) { 00145 dprintf_small("BufferedIO::writeFrame esID %llu: Cannot write zero sized frames\n", es->getStreamId()); 00146 return 0; 00147 } 00148 00149 dprintf_full("BufferedIO::writeFrame: Storing %i bytes of CTS %i into buffer (already holds %i frames)\n", 00150 frm->getAU()->size, frm->getAU()->cts, buffer.size()); 00151 00152 es->getFrameStatistic()->setBit(frm->getAU()->cts/es->getVOPTimeIncrement()); 00153 00154 // buffer the frame FIFO style 00155 addToBuffer(frm); 00156 frm->markForDelete(false); //take away from DataChannel GarbageCollector, will be deleted in MuxDemuxIO 00157 00158 muxio->processFrame(); 00159 00160 framesSeen++; 00161 00162 #ifdef _POSIX_PRIORITY_SCHEDULING 00163 sched_yield(); //this is necessary to give parallel getFrames a chance 00164 #endif 00165 00166 return true; 00167 } 00168 00169 s64 BufferedIO::nextCTSinBuf() { 00170 00171 if (!buffer.empty()) { 00172 return buffer.front()->getAU()->cts; 00173 } else 00174 return -1; 00175 } 00176 00177 00182 Frame *BufferedIO::getFrame() { 00183 Frame *frm = NULL; 00184 00185 dprintf_full("BufferedIO::getFrame: ES-ID %lli state %i, buffer: %i frames\n",es->getStreamId(), state, buffer.size()); 00186 00187 if ( (state != OPEN) && (state != CLOSING)) 00188 return NULL; 00189 00190 if (atFileStart) { 00191 atFileStart = false; 00192 // return NULL; 00193 } 00194 00195 if (!writeOnly && muxio->getState() != STREAMEOF) 00196 muxio->processFrame(); 00197 00198 if (!buffer.empty()) { 00199 frm = buffer.front(); 00200 buffer.pop_front(); 00201 00202 lastCTSSeen = frm->getAU()->cts; 00203 framesSeen++; 00204 currentFrameNumber++; 00205 dprintf_full("BufferedIO::getFrame: %p AU %p ES-ID %lli cts %i size %i, %i frames left in buffer\n", frm, frm->getAU(), 00206 es->getStreamId(), frm->getAU()->cts, frm->getAU()->size, buffer.size()); 00207 00208 } else { //buffer is empty 00209 if (muxio->getState() == OPEN) { 00210 dprintf_full("BufferedIO::getFrame: ES-ID %lli no frame in buffer right now!\n",es->getStreamId()); 00211 } else 00212 state = muxio->getState(); //may be closed 00213 } 00214 00215 #ifdef _POSIX_PRIORITY_SCHEDULING 00216 sched_yield(); //this is necessary to give parallel getFrames a chance 00217 #endif 00218 00219 return frm; 00220 } 00221 00222 00223 bool BufferedIO::destroy() { 00224 00225 close(); 00226 00227 return true; 00228 }