void CMediaPlayer::PlayFunc(ThreadParam *pParam) { CMediaSource *pSource; CMediaDecoder *pDecoder; CMediaRenderer *pRenderer; int nTime; bool bDrop; int nReadSize, nSrcSize, nDecSize, nRndSize; unsigned char *pSrcFrame, *pDecFrame, *pRndFrame; pSource = pParam->pSource; pDecoder = pParam->pDecoder; pRenderer = pParam->pRenderer; nTime = 0; bDrop = false; if (pDecoder != NULL) { nReadSize = pDecoder->GetInputSize(); pSrcFrame = new unsigned char[nReadSize]; nDecSize = pDecoder->GetOutputSize(); pDecFrame = new unsigned char[nDecSize]; pRndFrame = pDecFrame; } else { nReadSize = 0x1000; pSrcFrame = new unsigned char[nReadSize]; pDecFrame = NULL; pRndFrame = pSrcFrame; } for (;;) { m_pSemaphore->Wait(); //when paused, this thread will be blocked here if (m_nState == STATE_STOP) { m_pSemaphore->Release(); break; } if (!pParam->bReferenceClock) if (nTime + 100 < m_pClock->GetTime()) //time stamp behind the clock too much bDrop = true; m_pMutex->Lock(); //only one thread can read data from media source nSrcSize = pSource->ReadData(pParam->nIndex, bDrop? NULL : pSrcFrame, nReadSize); //read a frame m_pMutex->Unlock(); if (nSrcSize == 0) //no more frame to render { pRenderer->Flush(true); m_pSemaphore->Release(); break; } nTime = pSource->GetOutputTime(pParam->nIndex); if (bDrop) //drop this frame bDrop = false; else { if (pDecoder != NULL) { if (pParam->type != RENDER_TYPE_SPDIF) nDecSize = pDecoder->Decode(pSrcFrame, nSrcSize, pDecFrame); else nDecSize = pDecoder->SPDIF(pSrcFrame, nSrcSize, pDecFrame); } else nDecSize = nSrcSize; nRndSize = nDecSize; if (!pParam->bReferenceClock) m_pClock->WaitFor(nTime); //wait until this frame can be rendered pRenderer->Write(pRndFrame, nRndSize); //render a frame if (pParam->bReferenceClock && nTime > 0) m_pClock->SetTime(nTime); //update clock } m_pSemaphore->Release(); } //while if (pParam->pDecoder) pParam->pDecoder->Flush(); delete[] pSrcFrame; delete[] pDecFrame; }