OGGMuxDemuxIO.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: OGGMuxDemuxIO.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 #ifdef ENABLE_OGG 00045 00046 #include "OGGMuxDemuxIO.hpp" 00047 #include "VideoESInfo.hpp" 00048 #include "AudioESInfo.hpp" 00049 #include "container/OGGContainerFile.hpp" 00050 00051 // redeclaration of static variables 00052 theora_info *OGGMuxDemuxIO::ti; 00053 theora_state *OGGMuxDemuxIO::ts; 00054 vorbis_info *OGGMuxDemuxIO::vi; 00055 vorbis_comment *OGGMuxDemuxIO::vc; 00056 vorbis_dsp_state *OGGMuxDemuxIO::vd; 00057 vorbis_block *OGGMuxDemuxIO::vb; 00058 00059 int OGGMuxDemuxIO::theorainitialized; 00060 int OGGMuxDemuxIO::vorbisinitialized; 00061 00062 vorbis_info* OGGMuxDemuxIO::getVorbisInfo(){ 00063 return vi; 00064 } 00065 vorbis_dsp_state* OGGMuxDemuxIO::getVorbisDspState(){ 00066 return vd; 00067 } 00068 vorbis_block* OGGMuxDemuxIO::getVorbisBlock(){ 00069 return vb; 00070 } 00071 00072 theora_state* OGGMuxDemuxIO::getTheoraState(){ 00073 return ts; 00074 } 00075 theora_info* OGGMuxDemuxIO::getTheoraInfo(){ 00076 return ti; 00077 } 00078 00079 void OGGMuxDemuxIO::initTheora(ESInfo *esi){ 00080 /* set up Theora encoder */ 00081 dprintf_full("OGGMuxDemuxIO::initTheora: entering...\n"); 00082 if(!theorainitialized){ 00083 dprintf_full("OGGMuxDemuxIO::initTheora: initializing\n"); 00084 int frame_x, frame_y, 00085 video_x, video_y, 00086 frame_x_offset, frame_y_offset; 00087 00088 ti = new theora_info; 00089 ts = new theora_state; 00090 00091 frame_x = ((VideoESInfo*)esi)->getWidth(); 00092 frame_y = ((VideoESInfo*)esi)->getHeight(); 00093 00094 // Theora has a divisible-by-sixteen restriction for the encoded video size 00095 // scale the frame size up to the nearest /16 and calculate offsets 00096 video_x = ((frame_x + 15) >>4) <<4; 00097 video_y = ((frame_y + 15) >>4) <<4; 00098 00099 // force offset to be even 00100 // this ensures that the chroma samples align properly with the luna samples 00101 frame_x_offset = ((video_x-frame_x)/2) & ~1; 00102 frame_y_offset = ((video_y-frame_y)/2) & ~1; 00103 00104 theora_info_init(ti); 00105 ti->width = video_x; 00106 ti->height = video_y; 00107 ti->frame_width = frame_x; 00108 ti->frame_height = frame_y; 00109 ti->offset_x = frame_x_offset; 00110 ti->offset_y = frame_y_offset; 00111 ti->fps_numerator = (int)((((VideoESInfo*)esi)->getFPS()) * 1000); 00112 ti->fps_denominator = 1000; 00113 ti->aspect_numerator = 1; 00114 ti->aspect_denominator = 1; 00115 ti->colorspace = OC_CS_UNSPECIFIED; 00116 // ti->pixelformat = OC_PF_420; 00117 ti->target_bitrate = esi->getAvgBandwidth(); // FIXME: 600 kbps 00118 dprintf_full("THEORA_ENC_SETUP: esi->getAvgBandwidth() == %u\n", esi->getAvgBandwidth()); 00119 ti->quality = 0; // 'cause target bitrate is set 00120 00121 ti->dropframes_p = 0; 00122 ti->quick_p = 1; 00123 ti->keyframe_auto_p = 1; 00124 ti->keyframe_frequency = 64; 00125 ti->keyframe_frequency_force = 64; 00126 ti->keyframe_data_target_bitrate = (ogg_uint32_t)(ti->target_bitrate * 1.5); 00127 ti->keyframe_auto_threshold = 80; 00128 ti->keyframe_mindistance = 8; 00129 ti->noise_sensitivity = 1; 00130 00131 theora_encode_init(ts, ti); 00132 } 00133 00134 theorainitialized=1; 00135 } 00136 00137 void OGGMuxDemuxIO::initVorbis(ESInfo *esi){ 00138 /* set up Vorbis encoder */ 00139 dprintf_full("OGGMuxDemuxIO::initVorbis: entering...\n"); 00140 if(!vorbisinitialized){ 00141 dprintf_full("OGGMuxDemuxIO::initVorbis: initializing\n"); 00142 00143 int audio_r, 00144 ret, 00145 samplerate; 00146 00147 samplerate = ((AudioESInfo*)esi)->getSampleRate(); 00148 00149 /* 00150 * audio-quality 00151 * int vorbis_encode_init(vorbis_info *vi, 00152 * long channels, 00153 * long rate, 00154 * 00155 * long max_bitrate, 00156 * long nominal_bitrate, 00157 * long min_bitrate); 00158 * 00159 * vi 00160 * pointer to an initialized vorbis_info struct. 00161 * channels 00162 * the number of channels to be encoded. 00163 * rate 00164 * the sampling rate of the source audio. 00165 * max_bitrate 00166 * desired maximum bitrate (limit). -1 indicates unset. 00167 * nominal_bitrate 00168 * desired average, or central, bitrate. -1 indicates unset. 00169 * min_bitrate 00170 * desired minimum bitrate. -1 indicates unset. 00171 */ 00172 // FIXME: hardcoded 128 kbps 00173 audio_r = 80*1000; 00174 dprintf_full("OGGMuxDemuxIO::initVorbis: avgBW: %i\n",esi->getAvgBandwidth()); 00175 audio_r = esi->getAvgBandwidth(); 00176 00177 vi = new vorbis_info; 00178 vc = new vorbis_comment; 00179 vd = new vorbis_dsp_state; 00180 vb = new vorbis_block; 00181 00182 vorbis_info_init(vi); 00183 ret = vorbis_encode_init(vi, 2, 44100, -1, audio_r, -1); 00184 if(ret){ 00185 dprintf_err("The Vorbis encoder could not set up a mode according to the requested bitrate.\n\n"); 00186 ::exit(1); 00187 } 00188 vorbis_comment_init(vc); 00189 vorbis_analysis_init(vd, vi); 00190 vorbis_block_init(vd, vb); 00191 } 00192 vorbisinitialized = 1; 00193 } 00194 00195 OGGMuxDemuxIO::OGGMuxDemuxIO(ByteStream *stream) : MuxDemuxIO(stream) { 00196 theorainitialized=0; 00197 vorbisinitialized=0; 00198 } 00199 00200 00201 OGGMuxDemuxIO::~OGGMuxDemuxIO() { 00202 if(vb){ 00203 vorbis_block_clear(vb); 00204 delete vb; 00205 vb=NULL; 00206 } 00207 if(vd){ 00208 vorbis_dsp_clear(vd); 00209 delete vd; 00210 vd=NULL; 00211 } 00212 if(vc){ 00213 vorbis_comment_clear(vc); 00214 delete vc; 00215 vc=NULL; 00216 } 00217 if(vi){ 00218 vorbis_info_clear(vi); 00219 delete vi; 00220 vi=NULL; 00221 } 00222 00223 } 00224 00226 int OGGMuxDemuxIO::writeFrame(Frame * frm, ESInfo *out_es) { 00227 00228 if (state != OPEN) 00229 this->open(); 00230 00231 if (state != OPEN || readOnly) { 00232 dprintf_err("OGGMuxDemuxIO::writeFrame: Stream not open (for writing?)!\n"); 00233 return 0; 00234 } 00235 00236 if (firstFrame) { //write Container Header to file 00237 // create new ogghandler 00238 osh_w = new OGGHandler(); 00239 firstFrame=false; 00240 srand(time(NULL)); 00241 { 00242 /* need two inequal serial numbers */ 00243 serialtheora = rand(); 00244 serialvorbis = rand(); 00245 if(serialtheora==serialvorbis) serialvorbis++; 00246 dprintf_full("OGGMuxDemuxIO::writeFrame: serialvorbis = %i, serialtheora = %i\n",serialvorbis,serialtheora); 00247 } 00248 osi = new OGGStreamInfo(); 00249 00250 OGGStreamInfo *vorbis_stream, *theora_stream; 00251 vorbis_stream = NULL; theora_stream = NULL; 00252 00253 00254 //write list of streamID and CODEC_ID 00255 map < int, BufferedIO* >::iterator currIO; 00256 for(currIO=ioList.begin(); currIO != ioList.end(); currIO++) { 00257 ESInfo *esi = currIO->second->getESInfo(); 00258 dprintf_full("OGGMuxDemuxIO::writeFrame: ESI = %p, %p == %p ??? %i\n", esi, &ioList.begin(), &ioList.end(), ioList.size()); 00259 // ti.vopinc = esi->getVOPTimeIncrement(); 00260 ogg_stream_state *tmp = new ogg_stream_state; 00261 00262 if (esi->isVisualStream()) { 00263 dprintf_full("OGGMuxDemuxIO::writeFrame: found visual stream\n"); 00264 ogg_stream_init(tmp, serialtheora); 00265 00266 theora_stream = new OGGStreamInfo(); 00267 00268 theora_stream->setStreamType(OGG_THEORA); 00269 theora_stream->setStreamID(serialtheora); 00270 theora_stream->setStreamState(tmp); 00271 dprintf_full("OGGMuxDemuxIO::writeframe: FPS: %f\n",((VideoESInfo*)esi)->getFPS()); 00272 00273 // ti.esi.vi.fps = (u32)ceil(((VideoESInfo*)esi)->getFPS()); 00274 // ti.esi.vi.width = (u32)((VideoESInfo*)esi)->getWidth(); 00275 // ti.esi.vi.height = (u32)((VideoESInfo*)esi)->getHeight(); 00276 // ti.esi.vi.aspectRatio = (float)((VideoESInfo*)esi)->getAspectRatio(); 00277 00278 initTheora(esi); 00279 00280 } else if (esi->isAudioStream()) { 00281 dprintf_full("OGGMuxDemuxIO::writeFrame: found audio stream\n"); 00282 ogg_stream_init(tmp, serialvorbis); 00283 00284 vorbis_stream = new OGGStreamInfo(); 00285 00286 vorbis_stream->setStreamType(OGG_VORBIS); 00287 vorbis_stream->setStreamID(serialvorbis); 00288 vorbis_stream->setStreamState(tmp); 00289 00290 // ti.esi.ai.sampleRate = ((AudioESInfo*)esi)->getSampleRate(); 00291 // ti.esi.ai.channels = ((AudioESInfo*)esi)->getAudioChannels(); 00292 // //copy first two characters 00293 // ti.esi.ai.language[1] = ((AudioESInfo*)esi)->getLanguage()[1]; 00294 // ti.esi.ai.language[2] = ((AudioESInfo*)esi)->getLanguage()[2]; 00295 00296 initVorbis(esi); 00297 } 00298 } 00299 00300 ogg_packet *op; 00301 ogg_page *og; 00302 og = new ogg_page; 00303 op = new ogg_packet; 00304 00305 // theora stream has to be first 00306 if(theora_stream != NULL){ 00307 // insert ogg-stream-info to ogg-stream-handler 00308 // if not present 00309 if(osh_w->osi == NULL) 00310 osh_w->osi = osi; 00311 00312 osi->append(theora_stream); 00313 00314 // write header pages of theorastream 00315 /* first packet will get its own page automatically */ 00316 dprintf_full("theora_encode_header\n"); 00317 theora_encode_header(ts, op); 00318 ogg_stream_packetin(osi->getStreamState(serialtheora), op); 00319 if(ogg_stream_pageout(osi->getStreamState(serialtheora), og)!=1){ 00320 dprintf_err("OGGMuxDemuxIO::writeFrame: Internal Ogg library error.\n"); 00321 ::exit(1); 00322 } 00323 stream->write(og->header, og->header_len); 00324 stream->write(og->body, og->body_len); 00325 00326 theora_comment *tc; 00327 tc = new theora_comment; 00328 theora_comment_init(tc); 00329 theora_encode_comment(tc, op); 00330 ogg_stream_packetin(osi->getStreamState(serialtheora), op); 00331 theora_encode_tables(ts, op); 00332 ogg_stream_packetin(osi->getStreamState(serialtheora), op); 00333 } 00334 // vorbis stream as second 00335 if(vorbis_stream != NULL){ 00336 // insert ogg-stream-info to ogg-stream-handler 00337 // if not present 00338 if(osh_w->osi == NULL) 00339 osh_w->osi = osi; 00340 osi->append(vorbis_stream); 00341 00342 // write header pages of vorbisstream 00343 ogg_packet *header; 00344 ogg_packet *header_comm; 00345 ogg_packet *header_code; 00346 00347 header = new ogg_packet; 00348 header_comm = new ogg_packet; 00349 header_code = new ogg_packet; 00350 00351 dprintf_full("vorbis_encode_header: vorbis_stream=%p vd=%p vc=%p header=%p header_comm=%p header_code=%p\n", 00352 vorbis_stream, vd, vc, header, header_comm, header_code); 00353 00354 vorbis_analysis_headerout(vd, vc, header, header_comm, header_code); 00355 dprintf_full("vorbis_header_encoded\n"); 00356 ogg_stream_packetin(osi->getStreamState(serialvorbis), header); 00357 if(ogg_stream_pageout(osi->getStreamState(serialvorbis), og) != 1){ 00358 dprintf_err("Internal Ogg library error.\n"); 00359 ::exit(1); 00360 } 00361 stream->write(og->header, og->header_len); 00362 stream->write(og->body, og->body_len); 00363 00364 ogg_stream_packetin(osi->getStreamState(serialvorbis), header_comm); 00365 ogg_stream_packetin(osi->getStreamState(serialvorbis), header_code); 00366 } 00367 00368 00369 /* create the remaining theora headers */ 00370 if(theora_stream != NULL){ 00371 /* flush the rest of the theora headers */ 00372 while(1){ 00373 int result = ogg_stream_flush(osi->getStreamState(serialtheora), og); 00374 if(result < 0){ 00375 /* theoretical can't get here */ 00376 dprintf_err("Internal Ogg library error.(THEORA)\n"); 00377 ::exit(1); 00378 } 00379 dprintf("OGGMuxDemuxIO:writeFrame: result = %i\n",result); 00380 if(result == 0) break; 00381 stream->write(og->header, og->header_len); 00382 stream->write(og->body, og->body_len); 00383 } 00384 } 00385 00386 /* create the remaining vorbis headers */ 00387 if(vorbis_stream != NULL){ 00388 /* flush the rest of the vorbis headers */ 00389 while(1){ 00390 int result = ogg_stream_flush(osi->getStreamState(serialvorbis), og); 00391 if(result < 0){ 00392 /* theoretically can't get here */ 00393 dprintf_err("Internal Ogg library error. (VORBIS)\n"); 00394 ::exit(1); 00395 } 00396 if(result == 0) break; 00397 stream->write(og->header, og->header_len); 00398 stream->write(og->body, og->body_len); 00399 } 00400 } 00401 00402 delete og; 00403 delete op; 00404 og = NULL; 00405 op = NULL; 00406 00407 } // if(firstFrame) 00408 00409 AU *au = frm->getAU(); 00410 ogg_packet *op = (ogg_packet*)au->payload; 00411 00412 ogg_page *og; 00413 og = new ogg_page; 00414 int ret; 00415 if(out_es->isAudioStream()){ 00416 ogg_stream_packetin(osi->getStreamState(serialvorbis), op); 00417 ret = ogg_stream_pageout(osi->getStreamState(serialvorbis), og); 00418 dprintf_full("OGGMuxDemuxIO::writeFrame: writing Audio-Frame (%i)\n", ret); 00419 } else { 00420 ogg_stream_packetin(osi->getStreamState(serialtheora), op); 00421 ret = ogg_stream_pageout(osi->getStreamState(serialtheora), og); 00422 dprintf_full("OGGMuxDemuxIO::writeFrame: writing Video-Frame (%i)\n", ret); 00423 } 00424 00425 if(ret != 0){ 00426 stream->write(og->header, og->header_len); 00427 stream->write(og->body, og->body_len); 00428 } 00429 00430 delete og; 00431 og = NULL; 00432 00433 //delete(au->payload); 00434 // ogg_packet_clear(op); 00435 // delete frm; 00436 // frm = NULL; 00437 00438 // ::exit(0); 00439 return 0; 00440 } 00441 00442 00443 00449 Frame *OGGMuxDemuxIO::getFrame() { 00450 // OGGHandler *osh = OGGContainerFile::getOGGHandler(); 00451 ogg_page og; 00452 00453 if(state != OPEN || !readOnly){ 00454 dprintf_err("OGGMuxDemuxIO::getFrame: Stream not open (for reading?) or EOF!\n"); 00455 return 0; 00456 } 00457 00458 OGGContainerFile::oggMutexLock("OGGMuxDemuxIO"); 00459 00460 double start_dtime, now_dtime; 00461 struct timeval now_tv; 00462 gettimeofday(&now_tv,NULL); 00463 start_dtime = now_tv.tv_sec + now_tv.tv_usec/1000000.0; 00464 00465 if(firstFrame && (state != OPEN)) 00466 this->open(); 00467 00468 // Do Header-Parsing 00469 // I do not need header-parsing again, 'cause i 've OGGHandler :) 00470 if(firstFrame){ 00471 // get OGGHandler 00472 osh = OGGContainerFile::getOGGHandler(); 00473 vorbisframesSeen=0; 00474 theoraframesSeen=0; 00475 // numStreams=0; 00476 // streamp=0; 00477 firstFrame=false; 00478 } 00479 00480 ogg_packet* op = new ogg_packet; 00481 00482 AU *au; 00483 Frame *frm; 00484 00485 bool processed = false; 00486 // do until at least one packet is processed. 00487 do{ 00488 u8* op_copy; 00489 OGGStreamInfo *osi=osh->osi; 00490 assert(osi); 00491 char* str; 00492 // now look in each Streamstate, if there is a packet ready 00493 do{ 00494 if(ogg_stream_packetout(osi->getStreamState(), op) > 0){ 00495 au = new AU(); 00496 // GOT PACKET FOR STREAM X 00497 dprintf_full("OGGMuxDemuxIO::getFrame: packetout OK (SIZE: %li), packetno = %li\n", 00498 op->bytes, (long int)op->packetno); 00499 00500 au->size=op->bytes; 00501 op_copy = new u8[sizeof(ogg_packet)+op->bytes]; 00502 00503 // copy all values from op to op_copy and 00504 // set packet* to object + sizeof(ogg_packet) 00505 // and copy packet to object + sizeof(ogg_packet) 00506 // to have all data in one place 00507 { 00508 ogg_packet *tmp = (ogg_packet*)op_copy; 00509 int op_size = sizeof(ogg_packet); 00510 memcpy(op_copy, op, op_size); 00511 tmp->packet = op_copy + op_size; 00512 memcpy(tmp->packet, op->packet, op->bytes); 00513 } 00514 00515 au->payload = op_copy; 00516 00517 /* 00518 * if streamtype == VORBIS, do VORBIS specific stuff 00519 */ 00520 if(osi->getStreamType() == OGG_VORBIS) { 00521 str="vorbis"; 00522 // TODO: 00523 Frame::FrameType type = Frame::VORBIS_AUDIO; 00524 dprintf_full("OGGMuxDemuxIO::getFrame: Frame (%i) for OGG_VORBIS (granulepos: %li)!!!\n", 00525 vorbisframesSeen,(long)op->granulepos); 00526 vorbis_info *vi = (vorbis_info*)osi->getCodecInfo(); 00527 // int time_increment = (int)((float)(576*90000)/vi->rate/4); 00528 00529 if(op->granulepos >= 0) { 00530 au->cts = (int)(((double)op->granulepos/(double)vi->rate)*90000.0); 00531 vorbisframesSeen = au->cts; 00532 } else { 00533 au->cts = vorbisframesSeen; // * es->getVOPTimeIncrement() ;//+ time_increment * vorbisframesSeen++; 00534 } 00535 //au->cts = 0; 00536 au->dts = au->cts; 00537 00538 au->sampleFlags = 0; 00539 au->err = SA_OK; 00540 frm = new Frame(type); 00541 frm->setStreamID(osi->getStreamID()); 00542 frm->setAU(au); 00543 00544 processed = true; 00545 00546 // dprintf_err("OGGMuxDemuxIO::getFrame: %s: %li\n",str,(long)op->granulepos); 00547 dprintf_full("OGGMuxDemuxIO::getFrame: Vorbis-Timestamp: pos(%li)/rate(%li) = %f, au->cts = %i, mycts = %i\n", 00548 (long)op->granulepos, 00549 (long)vi->rate, 00550 ((double)op->granulepos/vi->rate), 00551 au->cts, 00552 (int)(((double)op->granulepos/(double)vi->rate)*90000.0) 00553 ); 00554 00555 dprintf_full("DEMUX_INFO: VORBIS, op-granule: %li, cts = %i, time = %f, framesSeen = %i\n", 00556 (long)op->granulepos, 00557 au->cts, ((double)op->granulepos/vi->rate), 00558 vorbisframesSeen); 00559 } 00560 /* 00561 * if streamtype == THEORA, do THEORA specific stuff 00562 */ 00563 else if(osi->getStreamType() == OGG_THEORA){ 00564 str="theora"; 00565 // CTS = numerator/denominator 00566 dprintf_full("OGGMuxDemuxIO::getFrame: Frame (%i) for OGG_THEORA (granulepos: %li)!!!\n", 00567 theoraframesSeen, (long int)op->granulepos); 00568 Frame::FrameType type = Frame::NN_VOP; 00569 theora_info *ti = (theora_info*)osi->getCodecInfo(); 00570 00571 au->cts = (u32)( 00572 90000.0 * 00573 (float) theoraframesSeen++ / 00574 ( 00575 (float)ti->fps_numerator / 00576 (float)ti->fps_denominator 00577 ) 00578 ); 00579 // au->cts = 0; 00580 au->dts = au->cts; 00581 00582 // dprintf_err("OGGMuxDemuxIO::getFrame: %s: %i\n",str,theoraframesSeen); 00583 dprintf_full("OGGMuxDemuxIO::getFrame: OGGStreamStateINFO: packetno: %li ==========================\n", 00584 (long int)osi->getStreamState()->packetno); 00585 au->sampleFlags = 0; 00586 au->err = SA_OK; 00587 00588 if(theora_packet_iskeyframe(op)){ 00589 dprintf_full("OGGMuxDemuxIO::getFrame: +KEYFRAME!!!\n"); 00590 type = Frame::I_VOP; 00591 }else{ 00592 dprintf_full("OGGMuxDemuxIO::getFrame: +NO keyframe!!!\n"); 00593 type = Frame::B_VOP; 00594 } 00595 00596 frm = new Frame(type); 00597 frm->setStreamID(osi->getStreamID()); 00598 frm->setAU(au); 00599 frm->setType(type); 00600 00601 dprintf_full("OGGMuxDemuxIO::getFrame frametype: += %i\n",frm->getType()); 00602 00603 processed = true; 00604 dprintf_full("DEMUX_INFO: THEORA, op-granule: %li, cts = %i, time = %f, fps = %f, framesSeen = %i\n", 00605 (long)op->granulepos, 00606 au->cts, au->cts/90000.0, (float)ti->fps_numerator/(float)ti->fps_denominator, 00607 theoraframesSeen); 00608 } 00609 } 00610 // if(processed)return frm; 00611 osi = osi->getNext(); 00612 }while(osi && !processed); 00613 00614 // dprintf_err("OGGMuxDemuxIO: packets seen: %li\n",packetsSeen++); 00615 00616 // if there is no packet for any stream... 00617 if(!processed && state!=STREAMEOF){ 00618 // do something to get one! 00619 // int ret = 0, ret1 = 0; 00620 dprintf_full("OGGMuxDemuxIO::getFrame: packetout returned no packet... getting new page!\n"); 00621 00622 // read some bytes 00623 int finished = 0; 00624 finished = OGGContainerFile::bufferData(stream, &(osh->oy)); 00625 dprintf_full("OGGMuxDemuxIO::getFrame: read %i bytes!\n", finished); 00626 00627 if(finished == 0 || finished == -1){ 00628 state = STREAMEOF; 00629 OGGContainerFile::oggMutexRelease("OGGMuxDemuxIO"); 00630 return NULL; 00631 } 00632 00633 // now try a pageout 00634 int ret = 0; 00635 while((ret=ogg_sync_pageout(&(osh->oy), &og))>0){ 00636 // queue page in appropriate stream 00637 dprintf_full("OGGMuxDemuxIO::getFrame: sync_pageout got a page!\n"); 00638 osi = osh->osi; 00639 // search for appropriate stream and buffer page 00640 if(osi->getStreamState(ogg_page_serialno(&og))) 00641 ogg_stream_pagein(osi->getStreamState(ogg_page_serialno(&og)), &og); 00642 else 00643 dprintf_full("OGGMuxDemuxIO::getFrame: EXTREME ERRORR!!!\n"); 00644 00645 } 00646 00647 } // if(!processed) 00648 else break; 00649 00650 }while(!processed); // until one packet is processed 00651 00652 delete op; 00653 gettimeofday(&now_tv,NULL); 00654 now_dtime = now_tv.tv_sec + now_tv.tv_usec/1000000.0; 00655 dprintf_full("OGGMuxDemuxIO::getFrame(): worked for %2.0f msecs\n", 00656 (now_dtime-start_dtime)*1000.0); 00657 00658 #ifdef _POSIX_PRIORITY_SCHEDULING 00659 sched_yield(); //this is necessary to give parallel getFrames a chance 00660 #endif 00661 00662 OGGContainerFile::oggMutexRelease("OGGMuxDemuxIO"); 00663 00664 if(state == STREAMEOF) 00665 return NULL; 00666 else 00667 return frm; 00668 } 00669 00670 00671 #endif