CRioMMVideo Class Reference

#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
RioFilesubTitle
CRioTimer timer
CommunicationStreamCommMultiStream
RioCallBackTransport callback_transport
RioMMExplorerrioMMExplorer
bool ReadBlockStatus

Private Member Functions

bool readSettings (void)
void writeDefaultSettings (void)
bool DealPendentEvents ()

Private Attributes

RioMMInterfaceriomminterface
bool makeLog
QString logData
QString logAppend
QString logAction
pthread_mutex_t log_mutex
QPtrStack< PlayThreadEventPTEventStack

Detailed Description

Definition at line 60 of file RioMMVideo.h.


Constructor & Destructor Documentation

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.

Parameters:
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 }


Member Function Documentation

void CRioMMVideo::appendLog ( QString  text  ) 

Definition at line 4033 of file RioMMVideo.cpp.

04034 {
04035     if( makeLog == false )
04036         return;
04037 
04038     pthread_mutex_lock( &log_mutex );
04039     logAppend += text;
04040     pthread_mutex_unlock( &log_mutex );
04041 }

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).

Parameters:
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.

Parameters:
PlayBuffer indica o bloco cujos fragmentos se quer liberar para exibição imediata.
Returns:
retorna true caso consiga liberar os fragmentos ou false caso os mesmos não esteja disponíveis.

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]

Implements CRioMMObject.

Definition at line 981 of file RioMMVideo.cpp.

00981 {}

void CRioMMVideo::FastRewind ( void   )  [virtual]

Implements CRioMMObject.

Definition at line 982 of file RioMMVideo.cpp.

00982 {}

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.

Parameters:
PlayBuffer é a posicao do vetor Request que aponta para o bloco cujos fragmentos, caso existam, devem ser liberados.
Returns:
retorna o tamanho em bytes do bloco recuperado.

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.

Returns:
retorna o valor do membro CurrentBlock.

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.

Returns:
retorna o valor do membro NextRequestBlock.

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.

Returns:
retorna o valor do membro TotalBlocks.

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.

Parameters:
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.

Returns:
retorna 1 caso não consiga criar a startReceiveThread da CommMultiStream ou não consiga abrir o socket com a CommMultiStream e retorna 0 caso contrário.

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, &copy_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  ) 

Definition at line 4043 of file RioMMVideo.cpp.

04044 {
04045     if( makeLog == false )
04046         return;
04047 
04048     pthread_mutex_lock( &log_mutex );
04049     logData += text;
04050     pthread_mutex_unlock( &log_mutex );
04051 }

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.

Returns:
true se cliente for líder ou sublíder e false caso contrário.

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.

Returns:
true caso algum bloco esteja disponível para ser tocado e false caso contrário.

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().

Returns:
retorna true se a chamada a ReadNextBlock retornar true (ou se ReadNextBlock não for chamada) e false caso contrário.

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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

04236 {
04237     this->target = target;
04238 }

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.

Parameters:
block Bloco a ser pesquisado se já existem fragmentos para ele.
Returns:
true caso encontre fragmentos para o bloco e false caso contrário.

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().

Returns:
retorna true se Leader_WaitMulticastBlocks ou WaitMulticastBlocks falharem ou false caso contrário.

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.

Returns:
retorna false caso WaitPrefetch() ou Move_Prefetch() retornem false e retorna true caso contrário.

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().

Returns:
true se há algum bloco, ainda que fragmentado, disponível para ser tocado e false caso contrário.

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 }


Field Documentation

Definition at line 112 of file RioMMVideo.h.

Definition at line 111 of file RioMMVideo.h.

bool CRioMMVideo::connectPI [protected]

Definition at line 92 of file RioMMVideo.h.

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.

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.

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.

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.

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.

Definition at line 113 of file RioMMVideo.h.

Definition at line 65 of file RioMMVideo.h.

Definition at line 236 of file RioMMVideo.h.

Reimplemented from CRioMMObject.

Definition at line 241 of file RioMMVideo.h.

Definition at line 109 of file RioMMVideo.h.

Definition at line 240 of file RioMMVideo.h.

int CRioMMVideo::target [protected]

Definition at line 84 of file RioMMVideo.h.

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.

Definition at line 239 of file RioMMVideo.h.


The documentation for this class was generated from the following files:
Generated on Wed Jul 4 16:03:32 2012 for RIO by  doxygen 1.6.3