#include <RioMMVideo.h>
Inherits CRioMMObject.
Public Member Functions | |
CRioMMVideo (char *, unsigned int, RioBlock, struct timeval RTT_average, RioMMInterface *, int block, ConfigData *, RioMMExplorer *) | |
CRioMMVideo é o construtor da classe CRioMMVideo. | |
~CRioMMVideo () | |
virtual void | Prefetch (void) |
Prefetch só é chamada quando o cliente esta no inicio (play). | |
bool | Move_Prefetch (void) |
Move_Prefetch faz o mesmo que o metodo Prefetch com a diferenca de que nao precisa se conectar na PI pois isto ja esta feito. | |
void | PlayBlock (int, int) |
PlayBlock escreve o bloco buf, de tamanho size, no buffer do mplayer para ser tocado imediatamente. | |
void | FastForward (void) |
void | FastRewind (void) |
void | GoTo (RioBlock) |
GoTo coloca o evento EVENT_GOTO na pilha de eventos tratada pela PlayThread. | |
void | Play (void) |
Play() inicia a execução do vídeo criando uma PlayThread, caso cliente ainda não tenha inicializado, ou dá prosseguimento à execução da mesma caso o cliente esteja em estado de pausa. | |
void | Pause (void) |
Pause coloca o evento EVENT_PAUSE na pilha de eventos tratada pela PlayThread. | |
void | Stop (void) |
Stop finaliza a execução do vídeo e mata a PlayThread em execução. | |
int | init (void) |
init faz inicializações da conexão com a PL (se o cliente estiver com connectPI == true) e inicializa os membros first, my_address e my_port. | |
bool | WaitPrefetch () |
WaitPrefetch apenas aguarda os blocos solicitados pela Prefetch. | |
void | WaitEndOfVideo (void) |
WaitEndOfVideo aguarda que o mplayer seja finalizado por detecção de EOF (término do arquivo de vídeo). | |
int | GetSubTitles (RioAccess, CRioStream *) |
void | PrefetchMutexLock (string msg="") |
PrefetchMutexLock trava o mutex PrefetchMutex. | |
void | PrefetchMutexUnlock (string msg="") |
PrefetchMutexUnlock destrava o mutex PrefetchMutex. | |
void | MulticastMutexLock (string msg="") |
MulticastMutexLock trava o mutex multicastMutex. | |
void | MulticastMutexUnlock (string msg="") |
MulticastMutexUnlock destrava o mutex multicastMutex. | |
void | MulticastWaitCondition (string msg="") |
MulticastWaitCondition trava o cliente aguardando a execução da MulticastReleaseCondition. | |
void | MulticastReleaseCondition (string msg="") |
MulticastReleaseCondition libera a execução do cliente travado pela execução da MulticastWaitCondition. | |
void | PlayPauseMutexLock (string msg="") |
PlayPauseMutexLock trava o mutex PlayPauseMutex. | |
void | PlayPauseMutexUnlock (string msg="") |
PlayPauseMutexUnlock destrava o mutex PlayPauseMutex. | |
RioBlock | GetCurrentPosition (void) |
GetCurrentPosition retorna o número do bloco que está sendo tocado neste momento. | |
RioBlock | GetTotalPositions (void) |
GetTotalPositions retorna o tamanho total do vídeo em número de blocos. | |
bool | isFirst (void) |
isFirst verifica se o cliente detém algum tipo de liderança (se é líder ou sublíder) e retorna true, caso positivo ou false, caso negativo. | |
void | SetTarget (int target) |
void | SetNextRequestBlock (int block) |
RioBlock | GetNextRequestBlock () |
GetNextRequestBlock retorna o próximo bloco a ser requisitado para o PlayOutBuffer. | |
void | ClearBuffer () |
void | Stream_Control (string msg="") |
bool | isPatching () |
int | FreeBlock (int PlayBuffer) |
Este metodo chama a FreeBlock da RioNetI que por sua vez verifica se chegaram fragmentos do bloco apontado pela posicao PlayBuffer (parametro) do vetor Request. | |
int | FreePendentBlocks (bool useCache, int nBuffers) |
bool | thereAreFragments (RioBlock block) |
thereAreFragments verifica se existem fragmentos para o bloco fornecido no parametro block. | |
void | SetWID (int) |
int | ProcessSignal (int, void *) |
void | appendLog (QString) |
void | inputLog (QString) |
void | inputLog (int, unsigned int=0, unsigned int=0) |
unsigned int | getCurrentPlayingBlock () |
const bool | getmakeLog () |
Static Public Member Functions | |
static void | MulticastCallBack (void *parm, int result) |
MulticastCallBack é chamada toda vez que um bloco multicast chega ou que o cliente chame a FreeBlock para um bloco multicast. | |
static void | CallBack (struct RioRequest *request) |
CallBack é chamada toda vez que um bloco unicast chegou e está pronto pra ser tocado (seja por ter chegado intacto ou via FreeBlock). | |
Data Fields | |
bool | waitingMSGCODE_IP |
bool | first |
bool | signal |
int | my_address |
int | my_port |
int | wId |
bool | syncOn |
CRioStream | Stream |
pthread_mutex_t | multicastMutex |
pthread_cond_t | multicastCondition |
Protected Member Functions | |
void | StartPlayer (void) |
Este metodo abre o mplayer e seta as saidas padroes para /dev/null. | |
bool | ReadNextBlock (unsigned int) |
bool | WaitFullBuffer () |
WaitFullBuffer requisita o número de blocos suficiente para encher o buffer e espera até que os mesmos cheguem para, então, liberar o mutex da playthread, mas se os blocos demorarem muito (na WaitPrefetch), então a FreeBlock é chamada para os fragmentos recebidos e o cliente toca tais fragmentos dando continuidade à execução do vídeo. | |
bool | WaitMulticastBlocks () |
WaitMulticastBlocks verifica se os blocos esperados se encontram na cache. | |
bool | Leader_WaitMulticastBlocks () |
Leader_WaitMulticastBlocks é a função de espera de blocos executada por um líder (apenas o líder pode executar este método). | |
bool | WaitBlocks () |
WaitBlocks aguarda a chegada dos blocos solicitados de acordo com o contexto do cliente. | |
bool | CallFreeBlock (int) |
CallFreeBlock chama a FreeBlock para liberar os fragmentos do bloco referente à posição PlayBuffer do buffer (Request[ PlayBuffer].Block) que já tiverem chegado. | |
bool | ReadBlock (int, RioBlock, RioStreamType, int, int) |
ReadBlock solicita o bloco block ao servidor, indicando, através de traffic, se a requisição é multicast ou unicast. | |
Static Protected Member Functions | |
static void * | PlayThread (void *) |
PlayThread controla a execução do vídeo e a recuperação dos blocos a serem tocados no momento da sua execução invocando, quando necessário, os métodos que manipulam requisições e recuperações de blocos no servidor e/ou em disco. | |
static void | PlayThreadCleanup (void *) |
Protected Attributes | |
int | pipe_player [2] |
char | pipe_buffer [MaxPipeDataSize] |
pid_t | playerPID |
unsigned int | PlayBuffer |
RioBlock | NextRequestBlock |
int | target |
pthread_t | PlayThreadID |
bool | Paused |
unsigned int | req_block |
bool | patching |
QStringList * | playerCmdLine |
Informa se cliente está em patching. | |
bool | connectPI |
int | PID |
int | ReadFrom |
QString | piHost |
bool | WaitingPrefetch |
pthread_mutex_t | PlayPauseMutex |
pthread_mutex_t | PrefetchMutex |
bool | HasSubTitle |
bool | useCache |
QString | User |
QString | player |
RioFile * | subTitle |
CRioTimer | timer |
CommunicationStream * | CommMultiStream |
RioCallBackTransport | callback_transport |
RioMMExplorer * | rioMMExplorer |
bool | ReadBlockStatus |
Private Member Functions | |
bool | readSettings (void) |
void | writeDefaultSettings (void) |
bool | DealPendentEvents () |
Private Attributes | |
RioMMInterface * | riomminterface |
bool | makeLog |
QString | logData |
QString | logAppend |
QString | logAction |
pthread_mutex_t | log_mutex |
QPtrStack< PlayThreadEvent > | PTEventStack |
Definition at line 60 of file RioMMVideo.h.
CRioMMVideo::CRioMMVideo | ( | char * | videoname, | |
unsigned int | blocksize, | |||
RioBlock | numBuffers, | |||
struct timeval | RTT_average, | |||
RioMMInterface * | rio, | |||
int | block, | |||
ConfigData * | config, | |||
RioMMExplorer * | rioMMExplorer | |||
) |
CRioMMVideo é o construtor da classe CRioMMVideo.
block | Informa em qual bloco deve ser iniciada a exibição do vídeo. | |
videoname | Informa o nome do vídeo no servidor que o cliente quer assistir. | |
numBuffers | Informa o tamanho do PlayOutBuffer do cliente. | |
rio | é um ponteiro para a RioMMInterface e serve para o cliente ter acesso aos métodos e membros da mesma. | |
config | Informa as opções passadas como parâmetro na chamada do cliente pelo shell. | |
rioMMExplorer | é um ponteiro para a classe rioMMExplorer que possibilita manipulação de arquivos no servidor bem como transferência de arquivos entre o servidor e o sistema local. |
Definition at line 65 of file RioMMVideo.cpp.
00069 :CRioMMObject( videoname, blocksize, numBuffers, average_RTT ) 00070 { 00071 this->ReadFrom = READFROM_SERVER; 00072 this->connectPI = config->getRioMMConnectPI(); 00073 this->piHost = config->getRioMMPIHost(); 00074 this->useCache = config->getRioMMUseCache(); 00075 this->User = config->getRioMMUser(); 00076 this->rioMMExplorer = rioMMExplorer; 00077 00078 #ifdef RIO_EMUL 00079 this->logPath = config->getRioMMLogPath(); 00080 #endif 00081 00082 this->riomminterface = rio; 00083 pthread_mutex_init( &log_mutex , NULL ); 00084 pthread_mutex_init( &multicastMutex , NULL ); 00085 pthread_mutex_init( &PlayPauseMutex , NULL ); 00086 pthread_mutex_init( &PrefetchMutex , NULL ); 00087 pthread_cond_init( &multicastCondition, NULL ); 00088 00089 syncOn = config->getRioMMSync(); 00090 Paused = false; 00091 00092 #ifndef RIO_EMUL 00093 HasSubTitle = false; 00094 subTitle = NULL; 00095 #endif 00096 00097 PlayBuffer = 0; 00098 PlayThreadID = 0; 00099 NextRequestBlock = block; 00100 target = INT_MAX; 00101 WaitingPrefetch = false; 00102 group_block = -1; 00103 req_block = 0; 00104 patching = false; 00105 my_address = 0; 00106 my_port = 0; 00107 playerPID = 0; 00108 playerCmdLine = NULL; 00109 PID = 0; 00110 first = false; 00111 wId = 0; 00112 CommMultiStream = NULL; 00113 player = ""; 00114 00115 //Esta variavel informa se o cliente está aguardando uma mensagem do tipo 00116 //MSGCODE_IP da PL. Isto foi necessário pois as vezes o cliente trava 00117 //aguardando tal mensagem mas recebe outras mensagens antes da esperada, 00118 //como a MSG_MODE, por exemplo. Estas outras mensagens devem ser ignoradas 00119 //até que o cliente receba de fato a mensagem que está esperando senão 00120 //efeitos colaterais acontecerão. 00121 waitingMSGCODE_IP = false; 00122 00123 #ifdef RIO_EMUL 00124 gettimeofday( &final_block_time, 0 ); 00125 gettimeofday( &timer_before , 0 ); 00126 gettimeofday( &timer_after , 0 ); 00127 gettimeofday( &diff_timer , 0 ); 00128 gettimeofday( &initial_time , 0 ); 00129 gettimeofday( &final_time , 0 ); 00130 Stopped = false; 00131 makeLog = false; 00132 multicast = -1; 00133 delayed_blocks = 0; 00134 lost_blocks = 0; 00135 m_log.open( "/dev/null" ); 00136 calculeted_time = 0; 00137 play_time = 0; 00138 timers = new print_log[ nBuffers ]; 00139 00140 //para não exibir o tempo com notação científica 00141 cout.flags(ios::fixed); 00142 cerr.flags(ios::fixed); 00143 m_log.flags(ios::fixed); 00144 #endif 00145 00146 for( unsigned int i = 0; i < nBuffers; i++ ) 00147 { 00148 Request[i].CallBackFunction = CRioMMVideo::CallBack; 00149 Request[i].User = (void *)i; 00150 Request[i].Result = S_OK; 00151 Request[i].Status = RIO_REQUEST_FREE; 00152 Request[i].reqid = 0; 00153 #ifdef RIO_EMUL 00154 timers[ i ].block = 0; 00155 gettimeofday( &timers[i].arrival_time, NULL ); 00156 gettimeofday( &timers[i].call_time , NULL ); 00157 #endif 00158 } 00159 00160 bufferStream = NULL; 00161 00162 for( unsigned int i = 0; i < 2; i++ ) 00163 pipe_player[ i ] = 0; 00164 00165 for( int i = 0; i < MaxPipeDataSize; i++ ) 00166 pipe_buffer[ i ] = ' '; 00167 00168 PTEventStack.setAutoDelete( true ); 00169 PTEventStack.clear(); 00170 00171 // Inicializa o estado da chamada ReadBlock como true (sucesso), pois 00172 // ainda nao executamos a funcao. 00173 00174 ReadBlockStatus = true; 00175 00176 }
CRioMMVideo::~CRioMMVideo | ( | ) |
Definition at line 179 of file RioMMVideo.cpp.
00180 { 00181 #ifdef RIO_DEBUG2 00182 RioErr << "[RioMMVideo] Entrei no destrutor " << endl; 00183 #endif 00184 00185 #ifdef RIO_EMUL 00186 requestedBlocks = lostBlocks + completeBlocks; 00187 completeBlocks -= partialBlocks; 00188 00189 m_log << "Blocos requisitados: " << requestedBlocks << endl 00190 << "Blocos completamente recebidos: " << completeBlocks << endl 00191 << "Blocos parcialmente recebidos: " << partialBlocks << endl 00192 << "Blocos perdidos: " << lostBlocks << endl 00193 << "Bytes exibidos: " << totalBytesPlayed << endl; 00194 if( requestedBlocks > 0 ) 00195 m_log << "Goodness: " << ( (float)totalBytesPlayed / 00196 (float)( requestedBlocks * 128 * 1024 ) ) * 100 << endl; 00197 #endif 00198 00199 if( PlayThreadID != 0 ) 00200 { 00201 if( pthread_cancel( PlayThreadID ) != 0 ) 00202 { 00203 #ifdef RIO_DEBUG2 00204 RioErr << "Destrutor - failed to cancel thread " << endl; 00205 #endif 00206 } 00207 else 00208 { 00209 #ifdef RIO_DEBUG2 00210 RioErr << "Destrutor - cancel thread OK " << endl; 00211 #endif 00212 } 00213 pthread_join( PlayThreadID, NULL ); 00214 } 00215 00216 #ifndef RIO_EMUL 00217 if( HasSubTitle ) 00218 { 00219 subTitle->Delete(); 00220 HasSubTitle = false; 00221 } 00222 // Remove o objeto subTitle. 00223 if( subTitle != NULL ) 00224 delete subTitle; 00225 #endif 00226 00227 if( bufferStream ) 00228 { 00229 delete bufferStream; 00230 } 00231 00232 #ifdef RIO_EMUL 00233 //Linha abaixo porque valgrind detectou memory leak quanto a a 00234 //locacao do vetor timers e o fato de nao haver sua delecao ao termino. 00235 delete[] timers; 00236 00237 m_log.close(); 00238 #endif 00239 00240 inputLog( QUIT ); 00241 }
void CRioMMVideo::appendLog | ( | QString | text | ) |
void CRioMMVideo::CallBack | ( | struct RioRequest * | request | ) | [static] |
CallBack é chamada toda vez que um bloco unicast chegou e está pronto pra ser tocado (seja por ter chegado intacto ou via FreeBlock).
Este método grava os dados recebidos na memória cache (disco) pois já tem os dados gravados no PlayOutBuffer (a RioNeti o faz).
request | ponteiro para a requisição de bloco que acabou de ser atendida (bloco pronto pra ser tocado). |
Reimplemented from CRioMMObject.
Definition at line 3532 of file RioMMVideo.cpp.
03533 { 03534 CRioMMVideo *videoPtr; 03535 03536 #ifdef RIO_DEBUG2 03537 RioErr << "[RioMMVideo] Entrei na CallBack" << endl; 03538 #endif 03539 03540 //FIXME: If I test it now, the player will block cause it is not ready to 03541 // skip blocks right now. 03542 //if( request->Result ) 03543 { 03544 #ifdef RANDOM_LOSS 03545 if( rand()<(RAND_MAX/2) ) 03546 { 03547 } 03548 else // else do if( rand()<(RAND_MAX/2) ) 03549 #endif 03550 { 03551 videoPtr = (CRioMMVideo *)request->Who; 03552 03553 videoPtr->inputLog( ARRIVING, request->Block ); 03554 03555 int index = request->Block % videoPtr->nBuffers; 03556 03557 #ifdef RIO_EMUL 03558 //This is done to log call arrival time 03559 gettimeofday( &videoPtr->timers[ 03560 (int) (long long int) request->User].arrival_time, 03561 0); 03562 03563 videoPtr->final_time.tv_sec = 03564 videoPtr->timers[ 03565 (int) (long long int) request->User].arrival_time.tv_sec - 03566 videoPtr->timers[(int) (long long int) request->User].call_time.tv_sec; 03567 videoPtr->final_time.tv_usec = 03568 videoPtr->timers[ 03569 (int) (long long int) request->User].arrival_time.tv_usec - 03570 videoPtr->timers[ 03571 (int) (long long int) request->User].call_time.tv_usec; 03572 03573 if( videoPtr->final_time.tv_usec < 0 ) 03574 { 03575 videoPtr->final_time.tv_sec -= 1; 03576 videoPtr->final_time.tv_usec += 1000000; 03577 } 03578 03579 videoPtr->calculeted_time = ( unsigned int ) 03580 ( videoPtr->final_time.tv_sec * 1000.0 + 03581 videoPtr->final_time.tv_usec/1000.0 03582 ); 03583 #endif 03584 03585 if( videoPtr->GetBufferStatus( (int) (long long int) request->User ) == BUFFEREMPTY ) 03586 { 03587 //Se cliente pediu duas vezes o mesmo bloco por causa do goto 03588 //copiar apenas o ultimo bloco recebido para nao prejudicar o 03589 //calculo do RTT na waitprefetch 03590 03591 //Se o reqid do bloco esperado for igual ao do bloco 03592 //que acabou de chegar devo setar o buffer para 03593 //que a PlayThread saiba que ele está disponível para consumo. 03594 if( request->reqid == videoPtr->Request[ index ].reqid ) 03595 { 03596 //SetBufferStatus envia o broadcast da condição 03597 //"Condition" 03598 videoPtr->SetBufferStatus( (int) (long long int) request->User, BUFFERFULL ); 03599 } 03600 #ifdef RIO_DEBUG2 03601 else 03602 { 03603 RioErr << "[CallBack] request->reqid = " << request->reqid 03604 << " videoPtr->Request[ index ].reqid = " 03605 << videoPtr->Request[ index ].reqid 03606 << endl; 03607 } 03608 #endif 03609 03610 #ifdef RIO_DEBUG2 03611 RioErr << "[RioMMVideo] CallBack VIDEO BLOCK: " 03612 << request->Block << endl; 03613 #endif 03614 03615 #ifdef RIO_EMUL 03616 timeval tv; 03617 gettimeofday( &tv, 0 ); 03618 videoPtr->m_log << (double)(tv.tv_sec + 03619 ( (double)tv.tv_usec / 1000000 )) ; 03620 videoPtr->m_log << " Recepção: " << request->Block << endl; 03621 #endif 03622 }//fim do if( videoPtr->GetBufferStatus(...) == BUFFEREMPTY ) 03623 #ifdef RIO_DEBUG2 03624 else 03625 { 03626 RioErr << "[RioMMVideo] CallBack: Buffer já se encontra cheio na" 03627 << " posicao " << request->User << ". Bloco " 03628 << request->Block << " (reqid " << request->reqid 03629 << ") deve ter sido requisitado mais de uma vez." 03630 << endl; 03631 } 03632 #endif 03633 03634 //Gravando o bloco na cache caso o bloco já não esteja lá. 03635 if( videoPtr->useCache ) 03636 { 03637 #ifdef RIO_DEBUG2 03638 RioErr << "!videoPtr->bufferStream->" 03639 << "exist( request->Block ) " 03640 << !videoPtr->bufferStream->exist( request->Block ) 03641 << " request->reqid " << request->reqid 03642 << " videoPtr->Request[ index ].reqid " 03643 << videoPtr->Request[ index ].reqid 03644 << " videoPtr->useCache " << videoPtr->useCache 03645 << " index " << index << endl; 03646 #endif 03647 03648 if( !videoPtr->bufferStream->exist( request->Block ) ) 03649 { 03650 #ifdef RIO_DEBUG2 03651 RioErr << "[CallBack] Gravando bloco " 03652 << request->Block << " (reqid " 03653 << request->reqid << ") na cache." 03654 << endl; 03655 #endif 03656 03657 videoPtr->bufferStream->writeBlock( request->Block, 03658 (unsigned char *) request->Buffer ); 03659 } 03660 } 03661 #ifdef RIO_DEBUG2 03662 else 03663 { 03664 RioErr << "[CallBack] Cache desabilitado. Bloco " 03665 << request->Block << " nao sera gravado." 03666 << endl; 03667 } 03668 #endif 03669 } // fim do else // else do if( rand()<(RAND_MAX/2) ) 03670 } //fim do //if( request->Result ) 03671 03672 #ifdef RIO_DEBUG2 03673 RioErr << "[RioMMVideo] Saindo da CallBack " << endl; 03674 #endif 03675 }
bool CRioMMVideo::CallFreeBlock | ( | int | PlayBuffer | ) | [protected] |
CallFreeBlock chama a FreeBlock para liberar os fragmentos do bloco referente à posição PlayBuffer do buffer (Request[ PlayBuffer].Block) que já tiverem chegado.
PlayBuffer | indica o bloco cujos fragmentos se quer liberar para exibição imediata. |
Definition at line 2272 of file RioMMVideo.cpp.
02273 { 02274 int freedSize; 02275 struct timeval now; 02276 struct timespec timeout; 02277 02278 #ifdef RIO_DEBUG2 02279 RioErr << "[RioMMVideo] CallFreeBlock - bloco/reqid = " 02280 << Request[ PlayBuffer ].Block << "/" << Request[ PlayBuffer ].reqid 02281 << endl; 02282 #endif 02283 02284 #ifdef RIO_DEBUG2 02285 RioErr << "[RioMMVideo] CallFreeBlock - Chamando FreeBlock para bloco " 02286 << Request[ PlayBuffer ].Block << ". PlayBuffer = " << PlayBuffer 02287 << endl; 02288 #endif 02289 02290 freedSize = FreeBlock( PlayBuffer ); 02291 02292 if( freedSize != 0 ) 02293 { 02294 Request[ PlayBuffer ].Size = freedSize; 02295 02296 #ifdef RIO_DEBUG2 02297 RioErr << "CallFreeBlock - FreeBlock liberou bloco " 02298 << Request[ PlayBuffer ].Block << "(size " << freedSize << ")" 02299 << endl; 02300 #endif 02301 02302 //Enquanto o bloco não for gravado no PlayOutBuffer ou não estiver 02303 //disponível na cache, ficarei neste looping aguardando sua 02304 //disponibilidade. Nota: Não se corre o risco de ficar eternamente no 02305 //loop pois como freedSize != 0, alguma coisa foi recuperada e, 02306 //portanto, está sendo escrita na cache e/ou no PlayOutBuffer neste 02307 //momento. 02308 while( ( GetBufferStatus( PlayBuffer ) == BUFFEREMPTY ) && 02309 ( useCache && 02310 ( bufferStream->readBlock( Request[ PlayBuffer ].Block, 02311 (unsigned char *) Request[ PlayBuffer ].Buffer ) != 0 02312 ) 02313 ) 02314 ) 02315 { 02316 #ifdef RIO_DEBUG2 02317 RioErr << "CallFreeBlock2 - Esperando 1 segundo pela sinalizacao " 02318 << "de chegada do bloco " << Request[ PlayBuffer ].Block 02319 << " (PlayOutBuffer posição " << PlayBuffer << ")." << endl; 02320 #endif 02321 02322 gettimeofday( &now, NULL ); 02323 timeout.tv_sec = now.tv_sec + 1; 02324 timeout.tv_nsec = now.tv_usec * 1000; 02325 02326 //FIXME: Há casos em que o cliente cai aqui sem ter travado o mutex 02327 //(problema de concorrência). Há que se fazer um estudo e 02328 //reimplementar a forma como este mutex é administrado no código. 02329 //A melhor forma de se detectar este problema é disparando muitos 02330 //clientes(emulador) e analisando os que não terminam normalmente. 02331 PlayThreadWaitCondition( &timeout, "cafrbl2" ); 02332 PlayThreadMutexUnlock( "cafrbl2" ); 02333 } 02334 02335 #ifdef RIO_DEBUG2 02336 RioErr << "CallFreeBlock -Saindo... Tamanho do bloco recuperado: " 02337 << Request[ PlayBuffer ].Size << endl; 02338 #endif 02339 02340 SetBufferStatus( PlayBuffer, BUFFERFULL ); 02341 return true; 02342 } 02343 else //else do if( freedSize != 0 ) 02344 { 02345 02346 if( useCache && 02347 ( bufferStream->readBlock( Request[ PlayBuffer ].Block, 02348 (unsigned char *) Request[ PlayBuffer ].Buffer ) == 0 02349 ) 02350 ) 02351 { 02352 #ifdef RIO_DEBUG2 02353 RioErr << "CallFreeBlock -Saindo... FreeBlock falhou mas eu tinha" 02354 << " o bloco " << Request[ PlayBuffer ].Block 02355 << " na cache e o recuperei." << endl; 02356 #endif 02357 02358 SetBufferStatus( PlayBuffer, BUFFERFULL ); 02359 return true; 02360 } 02361 else 02362 { 02363 #ifdef RIO_DEBUG2 02364 RioErr << "[CallFreeBlock] Retornando false: bloco não recuperado." 02365 << endl; 02366 #endif 02367 02368 return false; 02369 } 02370 } // fim do else do if( freedSize != 0 ) 02371 }
void CRioMMVideo::ClearBuffer | ( | ) |
Definition at line 3811 of file RioMMVideo.cpp.
03812 { 03813 unsigned int i; 03814 03815 #ifdef RIO_DEBUG2 03816 RioErr << "[ClearBuffer] Limpando buffer..." << endl; 03817 RioErr << "\t fullBuffers = " << fullBuffers << endl; 03818 #endif 03819 03820 for( i = 0; i < nBuffers; i++ ) 03821 { 03822 #ifdef RIO_DEBUG2 03823 RioErr << "[ClearBuffer] Cancelando espera do bloco " 03824 << Request[i].Block << ", reqid " << Request[i].reqid << endl; 03825 #endif 03826 03827 Object.CancelExpect( Request[i].reqid ); 03828 03829 #ifdef RIO_DEBUG2 03830 RioErr << "\t BufferStatus = " << BufferStatus[i] << "==>0" << endl; 03831 RioErr << "\t Result = " << Request[i].Result << "==>0" << endl; 03832 RioErr << "\t Status = " << Request[i].Status << "==>0" << endl; 03833 RioErr << "\t reqid = " << Request[i].reqid << "==>0" << endl; 03834 RioErr << "\t Block = " << Request[i].Block << " ==> não muda." << endl; 03835 RioErr << "\t -----------------------" << endl; 03836 #endif 03837 03838 BufferStatus[i] = BUFFEREMPTY; 03839 Request[i].User = (void *)i; 03840 Request[i].Result = S_OK; 03841 Request[i].Status = RIO_REQUEST_FREE; 03842 Request[i].reqid = 0; 03843 } 03844 fullBuffers = 0; 03845 }
bool CRioMMVideo::DealPendentEvents | ( | ) | [private] |
Definition at line 1768 of file RioMMVideo.cpp.
01769 { 01770 01771 if( !PTEventStack.isEmpty() ) 01772 { 01773 PlayThreadEvent *event = NULL; 01774 01775 waitingMSGCODE_IP = true; //A partir de agora o cliente deve ignorar 01776 //mensagens MSGCODE_MODE pois ele acaba de 01777 //interagir e enviará uma mensagem à PL 01778 //informando isto. 01779 01780 #ifdef RIO_DEBUG2 01781 RioErr << "Pilha de eventos tem " << PTEventStack.count() 01782 << " eventos. Processando-os." << endl; 01783 #endif 01784 01785 bool jumped = false; 01786 01787 //Tratando a lista de eventos no quesito prioridade: Apenas um evento 01788 //desta lista será tratado e os demais serão descartados. 01789 while( !PTEventStack.isEmpty() ) 01790 { 01791 PlayThreadEvent *thisevent; 01792 thisevent = PTEventStack.pop(); 01793 01794 if( thisevent->event == EVENT_PAUSE ) 01795 { 01796 #ifdef RIO_DEBUG2 01797 RioErr << "Encontrado um PAUSE na pilha de eventos... " 01798 << "Ignorando os demais e limpando a pilha." << endl; 01799 #endif 01800 01801 //Se o evento é EVENT_PAUSE então os demais eventos da lista 01802 //serão ignorados pois ele tem prioridade sobre o GOTO. 01803 //Pegarei este evento e limparei a pilha. 01804 if( event != NULL ) delete event; 01805 event=thisevent; 01806 PTEventStack.clear(); 01807 break; 01808 } 01809 else if( thisevent->event == EVENT_GOTO ) 01810 { 01811 //No caso de o evento escolhido ser um EVENT_GOTO então 01812 //só devo pegar o último executado (topo da pilha), portanto 01813 //ignoro os demais. 01814 if( jumped == false ) 01815 { 01816 #ifdef RIO_DEBUG2 01817 RioErr << "Encontrado um GOTO " << thisevent->target 01818 << " na pilha de eventos... Ignorando os demais " 01819 << "pulos." << endl; 01820 #endif 01821 01822 jumped = true; 01823 event=thisevent; 01824 continue; 01825 } 01826 else 01827 { 01828 #ifdef RIO_DEBUG2 01829 RioErr << "Encontrado outro GOTO(para " << thisevent->target 01830 << ") na pilha de eventos... Este será ignorado." 01831 << endl; 01832 #endif 01833 01834 delete thisevent; 01835 continue; 01836 } 01837 } 01838 else 01839 { 01840 #ifdef RIO_DEBUG2 01841 RioErr << "[RioMMVideo] DealPendentEvents: Evento " 01842 << thisevent->event << " inválido!" << endl; 01843 #endif 01844 01845 delete thisevent; 01846 01847 //Em caso de evento desconhecido retorno com falha. 01848 return false; 01849 } 01850 } // fim do while( !PTEventStack.isEmpty() ) 01851 01852 switch( event->event ) 01853 { 01854 case EVENT_PAUSE: 01855 { 01856 #ifdef RIO_DEBUG2 01857 RioErr << "Evento PAUSE - Source: " << event->source 01858 << ", Target: " << event->target << endl; 01859 #endif 01860 01861 delete event; 01862 01863 //Duas ações pause seguidas não despausam o vídeo. Ignorando 01864 //estas ocorrências. 01865 if( Paused ) 01866 return true; 01867 01868 #ifdef RIO_EMUL 01869 m_log << "Pause" << endl; 01870 #endif 01871 01872 PrefetchMutexLock( "Pause1" ); 01873 PlayPauseMutexLock( "Pause2" ); 01874 01875 Paused = true; 01876 01877 if( connectPI ) 01878 { 01879 MulticastMutexLock( "Pause3" ); 01880 01881 #ifdef RIO_DEBUG2 01882 RioErr << "[Pause] - Enviando msg ACTION_PAUSE pra PL." 01883 << endl; 01884 #endif 01885 01886 CommMultiStream->sendMoveMsg( PID, ACTION_PAUSE ); 01887 MulticastWaitCondition( "Pause3" ); 01888 MulticastMutexUnlock( "Pause3" ); 01889 01890 first = isFirst(); 01891 01892 if( group_block != -1 ) 01893 group_block = -1; 01894 }// fim do if( connectPI ) 01895 01896 PrefetchMutexUnlock( "Pause1" ); 01897 01898 /* Embeded mode, ask to RIOxine to stop itself*/ 01899 if( wId && ( player == RIOXINE_PLAYER ) ) 01900 kill( playerPID, SIGUSR1 ); 01901 01902 //Quando cliente pausa, entra na lista de inativos, logo deixa de ter um 01903 //alvo a ser alcançado até que reinicialize a axecução do vídeo. 01904 target = INT_MAX; 01905 01906 //Como a acao sendo executada eh uma pausa, o cliente mantera em memoria os 01907 //blocos pendentes ate que volte a exibir o video e venha a chamar a 01908 //FreeBlock. Para minimizar este uso de memoria chamamos a FreePendentBlocks 01909 //abaixo. 01910 01911 #ifdef RIO_DEBUG2 01912 int freedPendentsSize = FreePendentBlocks( useCache, nBuffers ); 01913 01914 RioErr << "[RioMMVideo] Pause - FreePendentBlocks liberou " 01915 << freedPendentsSize << " bytes de blocos pendentes." << endl; 01916 #else 01917 FreePendentBlocks( useCache, nBuffers ); 01918 #endif 01919 01920 #ifdef RIO_DEBUG2 01921 RioErr << "Saindo da Pause " << endl; 01922 #endif 01923 01924 break; 01925 } // fim do case EVENT_PAUSE: 01926 01927 case EVENT_GOTO: 01928 { 01929 #ifdef RIO_DEBUG2 01930 RioErr << "Evento GOTO - Source: " << event->source 01931 << ", Target: " << event->target << endl; 01932 #endif 01933 01934 RioBlock block = event->target; 01935 delete event; 01936 01937 #ifdef RIO_DEBUG2 01938 RioErr << "[GoTo] pulando do bloco " << NextRequestBlock 01939 << " para o bloco " 01940 << block << endl; 01941 #endif 01942 01943 if( Paused ) 01944 { 01945 Paused = false; 01946 PlayPauseMutexUnlock( "GoTo1" ); 01947 } 01948 01949 if( connectPI && ( group_block != -1 ) ) 01950 group_block = -1; 01951 01952 if( PlayThreadID == 0 ) 01953 { 01954 NextRequestBlock = block; 01955 Play(); 01956 } 01957 else 01958 { 01959 MoveAction action; 01960 01961 if( NextRequestBlock < block ) 01962 action = ACTION_FORWARD; 01963 else 01964 action = ACTION_REWIND; 01965 01966 //Abaixo podemos fingir que o cliente multicast nao usa 01967 //cache. Para isto basta substituir o "if 0" por "if 1" 01968 //antes de compilar. Com isto serão "descartados" os blocos 01969 //que estiverem antes da posição do salto: Se o cliente 01970 //saltou para o bloco x então todo bloco y < x será 01971 //descartado 01972 #if 0 01973 { 01974 for( int i = 0; i < block; i++ ) 01975 { 01976 bufferStream->dropBlock(i); 01977 01978 #ifdef RIO_DEBUG2 01979 RioErr << "Simulando liberacao do bloco " 01980 << i << " da cache na GoTo." << endl; 01981 #endif 01982 } 01983 } 01984 #endif 01985 01986 NextRequestBlock = block; 01987 01988 if( NextRequestBlock >= TotalBlocks ) 01989 NextRequestBlock = TotalBlocks-1; 01990 01991 if( connectPI ) 01992 { 01993 MulticastMutexLock( "GoTo2" ); 01994 01995 #ifdef RIO_DEBUG2 01996 RioErr << "[GoTo] Se bloco " << NextRequestBlock 01997 << " não existir, chamarei CallFreeBlock pro " 01998 << "bloco " << Request[PlayBuffer].Block << "." 01999 << endl; 02000 #endif 02001 02002 if( bufferStream->exist( NextRequestBlock ) || 02003 thereAreFragments( NextRequestBlock ) 02004 ) 02005 { 02006 //Se o cliente já tiver os blocos em disco ou se já tiver 02007 //recebido fragmentos do mesmo, os recuperará e entrará em 02008 //estado de inativo 02009 02010 #ifdef RIO_DEBUG2 02011 RioErr << "[GoTo] Jump pra área de blocos que já tem na cache." 02012 << " PID: " << PID << ", action: " << action 02013 << " block: -1.\n"; 02014 RioErr << "Cliente será removido para lista de inativos." << endl; 02015 #endif 02016 02017 CommMultiStream->sendMoveMsg( PID, action, -1 ); 02018 ReadFrom = READFROM_BUFFER; 02019 } 02020 else //else do if( bufferStream->exist( ... 02021 { 02022 #ifdef RIO_DEBUG2 02023 RioErr << "[GoTo] Sending MoveMsg " << " PID: " 02024 << PID << ", action: " 02025 << CommMultiStream->MoveAction2String( action ) 02026 << ", block: " << NextRequestBlock << endl; 02027 #endif 02028 02029 CommMultiStream->sendMoveMsg( PID, action, 02030 NextRequestBlock ); 02031 ReadFrom = READFROM_SERVER; 02032 } // fim do else do if( bufferStream->exist( ... 02033 02034 MulticastWaitCondition( "GoTo2" ); 02035 MulticastMutexUnlock( "GoTo2" ); 02036 02037 first = isFirst(); 02038 } // fim do if( connectPI ) 02039 02040 Paused = false; 02041 PlayPauseMutexUnlock( "GoTo3" ); 02042 if( WaitFullBuffer() == false ) 02043 { 02044 #ifdef RIO_DEBUG2 02045 RioErr << "[RioMMVideo] WaitFullBuffer == false. Chamando Stop() " 02046 << endl; 02047 #endif 02048 02049 Stop(); 02050 } 02051 } //fim do else do if( PlayThreadID == 0 ) 02052 break; 02053 } // fim do case EVENT_GOTO: 02054 }// fim do switch( event->event ) 02055 } // fim do if( !PTEventStack.isEmpty() ) 02056 #ifdef RIO_DEBUG2 02057 else 02058 { 02059 RioErr << "Pilha de eventos vazia. Retornando." << endl; 02060 } 02061 #endif 02062 02063 return true; 02064 }
void CRioMMVideo::FastForward | ( | void | ) | [virtual] |
void CRioMMVideo::FastRewind | ( | void | ) | [virtual] |
int CRioMMVideo::FreeBlock | ( | int | PlayBuffer | ) |
Este metodo chama a FreeBlock da RioNetI que por sua vez verifica se chegaram fragmentos do bloco apontado pela posicao PlayBuffer (parametro) do vetor Request.
Caso verdadeiro, os fragmentos sao gravados no buffer do cliente e o bloco é liberado para ser tocado.
PlayBuffer | é a posicao do vetor Request que aponta para o bloco cujos fragmentos, caso existam, devem ser liberados. |
Definition at line 3847 of file RioMMVideo.cpp.
03848 { 03849 RioStreamType traffic; 03850 unsigned int free_block; 03851 03852 if( connectPI && !bufferStream->isUnicast( Request[ PlayBuffer ].Block ) ) 03853 { 03854 traffic = MULTICASTTRAFFIC; 03855 //Um bloco, pra ser recuperado na RioNeti, precisa do reqid; porém, 03856 //neste caso, o cliente não fez um pedido(que geraria o reqid), 03857 //mas está recebendo um bloco solicitado pelo líder deste grupo 03858 //(através do fluxo multicast). Quando isto acontece, a RioNeti, 03859 //não tendo um reqid associado a tal bloco, cria um sob demanda 03860 //que só poderá ser localizado através do número do bloco. 03861 free_block = Request[ PlayBuffer ].Block; 03862 03863 #ifdef RIO_DEBUG2 03864 RioErr << "[RioMMVideo] Chamada a FreeBlock pra bloco de id " 03865 << free_block << " modo MULTICAST." << endl; 03866 #endif 03867 } 03868 else 03869 { 03870 traffic = UNICASTTRAFFIC; 03871 free_block = Request[ PlayBuffer ].reqid; 03872 03873 #ifdef RIO_DEBUG2 03874 RioErr << "[RioMMVideo] Chamada a FreeBlock pra bloco de id " 03875 << free_block << " modo UNICAST." << endl; 03876 #endif 03877 } 03878 03879 return( Object.FreeBlock( free_block, traffic ) ); 03880 }
int CRioMMVideo::FreePendentBlocks | ( | bool | useCache, | |
int | nBuffers | |||
) |
Definition at line 3882 of file RioMMVideo.cpp.
03883 { 03884 return( Object.FreePendentBlocks( useCache, nBuffers ) ); 03885 }
unsigned int CRioMMVideo::getCurrentPlayingBlock | ( | ) | [virtual] |
Reimplemented from CRioMMObject.
Definition at line 4018 of file RioMMVideo.cpp.
04019 { 04020 unsigned int currentPlayingBlock; 04021 04022 if( PlayThreadID == 0 ) 04023 currentPlayingBlock = 0; 04024 else 04025 currentPlayingBlock = Request[ PlayBuffer ].Block; 04026 04027 return currentPlayingBlock; 04028 }
RioBlock CRioMMVideo::GetCurrentPosition | ( | void | ) | [virtual] |
GetCurrentPosition retorna o número do bloco que está sendo tocado neste momento.
Implements CRioMMObject.
Definition at line 1232 of file RioMMVideo.cpp.
01233 { 01234 return( CurrentBlock ); 01235 }
const bool CRioMMVideo::getmakeLog | ( | ) |
Definition at line 3985 of file RioMMVideo.cpp.
03986 { 03987 return makeLog; 03988 }
RioBlock CRioMMVideo::GetNextRequestBlock | ( | ) |
GetNextRequestBlock retorna o próximo bloco a ser requisitado para o PlayOutBuffer.
Definition at line 1237 of file RioMMVideo.cpp.
01238 { 01239 return( NextRequestBlock ); 01240 }
int CRioMMVideo::GetSubTitles | ( | RioAccess | access, | |
CRioStream * | stream | |||
) |
Definition at line 853 of file RioMMVideo.cpp.
00854 { 00855 int rc; 00856 char subTitleFilename[ 80 ]; 00857 00858 sprintf( subTitleFilename, "%s.subtitle", MMObjectName ); 00859 00860 #ifdef RIO_DEBUG2 00861 RioErr << "Try to open subtitles" << subTitleFilename << endl; 00862 #endif 00863 00864 subTitle = new RioFile( subTitleFilename, BlockSize ); 00865 00866 rc = subTitle->Open( access, stream ); 00867 if( rc < 0 ) 00868 { 00869 #ifdef RIO_DEBUG2 00870 RioErr << "Could not find subtitles" << endl; 00871 #endif 00872 00873 return rc; 00874 } 00875 00876 subTitle->Download(); 00877 HasSubTitle = true; 00878 00879 #ifdef RIO_DEBUG2 00880 RioErr << "Using subtitles" << endl; 00881 #endif 00882 00883 return 0; 00884 }
RioBlock CRioMMVideo::GetTotalPositions | ( | void | ) | [virtual] |
GetTotalPositions retorna o tamanho total do vídeo em número de blocos.
Implements CRioMMObject.
Definition at line 1242 of file RioMMVideo.cpp.
01243 { 01244 return( TotalBlocks ); 01245 }
void CRioMMVideo::GoTo | ( | RioBlock | block | ) | [virtual] |
GoTo coloca o evento EVENT_GOTO na pilha de eventos tratada pela PlayThread.
Assim que a PlayThread ler este evento ela fará o salto para o bloco indicado pelo parâmetro block e tomará as medidas cabíveis para encher o PlayOutBuffer.
block | informa para qual bloco a aplicação deve ser direcionada, isto é, dada a interação do usuário, qual o próximo bloco deve ser tocado (caso o cliente já o tenha em disco) ou solicitado ao servidor (se o cliente não tiver o bloco em disco). Neste último caso, Move_Prefetch é chamada para que o cliente encha o PlayOutBuffer antes de prosseguir com a execução do vídeo. |
Implements CRioMMObject.
Definition at line 1019 of file RioMMVideo.cpp.
01020 { 01021 if( PlayThreadID == 0 ) 01022 { 01023 NextRequestBlock = (RioBlock) block; 01024 Play(); 01025 } 01026 else 01027 { 01028 //Colocando o evento GoTo na pilha de eventos da PlayThread. 01029 PlayThreadEvent *thisEvent = new PlayThreadEvent(); 01030 thisEvent->event = EVENT_GOTO; 01031 thisEvent->source = NextRequestBlock; 01032 thisEvent->target = block; 01033 PTEventStack.push( thisEvent ); 01034 } 01035 }
int CRioMMVideo::init | ( | void | ) | [virtual] |
init faz inicializações da conexão com a PL (se o cliente estiver com connectPI == true) e inicializa os membros first, my_address e my_port.
Implements CRioMMObject.
Definition at line 643 of file RioMMVideo.cpp.
00644 { 00645 if( !readSettings() ) 00646 writeDefaultSettings(); 00647 00648 if( useCache ) 00649 this->bufferStream = new BufferStream( MMObjectName, 00650 ( unsigned int ) TotalBlocks, 00651 ( unsigned int ) BlockSize 00652 ); 00653 00654 if( connectPI ) 00655 { 00656 char ip[ 16 ]; 00657 00658 callback_transport.block = 0; 00659 callback_transport.object = (void *)this; 00660 callback_transport.main_callback = MulticastCallBack; 00661 callback_transport.callback = MulticastCallBack; 00662 00663 CommMultiStream = new CommunicationStream( &Object, 0, 00664 (void *) &callback_transport, this->bufferStream, this ); 00665 00666 struct hostent *host2ip; 00667 host2ip = gethostbyname( piHost ); 00668 if( host2ip->h_addr ) 00669 strcpy( ip, 00670 inet_ntoa(*(reinterpret_cast<in_addr*>(host2ip->h_addr))) 00671 ); 00672 00673 AddressIP *address = new AddressIP( ip, COMMPORT ); 00674 00675 #ifdef RIO_DEBUG2 00676 RioErr << "[RioMMVideo] PI HOSTNAME: " << piHost.ascii() << " " 00677 << my_address << endl; 00678 #endif 00679 00680 int sd = CommMultiStream->createSocket( address ); 00681 if( sd == -1 ) 00682 { 00683 RioErr << "Error creating socket " << endl; 00684 return( 1 ); 00685 } 00686 00687 delete address; 00688 00689 CommunicationStreamThreadParam *p; 00690 p = new CommunicationStreamThreadParam(); 00691 p->port = COMMPORT; 00692 p->stream = CommMultiStream; 00693 00694 pthread_t rThread; 00695 00696 if( pthread_create( &rThread, NULL, 00697 CommunicationStream::startReceiveThread, p ) != 0 ) 00698 { 00699 delete p; 00700 RioErr << "Could not create communication thread" << endl; 00701 return( 1 ); 00702 } 00703 00704 int FlagRequests = 1; 00705 int rc = 0; 00706 00707 rc = GetObject()->GetMulticastInfo( &FlagRequests, &PID ); 00708 00709 if( FAILED( rc ) ) 00710 { 00711 RioErr << " não conseguiu pegar informacoes multicast. " << endl; 00712 exit( 0 ); 00713 } 00714 00715 #ifdef RIO_DEBUG2 00716 RioErr << "[RioMMVideo] PID: " << PID << endl; 00717 #endif 00718 00719 this->PID = PID; 00720 00721 FD_SET( sd, CommMultiStream->readfds ); 00722 00723 CommMultiStream->getTable()->insert( new CommunicationItem( PID, sd ) ); 00724 00725 MulticastMutexLock( "init1" ); 00726 CommMultiStream->sendPIDMsg( PID ); 00727 MulticastWaitCondition( "init1" ); 00728 MulticastMutexUnlock( "init1" ); 00729 } 00730 00731 #ifdef RIO_EMUL 00732 //Reading file to get block play time 00733 int *blocks_size; 00734 char video_name[ 256 ]; 00735 char line[ 256 ]; 00736 int i = 0; 00737 FILE *block_time; 00738 00739 blocks_size = (int *)malloc( TotalBlocks * sizeof( int ) ); 00740 00741 //Se a variável de ambiente CACTIMESPATH estiver setada, 00742 //seu valor será atribuído à variável video_name. CACTIMESPATH 00743 //indica o diretório onde o arquivo de cactimes deve ser procurado. Caso 00744 //esta variável de ambiente não esteja setada, será admitido que o arquivo 00745 //cactimes está no diretório corrente (de onde o cliente foi disparado). 00746 if( getenv( "CACTIMESPATH" ) ) 00747 { 00748 strcpy( video_name, getenv( "CACTIMESPATH" ) ); 00749 strcat( video_name, MMObjectName ); 00750 } 00751 else 00752 strcpy( video_name, MMObjectName ); 00753 00754 // Elimina a extensao .mpg ou .mpeg, se esta existir 00755 char *pext; 00756 // Procura pela extensao 00757 pext = strstr( video_name, ".mpg" ); 00758 if( pext == NULL ) 00759 pext = strstr( video_name, ".mpeg" ); 00760 // Se a achamos (pext != NULL), entao basta colocar um 0 na posicao para 00761 // eliminar a extensao 00762 if( pext != NULL ) 00763 *pext = 0; 00764 // Concatena o .cactimes ao nome (sem .mpg ou .mpeg agora). 00765 strcat( video_name, ".cactimes" ); 00766 00767 if( ( block_time = fopen( video_name, "r" ) ) == NULL ) 00768 { 00769 RioErr << "Cannot open cactimes file " << video_name << endl 00770 << "Você deve setar corretamente a variável de ambiente " 00771 << "\"CACTIMESPATH\" e lembrar-se de exportá-la ou deve " 00772 << "colocar o arquivo cactimes no mesmo diretório que roda" 00773 << "o cliente riommclient." << endl; 00774 if( getenv( "CACTIMESPATH" ) ) 00775 RioErr << "Valor atual de CACTIMESPATH = \"" 00776 << getenv( "CACTIMESPATH" ) << "\"" << endl; 00777 else 00778 RioErr << "variavel de ambiente CACTIMESPATH nao foi definida" 00779 << endl; 00780 if ( kill( getpid(), SIGKILL ) == -1 ) 00781 RioErr << "CRioMMVideo::init erro " << errno << " (" 00782 << strerror( errno ) << ") ao tentar matar o processo " 00783 << endl; 00784 else 00785 while ( 1 ) ; // Fica em loop ate o programa ser terminado 00786 } 00787 00788 i = 0; 00789 00790 while( fgets( line, 99, block_time ) != NULL ) 00791 { 00792 if( sscanf( line, "%d\n", &blocks_size[ i ] ) != 1 ) 00793 { 00794 RioErr << "[RioMMClient]: Wrong input format." << endl; 00795 if ( kill( getpid(), SIGKILL ) == -1 ) 00796 RioErr << "CRioMMVideo::init erro " << errno << " (" 00797 << strerror( errno ) << ") ao tentar matar o processo " 00798 << endl; 00799 else 00800 while ( 1 ) ; // Fica em loop ate o programa ser terminado 00801 } 00802 i++; 00803 } 00804 00805 // Verifica se o numero total de blocos do video e igual ao numero de 00806 // linhas lidas do arquivo .cactimes. Como a variavel i tera este numero de 00807 // linhas lidos, e como a variavel da classe TotalBlocks contem o numero 00808 // de blocos do disco, bastara que verifiquemos se i e igual a TotalBlocks 00809 // e, caso nao seja, abortar o cliente com uma mensagem de erro. 00810 00811 if( (unsigned int) i != TotalBlocks ) 00812 { 00813 RioErr << "O formato do arquivo cactimes " << video_name << " esta " 00814 << "incorreto: possui " << i << " linhas e deveria ter " 00815 << TotalBlocks << " linhas." << endl; 00816 if ( kill( getpid(), SIGKILL ) == -1 ) 00817 RioErr << "CRioMMVideo::init erro " << errno << " (" 00818 << strerror( errno ) << ") ao tentar matar o processo " 00819 << endl; 00820 else 00821 while ( 1 ) ; // Fica em loop ate o programa ser terminado 00822 } 00823 00824 SetBlocksDuration( blocks_size ); 00825 #endif 00826 00827 first = isFirst(); 00828 00829 #ifdef RIO_DEBUG2 00830 RioErr << "[RioMMVideo]: Valor de first: " << first << "." << endl; 00831 #endif 00832 00833 Getmyaddr( &my_address, &my_port ); 00834 00835 #ifdef RIO_EMUL 00836 QString outputLogPath; 00837 outputLogPath = logPath; 00838 00839 #ifdef RIO_DEBUG2 00840 RioErr << "[RioMMVideo - init] Arquivo de log de saída sendo criado. Nome: " 00841 << outputLogPath.ascii() << endl; 00842 #endif 00843 00844 m_log.close(); 00845 sprintf( LOGARRIVAL, "%s", outputLogPath.latin1() ); 00846 m_log.open( LOGARRIVAL ); 00847 #endif 00848 00849 return 0; 00850 }
void CRioMMVideo::inputLog | ( | int | action, | |
unsigned int | block = 0 , |
|||
unsigned int | size = 0 | |||
) | [virtual] |
Reimplemented from CRioMMObject.
Definition at line 4053 of file RioMMVideo.cpp.
04054 { 04055 if( makeLog == false ) 04056 return; 04057 04058 struct timeval time; 04059 long long int total_time; 04060 04061 gettimeofday( &time, 0 ); 04062 total_time = (1000000 * (long long int) time.tv_sec) + 04063 (long long int)time.tv_usec; 04064 04065 pthread_mutex_lock( &log_mutex ); 04066 04067 #ifdef USE_QT_GRID 04068 // Adaptação para a Qt 3.1 (usada na GRID) 04069 logAction += QString().sprintf( "%lli\t", total_time ); 04070 #else 04071 logAction += QString( "%1\t" ).arg( total_time ); 04072 #endif 04073 04074 switch( action ) 04075 { 04076 case BPLAY: 04077 logAction += "bplay"; 04078 break; 04079 case BPAUSE: 04080 logAction += "bpause"; 04081 break; 04082 case BFFORWARD: 04083 logAction += "bffwrd"; 04084 break; 04085 case BFREWIND: 04086 logAction += "bfrew"; 04087 break; 04088 case STOP: 04089 logAction += "stop"; 04090 break; 04091 case PLAYING: 04092 logAction += "plays"; 04093 break; 04094 case JUMPBAR: 04095 logAction += "jmpbar"; 04096 break; 04097 case JUMPTOPIC: 04098 logAction += "jmptop"; 04099 break; 04100 case REQSERV: 04101 logAction += "reqserv"; 04102 break; 04103 case REQCACHE: 04104 logAction += "reqcache"; 04105 break; 04106 case ARRIVING: 04107 logAction += "arrives"; 04108 break; 04109 case QUIT: 04110 logAction += "quit"; 04111 } 04112 04113 if( action != QUIT ) //unica acao que não precisa da informação "block" 04114 logAction += QString( "\t%1" ).arg( block ); 04115 04116 if( action == PLAYING ) //unica acao que precisa da informacao "size" 04117 logAction += QString( "\t%1\n" ).arg( size ); 04118 else 04119 logAction += "\n"; 04120 04121 pthread_mutex_unlock( &log_mutex ); 04122 04123 //Se acao = quit, fechar arquivo de log e fazer upload do mesmo 04124 if( action == QUIT ) 04125 { 04126 time_t t; 04127 t = ::time( NULL ); 04128 04129 pthread_mutex_lock( &log_mutex ); 04130 04131 logData.prepend( QString( "Log date: %1").arg( ctime( &t ) ) ); 04132 04133 //Adicionando informacoes extras ao log (incluidas com o metodo 04134 //appendLog()). Estas informacoes serao inseridas antes do log do 04135 //arquivo de configuração do riommclient 04136 int ins_pos = logData.find( 04137 "\n------------------Command Options-----------------\n" ); 04138 logData.insert( ins_pos, logAppend ); 04139 04140 // Inserindo log de ações ao log definitivo 04141 logData.append( logAction ); 04142 04143 char logFileName[MAXNAMELEN] = ""; 04144 strcpy( logFileName, "/tmp/RIOActionLog.XXXXXX" ); 04145 04146 int fd = mkstemp( logFileName ); 04147 if( fd ) 04148 close( fd ); 04149 else 04150 { 04151 RioErr << "Could not create file " << logFileName << endl; 04152 return; 04153 } 04154 04155 QFile logFile( QString( "%1" ).arg( logFileName ) ); 04156 QTextStream tslogFile; 04157 if( !logFile.open( IO_WriteOnly ) ) 04158 { 04159 RioErr << "Could not open created file " << logFileName << endl; 04160 return; 04161 } 04162 04163 tslogFile.setDevice( &logFile ); 04164 tslogFile << logData.latin1(); 04165 04166 pthread_mutex_unlock( &log_mutex ); 04167 04168 04169 logFile.close(); 04170 04171 QString src; 04172 QString dst; 04173 ObjectInfo objectInfo; 04174 gzFile zipfile; 04175 int logfile; 04176 int byread; 04177 char buf[ 1024 ]; 04178 bool status = true; 04179 04180 //Compactando arquivo de log 04181 src = QString( "%1.gz" ).arg( logFileName ); 04182 zipfile = gzopen( src.ascii(), "w9" ); 04183 logfile = open( logFileName, O_RDONLY ); 04184 04185 while( ( byread = read( logfile, buf, 1024 ) ) > 0 ) 04186 gzwrite( zipfile, buf, byread ); 04187 04188 close( logfile ); 04189 gzclose( zipfile ); 04190 04191 //uploading arquivo de log compactado 04192 dst = QString( "/var/log/%1" ).arg( src ).remove( "/tmp/" ); 04193 04194 status = rioMMExplorer->getObjectInfo( ( char* )src.ascii(), NULL, 04195 04196 &objectInfo ); 04197 04198 bool copy_allowed = true; 04199 04200 if( status ) 04201 status = rioMMExplorer->cp( NULL, rioMMExplorer->getSession(), 04202 &objectInfo, ( char* )dst.ascii(), 04203 false, false, ©_allowed ); 04204 if( !status ) 04205 RioErr << "nao consegui fazer o upload do arquivo de log." << endl; 04206 04207 //removendo os arquivos temporarios (log local) 04208 //Arquivo gz 04209 if( rioMMExplorer->rm( &objectInfo, NULL, false ) == false ) 04210 { 04211 #ifdef RIO_DEBUG2 04212 RioErr << "Nao consegui remover o arquivo temporario " 04213 << objectInfo.getFullName() << "." << endl; 04214 #endif 04215 } 04216 04217 //Arquivo que foi "gzipado" 04218 if( !rioMMExplorer->getObjectInfo( logFileName, NULL, &objectInfo ) || 04219 !rioMMExplorer->rm( &objectInfo, NULL, false ) 04220 ) 04221 { 04222 #ifdef RIO_DEBUG2 04223 RioErr << "Nao consegui remover o arquivo temporario " 04224 << objectInfo.getFullName() << "." << endl; 04225 #endif 04226 } 04227 } //fim do if( action == QUIT ) 04228 }
void CRioMMVideo::inputLog | ( | QString | text | ) |
bool CRioMMVideo::isFirst | ( | void | ) |
isFirst verifica se o cliente detém algum tipo de liderança (se é líder ou sublíder) e retorna true, caso positivo ou false, caso negativo.
Definition at line 255 of file RioMMVideo.cpp.
00256 { 00257 ClientMode status = PASSIVE; 00258 00259 if( connectPI ) 00260 status = CommMultiStream->getTable()->searchPidForMode( PID ); 00261 00262 return ( ( status == LEADER ) || 00263 ( status == SUBLEADER ) 00264 ); 00265 }
bool CRioMMVideo::isPatching | ( | ) |
Definition at line 4230 of file RioMMVideo.cpp.
04231 { 04232 return patching; 04233 }
bool CRioMMVideo::Leader_WaitMulticastBlocks | ( | ) | [protected] |
Leader_WaitMulticastBlocks é a função de espera de blocos executada por um líder (apenas o líder pode executar este método).
Este método verifica se tem blocos necessários para encher o PlayOutBuffer. Caso não tenha, verifica se tem fragmentos (chamando a CallFreeBlock). Caso ainda assim não tenha nada, então solicita o(s) bloco(s) que não tenha ao servidor (pela ReadBlock). No caso de este método não conseguir recuperar nenhum bloco ou nenhum fragento na CallFreeBlock, então esperará pelos blocos solicitados na (terceira situação descrita acima) até um limite de tempo. Se este limite for ultrapassado então CallFreeBlock será chamado para estes blocos. Nota: Este método só é chamado na WaitBlocks.
Definition at line 2543 of file RioMMVideo.cpp.
02544 { 02545 bool empty_buffer = true; 02546 struct timeval now; 02547 struct timespec timeout; 02548 unsigned int i; 02549 unsigned int full = 0; 02550 unsigned int steps = 0; 02551 unsigned int index; 02552 static unsigned int exit = 0; 02553 02554 #ifdef RIO_DEBUG2 02555 RioErr << "[RioMMVideo]: Leader_WaitMulticastBlocks..." << endl; 02556 #endif 02557 02558 while( empty_buffer ) 02559 { 02560 if( full > 0 ) 02561 full = 0; 02562 02563 for( i = 0; i < nBuffers; i++ ) 02564 { 02565 index = (req_block + i) % nBuffers; 02566 if( useCache && bufferStream->exist( req_block + i ) ) 02567 { 02568 #ifdef RIO_DEBUG2 02569 RioErr << "Leader_WaitMulticastBlocks() - Bloco " 02570 << req_block + i << " ja existe. " 02571 << "Gravando no PlayOutBuffer " << index << endl; 02572 #endif 02573 02574 Request[ index ].Block = req_block + i; 02575 Request[ index ].Result = S_OK; 02576 Request[ index ].Status = RIO_REQUEST_COMPLETED; 02577 Request[ index ].Who = this; 02578 02579 bufferStream->readBlock( Request[ index ].Block, 02580 (unsigned char *)Request[index].Buffer); 02581 02582 PlayThreadMutexUnlock( "lewtmtbl1" ); 02583 SetBufferStatus( index, BUFFERFULL ); 02584 full++; 02585 steps++; 02586 } 02587 else //else do if( useCache && bufferStream->exist( ... 02588 { 02589 Request[ index ].Block = req_block + i; 02590 Request[ index ].Result = S_OK; 02591 Request[ index ].Status = RIO_REQUEST_COMPLETED; 02592 Request[ index ].Who = this; 02593 02594 #ifdef RIO_DEBUG2 02595 RioErr << "[RioMMVideo] Leader_WaitMulticastBlocks chamando " 02596 << "CallFreeBlock pra ver se há fragmentos do bloco " 02597 << req_block + i << endl; 02598 #endif 02599 02600 if( CallFreeBlock( index ) ) 02601 { 02602 PlayThreadMutexUnlock( "lewtmtbl2" ); 02603 SetBufferStatus( index, BUFFERFULL ); 02604 full++; 02605 steps++; 02606 } 02607 else if( steps < nBuffers ) // else do if( CallFreeBlock( ind... 02608 { 02609 if( !ReadBlock( index, req_block + i, UNICASTTRAFFIC, 02610 0, 0 ) ) 02611 { 02612 #ifdef RIO_DEBUG2 02613 RioErr << "[Leader_WaitMulticastBlocks] - Saindo... " 02614 << "Erro no pedido do bloco " << req_block 02615 << endl; 02616 #endif 02617 02618 return( false ); 02619 } 02620 02621 steps++; 02622 } // fim do else if( steps < nBuffers ) 02623 } //fim do else do if( useCache && bufferStream->exist( ... 02624 } //fim do for( i = 0; i < nBuffers; i++ ) 02625 02626 if( full > 0 && steps >= nBuffers ) 02627 { 02628 #ifdef RIO_DEBUG2 02629 RioErr << "[Leader_WaitMulticastBlocks] Ja chegou algum bloco " 02630 << endl; 02631 #endif 02632 02633 empty_buffer = false; 02634 } 02635 else 02636 { 02637 #ifdef RIO_DEBUG2 02638 RioErr << "[Leader_WaitMulticastBlocks] Nenhum bloco chegou... " 02639 << "Esperando mais." << endl; 02640 #endif 02641 02642 if( Paused ) 02643 { 02644 PlayPauseMutexLock( "lewtmtbl4" ); 02645 empty_buffer = false; 02646 } 02647 else // else do if( Paused ) 02648 { 02649 gettimeofday( &now, NULL ); 02650 timeout.tv_sec = now.tv_sec + 1; 02651 timeout.tv_nsec = now.tv_usec * 1000; 02652 02653 PlayThreadWaitCondition( &timeout, "lewtmtbl6" ); 02654 PlayThreadMutexUnlock( "lewtmtbl6" ); 02655 02656 for( i = 0; i < nBuffers; i++ ) 02657 { 02658 PlayBuffer = (req_block + i) % nBuffers; 02659 02660 if( CallFreeBlock( PlayBuffer ) == false ) 02661 { 02662 #ifdef RIO_DEBUG2 02663 RioErr << "[WaitBlocks] 4 - Bloco esperado (" 02664 << Request[PlayBuffer].Block 02665 << ") nao recuperado " << endl; 02666 #endif 02667 } 02668 } 02669 02670 //Atualizando o valor de playbuffer 02671 PlayBuffer = req_block % nBuffers; 02672 exit++; 02673 } // fim do else do if( Paused ) 02674 02675 if( exit == ( 3 * nBuffers ) ) 02676 { 02677 #ifdef RIO_DEBUG2 02678 RioErr << "Leader_WaitMulticastBlocks - Saindo " 02679 << "e retornando erro. Exit: " << exit << endl; 02680 #endif 02681 02682 return( false ); 02683 } // fim do if( exit == ( 3 * nBuffers ) ) 02684 } //fim do else do if( full > 0 && steps > nBuffers ) 02685 } //fim do while( empty_buffer ) 02686 02687 #ifdef RIO_DEBUG2 02688 RioErr << "[RioMMVideo] Saindo da Leader_WaitMulticastBlocks..." << endl; 02689 #endif 02690 02691 return( true ); 02692 }
bool CRioMMVideo::Move_Prefetch | ( | void | ) |
Move_Prefetch faz o mesmo que o metodo Prefetch com a diferenca de que nao precisa se conectar na PI pois isto ja esta feito.
Nota: Move_Prefetch() só é chamada pela WaitFullBuffer().
Definition at line 580 of file RioMMVideo.cpp.
00581 { 00582 #ifdef RIO_DEBUG2 00583 RioErr << "[RioMMVideo] Entrei na Move_Prefetch..." << endl; 00584 #endif 00585 00586 unsigned int index = NextRequestBlock % nBuffers; 00587 00588 if( WaitingPrefetch ) 00589 { 00590 #ifdef RIO_DEBUG2 00591 RioErr << "[Move_Prefetch] Cliente estava aguardando na WaitPrefetch " 00592 << "enquanto interagiu. Espera dos pedidos anteriores sendo " 00593 << "cancelada, novos pedidos sendo feitos." << endl; 00594 #endif 00595 00596 //Se cliente já estava na WaitPrefetch e entrou na Move_Prefetch então é 00597 //porque ele interagiu enquanto estava em espera de enchimento do 00598 //PlayOutBuffer. Com isto, a espera na WaitPrefetch tem que ser 00599 //cancelada (o que é feito liberando-se o mutex abaixo que é o meio pelo 00600 //qual a WaitPrefetch fica presa aguardando o enchimento do 00601 //PlayOutBuffer) para que o PlayOutBuffer possa ser limpo (ClearBuffer 00602 //chamada abaixo) e preparado para a chegada dos blocos desta nova 00603 //requisição, fruto da interação do cliente. 00604 PlayThreadMutexLock( "mvprefetch" ); 00605 PlayThreadReleaseCondition( "mvprefetch" ); 00606 PlayThreadMutexUnlock( "mvprefetch" ); 00607 WaitingPrefetch = false; 00608 } 00609 00610 ClearBuffer(); 00611 PlayBuffer = index; 00612 00613 for(unsigned int i = 0; i < nBuffers; i++ ) 00614 { 00615 index = NextRequestBlock % nBuffers; 00616 00617 #ifdef RIO_DEBUG2 00618 RioErr << "[RioMMVideo] Move_Prefetch... pedindo bloco " 00619 << NextRequestBlock << "(index " << index << ")" << endl; 00620 #endif 00621 00622 gettimeofday( &calculete_RTT[ index ].initial_time, 0); 00623 calculete_RTT[ index ].block = 0; 00624 00625 00626 if( ReadNextBlock( index ) == false ) 00627 { 00628 #ifdef RIO_DEBUG2 00629 RioErr << "[RioMMVideo] Move_Prefetch: Erro na ReadNextBlock." 00630 << endl; 00631 #endif 00632 return( false ); 00633 } 00634 } 00635 00636 #ifdef RIO_DEBUG2 00637 RioErr << "[RioMMVideo] Saindo da Move_Prefetch..." << endl; 00638 #endif 00639 00640 return( true ); 00641 }
void CRioMMVideo::MulticastCallBack | ( | void * | parm, | |
int | result | |||
) | [static] |
MulticastCallBack é chamada toda vez que um bloco multicast chega ou que o cliente chame a FreeBlock para um bloco multicast.
Se o bloco que acabou de chegar for um dos blocos solicitados ao servidor por este cliente recentemente, então o bloco será gravado no PlayOutBuffer. Acontecendo isto, ou não, o bloco será gravado no disco para eventual uso posterior.
Definition at line 3685 of file RioMMVideo.cpp.
03686 { 03687 RioCallBackTransport *callback = (RioCallBackTransport *) parm; 03688 CRioMMVideo *videoPtr = (CRioMMVideo *) callback->object; 03689 bool blockRecorded = false; 03690 03691 #ifdef RIO_DEBUG2 03692 RioErr << "[MulticastCallBack] PID: " << videoPtr->PID 03693 << ", callback->block: " << callback->block 03694 << ", first: " << videoPtr->first 03695 << ", patching = " << videoPtr->patching << endl; 03696 #endif 03697 03698 //Se o bloco que acabou de chegar foi recentemente solicitado pelo cliente 03699 //então ele será gravado no PlayOutBuffer. 03700 for( unsigned int index = 0; index < videoPtr->nBuffers; index ++ ) 03701 { 03702 if( ( signed ) videoPtr->Request[ index ].Block == callback->block ) 03703 { 03704 if( videoPtr->GetBufferStatus( index ) == BUFFEREMPTY ) 03705 { 03706 blockRecorded = true; 03707 #ifdef RIO_DEBUG2 03708 RioErr << "MulticastCallBack - copiando bloco " 03709 << callback->block << ", " 03710 << videoPtr->Request[ index ].Size 03711 << " bytes, para PlayOutBuffer " << index << endl; 03712 #endif 03713 03714 videoPtr->Request[ index ].User = (void *) index; 03715 videoPtr->Request[ index ].Block = callback->block; 03716 videoPtr->Request[ index ].Result = S_OK; 03717 videoPtr->Request[ index ].Status = RIO_REQUEST_COMPLETED; 03718 videoPtr->Request[ index ].Who = videoPtr; 03719 memcpy( videoPtr->Request[ index ].Buffer, callback->data, 03720 videoPtr->Request[ index ].Size ); 03721 03722 videoPtr->SetBufferStatus( index, BUFFERFULL ); 03723 } 03724 #ifdef RIO_DEBUG2 03725 else 03726 { 03727 RioErr << "[MulticastCallBack] BUFFERFULL: Bloco não será gravado " 03728 << "na cache." << endl; 03729 } 03730 #endif 03731 break; 03732 } 03733 } 03734 03735 #ifdef RIO_DEBUG2 03736 if( !blockRecorded ) 03737 { 03738 RioErr << "[MulticastCallBack] Bloco recebido(" 03739 << callback->block << ") não será gravado no " 03740 << "PlayOutBuffer por não ser um dos blocos esperados" << endl; 03741 } 03742 #endif 03743 03744 //Gravando os dados no disco. 03745 #ifdef RIO_DEBUG2 03746 RioErr << "[MulticastCallBack] Gravando bloco " << callback->block 03747 << " na cache." << endl; 03748 #endif 03749 03750 if( videoPtr->useCache ) 03751 { 03752 if( !videoPtr->bufferStream->exist( callback->block ) ) 03753 { 03754 #ifdef RIO_DEBUG2 03755 RioErr << "[CallBack] Gravando bloco " 03756 << callback->block << " na cache." 03757 << endl; 03758 #endif 03759 03760 videoPtr->bufferStream->writeBlock( callback->block, 03761 (unsigned char *) callback->data ); 03762 } 03763 #ifdef RIO_DEBUG2 03764 else 03765 { 03766 RioErr << "[MulticastCallBack] Bloco " << callback->block 03767 << " já existe na cache e será descartado." 03768 << endl; 03769 } 03770 #endif 03771 } 03772 #ifdef RIO_DEBUG2 03773 else 03774 { 03775 RioErr << "[MulticastCallBack] Cache desabilitado. Bloco " 03776 << callback->block << " nao sera gravado." 03777 << endl; 03778 } 03779 #endif 03780 03781 //Liberando a memória (dados de vídeo e desalocando 03782 //struct RioCallBackTransport) 03783 delete[] callback->data; 03784 delete callback; 03785 03786 #ifdef RIO_EMUL 03787 int index = callback->block % videoPtr->nBuffers; 03788 //This is done to log call arrival time 03789 gettimeofday( &videoPtr->timers[ index ].arrival_time, 0); 03790 03791 videoPtr->final_time.tv_sec = 03792 videoPtr->timers[ index ].arrival_time.tv_sec - 03793 videoPtr->initial_time.tv_sec; 03794 videoPtr->final_time.tv_usec = 03795 videoPtr->timers[ index ].arrival_time.tv_usec - 03796 videoPtr->initial_time.tv_usec; 03797 03798 if( videoPtr->final_time.tv_usec < 0 ) 03799 { 03800 videoPtr->final_time.tv_sec -= 1; 03801 videoPtr->final_time.tv_usec += 1000000; 03802 } 03803 03804 videoPtr->calculeted_time = ( unsigned int ) 03805 ( videoPtr->final_time.tv_sec * 1000.0 + 03806 videoPtr->final_time.tv_usec/1000.0 03807 ); 03808 #endif 03809 }
void CRioMMVideo::MulticastMutexLock | ( | string | msg = "" |
) |
MulticastMutexLock trava o mutex multicastMutex.
msg | é usado apenas no modo RIO_DEBUG2 para facilitar depurações de clientes travados em mutex's. |
Definition at line 2373 of file RioMMVideo.cpp.
02374 { 02375 #ifdef RIO_DEBUG2 02376 if( msg.length() ) 02377 RioErr << "[MulticastMutexLock] " << msg << "... " << endl; 02378 #endif 02379 02380 pthread_mutex_lock( &multicastMutex ); 02381 02382 #ifdef RIO_DEBUG2 02383 if( msg.length() ) 02384 RioErr << "..." << msg << " OK!" << endl; 02385 #endif 02386 }
void CRioMMVideo::MulticastMutexUnlock | ( | string | msg = "" |
) |
MulticastMutexUnlock destrava o mutex multicastMutex.
msg | é usado apenas no modo RIO_DEBUG2 para facilitar depurações de clientes travados em mutex's. |
Definition at line 2388 of file RioMMVideo.cpp.
02389 { 02390 #ifdef RIO_DEBUG2 02391 if( msg.length() ) 02392 RioErr << "[MulticastMutexUnlock] " << msg << endl; 02393 #endif 02394 02395 pthread_mutex_unlock( &multicastMutex ); 02396 }
void CRioMMVideo::MulticastReleaseCondition | ( | string | msg = "" |
) |
MulticastReleaseCondition libera a execução do cliente travado pela execução da MulticastWaitCondition.
msg | é usado apenas no modo RIO_DEBUG2 para facilitar depurações de clientes travados em mutex's. |
Definition at line 2413 of file RioMMVideo.cpp.
02414 { 02415 #ifdef RIO_DEBUG2 02416 if( msg.length() ) 02417 RioErr << "[MulticastReleaseCondition] " << msg << endl; 02418 #endif 02419 02420 pthread_cond_broadcast( &multicastCondition ); 02421 waitingMSGCODE_IP = false; 02422 }
void CRioMMVideo::MulticastWaitCondition | ( | string | msg = "" |
) |
MulticastWaitCondition trava o cliente aguardando a execução da MulticastReleaseCondition.
msg | é usado apenas no modo RIO_DEBUG2 para facilitar depurações de clientes travados em mutex's. |
Definition at line 2398 of file RioMMVideo.cpp.
02399 { 02400 #ifdef RIO_DEBUG2 02401 if( msg.length() ) 02402 RioErr << "[MulticastWaitCondition] " << msg << "... " << endl; 02403 #endif 02404 02405 pthread_cond_wait( &multicastCondition, &multicastMutex ); 02406 02407 #ifdef RIO_DEBUG2 02408 if( msg.length() ) 02409 RioErr << "..." << msg << " OK!" << endl; 02410 #endif 02411 }
void CRioMMVideo::Pause | ( | void | ) | [virtual] |
Pause coloca o evento EVENT_PAUSE na pilha de eventos tratada pela PlayThread.
Assim que a PlayThread ler este evento ela suspenderá temporariamente a execução do vídeo no cliente mas não matará a PlayThread.
Implements CRioMMObject.
Definition at line 1136 of file RioMMVideo.cpp.
01137 { 01138 if( PlayThreadID != 0 ) 01139 { 01140 //Colocando o evento Pause na pilha de eventos da PlayThread. 01141 PlayThreadEvent *thisEvent = new PlayThreadEvent(); 01142 thisEvent->event = EVENT_PAUSE; 01143 thisEvent->source = NextRequestBlock; 01144 thisEvent->target = NextRequestBlock; 01145 PTEventStack.push( thisEvent ); 01146 } 01147 }
void CRioMMVideo::Play | ( | void | ) | [virtual] |
Play() inicia a execução do vídeo criando uma PlayThread, caso cliente ainda não tenha inicializado, ou dá prosseguimento à execução da mesma caso o cliente esteja em estado de pausa.
Implements CRioMMObject.
Definition at line 1149 of file RioMMVideo.cpp.
01150 { 01151 PlayBuffer = NextRequestBlock % nBuffers; 01152 01153 #ifdef RIO_EMUL 01154 m_log << "Play " << NextRequestBlock << endl; 01155 Stopped = false; 01156 #endif 01157 01158 #ifdef RIO_DEBUG2 01159 RioErr << "[RioMMVideo] Play - NextRequestBlock = " << NextRequestBlock 01160 << endl; 01161 #endif 01162 01163 if( PlayThreadID == 0 ) 01164 { 01165 #ifdef RIO_DEBUG2 01166 RioErr << "[RioMMVideo] Play - Criando PlayThread." 01167 << endl; 01168 #endif 01169 01170 if( pthread_create( &PlayThreadID, NULL, &PlayThread, this ) ) 01171 { 01172 RioErr << "Could not create play thread" << endl; 01173 return; 01174 } 01175 } 01176 else // else do if( PlayThreadID == 0 ) 01177 { 01178 if( connectPI ) 01179 { 01180 if( bufferStream->exist( NextRequestBlock ) ) 01181 { 01182 #ifdef RIO_DEBUG2 01183 RioErr << "[PLAY] Buffer Exist: Cliente vai ler do buffer e " 01184 << "não precisa avisar isto à PL." << endl; 01185 #endif 01186 01187 ReadFrom = READFROM_BUFFER; 01188 } 01189 else // else do if( bufferStream->exist( NextRequ... 01190 { 01191 #ifdef RIO_DEBUG2 01192 RioErr << "[PLAY] Buffer Doesn't Exist " << NextRequestBlock 01193 << endl; 01194 #endif 01195 01196 MulticastMutexLock( "Play1" ); 01197 CommMultiStream->sendMoveMsg( PID, ACTION_PLAY, 01198 NextRequestBlock ); 01199 MulticastWaitCondition( "Play1" ); 01200 MulticastMutexUnlock( "Play1" ); 01201 01202 ReadFrom = READFROM_SERVER; 01203 } 01204 01205 first = isFirst(); 01206 }// fim do if( connectPI ) 01207 01208 if( Paused ) 01209 { 01210 //Cliente entrando no patching 01211 01212 PlayPauseMutexUnlock( "Play2" ); 01213 Paused = false; 01214 01215 #ifdef RIO_DEBUG2 01216 RioErr << "[RioMMVideo] Liberou mutex playpause " << endl; 01217 #endif 01218 01219 /*Embeded mode, ask to RIOxine to stop itself*/ 01220 if( wId && ( player == RIOXINE_PLAYER ) ) 01221 kill( playerPID, SIGUSR1 ); 01222 } 01223 } //fim do else do if( PlayThreadID == 0 ) 01224 }
void CRioMMVideo::PlayBlock | ( | int | buf, | |
int | size | |||
) |
PlayBlock escreve o bloco buf, de tamanho size, no buffer do mplayer para ser tocado imediatamente.
buf | são os dados a serem gravados no pipe do mplayer. | |
size | é a quantidade de dados em bytes a ser escrita no buffer do mplayer. |
Definition at line 886 of file RioMMVideo.cpp.
00887 { 00888 int sent = 0; 00889 int n; 00890 int nwrite; 00891 char *buffer = (char *)Request[ buf ].Buffer; 00892 00893 #ifdef RIO_DEBUG2 00894 RioErr << "[RioMMVideo] Entrei na PlayBlock() (size = " 00895 << size << ")" << endl; 00896 #endif 00897 00898 timer.Reset(); 00899 timer.Start(); 00900 00901 PlayPauseMutexLock( "plblk1" ); 00902 while( sent < size ) 00903 { 00904 n = size - sent; 00905 if( n > MaxPipeDataSize ) 00906 n = MaxPipeDataSize; 00907 00908 nwrite = write( pipe_player[ 1 ], (void*)buffer, n ); 00909 00910 if( nwrite < 0 ) 00911 Rioperror( "write: pipe mpeg player" ); 00912 #ifdef RIO_DEBUG2 00913 else if( nwrite != MaxPipeDataSize ) 00914 { 00915 RioErr << "[PlayBlock] Escrito apenas " << nwrite 00916 << " de " << n << " bytes no pipe_player." << endl; 00917 } 00918 #endif 00919 00920 sent += nwrite; 00921 buffer += nwrite; 00922 } 00923 PlayPauseMutexUnlock( "plblk1" ); 00924 00925 timer.Stop(); 00926 avgBlockTime = ((avgBlockTime * n_blocks_played) + 00927 timer.Get())/(n_blocks_played+1); 00928 n_blocks_played++; 00929 00930 #ifdef RIO_DEBUG2 00931 RioErr << avgBlockTime/1000.0f << endl; 00932 #endif 00933 00934 //log de comportamento 00935 inputLog( PLAYING, Request[ PlayBuffer ].Block, ( unsigned int )size ); 00936 00937 // last_played é usada pois a interface não executa o evento 00938 // QEvent::User(atualizar barra de progresso) antes do valor de 00939 //Request[buf].Block ser alterado 00940 last_played = Request[buf].Block; 00941 00942 //Nao atualizo a interface se houve algum evento recentemente (este foi 00943 //colocado na pilha de eventos) para evitar que a barra de progresso e/ou o 00944 //indoce fiquem saltando 00945 #ifdef RIO_DEBUG2 00946 RioErr << "Update interface?" << endl; 00947 #endif 00948 if( PTEventStack.isEmpty() && 00949 ( (unsigned) labs( NextRequestBlock - last_played ) <= nBuffers ) 00950 ) 00951 { 00952 #ifdef RIO_DEBUG2 00953 RioErr << "Update interface!" << endl; 00954 #endif 00955 if( riomminterface ) 00956 { 00957 #ifdef RIO_DEBUG2 00958 RioErr << "Played block: sending event to interface" << endl; 00959 #endif 00960 //Enviando evento pra interface atualizar a barra de progresso 00961 //do vídeo. 00962 QCustomEvent *event = new QCustomEvent( QEvent::User, 00963 &last_played ); 00964 QApplication::postEvent( (QObject*)riomminterface, event ); 00965 } 00966 } 00967 00968 // Forçar a barra de progresso exibir 100% no fim do vídeo 00969 if( riomminterface && ( Request[ buf ].Block == (TotalBlocks - 1) ) ) 00970 { 00971 QCustomEvent *event = new QCustomEvent( QEvent::User, &TotalBlocks ); 00972 QApplication::postEvent( (QObject*)riomminterface, event ); 00973 } 00974 00975 #ifdef RIO_DEBUG2 00976 RioErr << "[RioMMVideo] Saindo da PlayBlock()" << endl; 00977 #endif 00978 }
void CRioMMVideo::PlayPauseMutexLock | ( | string | msg = "" |
) |
PlayPauseMutexLock trava o mutex PlayPauseMutex.
msg | é usado apenas no modo RIO_DEBUG2 para facilitar depurações de clientes travados em mutex's. |
Definition at line 2424 of file RioMMVideo.cpp.
02425 { 02426 #ifdef RIO_DEBUG2 02427 if( msg.length() ) 02428 RioErr << "[PlayPauseMutexLock] " << msg << "... " << endl; 02429 #endif 02430 02431 pthread_mutex_lock( &PlayPauseMutex ); 02432 02433 #ifdef RIO_DEBUG2 02434 if( msg.length() ) 02435 RioErr << "..." << msg << " OK!" << endl; 02436 #endif 02437 }
void CRioMMVideo::PlayPauseMutexUnlock | ( | string | msg = "" |
) |
PlayPauseMutexUnlock destrava o mutex PlayPauseMutex.
msg | é usado apenas no modo RIO_DEBUG2 para facilitar depurações de clientes travados em mutex's. |
Definition at line 2439 of file RioMMVideo.cpp.
02440 { 02441 #ifdef RIO_DEBUG2 02442 if( msg.length() ) 02443 RioErr << "[PlayPauseMutexUnlock] " << msg << endl; 02444 #endif 02445 02446 pthread_mutex_unlock( &PlayPauseMutex ); 02447 }
void * CRioMMVideo::PlayThread | ( | void * | videoObject | ) | [static, protected] |
PlayThread controla a execução do vídeo e a recuperação dos blocos a serem tocados no momento da sua execução invocando, quando necessário, os métodos que manipulam requisições e recuperações de blocos no servidor e/ou em disco.
videoObject | é um ponteiro para esta instância da RioMMVideo pois uma thread precisa disto para acessar os membros e demais métodos desta classe. |
Definition at line 1247 of file RioMMVideo.cpp.
01248 { 01249 CRioMMVideo *Video; 01250 int curBlockSize; 01251 unsigned int ind; 01252 struct timeval now; 01253 struct timespec timeout; 01254 bool free_status = true; 01255 int maxbuf0 = 0; 01256 01257 pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL ); 01258 pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL ); 01259 pthread_cleanup_push( CRioMMVideo::PlayThreadCleanup, videoObject ); 01260 01261 Video = (CRioMMVideo *)videoObject; 01262 01263 #ifdef RIO_EMUL 01264 //The player isn't started 01265 int *duration; 01266 int indice; 01267 duration = Video->GetBlocksDuration(); 01268 #else 01269 #ifdef RIO_DEBUG2 01270 RioErr << "" << endl; //temporary 01271 RioErr << "CVS tag version: " VERSION << endl; 01272 RioErr << "**********************Start Player***********************" 01273 << endl; 01274 RioErr << "" << endl; //temporary; 01275 #endif 01276 01277 //Abrindo o mplayer e configurando o mesmo 01278 Video->StartPlayer(); 01279 #endif 01280 01281 //Uma vez que WaitPrefetch() será chamada depois de Prefetch(), pode 01282 //acontecer de os blocos chegarem antes que a WaitPrefetch esteja preparada. 01283 //Com isto, a função pthread_cond_broadcast (da SetBufferStatus chamada pela 01284 //CallBack) seria chamada antes da pthread_cond_timedwait. Para evitar isto, 01285 //PlayThreadMutex será locked abaixo. Nota: pthread_cond_timedwait unloca 01286 //PlayThreadMutex quando é executada. 01287 Video->PlayThreadMutexLock( "plthr1" ); 01288 Video->Prefetch(); 01289 01290 if( Video->WaitPrefetch() == false ) 01291 { 01292 RioErr << "***|------------------------------------------|***" << endl; 01293 RioErr << "***|[Playthread] Blocos iniciais não chegaram.|***" << endl; 01294 RioErr << "***|------------------------------------------|***" << endl; 01295 01296 pthread_exit( NULL ); 01297 } 01298 01299 if( !Video->CanStart() ) 01300 { 01301 RioErr << "[Playthread] Cant't start video " << endl; 01302 pthread_exit( NULL ); 01303 // If you can't Start, it might be an server error and you must 01304 // halt your program 01305 } 01306 01307 while( 1 ) 01308 { 01309 #ifdef RIO_DEBUG2 01310 switch( Video->getMode() ) 01311 { 01312 case LEADER: 01313 RioErr << "\033[01;40;36m"; //lider imprime logs em cyan 01314 RioErr << "Sou líder!!!" << endl; 01315 break; 01316 case SUBLEADER: 01317 RioErr << "\033[01;40;31m"; //sublider imprime em vermelho 01318 RioErr << "Sou sublíder!!!" << endl; 01319 break; 01320 case PASSIVE: 01321 RioErr << "\033[01;40;33m"; //passive imprime em amarelo 01322 RioErr << "Sou passivo!!!" << endl; 01323 break; 01324 default: 01325 RioErr << "\033[0m"; //inactive/unavailable imprime logs em branco 01326 if( Video->connectPI ) 01327 RioErr << "Sou inativo ou indisponível!!!" << endl; 01328 else 01329 RioErr << "Sou cliente unicast." << endl; 01330 } 01331 RioErr << "GetFullBuffers = " << Video->GetFullBuffers() << endl; 01332 #endif 01333 01334 while( Video->GetFullBuffers() > 0 ) 01335 { 01336 if( Video->DealPendentEvents() == false ) 01337 { 01338 #ifdef RIO_DEBUG2 01339 RioErr << "[RioMMVideo] Evento inválido. Saindo da PlayThread" 01340 << endl; 01341 #endif 01342 01343 pthread_exit( NULL ); 01344 } 01345 01346 #ifdef RIO_DEBUG2 01347 switch( Video->getMode() ) 01348 { 01349 case LEADER: 01350 RioErr << "\033[01;40;36m"; //lider imprime logs em cyan 01351 RioErr << "Sou líder!!!" << endl; 01352 break; 01353 case SUBLEADER: 01354 RioErr << "\033[01;40;31m"; //sublider imprime em vermelho 01355 RioErr << "Sou sublíder!!!" << endl; 01356 break; 01357 case PASSIVE: 01358 RioErr << "\033[01;40;33m"; //passive imprime em amarelo 01359 RioErr << "Sou passivo!!!" << endl; 01360 break; 01361 default: 01362 RioErr << "\033[0m"; //inative/unavailable imprime em branco 01363 if( Video->connectPI ) 01364 RioErr << "Sou inativo ou indisponível!!!" << endl; 01365 else 01366 RioErr << "Sou cliente unicast." << endl; 01367 } 01368 #endif 01369 01370 Video->PlayThreadMutexUnlock( "plthr1" ); 01371 01372 usleep( 1000 ); 01373 01374 Video->PrefetchMutexLock( "plthr2" ); 01375 01376 if( Video->Request[ Video->PlayBuffer ].Block < 01377 Video->TotalBlocks-1 01378 ) 01379 { 01380 curBlockSize = Video->Request[ Video->PlayBuffer ].Size; 01381 } 01382 else 01383 { 01384 if( Video->Request[ Video->PlayBuffer ].Block == 01385 ( Video->TotalBlocks - 1 ) 01386 ) 01387 curBlockSize = Video->ObjSize - ( Video->BlockSize * 01388 (Video->TotalBlocks-1) ); //%Video->BlockSize; 01389 else 01390 { 01391 RioErr << "[PlayThread] Unbounded streams are not supported " 01392 << "yet!" << endl; 01393 pthread_exit( NULL ); 01394 } 01395 } // fim do else do if( Video->Request[ Video->PlayBuffer ].Bloc... 01396 01397 // if the next block did not arrive and there is some block at the 01398 // buffer jump the next block 01399 if( Video->GetBufferStatus( Video->PlayBuffer ) != BUFFERFULL ) 01400 { 01401 #ifdef RIO_DEBUG2 01402 RioErr << "[Playthread] buffer empty " << Video->PlayBuffer 01403 << endl; 01404 #endif 01405 01406 if( Video->useCache && 01407 ( Video->bufferStream->readBlock( 01408 Video->Request[ Video->PlayBuffer ].Block, 01409 (unsigned char *)Video->Request[Video->PlayBuffer].Buffer 01410 ) == 0 01411 ) 01412 ) 01413 { 01414 #ifdef RIO_DEBUG2 01415 RioErr << "[PlayThread] Copiando bloco " 01416 << Video->Request[ Video->PlayBuffer ].Block 01417 << " para playbuffer " << Video->PlayBuffer 01418 << endl; 01419 #endif 01420 01421 #ifdef RIO_EMUL 01422 timeval tv; 01423 gettimeofday( &tv, 0 ); 01424 Video->m_log << tv.tv_sec << "." 01425 << ( (double) tv.tv_usec / 1000000 ); 01426 Video->m_log << " Cache : " 01427 << Video->Request[ 01428 Video->PlayBuffer ].Block << endl; 01429 #endif 01430 } 01431 else // else do if( Video->useCache ) 01432 { 01433 #ifdef RIO_DEBUG2 01434 RioErr << "[Playthread] Esperando chegada de bloco " 01435 << Video->Request[ Video->PlayBuffer ].Block 01436 << endl; 01437 #endif 01438 01439 gettimeofday( &now, NULL ); 01440 timeout.tv_sec = now.tv_sec + 1; 01441 timeout.tv_nsec = now.tv_usec * 1000; 01442 01443 //Fazendo a thread esperar até a chegada do bloco ou 01444 //até timeout => ETIMEDOUT 01445 Video->PlayThreadMutexLock( "plthr3" ); 01446 Video->PlayThreadWaitCondition( &timeout, "plthr3" ); 01447 Video->PlayThreadMutexUnlock( "plthr3" ); 01448 01449 //A chamada Video->PlayThreadWaitCondition( &timeout ) 01450 //é utilizada para fazer a thread ficar inativa durante 01451 //o tempo indicado por "timeout". Quando este tempo 01452 //expira o método retorna o código ETIMEOUT. Esse 01453 //período de inatividade pode ser interrompido por uma 01454 //chamada a pthread_cond_broadcast. Quando isso 01455 //acontecer o método vai retornar o valor 0. 01456 //A linha a seguir foi substituída para considerar o 01457 //caso onde o resultado de 01458 //Video->PlayThreadWaitCondition( &timeout ) é 0 devido 01459 //a chegada de um bloco subsequente ao bloco esperado. 01460 //Dessa maneira o cliente não vai se enganar e tentar 01461 //exibir um bloco que não foi recebido. O teste de 01462 //recepção de um bloco agora é feito sobre a situação do 01463 //buffer. Se este estiver vazio significa que o bloco 01464 //esperado não foi recebido. 01465 01466 //O bloco esperado não foi recebido ainda 01467 if( Video->GetBufferStatus( Video->PlayBuffer ) != 01468 BUFFERFULL ) 01469 { 01470 if( Video->CallFreeBlock( Video->PlayBuffer ) ) 01471 { 01472 #ifdef RIO_EMUL 01473 Video->m_log << "Recuperado : " 01474 << Video->Request[ Video->PlayBuffer ].Block 01475 << " tamanho: " << curBlockSize << " Bytes" 01476 << endl; 01477 partialBlocks++; 01478 #endif 01479 01480 free_status = true; 01481 curBlockSize = Video->Request[ 01482 Video->PlayBuffer].Size; 01483 01484 } 01485 else // else do if(Video->CallFreeBlock(Video->P... 01486 { 01487 #ifdef RIO_EMUL 01488 Video->m_log << "Perdido: " 01489 << Video->Request[ 01490 Video->PlayBuffer ].Block << endl; 01491 lostBlocks++; 01492 #endif 01493 01494 #ifdef RIO_DEBUG2 01495 RioErr << "Playthread - nao existe referencia do " 01496 << "bloco: " << Video->Request[ 01497 Video->PlayBuffer].Block 01498 << endl; 01499 #endif 01500 01501 free_status = false; 01502 Video->Object.CancelExpect( Video->Request[ 01503 Video->PlayBuffer].reqid ); 01504 } // fim do else do if(Video->CallFreeBlock(Video... 01505 01506 //Por convencao os blocos pendentes serao liberados 01507 //sempre que a FreeBlock for chamada, por isso abaixo 01508 //sera chamada a FreePendentBlocks. A FreePendentBlocks 01509 //deve ser chamada periodicamente mas para nao 01510 //implementar uma thread apenas para este fim, 01511 //resolveu-se chama-la em pontos estrategicos, onde a 01512 //FreeBlock fosse chamada, pois isto implica que ha 01513 //perdas no ambiente, e so neste caso eh que a 01514 //FreePendentBlocks tem sua serventia. Como este metodo 01515 //eh custoso, nao eh ideal chama-lo em todas as 01516 //situacoes que se chama a FreeBlock. 01517 01518 #ifdef RIO_DEBUG2 01519 int freedPendentsSize = Video->FreePendentBlocks( 01520 Video->useCache, Video->nBuffers ); 01521 RioErr << "[RioMMVideo] PlayThread - FreePendentBlocks " 01522 << "liberou " << freedPendentsSize 01523 << " bytes de blocos pendentes." << endl; 01524 #else 01525 Video->FreePendentBlocks( Video->useCache, 01526 Video->nBuffers ); 01527 #endif 01528 } //fim do if( Video->GetBufferStatus( ... 01529 } //fim do else do if( Video->useCache ) 01530 } // fim do if( Video->GetBufferStatus( Video->PlayBuffer )... 01531 01532 if( free_status ) 01533 #ifdef RIO_EMUL 01534 //Reading block play time from file and executing usleep 01535 { 01536 Video->PlayPauseMutexLock( "plthr4" ); 01537 indice = Video->Request[ Video->PlayBuffer ].Block; 01538 01539 #ifdef RIO_DEBUG2 01540 RioErr << "Playthread --------------> Tocando bloco " 01541 << Video->Request[ Video->PlayBuffer ].Block 01542 << " posicao buffer: " << Video->PlayBuffer 01543 << " duração " << duration[ indice ] << endl; 01544 string message; 01545 message = "meu pid é "; 01546 message += int2string( (int) Video->PID ); 01547 message += "\n"; 01548 Video->printDebug( 1, message ); 01549 #endif 01550 01551 //notificação de execução de um bloco 01552 timeval tv; 01553 gettimeofday( &tv, 0 ); 01554 Video->m_log 01555 << (double)(tv.tv_sec + ( (double)tv.tv_usec / 1000000 )) 01556 << " Execução: " << indice << endl; 01557 //só considero que um bloco foi recebido se este for executado, 01558 //isso evita fazer contabilizações erradas para o caso do 01559 //emulador receber um bloco e sofrer um stop antes da execução 01560 //do mesmo 01561 completeBlocks++; 01562 //Acumulando o total de bytes recebidos para calcular goodness 01563 totalBytesPlayed = totalBytesPlayed + 01564 Video->Request[ Video->PlayBuffer ].Size; 01565 01566 usleep( duration[ indice ] ); 01567 01568 //Abaixo podemos fingir que o cliente multicast nao usa cache. 01569 //Para isto basta substituir o "if 0" por "if 1" antes de 01570 //compilar. Vale lembrar que o ifdef abaixo nao poderia ser 01571 //substituido por um "if( useCache )"pois os blocos que chegam 01572 //via multicast sempre sao armazenados na cache quando o client 01573 //nao precisa deles no momento da chegada. O que eh feito no 01574 //abaixo eh "fingir" que o bloco, apos consumido, eh retirado 01575 //da cache, isto eh, eh como se a cache fosse uma cache 01576 //temporaria, apenas para guardar blocos ateh que sejam 01577 //consumidos, sendo os tais liberados imediatamente apos seu 01578 //consumo. 01579 #if 0 01580 { 01581 Video->bufferStream->dropBlock( 01582 Video->Request[ Video->PlayBuffer ].Block ); 01583 01584 #ifdef RIO_DEBUG2 01585 RioErr << "Simulando liberacao do bloco" 01586 << Video->Request[ Video->PlayBuffer ].Block 01587 << " da cache." << endl; 01588 #endif 01589 } 01590 #endif 01591 01592 gettimeofday( &Video->timer_after, 0 ); 01593 Video->diff_timer.tv_sec = Video->timer_after.tv_sec - 01594 Video->timer_before.tv_sec; 01595 01596 Video->diff_timer.tv_usec = Video->timer_after.tv_usec - 01597 Video->timer_before.tv_usec; 01598 01599 if( Video->diff_timer.tv_usec < 0 ) 01600 { 01601 Video->diff_timer.tv_sec -= 1; 01602 Video->diff_timer.tv_usec += 1000000; 01603 } 01604 01605 Video->play_time = (unsigned int)( Video->diff_timer.tv_sec * 01606 1000000.0 + 01607 Video->diff_timer.tv_usec); 01608 01609 Video->PlayPauseMutexUnlock( "plthr4" ); 01610 } 01611 #else // else do ifdef RIO_EMUL 01612 { 01613 #ifdef RIO_DEBUG2 01614 RioErr << "Playthread --------------> Tocando bloco " 01615 << Video->Request[ Video->PlayBuffer ].Block 01616 << " posicao buffer: " << Video->PlayBuffer << endl; 01617 string message; 01618 message = "meu pid é "; 01619 message += int2string( (int) Video->PID ); 01620 message += "\n"; 01621 Video->printDebug( 1, message ); 01622 #endif 01623 01624 Video->PlayBlock( Video->PlayBuffer, curBlockSize ); 01625 } 01626 #ifdef RIO_DEBUG2 01627 else 01628 { 01629 RioErr << "Playthread - free_status = " 01630 << (free_status? "true":"false") 01631 << ": Bloco não será tocado." << endl; 01632 } 01633 #endif // endif do ifdef RIO_DEBUG2 01634 #endif // endif do ifdef RIO_EMUL 01635 01636 if( free_status ) 01637 { 01638 #ifdef RIO_DEBUG2 01639 RioErr << "Liberando espaco: " << Video->PlayBuffer 01640 << " no playbuffer " << endl; 01641 #endif 01642 01643 Video->SetBufferStatus( Video->PlayBuffer, BUFFEREMPTY ); 01644 } 01645 else 01646 free_status = true; 01647 01648 #ifndef RIO_EMUL 01649 Video->SyncMedia( (void *)Video->Request[ 01650 Video->PlayBuffer ].Block ); 01651 #endif 01652 01653 // Aquire mutex again 01654 Video->PlayThreadMutexLock( "plthr5" ); 01655 01656 // Remember buffer index 01657 ind = Video->PlayBuffer; 01658 01659 // Update index to next buffer to be played 01660 Video->PlayBuffer++; 01661 if( Video->PlayBuffer >= Video->nBuffers ) 01662 Video->PlayBuffer = 0; 01663 01664 #ifdef RIO_DEBUG2 01665 RioErr << "[PlayThread] PlayBuffer atualizado para " 01666 << Video->PlayBuffer << endl; 01667 #endif 01668 01669 // Since this buffer is now empty, request new data if did not reach 01670 // end of object 01671 if( Video->NextRequestBlock < Video->TotalBlocks ) 01672 { 01673 #ifdef RIO_DEBUG2 01674 RioErr << "Playthread - Precisando do bloco " 01675 << Video->NextRequestBlock << endl; 01676 #endif 01677 01678 if( Video->ReadNextBlock( ind ) == false ) 01679 { 01680 #ifdef RIO_DEBUG2 01681 RioErr << "Finalizando playthread. Erro na " 01682 << "ReadNextBlock( " << ind << " )." << endl; 01683 #endif 01684 01685 pthread_exit( NULL ); 01686 } 01687 } // fim do if( Video->NextRequestBlock <= Video->TotalBlocks ) 01688 else 01689 { 01690 #ifdef RIO_DEBUG2 01691 RioErr << "PlayThread - Bloco " << Video->NextRequestBlock 01692 << " náo será solicitado pois NextRequestBlock > " 01693 << "TotalBlocks" << endl; 01694 #endif 01695 01696 // if this was last block, finish 01697 if( Video->Request[ind].Block == ( Video->TotalBlocks - 1 ) ) 01698 { 01699 #ifdef RIO_DEBUG2 01700 RioErr << "[RioMMVideo] Ultimo bloco do filme: " 01701 << Video->Request[ind].Block << endl; 01702 #endif 01703 01704 //Esperar tocar o último bloco 01705 usleep( 2000000 ); 01706 01707 pthread_exit( NULL ); 01708 } 01709 01710 if( Video->NextRequestBlock > Video->TotalBlocks ) 01711 pthread_exit( NULL ); 01712 } 01713 01714 Video->PrefetchMutexUnlock( "plthr6" ); 01715 01716 #ifdef RIO_DEBUG2 01717 RioErr << "GetFullBuffers = " << Video->GetFullBuffers() << endl; 01718 #endif 01719 } //fim do while( Video->GetFullBuffers() > 0 ) 01720 01721 if( Video->DealPendentEvents() == false ) 01722 { 01723 #ifdef RIO_DEBUG2 01724 RioErr << "[RioMMVideo] Evento inválido. Saindo da PlayThread" << endl; 01725 #endif 01726 01727 pthread_exit( NULL ); 01728 } 01729 01730 #ifdef RIO_DEBUG2 01731 RioErr << "[RioMMVideo] PlayThread: Chamando WaitBlocks" << endl; 01732 #endif 01733 01734 if( Video->WaitBlocks() == false ) 01735 { 01736 #ifdef RIO_DEBUG2 01737 RioErr << "[RioMMVideo] Saindo da PlayThread" << endl; 01738 #endif 01739 pthread_exit( NULL ); 01740 } 01741 01742 //Dando um limite para interações nulas, isto eh, GetFullBuffers==0. 01743 //Isto impede que o cliente fique eternamente neste loop caso nao receba 01744 //nenhum bloco apos "maxbuf0" iteracao com GetFullBuffers valendo zero. 01745 if( Video->GetFullBuffers() == 0 ) 01746 { 01747 maxbuf0++; 01748 if( maxbuf0 >= 20 ) 01749 { 01750 #ifdef RIO_DEBUG_EMUL 01751 RioErr << "[RioMMVideo] Saindo da PlayThread. Cliente " 01752 << "finalizando por inanicao." << endl; 01753 #endif 01754 01755 pthread_exit( NULL ); 01756 } 01757 } 01758 else 01759 { 01760 maxbuf0=0; 01761 } 01762 } //fim do while( 1 ) 01763 01764 pthread_cleanup_pop( 1 ); 01765 pthread_exit( NULL ); 01766 }
void CRioMMVideo::PlayThreadCleanup | ( | void * | videoObject | ) | [static, protected] |
Definition at line 2475 of file RioMMVideo.cpp.
02476 { 02477 CRioMMVideo *Video; 02478 02479 #ifdef RIO_DEBUG2 02480 RioErr << "[RioMMVideo]: Entrei na PlayThreadCleanup" << endl; 02481 #endif 02482 02483 Video = (CRioMMVideo *)videoObject; 02484 02485 Video->PlayThreadID = 0; 02486 02487 #ifndef RIO_EMUL 02488 kill( Video->playerPID, SIGKILL ); 02489 #else 02490 Video->finalize_emul = true; 02491 #endif 02492 02493 Video->PlayPauseMutexUnlock( "plthcl1" ); 02494 Video->PlayThreadMutexUnlock( "plthcl2" ); 02495 Video->PrefetchMutexUnlock( "plthcl3"); 02496 02497 #ifdef RIO_EMUL 02498 if( !Video->Stopped ) 02499 { 02500 Video->Stop(); 02501 Video->Close(); 02502 } 02503 #endif 02504 02505 #ifdef RIO_DEBUG2 02506 RioErr << "[RioMMVideo]: Saindo da PlayThreadCleanup" << endl; 02507 #endif 02508 02509 // Verifica se o termino foi porque o pedido de um bloco nao pode ser feito 02510 // devido a um erro na conexao TCP. 02511 02512 if( !Video->ReadBlockStatus ) 02513 { 02514 // Obtem o pid do Tgif e mata o processo executando o Tgif. Estamos 02515 // supondo que o Tgif sempre e a unica media usada. Para os primeiros 02516 // cursos do CEDERJ, que usam o browser, isso nao ira funcionar, porque 02517 // o objeto seria do tipo RioMMBrowser (no caso do cliente ser executado 02518 // pela linha de comando) ou RioMMEmbed (no caso do cliente ser 02519 // executado a partir do plugin do browser). 02520 // Obs: Isso somente sera feito se estivermos usando o Tgif, isto e, se 02521 // o numero de medias for maior do que 0 02522 if( Video->GetNMedias() > 0 ) 02523 { 02524 CRioMMTgif *Tgif; 02525 Tgif = (CRioMMTgif * ) Video->GetMedia( 0 ); 02526 // Mata o processo do Tgif 02527 kill( Tgif->GetTgifpid(), SIGKILL ); 02528 } 02529 02530 #ifdef RIO_EMUL 02531 Video->m_log << "Erro ao ler o ultimo bloco: server is down?" << endl; 02532 raise( SIGTERM ); 02533 #else 02534 // Envia uma mensagem para a aplicacao finalizar 02535 QCustomEvent *event; 02536 event = new QCustomEvent( ( QEvent::Type )( QEvent::User + 9 ), 02537 NULL ); 02538 QApplication::postEvent( (QObject*) Video->riomminterface, event ); 02539 #endif 02540 } 02541 }
void CRioMMVideo::Prefetch | ( | void | ) | [virtual] |
Prefetch só é chamada quando o cliente esta no inicio (play).
Neste caso ela faz tantas requisições de blocos quantas forem necessárias para encher o PlayOutBuffer do cliente.
Reimplemented from CRioMMObject.
Definition at line 508 of file RioMMVideo.cpp.
00509 { 00510 unsigned int limit = NextRequestBlock + nBuffers; 00511 unsigned int index = NextRequestBlock % nBuffers; 00512 00513 #ifdef RIO_DEBUG2 00514 RioErr << "[Prefetch] Entrei na Prefetch..." << endl; 00515 #endif 00516 00517 ClearBuffer(); 00518 00519 if( connectPI ) 00520 { 00521 00522 if( bufferStream->exist( NextRequestBlock ) ) 00523 { 00524 #ifdef RIO_DEBUG2 00525 RioErr << "Prefetch - Cliente iniciou execução mas já tem blocos " 00526 << "na cache. A PL não será notificada." << endl; 00527 #endif 00528 00529 ReadFrom = READFROM_BUFFER; 00530 } 00531 else 00532 { 00533 #ifdef RIO_DEBUG2 00534 RioErr << "Prefetch - cliente avisando acao ACTION_PLAY e sendo " 00535 << "alocado em grupo." << endl; 00536 #endif 00537 00538 MulticastMutexLock( "prefe1" ); 00539 CommMultiStream->sendMoveMsg( PID, ACTION_PLAY, NextRequestBlock ); 00540 MulticastWaitCondition( "prefe1" ); 00541 MulticastMutexUnlock( "prefe1" ); 00542 00543 ReadFrom = READFROM_SERVER; 00544 } 00545 00546 first = isFirst(); 00547 } // fim do if( connectPI ) 00548 00549 while( NextRequestBlock < limit ) 00550 { 00551 #ifdef RIO_DEBUG2 00552 RioErr << "[Prefetch] Request Block " << NextRequestBlock << endl; 00553 #endif 00554 00555 gettimeofday( &calculete_RTT[ index ].initial_time, 0 ); 00556 calculete_RTT[ index ].block = 0; 00557 if( ReadNextBlock( index ) == false ) 00558 { 00559 #ifdef RIO_DEBUG2 00560 RioErr << "[RioMMVideo Prefetch] ReadNextBlock retornou false!! " 00561 << "Chamando Stop()" << endl; 00562 #endif 00563 00564 Stop(); 00565 } 00566 00567 index = NextRequestBlock % nBuffers; 00568 } 00569 00570 #ifndef RIO_EMUL 00571 for( unsigned int i = 0; i < nMedias; i++ ) 00572 Media[i]->Prefetch(); 00573 #endif 00574 00575 #ifdef RIO_DEBUG2 00576 RioErr << "[Prefetch] Saindo da prefetch " << endl; 00577 #endif 00578 }
void CRioMMVideo::PrefetchMutexLock | ( | string | msg = "" |
) |
PrefetchMutexLock trava o mutex PrefetchMutex.
msg | é usado apenas no modo RIO_DEBUG2 para facilitar depurações de clientes travados em mutex's. |
Definition at line 2449 of file RioMMVideo.cpp.
02450 { 02451 #ifdef RIO_DEBUG2 02452 if( msg.length() ) 02453 RioErr << "[PrefetchMutexLock] " << msg << "... " << endl; 02454 #endif 02455 02456 pthread_mutex_lock( &PrefetchMutex ); 02457 02458 #ifdef RIO_DEBUG2 02459 if( msg.length() ) 02460 RioErr << "..." << msg << " OK!" << endl; 02461 #endif 02462 }
void CRioMMVideo::PrefetchMutexUnlock | ( | string | msg = "" |
) |
PrefetchMutexUnlock destrava o mutex PrefetchMutex.
msg | é usado apenas no modo RIO_DEBUG2 para facilitar depurações de clientes travados em mutex's. |
Definition at line 2464 of file RioMMVideo.cpp.
02465 { 02466 #ifdef RIO_DEBUG2 02467 if( msg.length() ) 02468 RioErr << "[PrefetchMutexUnlock] " << msg << endl; 02469 #endif 02470 02471 pthread_mutex_unlock( &PrefetchMutex ); 02472 }
int CRioMMVideo::ProcessSignal | ( | int | sig, | |
void * | data | |||
) | [virtual] |
Reimplemented from CRioMMObject.
Definition at line 3996 of file RioMMVideo.cpp.
03997 { 03998 int status = 0; 03999 switch( sig ) 04000 { 04001 case SIGHUP: // signal 1 04002 readSettings(); 04003 break; 04004 04005 case SIGCHLD: // signal 17 04006 if( (int) (long long int) data == playerPID ) 04007 status = 2; 04008 break; 04009 } 04010 04011 /* if it is not fatal, forward signal to the slave medias */ 04012 if( status != 2 ) 04013 CRioMMObject::ProcessSignal( sig, data ); 04014 04015 return( status ); 04016 }
bool CRioMMVideo::ReadBlock | ( | int | index, | |
RioBlock | block, | |||
RioStreamType | traffic, | |||
int | ip, | |||
int | port | |||
) | [protected] |
ReadBlock solicita o bloco block ao servidor, indicando, através de traffic, se a requisição é multicast ou unicast.
Definition at line 2820 of file RioMMVideo.cpp.
02822 { 02823 bool status = true; 02824 02825 #ifdef RIO_EMUL 02826 //notificação do pedido 02827 timeval tv; 02828 gettimeofday( &tv, 0 ); 02829 m_log << (double)(tv.tv_sec + ( (double)tv.tv_usec / 1000000 )) ; 02830 m_log << " Pedido: " << block << endl; 02831 requestedBlocks++; 02832 #endif 02833 02834 #ifdef RIO_DEBUG2 02835 struct in_addr printIP; 02836 printIP.s_addr = (unsigned int) ip; 02837 if( traffic == MULTICASTTRAFFIC ) 02838 RioErr << "[ReadBlock] Requisitando Multicast. block: " << block 02839 << " ip: " << inet_ntoa( printIP ) << " porta: " << ntohs( port ) 02840 << endl; 02841 else 02842 RioErr << "[ReadBlock] Requisitando Patching or Unicast. block: " 02843 << block << " ip: " << inet_ntoa( printIP ) << " porta: " 02844 << ntohs( port ) << endl; 02845 #endif 02846 02847 if( !Read( index, block, traffic, ip, ntohs(my_port) ) ) 02848 { 02849 #ifndef RIO_EMUL 02850 // Imprime uma mensagem de erro. 02851 sendMsg( QString( "RioMMVideo" ), 02852 QString( "Error receiving data: Server is down?" ), 02853 riomminterface ); 02854 #ifdef RIO_DEBUG2 02855 RioErr << "[ReadBlock] Erro no pedido do bloco " << block << endl; 02856 #endif 02857 #endif 02858 02859 status = false; 02860 } 02861 02862 inputLog( REQSERV, block ); //log de comportamento do usuario 02863 02864 // Garda o estado da execucao atual da funcao na variavel da classe que 02865 // armazena o estado da ultima chamada da funcao ReadBlock. 02866 02867 ReadBlockStatus = status; 02868 02869 return( status ); 02870 }
bool CRioMMVideo::ReadNextBlock | ( | unsigned int | index | ) | [protected] |
Definition at line 2872 of file RioMMVideo.cpp.
02873 { 02874 bool status = true; 02875 bool disableMulticastRequest = false; 02876 02877 #ifdef RIO_DEBUG2 02878 RioErr << "[ReadNextBlock] index = " << index 02879 << ", group_block = " << group_block 02880 << ", NextRequestBlock = " << NextRequestBlock 02881 << ", TotalBlocks = " << TotalBlocks 02882 << ", target = " << target 02883 #ifdef RIO_EMUL 02884 << ", Stopped = " << Stopped 02885 #endif 02886 << ", connectPI = " << connectPI << endl; 02887 #endif 02888 02889 //group_block != -1 indica que o cliente é lider forçado, isto é, que ele 02890 //está tocando um bloco 'x' diferente daquele que está solicitando para o 02891 //grupo, digamos o bloco 'y'. Neste caso, necessariamente y>x. Quando o 02892 //cliente é um líder natural, isto é, x=y, a requisição para o grupo não 02893 //será feita via MulticastRead(), mas via Read(). 02894 //Obs: ( group_block!=-1 ) implica em ( first == true ) (nao vale a volta) 02895 if( group_block != -1 && first ) 02896 { 02897 //Na segunda restrição do if abaixo tem-se group_block + 1 pois o líder 02898 //antigo já pediu o bloco group_block, logo, provavelmente este cliente 02899 //aqui, que estava escutando o fluxo do antigo líder, já tem o bloco de 02900 //número group_block na cache. 02901 //A terceira restrição, ( ( group_block + 1 ) != target ), impede que um 02902 //sublíder envie ACTION_READBUFFER ao chegar ao seu target. Nesse caso 02903 //ele enviará um ACTION_REACHLEADER mais adiante no código (esta 02904 //restrição se trata de um sublíder e não de um líder pois um líder não 02905 //tem target (target de líder é igual a INT_MAX)). 02906 if( (unsigned int) group_block == TotalBlocks ) 02907 { 02908 #ifdef RIO_DEBUG2 02909 RioErr << "O bloco relativo a este grupo já alcançou o fim do " 02910 << "vídeo. Como sou líder, deixarei a liderança e não " 02911 << "farei mais pedidos. Enviando ACTION_READBUFFER " 02912 << "para PL." << endl; 02913 #endif 02914 02915 //Como group_block == TotalBlocks, a mensagem abaixo não 02916 //significará, de fato, que o cliente estará em situação de ler 02917 //do buffer. Na verdade quer dizer que o cliente quer sair do 02918 //grupo pois não há mais pedidos a se fazer para este grupo. 02919 //A PL, ao receber o pedido com TotalBlocks, saberá que este grupo 02920 //deve ser extinto. Preciso travar no mutex para que a PL tenha 02921 //tempo de me avisar que perdi a liderança antes de sair deste 02922 //método(ReadNextBlock) pois tão logo saia dele será chamada a 02923 //Stop() 02924 MulticastMutexLock( "renxbl1a" ); 02925 CommMultiStream->sendMoveMsg( PID, ACTION_READBUFFER, group_block ); 02926 MulticastWaitCondition( "renxbl1a" ); 02927 MulticastMutexUnlock( "renxbl1a" ); 02928 } 02929 else if( group_block >= target ) 02930 { 02931 #ifdef RIO_DEBUG2 02932 RioErr << "O bloco relativo a este grupo é o meu target. " 02933 << "Enviando ACTION_REACHLEADER à PL." 02934 << endl; 02935 #endif 02936 02937 //Neste caso aqui o sublíder não precisa aguardar uma 02938 //mensagem de retorno da PL, por isto não chama o método 02939 //MulticastWaitCondition(). Esta mensagem serve apenas para 02940 //a PL ficar notificada de que o sublíder alcançou seu líder 02941 //e, portanto, terminou o processo de merging. 02942 CommMultiStream->sendMoveMsg( PID, ACTION_REACHLEADER, 02943 group_block ); 02944 target = INT_MAX; 02945 group_block = -1; //deixando de ser sublíder para ser passivo. 02946 02947 if( patching ) 02948 Stream_Control( "renxbl1" ); 02949 } 02950 else if( useCache && 02951 bufferStream->exist( ( unsigned int ) group_block + 1 ) && 02952 ( ( group_block + 1 ) < target ) 02953 ) 02954 { 02955 #ifdef RIO_DEBUG2 02956 RioErr << "O bloco relativo a este grupo já está em meu cache." 02957 << " Como sou líder, deixarei a liderança e não farei mais" 02958 << " pedidos. Enviando ACTION_READBUFFER para PL." 02959 << endl; 02960 #endif 02961 02962 MulticastMutexLock( "renxbl1b" ); 02963 CommMultiStream->sendMoveMsg( PID, ACTION_READBUFFER, 02964 group_block + 1 ); 02965 MulticastWaitCondition( "renxbl1b" ); 02966 MulticastMutexUnlock( "renxbl1b" ); 02967 } 02968 else // else do if( ( (unsigned int) group_block == TotalBlocks ) ||... 02969 { 02970 #ifdef RIO_DEBUG2 02971 RioErr << "Pedido para grupo. Bloco " << group_block << "." 02972 << endl; 02973 #endif 02974 02975 //pedindo bloco para o grupo 02976 if( !MulticastRead( group_block, MULTICASTTRAFFIC ) ) 02977 { 02978 #ifdef RIO_DEBUG2 02979 RioErr << "[ReadNextBlock] Erro no pedido de bloco multicast " 02980 << group_block << ". É possível que os outros clientes " 02981 << "parem de funcionar caso eu entre aqui!" << endl; 02982 #endif 02983 02984 status = false; 02985 } 02986 else //else do if( !MulticastRead( group_block, MULTICASTTRAFFIC ) ) 02987 { 02988 //O cliente pode estar fazendo patching e ainda estar pedindo 02989 //para o grupo e, por isto, deve gerenciar estes dois pedidos. 02990 group_block++; 02991 disableMulticastRequest = true; 02992 } //fim do else do if( !MulticastRead( group_block, MULTICASTTRAF... 02993 } //fim do else do if( ( (unsigned int) group_block == TotalBlocks ) ... 02994 } //fim do if( group_block != -1 ) 02995 02996 if( connectPI ) 02997 { 02998 if( ( NextRequestBlock < TotalBlocks ) && status ) 02999 { 03000 if( bufferStream->exist( NextRequestBlock ) ) 03001 { 03002 //O bloco NextRequestBlock está presente na cache 03003 03004 if( ReadFrom == READFROM_SERVER ) 03005 { 03006 if( !disableMulticastRequest ) 03007 { 03008 //Só entro neste if acima no caso de não ser um 03009 //(sub)líder forçado que tenha pedido um bloco para 03010 //o grupo no MulticastRead() acima (isto é, sou 03011 //passivo, (sub)líder natural ou (sub)líder que não 03012 //tenha pedido bloco na MulticastRead() acima por 03013 //algum motivo.) 03014 03015 if( first ) 03016 { 03017 if( ( group_block == -1 ) && 03018 ( NextRequestBlock < (RioBlock)target ) 03019 ) 03020 { 03021 //a restrição NextRequestBlock < target 03022 //evita que o líder envie ACTION_READBUFFER 03023 //aqui pois abaixo será enviado um 03024 //ACTION_REACHLEADER 03025 03026 #ifdef RIO_DEBUG2 03027 RioErr << "Cliente vai ler dados do buffer e," 03028 << " por ser (sub)lider natural, vai " 03029 << "enviar ACTION_READBUFFER pra PL " 03030 << "que saberá o que ele deve fazer." 03031 << endl; 03032 #endif 03033 03034 //Se este cliente for um sublíder, ele 03035 //será transferido para a lista de inativos 03036 //e repassará a subliderança para o próximo 03037 //submembro, caso exista. 03038 03039 MulticastMutexLock( "renxbl2" ); 03040 CommMultiStream->sendMoveMsg( PID, 03041 ACTION_READBUFFER, 03042 NextRequestBlock ); 03043 MulticastWaitCondition( "renxbl2" ); 03044 MulticastMutexUnlock( "renxbl2" ); 03045 } 03046 #ifdef RIO_DEBUG2 03047 else if( group_block != -1 ) 03048 { 03049 RioErr << "Cliente vai ler dados do buffer" 03050 << " mas por ser lider forçado, não " 03051 << "vai enviar ACTION_READBUFFER pra" 03052 << " PL pois está pedindo à frente." 03053 << endl; 03054 } 03055 #endif 03056 } 03057 else //else do if( first ) 03058 { 03059 if( patching && ( target != INT_MAX ) ) 03060 { 03061 //Neste caso sou passivo, estou fazendo 03062 //patching e encontrei dados na cache. 03063 //Verificando se posso sair do patching (se 03064 //tenho todos os blocos até o meu target na 03065 //cache). 03066 03067 #ifdef RIO_DEBUG2 03068 RioErr << "[ReadNextBlock] Cliente tem dados " 03069 << "na cache mas ainda não alcançou " 03070 << "seu target. Verificando se pode " 03071 << "sair do patching." << endl; 03072 #endif 03073 03074 bool keepOnPathcing = true; 03075 for( int i = NextRequestBlock + 1; 03076 ( i <= target ) && keepOnPathcing; 03077 i++ 03078 ) 03079 { 03080 keepOnPathcing = bufferStream->exist(i); 03081 } 03082 03083 //Cliente alcançou o líder precocemente. 03084 //Saindo do patching. 03085 if( !keepOnPathcing ) 03086 { 03087 #ifdef RIO_DEBUG2 03088 RioErr << "[ReadNextBlock] Cliente " 03089 << "alcançou o líder antes " 03090 << "do target ser alcançado." 03091 << "Saindo do patching." 03092 << endl; 03093 #endif 03094 03095 //Informando à PL que alcancei o líder. 03096 CommMultiStream->sendMoveMsg( PID, 03097 ACTION_REACHLEADER, 03098 NextRequestBlock ); 03099 target = INT_MAX; 03100 Stream_Control( "renxbl1" ); 03101 } 03102 } 03103 } //fim do else do if( first ) 03104 } 03105 #ifdef RIO_DEBUG2 03106 else if( patching ) 03107 RioErr << " NÃO PODERIA ENTRAR AQUI! Como posso ser " 03108 << "líder forçado e estar em patching?!?!?!" 03109 << endl; 03110 #endif 03111 03112 ReadFrom = READFROM_BUFFER; 03113 } //fim do if( ReadFrom == READFROM_SERVER ) 03114 } 03115 else //else do if( useCache && bufferStream->exist(... 03116 { 03117 //O bloco NextRequestBlock não está presente na cache 03118 03119 if( !first ) 03120 { 03121 if( ReadFrom == READFROM_BUFFER ) 03122 { 03123 if( !thereAreFragments( NextRequestBlock ) ) 03124 { 03125 //FIXME: Ha um caso que deveria ser tratado aqui:No 03126 //caso de o cliente estar em um grupo, recebendo 03127 //passivamente os blocos sem fazer patching e 03128 //ainda nao ter alcancado seu target, entao ele 03129 //devera apenas setar o membro ReadFrom para 03130 //READFROM_SERVER, nao deveria enviar a mensagem 03131 //ACTION_PLAY pois ele provavelmente serah alocado 03132 //no mesmo grupo que se encontra agora. Para 03133 //entender melhor esta situacao comsidere o seguinte 03134 //caso: um cliente "c" entra no sistema e pula 03135 //para o bloco 100, recebe dos blocos 100 ao 150, 03136 //interage para o bloco 80 e eh alocado em um grupo 03137 //"G" cujo lider "l" estah requisitando o bloco 160. 03138 //Neste caso "c" tocarah os blocos 80,81,... 03139 //enquanto recebe os blocos 160,161,... de $G$. 03140 //Quando "c" chegar ao bloco 100, apersar de ter do 03141 //bloco 100 ao 150 na cache, ele nao o enviarah 03142 //ACTION_READBUFF ao PL, mas quando chegar ao 151 03143 //enviarah um ACTION_PLAY(codigo abaixo) 03144 //desnecessariamente pois jah estah recebendo blocos 03145 //corretos de $G$. Se ele cair em outro grupo 03146 //certamente terah uma launa de blocos a preencher, 03147 //o que acarretara em mais requisicoes unicast's. 03148 03149 #ifdef RIO_DEBUG2 03150 RioErr << "[ReadNextBlock] BLOCO " 03151 << NextRequestBlock 03152 << " NÃO EXISTE - Enviando mensagem " 03153 << "ACTION_PLAY para bloco " 03154 << NextRequestBlock << endl; 03155 #endif 03156 03157 MulticastMutexLock( "renxbl3" ); 03158 CommMultiStream->sendMoveMsg( PID, ACTION_PLAY, 03159 NextRequestBlock ); 03160 MulticastWaitCondition( "renxbl3" ); 03161 MulticastMutexUnlock( "renxbl3" ); 03162 03163 ReadFrom = READFROM_SERVER; 03164 } 03165 #ifdef RIO_DEBUG2 03166 else 03167 { 03168 RioErr << "[ReadNextBlock] BLOCO " 03169 << NextRequestBlock 03170 << " NÃO EXISTE mas eu tenho seus " 03171 << "fragmentos e os recuperarei." 03172 << endl; 03173 } 03174 #endif 03175 } 03176 #ifdef RIO_DEBUG2 03177 else 03178 { 03179 RioErr << "[ReadNextBlock] ReadFrom == READFROM_SERVE" 03180 << "R para bloco " << NextRequestBlock << endl; 03181 } 03182 #endif 03183 } //fim do if( !first ) 03184 } //fim do else do if( useCache && bufferStream->exist(... 03185 03186 if( NextRequestBlock >= (RioBlock)target ) 03187 { 03188 #ifdef RIO_DEBUG2 03189 RioErr << "Alcançado o líder... " << NextRequestBlock 03190 << " >= " << (RioBlock)target << endl; 03191 03192 if( useCache && bufferStream->exist( NextRequestBlock ) ) 03193 { 03194 RioErr << "Cliente alcançou o líder. Vai ler " 03195 << "dados do buffer e continua " 03196 << "escutando fluxo multicast." 03197 << endl; 03198 } 03199 else 03200 { 03201 RioErr << "Cliente alcançou o líder mas não " 03202 << "tem os dados no buffer. Avisando à " 03203 << "PL." << endl; 03204 } 03205 #endif 03206 03207 //neste caso aqui o cliente não precisa aguardar uma 03208 //mensagem de retorno da PL, por isto não chama o método 03209 //MulticastWaitCondition(). Esta mensagem serve apenas para 03210 //a PL ficar notificada de que o cliente alcançou seu líder 03211 //e, portanto, saiu do patching. 03212 CommMultiStream->sendMoveMsg( PID, 03213 ACTION_REACHLEADER, 03214 NextRequestBlock ); 03215 03216 //setando target para infinito para evitar que esta 03217 //mensagem seja enviada daqui pra frente (só devo 03218 //enviá-la uma vez no momento em que o cliente alcançar 03219 //seu líder) 03220 target = INT_MAX; 03221 03222 if( patching ) 03223 Stream_Control( "reachingLeader" ); 03224 } // fim do if( NextRequestBlock >= (RioBlock)target ) 03225 #ifdef RIO_DEBUG2 03226 else 03227 { 03228 if( target != INT_MAX ) 03229 RioErr << "[ReadNextBlock] Patching size = " 03230 << (RioBlock)target - NextRequestBlock 03231 << endl; 03232 else 03233 RioErr << "[ReadNextBlock] No target to reach!" 03234 << endl; 03235 } 03236 #endif 03237 } 03238 else // else do if( ( NextRequestBlock < TotalBlocks ) && status ) 03239 { 03240 status = false; 03241 } // fim do else do if( ( NextRequestBlock < TotalBlocks ) && st... 03242 } //fim do if( connectPI ) 03243 03244 if( ( NextRequestBlock < TotalBlocks ) && status ) 03245 { 03246 if( useCache ) 03247 { 03248 Request[ index ].Block = NextRequestBlock; 03249 if( bufferStream->readBlock( Request[ index].Block, 03250 ( unsigned char * ) Request[ index ].Buffer ) != 0 ) 03251 { 03252 //O bloco NextRequestBlock não está presente na cache 03253 if( connectPI ) 03254 { 03255 //O if abaixo é executado para os clientes que não são 03256 //líderes naturais, isto é, é executado para clientes 03257 //passivos, inativos ou para líderes forçados 03258 if( !( first && ( group_block == -1 ) ) ) 03259 { 03260 #ifdef RIO_DEBUG2 03261 RioErr << "[ReadNextBlock] bloco " 03262 << NextRequestBlock << " não está na cache" 03263 << ". Verificando se há fragmentos do mesmo" 03264 << endl; 03265 #endif 03266 03267 //O cliente pode ter recebido alguns fragmentos 03268 //deste bloco via multicast. FreeBlock verifica 03269 //isto. 03270 if( !thereAreFragments( NextRequestBlock ) ) 03271 { 03272 #ifdef RIO_DEBUG2 03273 RioErr << "[ReadNextBlock] Não há fragmentos do " 03274 << "bloco " << NextRequestBlock 03275 << ". Solicitando ao servidor." << endl; 03276 #endif 03277 03278 //Nenhum fragemto fio recebido. Solicitando ao 03279 //servidor 03280 03281 status = ReadBlock( index, NextRequestBlock, 03282 UNICASTTRAFFIC, 03283 my_address, my_port ); 03284 } 03285 else 03286 { 03287 if( CallFreeBlock( index ) == false ) 03288 { 03289 #ifdef RIO_DEBUG2 03290 RioErr << "[ReadNextBlock] Bloco " 03291 << Request[PlayBuffer].Block 03292 << " nao recuperado." << endl; 03293 #endif 03294 } 03295 #ifdef RIO_DEBUG2 03296 else 03297 { 03298 RioErr << "[ReadNextBlock] Bloco " 03299 << NextRequestBlock << " tem fragmentos " 03300 << "recebidos via multicast e estes " 03301 << "foram recuperados." << endl; 03302 } 03303 #endif 03304 03305 //Nesta situacao aqui chamaremos a FreePendentBlocks 03306 //apenas se a FreeBlock conseguir recuperar algum 03307 //fragmento, o que sinaliza perda na rede, por causa 03308 //do alto custo da FreePendentBlocks. 03309 #ifdef RIO_DEBUG2 03310 int freedPendentsSize = FreePendentBlocks( useCache, 03311 nBuffers ); 03312 03313 RioErr << "[RioMMVideo] ReadNextBlock - " 03314 << "FreePendentBlocks liberou " 03315 << freedPendentsSize << " bytes de blocos " 03316 << "pendentes." << endl; 03317 #else 03318 FreePendentBlocks( useCache, nBuffers ); 03319 #endif 03320 } 03321 03322 } 03323 else // else do if( !( first && ( group_block == -1 )... 03324 { 03325 //Como sou líder natural, peço bloco para o grupo. 03326 #ifdef RIO_DEBUG2 03327 RioErr << "[ReadNextBlock] Bloco " << NextRequestBlock 03328 << " não está na cache. Sou lider natural e o " 03329 << "pedirei para o grupo." << endl; 03330 #endif 03331 status = ReadBlock( index, NextRequestBlock, 03332 MULTICASTTRAFFIC, 03333 0, 0 ); 03334 } 03335 } 03336 else //else do if( connectPI ) 03337 { 03338 #ifdef RIO_EMUL 03339 gettimeofday( &timers[ index ].call_time, 0); 03340 #endif 03341 03342 #ifdef RIO_DEBUG2 03343 RioErr << "[ReadNextBlock] Sou cliente unicast. " 03344 << "Pedindo bloco " << NextRequestBlock 03345 << "." << endl; 03346 #endif 03347 03348 status = ReadBlock( index, NextRequestBlock, 03349 UNICASTTRAFFIC, my_address, 03350 my_port ); 03351 } // fim do else do if( connectPI ) 03352 } 03353 else //else do if( bufferStream->readBlock( Request[ index]... 03354 { 03355 //O bloco NextRequestBlock está presente na cache 03356 03357 #ifdef RIO_EMUL 03358 //notificação de recuperação do bloco na cache 03359 timeval tv; 03360 gettimeofday( &tv, 0 ); 03361 m_log << (double)(tv.tv_sec + ((double)tv.tv_usec / 1000000 )); 03362 m_log << " Recuperado da cache: " << NextRequestBlock << endl; 03363 #endif 03364 03365 #ifdef RIO_DEBUG2 03366 RioErr << "[ReadNextBlock] Bloco " << NextRequestBlock 03367 << " foi encontrado na cache e será gravado no " 03368 << "PlayOutBuffer " << index << endl; 03369 #endif 03370 03371 inputLog( REQCACHE, NextRequestBlock ); 03372 03373 //Sinalizando ao waitprefetch que bloco ja existe no buffer 03374 int inc; 03375 inc = index; 03376 calculete_RTT[ index ].block = inc++; 03377 03378 Request[ index ].Block = NextRequestBlock; 03379 Request[ index ].Result = S_OK; 03380 Request[ index ].Status = RIO_REQUEST_COMPLETED; 03381 Request[ index ].Who = this; 03382 03383 PlayThreadMutexUnlock( "renxbl4" ); 03384 SetBufferStatus( index, BUFFERFULL ); 03385 } //fim do else do if( bufferStream->readBlock( Request[ inde... 03386 } 03387 else //else do if( useCache ) 03388 { 03389 #ifdef RIO_DEBUG2 03390 RioErr << "[ReadNextBlock] Não uso cache. " 03391 << "Pedindo bloco " << NextRequestBlock 03392 << " unicast." << endl; 03393 #endif 03394 03395 status = ReadBlock( index, NextRequestBlock, UNICASTTRAFFIC, 03396 my_address, my_port ); 03397 } // fim do else do if( useCache ) 03398 03399 NextRequestBlock++; 03400 } 03401 else // else do if( NextRequestBlock < TotalBlocks ) 03402 { 03403 status = false; 03404 } 03405 03406 return( status ); 03407 }
bool CRioMMVideo::readSettings | ( | void | ) | [private] |
Definition at line 3923 of file RioMMVideo.cpp.
03924 { 03925 ConfigData config; 03926 bool ok1 = false, 03927 ok2 = false; 03928 QString temp, opt_value; 03929 QStringList keys; 03930 03931 config.readRioMMClientSettings(); 03932 opt_value = config.getRioMMVVersion(); 03933 if( opt_value != QString::null ) 03934 { 03935 //Se a versao do arquivo riorc for diferente de 03936 //RIORC_RIOMMVIDEO_VERSION, seus dados serão ignorados e os valores 03937 //defaults serão escritos no mesmo através da função 03938 //writeDefaultSettings assim que esta função retornar false. 03939 if( opt_value == RIORC_RIOMMVIDEO_VERSION ) 03940 { 03941 ok1 = true; 03942 03943 #ifndef RIO_EMUL 03944 opt_value = config.getRioMMVMakelog(); //default value: "true" 03945 if( opt_value == "false" ) 03946 makeLog = false; 03947 else 03948 makeLog = true; 03949 #else 03950 // Não deve ser gerado log de comportamento em modo Emulação 03951 makeLog = false; 03952 #endif 03953 03954 player = config.getRioMMVPlayer(); 03955 if( player != QString::null ) 03956 { 03957 ok2 = true; 03958 temp = config.getRioMMVMPlayerBinary(); 03959 if( playerCmdLine ) 03960 delete playerCmdLine; 03961 playerCmdLine = new QStringList(); 03962 playerCmdLine->append( temp ); 03963 03964 #ifndef RIO_EMUL 03965 if( HasSubTitle ) 03966 *playerCmdLine += QStringList::split( " ", 03967 config.getRioMMVMPlayerSubtitle() ); 03968 #endif 03969 03970 if( wId != 0 ) 03971 { 03972 *playerCmdLine += QStringList::split( " ", 03973 config.getRioMMVMPlayerEmbeded() ); 03974 } 03975 03976 *playerCmdLine += QStringList::split( " ", 03977 config.getRioMMVMPlayerArguments() ); 03978 } 03979 } 03980 } 03981 03982 return( ok1 && ok2 ); 03983 }
void CRioMMVideo::SetNextRequestBlock | ( | int | block | ) |
Definition at line 4240 of file RioMMVideo.cpp.
04241 { 04242 NextRequestBlock = block; 04243 }
void CRioMMVideo::SetTarget | ( | int | target | ) |
Definition at line 4235 of file RioMMVideo.cpp.
void CRioMMVideo::SetWID | ( | int | windowId | ) |
Definition at line 3892 of file RioMMVideo.cpp.
03893 { 03894 wId = windowId; 03895 }
void CRioMMVideo::StartPlayer | ( | void | ) | [protected] |
Este metodo abre o mplayer e seta as saidas padroes para /dev/null.
Definition at line 3460 of file RioMMVideo.cpp.
03461 { 03462 setbuffer( stdin, pipe_buffer, (size_t)MaxPipeDataSize ); 03463 // create pipe to send data to player 03464 if( pipe( pipe_player ) < 0 ) 03465 { 03466 Rioperror("pipe(). Failed to create pipe to player."); 03467 return; 03468 } 03469 03470 // associate pipe input to stdin 03471 if( dup2( pipe_player[0], 0 ) == -1 ) 03472 { 03473 Rioperror("dup2(). Failed to associate pipe to stdin."); 03474 return; 03475 } 03476 setbuffer( stdin, pipe_buffer, (size_t)MaxPipeDataSize ); 03477 03478 // start program mpeg player 03479 if( (playerPID = fork()) != 0 ) 03480 { 03481 if( playerPID < 0 ) 03482 { 03483 Rioperror("fork(). Failed to fork process."); 03484 return; 03485 } 03486 } 03487 else 03488 { 03489 #ifndef RIO_DEBUG2 03490 int null_file; 03491 03492 // redirect stdout and stderr from player to /dev/null 03493 null_file = open( "/dev/null", O_WRONLY ); 03494 if( null_file != -1 ) 03495 { 03496 dup2( null_file, 1 ); 03497 dup2( null_file, 2 ); 03498 } 03499 #endif 03500 03501 int argc = 0; 03502 char **argv; 03503 QString title(MMObjectName); 03504 QString wId_str; 03505 03506 argv=(char**)malloc(sizeof(char*)*(playerCmdLine->count() + 1)); 03507 wId_str.sprintf("%d",wId); 03508 for( QStringList::Iterator it=playerCmdLine->begin(); 03509 it != playerCmdLine->end(); 03510 it++ 03511 ) 03512 { 03513 (*it).replace( "%w", wId_str ); 03514 (*it).replace( "%s", subTitle->GetLocalFilename() ); 03515 (*it).replace( "%t", title.section('/',-1) ); 03516 argv[ argc++ ] = strdup( (*it).latin1() ); 03517 } 03518 03519 //Pra tese: valgrind está acusando erro aqui: 03520 //Invalid read of size 4...Address 0x52BFE5D0 is not stack'd, malloc'd 03521 //or (recently) free'd. 03522 //Ver o que isto significa! 03523 argv[ argc++ ] = NULL; 03524 if( execvp( argv[ 0 ], argv ) < 0 ) 03525 { 03526 Rioperror( "execvp(): Failed to execute mpeg player" ); 03527 exit( 1 ); 03528 } 03529 } //fim do else do if( (playerPID = fork()) != 0 ) 03530 }
void CRioMMVideo::Stop | ( | void | ) | [virtual] |
Stop finaliza a execução do vídeo e mata a PlayThread em execução.
Implements CRioMMObject.
Definition at line 1037 of file RioMMVideo.cpp.
01038 { 01039 bool inPause = Paused; 01040 01041 #ifdef RIO_EMUL 01042 Stopped = true; 01043 #endif 01044 01045 #ifdef RIO_DEBUG2 01046 RioErr << "[RioMMVideo] Entrei na stop..." << endl; 01047 #endif 01048 01049 if( PlayThreadID != 0 ) 01050 { 01051 if( pthread_cancel( PlayThreadID ) != 0 ) 01052 { 01053 #ifdef RIO_DEBUG2 01054 RioErr << "Stop - failed to cancel thread " << endl; 01055 #endif 01056 } 01057 else 01058 { 01059 #ifdef RIO_DEBUG2 01060 RioErr << "Stop - cancel thread OK " << endl; 01061 #endif 01062 } 01063 01064 if( Paused ) 01065 { 01066 Paused = false; 01067 PlayPauseMutexUnlock( "Stop1" ); 01068 } 01069 } 01070 01071 if( connectPI ) 01072 { 01073 if( group_block != -1 ) 01074 group_block = -1; 01075 01076 //Se o cliente estiver em pausa então ele está na lista de inativos da 01077 //PL, logo não deve enviar ACTION_STOP neste momento pois a PL nada fará 01078 //de útil com esta mensagem. 01079 if( !inPause ) 01080 { 01081 MulticastMutexLock( "Stop2" ); 01082 01083 #ifdef RIO_DEBUG2 01084 RioErr << "Enviando ACTION_STOP pra PL." << endl; 01085 #endif 01086 01087 CommMultiStream->sendMoveMsg( PID, ACTION_STOP ); 01088 01089 #ifdef RIO_DEBUG2 01090 RioErr << "[RioMMVideo] Stop: Waiting Condition" << endl; 01091 #endif 01092 01093 MulticastWaitCondition( "Stop2" ); 01094 MulticastMutexUnlock( "Stop2" ); 01095 } // fim do if( !inPause ) 01096 } // fim do if( connectPI ) 01097 01098 fullBuffers = 0; 01099 NextRequestBlock = 0; 01100 PlayBuffer = 0; 01101 PlayThreadID = 0; 01102 Paused = false; 01103 target = INT_MAX; 01104 PrefetchMutexUnlock( "Stop3" ); 01105 01106 //Como a acao sendo executada eh um stop, o cliente mantera em memoria os 01107 //blocos pendentes ate que volte a exibir o video e venha a chamar a 01108 //FreeBlock. Para minimizar este uso de memoria chamamos a FreePendentBlocks 01109 //abaixo. 01110 01111 #ifdef RIO_DEBUG2 01112 int freedPendentsSize = FreePendentBlocks( useCache, nBuffers ); 01113 RioErr << "[RioMMVideo] Stop - FreePendentBlocks liberou " 01114 << freedPendentsSize << " bytes de blocos pendentes." << endl; 01115 #else 01116 FreePendentBlocks( useCache, nBuffers ); 01117 #endif 01118 01119 CRioMMObject::Stop(); 01120 }
void CRioMMVideo::Stream_Control | ( | string | msg = "" |
) |
Definition at line 3414 of file RioMMVideo.cpp.
03415 { 03416 #ifdef RIO_DEBUG2 03417 RioErr << "[Stream_Control] " << msg << endl; 03418 #endif 03419 03420 if( patching ) 03421 { 03422 patching = false; 03423 03424 #ifdef RIO_EMUL 03425 //Send message to copy to log file 03426 multicast = -1; 03427 if( connectPI ) 03428 CommMultiStream->sendFluxoMsg( PID, -1/*indica patching = false*/, 03429 multicast ); 03430 #endif 03431 03432 #ifdef RIO_DEBUG2 03433 RioErr << "[RioMMVideo] Cliente " << PID << " saiu do patching " 03434 << endl; 03435 #endif 03436 } 03437 else // if( patching == -1 ) 03438 { 03439 patching = true; 03440 03441 #ifdef RIO_EMUL 03442 //Send message to copy to log file 03443 multicast = -1; 03444 03445 if( connectPI ) 03446 CommMultiStream->sendFluxoMsg( PID, 1/*indica que patching = true*/, 03447 multicast ); 03448 #endif 03449 03450 #ifdef RIO_DEBUG2 03451 RioErr << "[RioMMVideo] Cliente " << PID << " entrou no patching " 03452 << endl; 03453 #endif 03454 } 03455 }
bool CRioMMVideo::thereAreFragments | ( | RioBlock | block | ) |
thereAreFragments verifica se existem fragmentos para o bloco fornecido no parametro block.
block | Bloco a ser pesquisado se já existem fragmentos para ele. |
Definition at line 3887 of file RioMMVideo.cpp.
03888 { 03889 return( Object.thereAreFragments( block ) ); 03890 }
bool CRioMMVideo::WaitBlocks | ( | ) | [protected] |
WaitBlocks aguarda a chegada dos blocos solicitados de acordo com o contexto do cliente.
Se for um cliente conectado à PL e for líder, WaitBlocks chama Leader_WaitMulticastBlocks; caso seja um cliente conectado à PL mas não líder e não estiver em patching, WaitBlocks chama WaitMulticastBlocks. Se cliente estiver conectado à PL mas estiver em patching, CallFreeBlock é chamada se o bloco não estiver em disco. O mesmo acontece para o cliente que não estiver conectado à PL. Nota: WaitBlocks só é chamada na PlayThread().
Definition at line 2066 of file RioMMVideo.cpp.
02067 { 02068 struct timeval now; 02069 struct timespec timeout; 02070 02071 PrefetchMutexLock( "wtblk1" ); 02072 02073 //Assume-se que uma vez conectao ao PL o cliente usa cache, portanto foram 02074 //removidos todos os if( useCache ) abaixo. 02075 if( connectPI ) 02076 { 02077 if( first ) 02078 { 02079 if( (signed) NextRequestBlock == group_block ) 02080 req_block = NextRequestBlock - ( nBuffers - 1 ); 02081 else 02082 req_block = NextRequestBlock - nBuffers; 02083 02084 PlayBuffer = ( req_block % nBuffers ); 02085 Request[ PlayBuffer ].Block = req_block; 02086 02087 #ifdef RIO_DEBUG2 02088 RioErr << "[WaitBlocks] PlayBuffer atualizado para " 02089 << PlayBuffer << endl; 02090 #endif 02091 02092 gettimeofday( &now, NULL ); 02093 timeout.tv_sec = now.tv_sec + 1; 02094 timeout.tv_nsec = now.tv_usec * 1000; 02095 02096 PlayThreadWaitCondition( &timeout, "wtblk2" ); 02097 PlayThreadMutexUnlock( "wtblk2" ); 02098 02099 #ifdef RIO_DEBUG2 02100 RioErr << "WaitBlocks - verificando chegada de bloco: " 02101 << req_block 02102 << endl; 02103 #endif 02104 02105 if( !bufferStream->exist( req_block ) ) 02106 { 02107 #ifdef RIO_DEBUG2 02108 RioErr << "WaitBlocks - playbuffer: " << PlayBuffer 02109 << " vazio. Chamando Leader_WaitMulticastBlocks" 02110 << endl; 02111 #endif 02112 02113 //A Leader_WaitMulticastBlocks também checa se o bloco 02114 //req_block está na cache, mas esta verificação precisa 02115 //estar aqui por causa do else abaixo. 02116 if( Leader_WaitMulticastBlocks() == false ) 02117 { 02118 PrefetchMutexUnlock( "wtblk3" ); 02119 return( false ); 02120 } 02121 } 02122 else //else do if( !bufferStream->exist( req_block ) ) 02123 { 02124 if( bufferStream->readBlock( 02125 Request[ PlayBuffer ].Block, 02126 (unsigned char *) Request[ PlayBuffer ].Buffer ) 02127 == 0 02128 ) 02129 { 02130 #ifdef RIO_DEBUG2 02131 RioErr << "WaitBlocks (1) req_block " << req_block 02132 << " disponível. Gravando no PlayOutBuffer " 02133 << PlayBuffer << endl; 02134 #endif 02135 SetBufferStatus( PlayBuffer, BUFFERFULL ); 02136 } 02137 } 02138 } 02139 else //else do if( first ) 02140 { 02141 //verificando bloco do patching 02142 if( patching ) 02143 { 02144 gettimeofday( &now, NULL ); 02145 timeout.tv_sec = now.tv_sec + 1; 02146 timeout.tv_nsec = now.tv_usec * 1000; 02147 02148 PlayThreadWaitCondition( &timeout, "wtblk4" ); 02149 PlayThreadMutexUnlock( "wtblk4" ); 02150 02151 //Se useCache == true e nao consegui pegar no buffer, 02152 //tento recuperar os fragmentos chamando a 02153 //CallFreeBlock. 02154 if( bufferStream->readBlock( Request[PlayBuffer].Block, 02155 (unsigned char *) Request[PlayBuffer].Buffer ) != 0 02156 ) 02157 { 02158 if( CallFreeBlock( PlayBuffer ) == false ) 02159 { 02160 #ifdef RIO_DEBUG2 02161 RioErr << "[WaitBlocks] 1 - Bloco esperado (" 02162 << Request[PlayBuffer].Block 02163 << ") nao recuperado " << endl; 02164 #endif 02165 } 02166 } 02167 else 02168 { 02169 #ifdef RIO_DEBUG2 02170 RioErr << "[WaitBlocks] Bloco " 02171 << Request[PlayBuffer].Block 02172 << " existe na cache e foi gravado no " 02173 << "PlayOutBuffer " << PlayBuffer 02174 << endl; 02175 #endif 02176 02177 SetBufferStatus( PlayBuffer, BUFFERFULL ); 02178 } 02179 } // abaixo o else do if( patching ) 02180 else if( WaitMulticastBlocks() == false ) 02181 { 02182 //verificando bloco multicast 02183 PrefetchMutexUnlock( "wtblk5" ); 02184 return( false ); 02185 } // fim do else if( WaitMulticastBlocks() == false ) 02186 } //fim do else do if( first ) 02187 } 02188 else //else do if( connectPI ) 02189 { 02190 #ifdef RIO_DEBUG2 02191 RioErr << "WaitBlocks - esperando sinal " << endl; 02192 #endif 02193 gettimeofday( &now, NULL ); 02194 02195 if( WaitingPrefetch ) 02196 { 02197 #ifdef RIO_DEBUG2 02198 RioErr << "[WaitBlocks] - WaitingPrefetch true.." << endl; 02199 #endif 02200 02201 if( ( now.tv_usec + RTT_window ) > 1000000 ) 02202 { 02203 timeout.tv_sec = now.tv_sec + (int)( RTT_window / 1000000 ); 02204 timeout.tv_nsec = ( now.tv_usec + ( RTT_window % 1000000 ) ) * 1000; 02205 } 02206 else 02207 { 02208 timeout.tv_sec = now.tv_sec; 02209 timeout.tv_nsec = ( now.tv_usec + RTT_window ) * 1000; 02210 } 02211 } 02212 else 02213 { 02214 #ifdef RIO_DEBUG2 02215 RioErr << "[WaitBlocks] - WaitingPrefetch false.." << endl; 02216 #endif 02217 02218 timeout.tv_sec = now.tv_sec + 1; 02219 timeout.tv_nsec = now.tv_usec * 1000; 02220 } 02221 02222 PlayThreadWaitCondition( &timeout, "wtblk6" ); 02223 PlayThreadMutexUnlock( "wtblk6" ); 02224 02225 #ifdef RIO_DEBUG2 02226 RioErr << "WaitBlocks - playbuffer: " << PlayBuffer << endl; 02227 #endif 02228 02229 for( unsigned int index = 0; index < nBuffers; index++ ) 02230 { 02231 if( useCache && ( GetBufferStatus( index ) == BUFFEREMPTY ) ) 02232 { 02233 if( bufferStream->readBlock( Request[ index ].Block, 02234 (unsigned char *) Request[ index ].Buffer ) == 0 02235 ) 02236 { 02237 #ifdef RIO_DEBUG2 02238 RioErr << "WaitBlocks: Gravando bloco " 02239 << Request[ index ].Block 02240 << " no PlayOutBuffer " << index << endl; 02241 #endif 02242 02243 SetBufferStatus( index, BUFFERFULL ); 02244 } 02245 else if( CallFreeBlock( index ) == false ) 02246 { 02247 #ifdef RIO_DEBUG2 02248 RioErr << "[WaitBlocks] 3 - Bloco esperado (" 02249 << Request[index].Block 02250 << ") nao recuperado " << endl; 02251 #endif 02252 } 02253 } 02254 else if( ( GetBufferStatus( index ) == BUFFEREMPTY ) && 02255 ( CallFreeBlock( index ) == false ) 02256 ) 02257 { 02258 #ifdef RIO_DEBUG2 02259 RioErr << "[WaitBlocks] 4 - Bloco esperado (" 02260 << Request[index].Block 02261 << ") nao recuperado " << endl; 02262 #endif 02263 } 02264 } 02265 } //fim do else do if( connectPI ) 02266 02267 PrefetchMutexUnlock( "wtblk1" ); 02268 02269 return( true ); 02270 }
void CRioMMVideo::WaitEndOfVideo | ( | void | ) |
WaitEndOfVideo aguarda que o mplayer seja finalizado por detecção de EOF (término do arquivo de vídeo).
Este método deve ser utilizado no momento de se mandar tocar o último bloco a fim de que a PlayThread aguarde o mplayer terminar a exibição do último bloco de vídeo antes de ser finalizada.
Definition at line 1226 of file RioMMVideo.cpp.
01227 { 01228 pthread_join( PlayThreadID, NULL ); 01229 PlayThreadID = 0; 01230 }
bool CRioMMVideo::WaitFullBuffer | ( | ) | [protected] |
WaitFullBuffer requisita o número de blocos suficiente para encher o buffer e espera até que os mesmos cheguem para, então, liberar o mutex da playthread, mas se os blocos demorarem muito (na WaitPrefetch), então a FreeBlock é chamada para os fragmentos recebidos e o cliente toca tais fragmentos dando continuidade à execução do vídeo.
Este método só é chamado na GoTo. O cliente esvazia o buffer e fica aguardando os blocos iniciais.
Definition at line 984 of file RioMMVideo.cpp.
00985 { 00986 #ifdef RIO_DEBUG2 00987 RioErr << "[RioMMVideo] Entrei na WaitFullBuffer..." << endl; 00988 #endif 00989 00990 PlayThreadMutexUnlock( "wtfubf1" ); 00991 if( Move_Prefetch() == false ) 00992 { 00993 #ifdef RIO_DEBUG2 00994 RioErr << "[RioMMVideo] Erro na Move_Prefetch. Saindo com erro da " 00995 << "WaitFullBuffer..." << endl; 00996 #endif 00997 00998 return( false ); 00999 } 01000 01001 //Como foi um jump, esperando servidor atualizar buffer 01002 if( WaitPrefetch() == false ) 01003 { 01004 #ifdef RIO_DEBUG2 01005 RioErr << "[RioMMVideo] Erro na WaitPrefetch. Saindo com erro da " 01006 << "WaitFullBuffer..." << endl; 01007 #endif 01008 01009 return( false ); 01010 } 01011 01012 #ifdef RIO_DEBUG2 01013 RioErr << "[RioMMVideo] Saindo da WaitFullBuffer..." << endl; 01014 #endif 01015 01016 return( true ); 01017 }
bool CRioMMVideo::WaitMulticastBlocks | ( | ) | [protected] |
WaitMulticastBlocks verifica se os blocos esperados se encontram na cache.
Caso positivo ela retorna imediatamente. Caso negativo ela aguarda os blocos chegarem por um determinado período. Este método só é chamado na WaitBlocks. Este método é executado por um membro de um grupo que pode virar líder. Esperando encher buffer...
Definition at line 2694 of file RioMMVideo.cpp.
02695 { 02696 bool empty_buffer = true; 02697 struct timeval now; 02698 struct timespec timeout; 02699 unsigned int i; 02700 unsigned int full = 0; 02701 unsigned int steps = 0; 02702 int expected_block; 02703 int wait_block; 02704 02705 wait_block = Request[PlayBuffer].Block; 02706 expected_block = wait_block; 02707 02708 while( empty_buffer ) 02709 { 02710 gettimeofday( &now, NULL ); 02711 timeout.tv_sec = now.tv_sec + 5; 02712 timeout.tv_nsec = now.tv_usec * 1000; 02713 02714 #ifdef RIO_DEBUG2 02715 RioErr << "WaitMulticastBlocks - wait_block " << expected_block << endl; 02716 #endif 02717 02718 for( i = 0; i < nBuffers; i++ ) 02719 { 02720 if( useCache && bufferStream->exist( i ) ) 02721 { 02722 #ifdef RIO_DEBUG2 02723 RioErr << "Bloco " << Request[ i ].Block << " ja existe na cache." << endl; 02724 #endif 02725 02726 full++; 02727 steps++; 02728 } // fim do if( useCache && bufferStream->exist(expected_block... 02729 } // fim do for( i = 0; i < nBuffers; i++ ) 02730 02731 //O if abaixo analisa o caso de já se ter em cache blocos suficientes 02732 //para encher o buffer ou se ele é líder. 02733 if( ( steps >= nBuffers ) || first ) 02734 { 02735 for( i = 0; i < nBuffers; i++ ) 02736 { 02737 if( useCache && bufferStream->exist( i ) ) 02738 { 02739 Request[ i ].Result = S_OK; 02740 Request[ i ].Status = RIO_REQUEST_COMPLETED; 02741 Request[ i ].Who = this; 02742 02743 #ifdef RIO_DEBUG2 02744 RioErr << "[WaitMulticastBlocks] Gravando bloco " 02745 << Request[ i ].Block << " no PlayOutBuffer " 02746 << i << endl; 02747 #endif 02748 02749 bufferStream->readBlock( Request[ i ].Block, 02750 (unsigned char *) Request[ i ].Buffer ); 02751 02752 PlayThreadMutexUnlock( "wtmtbl1" ); 02753 SetBufferStatus( i, BUFFERFULL ); 02754 } 02755 } 02756 02757 empty_buffer = false; 02758 /*if( GetFullBuffers() != 0 ) 02759 { 02760 PlayBuffer = wait_block % nBuffers; 02761 NextRequestBlock = wait_block + nBuffers; 02762 wait_block = -1; 02763 02764 #ifdef RIO_DEBUG2 02765 RioErr << "WaitMulticastBlocks - saindo. " 02766 << "Atualizando playbuffer: " << PlayBuffer 02767 << " NextRequestBlock: " << NextRequestBlock 02768 << endl; 02769 #endif 02770 }*/ 02771 } 02772 else //else do if( ( full > 0 && steps >= nBuffers ) || first ) 02773 { 02774 if( Paused ) 02775 { 02776 empty_buffer = false; 02777 PlayPauseMutexLock( "wtmtbl4" ); 02778 } 02779 else //else do if( Paused ) 02780 { 02781 PlayThreadWaitCondition( &timeout, "wtmtbl5" ); 02782 PlayThreadMutexUnlock( "wtmtbl5" ); 02783 02784 for( i = 0; i < nBuffers; i++ ) 02785 { 02786 //Coloquei este if aqui pois um dos blocos do 02787 //PlayOutBuffer pode ter chegado no 02788 //PlayThreadWaitCondition acima. 02789 if( BufferStatus[i] == BUFFEREMPTY ) 02790 { 02791 if( CallFreeBlock( i ) == false ) 02792 { 02793 #ifdef RIO_DEBUG2 02794 RioErr << "[WaitBlocks] 5 - Bloco esperado (" 02795 << Request[i].Block 02796 << ") nao recuperado." << endl; 02797 #endif 02798 } 02799 } 02800 02801 steps++; 02802 } // fim do for( i = 0; i < nBuffers; i++ ) 02803 02804 if( ( full == 0 ) && 02805 ( steps >= ( nBuffers * nBuffers ) ) 02806 ) 02807 return( false ); 02808 } //fim do else do if( Paused ) 02809 } //fim do else do if( ( full > 0 && steps >= nBuffers ) || first ) 02810 } //fim do while( empty_buffer ) 02811 02812 return( true ); 02813 }
bool CRioMMVideo::WaitPrefetch | ( | void | ) | [virtual] |
WaitPrefetch apenas aguarda os blocos solicitados pela Prefetch.
Nesta funcao, quando ocorre um timeout, ele simplesmente ignora o que não chegou e inicia a exibição, mesmo sem o buffer completo. Isto não é um erro, mas decidiu-se que nao valia a pena aumentar o startup delay do cliente para encher completamente o buffer. Nota: WaitPrefetch() só é chamada na WaitFullBuffer e no início da PlayThread() como fruto de chamada a Prefetch() ou Move_Prefetch().
Reimplemented from CRioMMObject.
Definition at line 267 of file RioMMVideo.cpp.
00268 { 00269 #ifdef RIO_DEBUG2 00270 RioErr << "[RioMMVideo] Entrei na WaitPrefetch " << endl; 00271 #endif 00272 00273 struct timespec timer; 00274 struct timespec timeout; 00275 int rc = 0; 00276 int nBlocks = 0; 00277 bool status = true; 00278 bool wait_again = true; 00279 unsigned int i; 00280 struct timeval now; 00281 CRioStream Stream; 00282 00283 if( riomminterface ) 00284 { 00285 //Enviando evento pra interface exibir uma mensagem de espera 00286 QCustomEvent *event = new QCustomEvent( QEvent::User + 10 ); 00287 QApplication::postEvent( (QObject*)riomminterface, event ); 00288 } 00289 00290 RTT_average = 0; 00291 00292 //tempo em microsegundos ( 0.5 segundos ) por bloco 00293 RTT_window = 2 * INITIAL_RTT * nBuffers; 00294 00295 gettimeofday( &now, 0 ); 00296 00297 if( ( now.tv_usec + RTT_window ) > 1000000 ) 00298 { 00299 timer.tv_sec = now.tv_sec + (int)( RTT_window / 1000000 ); 00300 timer.tv_nsec = ( now.tv_usec + ( RTT_window % 1000000 ) ) * 1000; 00301 } 00302 else 00303 { 00304 timer.tv_sec = now.tv_sec; 00305 timer.tv_nsec = ( now.tv_usec + RTT_window ) * 1000; 00306 } 00307 00308 #ifdef RIO_DEBUG2 00309 RioErr << "WaitPrefetch - valor inicial de RTT_window: " 00310 << RTT_window << endl; 00311 00312 RioErr << "Primeiro timer calculado: " << timer.tv_sec 00313 << " sec " << timer.tv_nsec << " nanosec " << endl; 00314 #endif 00315 00316 do 00317 { 00318 WaitingPrefetch = false; 00319 00320 for( i = 0; i < nBuffers; i++ ) 00321 { 00322 if( BufferStatus[i] == BUFFEREMPTY ) 00323 WaitingPrefetch = true; 00324 else // neste caso, BufferStatus[i] == BUFFERFULL 00325 nBlocks++; 00326 } 00327 00328 #ifdef RIO_DEBUG2 00329 RioErr << "[WaitPrefetch] WaitingPrefetch = " << WaitingPrefetch 00330 << endl; 00331 #endif 00332 00333 if( WaitingPrefetch ) 00334 { 00335 rc = 0; 00336 00337 #ifdef RIO_DEBUG2 00338 RioErr << "[WaitPrefetch] Esperando timeout ... " 00339 << timer.tv_sec - now.tv_sec << "s " 00340 << timer.tv_nsec-(now.tv_usec*1000) << "ns" << endl; 00341 #endif 00342 00343 //Cliente travando aqui só será liberado após chegada do bloco e 00344 //chamada ao método SetBufferStatus. 00345 rc = PlayThreadWaitCondition( &timer, "wapr1" ); 00346 PlayThreadMutexUnlock( "wapr1" ); 00347 00348 if( rc == ETIMEDOUT ) 00349 { 00350 #ifdef RIO_DEBUG2 00351 RioErr << "[WaitPrefetch] Tempo expirou " << endl; 00352 #endif 00353 00354 // Se nao esperei o suficiente, espero mais uma vez 00355 if( wait_again ) 00356 { 00357 //calculando novo timer 00358 gettimeofday( &now, 0 ); 00359 00360 if( ( now.tv_usec + RTT_window ) > 1000000 ) 00361 { 00362 timer.tv_sec = now.tv_sec + 00363 (int)( RTT_window/1000000 ); 00364 timer.tv_nsec = ( now.tv_usec + 00365 ( RTT_window % 1000000 ) ) * 1000; 00366 } 00367 else 00368 { 00369 timer.tv_sec = now.tv_sec; 00370 timer.tv_nsec = ( now.tv_usec + RTT_window ) * 1000; 00371 } 00372 00373 #ifdef RIO_DEBUG2 00374 RioErr << "WaitPrefetch - atualizando timer: " 00375 << timer.tv_sec << " sec " << timer.tv_nsec 00376 << " nano " << endl; 00377 #endif 00378 00379 wait_again = false; 00380 } 00381 else // else do if( wait_again ) 00382 { 00383 #ifdef RIO_DEBUG2 00384 RioErr << "RioMMVideo - Verificando se ja recebeu algum " 00385 << "fragmento " << endl; 00386 #endif 00387 00388 for( i = 0; i < nBuffers; i ++ ) 00389 { 00390 if( BufferStatus[i] == BUFFEREMPTY ) 00391 { 00392 rc = FreeBlock( i ); 00393 if( rc != 0 ) 00394 { 00395 nBlocks++; 00396 00397 #ifdef RIO_DEBUG2 00398 RioErr << "WaitPrefetch - freeblock OK. " 00399 << "Esperando timeout. Bloco " 00400 << Request[ i ].Block << " Valor " 00401 << "retornado do bloco: " << rc 00402 << endl; 00403 #endif 00404 00405 gettimeofday( &now, NULL ); 00406 timeout.tv_sec = now.tv_sec + 1; 00407 timeout.tv_nsec = now.tv_usec * 1000; 00408 00409 //Aguardando os blocos recuperados pela 00410 //FreeBlock serem gravados no PlayOutBuffer 00411 //(CallBack será chamada para tal) 00412 PlayThreadWaitCondition( &timeout, 00413 "wapr2" ); 00414 PlayThreadMutexUnlock( "wapr2" ); 00415 00416 if( BufferStatus[i] != BUFFEREMPTY && 00417 useCache ) 00418 { 00419 Request[ i ].Size = rc; 00420 00421 #ifdef RIO_DEBUG2 00422 RioErr << "Tamanho do bloco recuperado: " 00423 << Request[ i ].Size << ", pos " 00424 << i << endl; 00425 #endif 00426 00427 bufferStream->readBlock( 00428 Request[i].Block, 00429 (unsigned char *) Request[ i ].Buffer 00430 ); 00431 } 00432 } 00433 #ifdef RIO_DEBUG2 00434 else //else do if ( rc != 0) (FreeBlock Not OK) 00435 { 00436 RioErr << "WaitPrefetch - Bloco " 00437 << Request[ i ].Block 00438 << " nao encontrado " << endl; 00439 }//fim do else do if ( rc != 0) 00440 #endif 00441 }//end-bufferstatus 00442 else 00443 { 00444 #ifdef RIO_DEBUG2 00445 RioErr << "Bloco " << Request[ i ].Block 00446 << " já chegou." << endl; 00447 #endif 00448 00449 nBlocks++; 00450 } 00451 }//end-for 00452 00453 if( nBlocks == 0 ) 00454 { 00455 #ifdef RIO_DEBUG_EMUL 00456 RioErr << "Finalizando cliente por timeout " << endl; 00457 #endif 00458 00459 #ifdef RIO_EMUL 00460 m_log << "Finalizando cliente por timeout " 00461 << endl; 00462 #endif 00463 00464 status = false; 00465 } // fim do if( nBlocks == 0 ) 00466 00467 #ifdef RIO_DEBUG2 00468 RioErr << "WaitingPrefetch = false " << endl; 00469 #endif 00470 00471 WaitingPrefetch = false; 00472 00473 } //fim do else do if( wait_again ) 00474 }// fim do if( rc == ETIMEDOUT ) 00475 #ifdef RIO_DEBUG2 00476 else if( rc != 0 ) 00477 { 00478 RioErr << "Erro no pthread_cond_timedwait: " 00479 << strerror( errno ) << endl; 00480 RioErr << "Timer values: " << timer.tv_sec << ":" 00481 << timer.tv_nsec << endl; 00482 } 00483 #endif 00484 } // fim do if( WaitingPrefetch ) 00485 }while( WaitingPrefetch ); 00486 00487 PlayThreadMutexUnlock( "wapr3" ); 00488 00489 #ifdef RIO_DEBUG2 00490 RioErr << "[RioMMVideo] Saindo da WaitPrefetch" << endl; 00491 #endif 00492 00493 if( riomminterface ) 00494 { 00495 //Enviando evento pra interface ocultar a mensagem de espera 00496 QCustomEvent *event = new QCustomEvent( QEvent::User + 11 ); 00497 QApplication::postEvent( (QObject*)riomminterface, event ); 00498 } 00499 00500 #ifndef RIO_EMUL 00501 for( unsigned int i = 0; i < nMedias; i++ ) 00502 Media[i]->WaitPrefetch(); 00503 #endif 00504 00505 return( status ); 00506 }
void CRioMMVideo::writeDefaultSettings | ( | void | ) | [private] |
Definition at line 3903 of file RioMMVideo.cpp.
03904 { 03905 ConfigData config; 03906 config.writeDefaultRioMMVideoSettings(); 03907 config.readRioMMClientSettings(); 03908 03909 player = DEFAULT_PLAYER; 03910 playerCmdLine = new QStringList( config.getRioMMVMPlayerBinary() ); 03911 if( wId != 0 ) 03912 { 03913 *playerCmdLine += QStringList::split( " ", config.getRioMMVMPlayerEmbeded() ); 03914 } 03915 *playerCmdLine += QStringList::split( " ", config.getRioMMVMPlayerArguments() ); 03916 }
RioCallBackTransport CRioMMVideo::callback_transport [protected] |
Definition at line 112 of file RioMMVideo.h.
CommunicationStream* CRioMMVideo::CommMultiStream [protected] |
Definition at line 111 of file RioMMVideo.h.
bool CRioMMVideo::connectPI [protected] |
Definition at line 92 of file RioMMVideo.h.
bool CRioMMVideo::first |
Definition at line 235 of file RioMMVideo.h.
bool CRioMMVideo::HasSubTitle [protected] |
Definition at line 102 of file RioMMVideo.h.
pthread_mutex_t CRioMMVideo::log_mutex [private] |
Definition at line 70 of file RioMMVideo.h.
QString CRioMMVideo::logAction [private] |
Definition at line 69 of file RioMMVideo.h.
QString CRioMMVideo::logAppend [private] |
Definition at line 68 of file RioMMVideo.h.
QString CRioMMVideo::logData [private] |
Definition at line 67 of file RioMMVideo.h.
bool CRioMMVideo::makeLog [private] |
Definition at line 66 of file RioMMVideo.h.
pthread_cond_t CRioMMVideo::multicastCondition |
Definition at line 243 of file RioMMVideo.h.
pthread_mutex_t CRioMMVideo::multicastMutex |
Definition at line 242 of file RioMMVideo.h.
Definition at line 237 of file RioMMVideo.h.
Definition at line 238 of file RioMMVideo.h.
RioBlock CRioMMVideo::NextRequestBlock [protected] |
Definition at line 83 of file RioMMVideo.h.
bool CRioMMVideo::patching [protected] |
Definition at line 90 of file RioMMVideo.h.
bool CRioMMVideo::Paused [protected] |
Definition at line 88 of file RioMMVideo.h.
int CRioMMVideo::PID [protected] |
Definition at line 93 of file RioMMVideo.h.
QString CRioMMVideo::piHost [protected] |
Definition at line 98 of file RioMMVideo.h.
char CRioMMVideo::pipe_buffer[MaxPipeDataSize] [protected] |
Definition at line 80 of file RioMMVideo.h.
int CRioMMVideo::pipe_player[2] [protected] |
Definition at line 78 of file RioMMVideo.h.
unsigned int CRioMMVideo::PlayBuffer [protected] |
Definition at line 82 of file RioMMVideo.h.
QString CRioMMVideo::player [protected] |
Definition at line 108 of file RioMMVideo.h.
QStringList* CRioMMVideo::playerCmdLine [protected] |
Informa se cliente está em patching.
Definition at line 91 of file RioMMVideo.h.
pid_t CRioMMVideo::playerPID [protected] |
Definition at line 81 of file RioMMVideo.h.
pthread_mutex_t CRioMMVideo::PlayPauseMutex [protected] |
Definition at line 100 of file RioMMVideo.h.
pthread_t CRioMMVideo::PlayThreadID [protected] |
Definition at line 87 of file RioMMVideo.h.
pthread_mutex_t CRioMMVideo::PrefetchMutex [protected] |
Definition at line 101 of file RioMMVideo.h.
QPtrStack<PlayThreadEvent> CRioMMVideo::PTEventStack [private] |
Definition at line 74 of file RioMMVideo.h.
bool CRioMMVideo::ReadBlockStatus [protected] |
Definition at line 131 of file RioMMVideo.h.
int CRioMMVideo::ReadFrom [protected] |
Definition at line 94 of file RioMMVideo.h.
unsigned int CRioMMVideo::req_block [protected] |
Definition at line 89 of file RioMMVideo.h.
RioMMExplorer* CRioMMVideo::rioMMExplorer [protected] |
Definition at line 113 of file RioMMVideo.h.
RioMMInterface* CRioMMVideo::riomminterface [private] |
Definition at line 65 of file RioMMVideo.h.
bool CRioMMVideo::signal |
Definition at line 236 of file RioMMVideo.h.
Reimplemented from CRioMMObject.
Definition at line 241 of file RioMMVideo.h.
RioFile* CRioMMVideo::subTitle [protected] |
Definition at line 109 of file RioMMVideo.h.
bool CRioMMVideo::syncOn |
Definition at line 240 of file RioMMVideo.h.
int CRioMMVideo::target [protected] |
Definition at line 84 of file RioMMVideo.h.
CRioTimer CRioMMVideo::timer [protected] |
Definition at line 110 of file RioMMVideo.h.
bool CRioMMVideo::useCache [protected] |
Definition at line 103 of file RioMMVideo.h.
QString CRioMMVideo::User [protected] |
Definition at line 104 of file RioMMVideo.h.
Definition at line 234 of file RioMMVideo.h.
bool CRioMMVideo::WaitingPrefetch [protected] |
Definition at line 99 of file RioMMVideo.h.
int CRioMMVideo::wId |
Definition at line 239 of file RioMMVideo.h.