Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members
ESSynchronizer.cpp
00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: ESSynchonizer.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 "ESSynchronizer.hpp" 00045 //#include <SDL.h> 00046 00047 00048 00049 ESSynchronizer::ESSynchronizer(ESInfo* esi, GlobalTimer * globalTimer) { 00050 gettimeofday(&tv,NULL); 00051 00052 this->globalTimer = globalTimer; 00053 cond_pause_mutex.initialize("ESSync-Cond_Pause_Mutex"); 00054 cond_pause.initialize(); 00055 paused = false; 00056 es=esi; 00057 strcpy(name,"ESSynchronizer"); 00058 outputRate = 1.0; 00059 frmCount = 0; 00060 dropCount = 0; 00061 } 00062 00063 00064 ESSynchronizer::~ESSynchronizer() { 00065 cond_pause.destroy(); 00066 cond_pause_mutex.destroy(); 00067 } 00068 00069 00070 void ESSynchronizer::initialize() { 00071 } 00072 00073 00074 bool ESSynchronizer::setOutputRateFactor(double factor) { 00075 if (factor <= 0.0 || !globalTimer) 00076 return false; 00077 globalTimer->setPaused(true); 00078 globalTimer->adjust(globalTimer->getActualSec() * outputRate / factor); 00079 outputRate = factor; 00080 globalTimer->setPaused(false); 00081 return true; 00082 } 00083 00084 00085 bool ESSynchronizer::adjust(double sec) { 00086 if (!globalTimer || sec < 0.0) 00087 return false; 00088 globalTimer->adjust(sec / outputRate); 00089 return true; 00090 } 00091 00092 00093 void ESSynchronizer::setPaused(bool pause) { 00094 cond_pause_mutex.lock(); 00095 paused = pause; 00096 if (!paused) 00097 cond_pause.signal(); 00098 cond_pause_mutex.release(); 00099 } 00100 00101 00102 /***************************************************************/ 00103 list < Frame * > ESSynchronizer::adapt(Frame * frm) { 00104 bool forwardFrame = false; 00105 list < Frame * >tmp; 00106 int act_wait; 00107 double t, tframe; 00108 00109 /* block until not paused */ 00110 cond_pause_mutex.lock(); 00111 while (paused) { 00112 dprintf_full("ESSynchronizer::adapt() PAUSED @ %4.2f sec, frame %i\n", 00113 globalTimer->getActualSec(), frm->getAU()->cts); 00114 cond_pause.condWait(cond_pause_mutex.getMutexObject()); 00115 } 00116 cond_pause_mutex.release(); 00117 00118 tmp.push_front(frm); 00119 00120 //TURN OFF SYNC IF BENCHMARKING NETWORK! 00121 #ifdef NETBENCH 00122 #define FORCE_DISPLAY 00123 #endif 00124 00125 #ifdef FORCE_DISPLAY 00126 forwardFrame = true; 00127 #endif 00128 00129 Frame::FrameType myType = frm->getType(); 00130 00131 00132 #ifndef LOCALBENCH 00133 if ((myType == Frame::I_VOP) || (myType == Frame::P_VOP) || (myType == Frame::HEADER_VOP)) 00134 forwardFrame = true; 00135 #endif 00136 00137 if(myType == Frame::NN_VOP || myType == Frame::MP3_AUDIO) 00138 forwardFrame = true; 00139 00140 00141 if (frmCount == 0) //always show first frame! 00142 forwardFrame = true; 00143 00144 frmCount++; 00145 00146 // a bypassing YUV_VOP or RGB_VOP is fully subjected to dropping, if time is out! 00147 00148 if(frm->getMediaTimeScale() == 0) 00149 frm->setMediaTimeScale(es->getMediaTimeScale()); 00150 00151 assert(frm->getMediaTimeScale() != 0); 00152 t = (double) frm->getMediaTimeScale(); 00153 if (outputRate != 1.0) 00154 t *= outputRate; 00155 tframe = (double)frm->getAU()->cts / t; // play-out time in seconds 00156 act_wait = (int) ((tframe - globalTimer->getActualSec()) * 1000.0 ); 00157 00158 //dprintf_full("ESSynchronizer::adapt() frame type=%d forwarding=%d cts=%d timescale(t)=%f tframe=%f\n", 00159 // myType, forwardFrame, frm->getAU()->cts, t, tframe); 00160 00161 /* Detect discontinuity in stream and re-synchronize GlobalTimer. 00162 * Re-synchronization is done only if the current frame is *ahead* 00163 * of play-out time to avoid competing with 00164 * SDLaudioIO:sdl_audio_callback(). 00165 */ 00166 if (act_wait > ESSYNC_DISCONT_MSECS) { 00167 dprintf_small("ESSynchronizer::adapt() detected stream discontinuity (%d > %d, " 00168 "re-synchronizing globalTimer to %4.2f sec\n", act_wait, ESSYNC_DISCONT_MSECS, tframe); 00169 globalTimer->adjust(tframe); 00170 act_wait = 0; 00171 } 00172 00173 //dprintf_full("ESSynchronizer::adapt @ %4.2f sec, outputRate %5.3f, frameCTS %i (size %i) -> act_wait: %i\n", 00174 // globalTimer->getActualSec(), outputRate, frm->getAU()->cts, frm->getAU()->size,act_wait); 00175 00176 if (act_wait > (-1) * ESSYNC_GRACE_MSECS) { 00177 forwardFrame = true; 00178 } 00179 00180 if (forwardFrame) { 00181 if(act_wait >= 10 /*&& frm->getType() != Frame::MP3_AUDIO*/) 00182 msleep(act_wait); 00183 } else { //not forward frame 00184 dprintf_err("ESSynchronizer::adapt -> act_wait: %i DROPPING frame (dropCount=%d) ... missed CTS %i!!!\n", 00185 act_wait, ++dropCount, frm->getAU()->cts); 00186 //deletion is done in DataChannel! 00187 frm->markForDelete(); 00188 return tmp; 00189 } 00190 00191 return tmp; 00192 }