BufferedMPGStreamReader.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: BufferedMPGStreamReader.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 "BufferedMPGStreamReader.hpp" 00045 00046 #include "VideoESInfo.hpp" 00047 #include "CompressedVideoFrame.hpp" 00048 #include "CompressedAudioFrame.hpp" 00049 #include "IO.hpp" 00050 #include "../net/SDP.hpp" 00051 #include "BitField.hpp" 00052 00053 00054 #include "../container/ISOMP4ContainerFile.hpp" 00055 00056 00057 BufferedMPGStreamReader::BufferedMPGStreamReader(ESInfo * esi, const char *file, 00058 bool write, bool omit, int bufferSize, int maxFrameSize): MPGStreamIO(esi, file, write, omit) 00059 { 00060 00061 dprintf_full("BufferedMPGStreamReader::BufferedMPGStreamReader file=%s writeonly=%s\n",(file?file:"NULL"),(write?"WRITE":"READ")); 00062 assert(esi); 00063 00064 assert(bufferSize > 0); 00065 buffer = new u8[SAFETYDIST + bufferSize]; 00066 initBuffer(); 00067 this->bufferSize = bufferSize; 00068 bufferAtEnd = false; 00069 00070 this->maxFrameSize = maxFrameSize; 00071 DTS = 0; 00072 } 00073 00074 00075 BufferedMPGStreamReader::~BufferedMPGStreamReader() 00076 { 00077 delete [] buffer; 00078 } 00079 00080 bool BufferedMPGStreamReader::testFileopen() 00081 { 00082 FILE *file = fopen(url, "rb"); 00083 if (file == NULL) { 00084 return false; 00085 } else { 00086 fclose(file); 00087 return true; 00088 } 00089 } 00090 00091 00092 void BufferedMPGStreamReader::initBuffer() 00093 { 00094 lastBytesBuffered = bytesBuffered = 0; 00095 //bytesRead = SAFETYDIST; 00096 bytesRead = 0; 00097 bytesReadTotal = 0; 00098 } 00099 00100 00101 bool BufferedMPGStreamReader::readBuffer() 00102 { 00103 if (bufferAtEnd) { 00104 state = CLOSED; 00105 return false; 00106 } 00107 00108 if (lastBytesBuffered != 0) { 00109 //copy bytes of last read access 00110 for (int i=0; i < SAFETYDIST; i++) buffer[i] = buffer[lastBytesBuffered+i]; 00111 } 00112 // dprintf_err("BufferedMPGStreamReader::readBuffer getting more data....\n"); 00113 lastBytesBuffered = bytesBuffered = fread(buffer + SAFETYDIST, sizeof(*buffer), bufferSize, io); 00114 if (bytesBuffered != bufferSize) { 00115 bufferAtEnd = true; 00116 bytesRead = 0; 00117 return false; 00118 //io will be closed by ::close() later! 00119 } 00120 bytesRead = 0; 00121 return true; 00122 } 00123 00124 00125 int BufferedMPGStreamReader::buffered_getc() 00126 { 00127 if (bytesBuffered == 0) { 00128 if (!readBuffer()) { 00129 return 0; 00130 } 00131 } 00132 bytesBuffered--; 00133 00134 bytesReadTotal++; 00135 return (int)buffer[bytesRead++ + SAFETYDIST]; 00136 } 00137 00138 00139 int BufferedMPGStreamReader::buffered_read(u8 *buf, int nrBytes) 00140 { 00141 for (int i = 0; i < nrBytes; i++) { 00142 buf[i] = buffered_getc(); 00143 } 00144 return nrBytes; 00145 } 00146 00147 int BufferedMPGStreamReader::buffered_copy(u8 *buf, int nrBytes) 00148 { 00149 int retVal = 0; 00150 00151 if (bytesBuffered == 0) { 00152 if (!readBuffer()) { 00153 return 0; 00154 } 00155 } 00156 00157 if (nrBytes <= bytesBuffered) { 00158 memcpy(buf, buffer + bytesRead + SAFETYDIST, nrBytes); 00159 bytesRead += nrBytes; 00160 bytesReadTotal += nrBytes; 00161 bytesBuffered -= nrBytes; 00162 retVal = nrBytes; 00163 } else { 00164 retVal = buffered_copy(buf, bytesBuffered); 00165 retVal += buffered_copy(buf+retVal, nrBytes-retVal); 00166 } 00167 00168 return retVal; 00169 } 00170 00171 00172 void BufferedMPGStreamReader::goBack(int nrBytes) 00173 { 00174 bytesRead -= nrBytes; 00175 bytesReadTotal -= nrBytes; 00176 bytesBuffered += nrBytes; 00177 } 00178 00179 00180 Frame *BufferedMPGStreamReader::getFrame() { 00181 if (writeOnly || state != OPEN) 00182 return NULL; 00183 00184 if (( (this->currentFrameNumber > this->endFrameNumber) && (endFrameNumber!=0) )) { // || feof(io)) { 00185 close(true); 00186 state=STREAMEOF; 00187 return NULL; 00188 } 00189 00190 // now read the frame 00191 AU *au = new AU(); 00192 Frame *frm = NULL; 00193 Frame::FrameType type = Frame::NN_VOP; 00194 00195 // parse MPGFile for VOB_Code if it is a visual stream 00196 00197 if(es->isVisualStream()) { 00198 // 00 00 01 182 dec -> 0x1B6 (=438 dec) 00199 u32 code = 2000; // don't init to 0, we want the code from the 2nd frame, not the first 00200 int i = 0; 00201 00202 u8 *data = new u8[MAX_FRAME_SIZE]; 00203 00204 do { 00205 data[i] = buffered_getc(); 00206 code = (code << 8) | data[i]; //(u8)buffered_getc(); 00207 i++; 00208 if ((i==4) && code == VOP_START_CODE) code = 0; 00209 } while ((code != VOP_START_CODE) && (i < maxFrameSize) && state != CLOSED); 00210 00211 if (code == VOP_START_CODE) { 00212 goBack(4); 00213 i -= 4; 00214 au->size = i; 00215 au->payload = new u8[i]; 00216 memcpy(au->payload, data, i); 00217 delete [] data; 00218 dprintf_full("BufferedMPGStreamReader::getFrame() read %d bytes of video frame\n", i); 00219 } 00220 00221 if (au->size == 0) { 00222 state = STREAMEOF; 00223 delete au; 00224 return NULL; 00225 } 00226 00227 au->prio = IO_NETWORK_HIGHEST_PRIORITY; 00228 au->duration = es->getVOPTimeIncrement(); 00229 au->cts = currentFrameNumber * es->getVOPTimeIncrement(); 00230 au->dts = currentFrameNumber * es->getVOPTimeIncrement(); 00231 au->sampleFlags = 0; 00232 if (code != VOP_START_CODE) 00233 au->err = SA_EOF; 00234 else 00235 au->err = SA_OK; 00236 00237 } 00238 00239 if(es->isAudioStream()) { //XXX not sure if it works properly 00240 // start code for MP3 frame is 11111111 111 (first 11 bits set) 00241 u32 code = 2000; // don't init to 0, we want the code from the 2nd frame, not the first 00242 int i = 0; 00243 00244 //special handling for first frame 00245 if (framesSeen == 0) { 00246 int ch = 0; 00247 au->payload = new u8[1024]; 00248 do { 00249 ch = buffered_getc(); 00250 au->payload[i] = ch; 00251 i++; 00252 code = (code << 8) | ch; 00253 } 00254 while ((code>>21) != 0x000007FF /*VOP_START_CODE for audio(actually MP3)*/); 00255 au->size = i; 00256 } else { 00257 au->payload = new u8[MAX_FRAME_SIZE]; 00258 au->size = buffered_copy(au->payload, maxFrameSize); 00259 } 00260 00261 dprintf_full("BufferedMPGStreamReader::getFrame() read %d bytes of audio frame\n", au->size); 00262 00263 au->cts = DTS; 00264 au->dts = DTS; 00265 au->duration = 0; 00266 au->sampleFlags = 0; 00267 au->err = SA_OK; 00268 00269 DTS += es->getVOPTimeIncrement(); 00270 } 00271 00272 // frame types will be detected in frm->setAU()! 00273 if(es->isVisualStream()) 00274 frm = new CompressedVideoFrame(type, ((VideoESInfo*)es)->getWidth(), ((VideoESInfo*)es)->getHeight()); 00275 else if(es->isAudioStream()) 00276 frm=new CompressedAudioFrame(type); 00277 else 00278 frm = new CompressedVideoFrame(type, 0, 0); 00279 frm->setAU(au); 00280 frm->setMediaTimeScale(es->getMediaTimeScale()); 00281 framesSeen++; 00282 currentFrameNumber++; 00283 00284 00285 #ifdef _POSIX_PRIORITY_SCHEDULING 00286 sched_yield(); 00287 #else 00288 // for windows pthread lib! 00289 #ifdef WIN32 00290 #ifndef WINCE 00291 sched_yield(); 00292 #else 00293 Sleep(1); 00294 #endif 00295 #endif 00296 #endif 00297 00298 return frm; 00299 } 00300 00301