📄 mediaplayer.cpp
字号:
// MediaPlayer.cpp: implementation of the CMediaPlayer class.
//
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "MediaPlayer.h"
#include "Log.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//##ModelId=4753B7E9039C
CMediaPlayer::CMediaPlayer(TWriteFrameCB cb, HWND hDrawWnd)
{
m_pCBFunc = cb;
m_hWnd = hDrawWnd;
m_bStreaming = FALSE;
m_bEndStream = FALSE;
m_pAviReader = new CAviReader();
m_pVidDecTask = new CVideoDecoderTask();
m_pAudDecTask = new CAudioDecoderTask();
m_pAudioRender = new CAudioRender();
m_pVideoRender = new CVideoRender();
m_PlayState = NONE;
m_nCount = 0;
}
//##ModelId=4753B7E9039E
CMediaPlayer::~CMediaPlayer()
{
UnInit();
if( m_pAviReader )
delete m_pAviReader;
if( m_pVidDecTask )
delete m_pVidDecTask;
if( m_pAudDecTask )
delete m_pAudDecTask;
if( m_pAudioRender )
delete m_pAudioRender;
if ( m_pVideoRender )
delete m_pVideoRender;
LogMsg(LOG_INFO, HCLN, "Uninitialize MediaPlayer!");
}
//##ModelId=4753B7E903AE
BOOL CMediaPlayer::Init(char *lpszAviFileName)
{
int nChunk;
int nFrame;
avi_t *pAviHdr;
//open avi file
if( m_pAviReader->OpenAviFile(lpszAviFileName) < 0 )
return FALSE;
strcpy(m_szAviFileName, lpszAviFileName);
pAviHdr = m_pAviReader->m_pAviFile;
m_pAviReader->SetAviReaderPos(0);
m_nStartTime = GetTickCount();
nChunk = 1024 * pAviHdr->a_chans* 2;
nFrame = (int)(pAviHdr->fps * 1.0 + 0.5);
m_pVideoStream = new CSyncFifo(3 * pAviHdr->width * pAviHdr->height, 40, nFrame, 1, FALSE, FALSE);
m_pAudioStream = new CSyncFifo(nChunk, (3 * pAviHdr->a_rate / 1024),
(2 * pAviHdr->a_rate / 1024), 1, FALSE, FALSE);
//video decoder task initialize
m_pVidDecTask->SetParam(pAviHdr->width, pAviHdr->height, CODEC_CSP_BGR);
m_pVidDecTask->InitDecTask(this, m_pVideoStream);
//video render init
m_pVideoRender->CreateVideoRender(m_hWnd, m_pCBFunc, pAviHdr->fps, pAviHdr->width, pAviHdr->height);
m_pVideoRender->m_pVideoStream = m_pVideoStream;
//audio decoder task initialize
AAC_DECPARAM decParam;
m_pAudDecTask->SetDecParam(pAviHdr->a_extradata, pAviHdr->a_extradata_size);
if( !m_pAudDecTask->InitDecTask(this, m_pAudioStream) )
return FALSE;
m_pAudDecTask->GetDecParam(&decParam);
//audio render init
if( !m_pAudioRender->CreateAudioRender(m_pVideoRender->m_hWnd,
decParam.sampleRate, decParam.numChannels, decParam.bitRate) )
return FALSE;
m_pAudioRender->m_pAudioStream = m_pAudioStream;
//create play monitor thread
m_hStop = CreateEvent(NULL, FALSE, FALSE, NULL);
if( !m_hStop )
return FALSE;
if( !Create(ThreadEntry, this) )
return FALSE;
m_PlayState = READY;
LogMsg(LOG_INFO, HCLN, "Initialize MediaPlayer!");
return TRUE;
}
BOOL CMediaPlayer::UnInit()
{
if( m_PlayState == NONE )
return FALSE;
//if current state is playing, stop media player.
Stop();
//
m_pAudioRender->DestroyAudioRender();
m_pVideoRender->DestroyVideoRender();
//stop decoding thread
if( !m_pAudDecTask->UninitDecTask() )
return FALSE;
if( !m_pVidDecTask->UninitDecTask() )
return FALSE;
m_pAviReader->CloseAviFile();
//close player monitor thread
if( GetHandle() )
{
SetEvent(m_hStop);
TerminateThread(GetHandle(), 0);
//WaitForClosure( INFINITE );
Close();
CloseHandle(m_hStop);
}
//free receive and stream syncfifo.
if( m_pAudioStream )
delete m_pAudioStream;
if( m_pVideoStream )
delete m_pVideoStream;
m_PlayState = NONE;
return TRUE;
}
void CMediaPlayer::GetAviHeader(AVIHDR *lpAviHdr)
{
avi_t *avi = m_pAviReader->m_pAviFile;
lpAviHdr->NumberOfStreams = WORD(avi->audio_strn > avi->video_strn ? avi->audio_strn : avi->video_strn) + 1;
//video
lpAviHdr->VideoTag = MAKEFOURCC(avi->video_tag[0], avi->video_tag[1], avi->video_tag[2], avi->video_tag[3]);
lpAviHdr->Width = avi->width;
lpAviHdr->Height = avi->height;
lpAviHdr->FramePerSec = avi->fps;
lpAviHdr->VideoNumberOfFrames = avi->video_frames;
//audio
lpAviHdr->AudioTag = (WORD)avi->a_fmt;
lpAviHdr->SamplesPerSec = avi->a_rate;
lpAviHdr->Channels = (WORD)avi->a_chans;
lpAviHdr->AudioNumberOfFrames = avi->audio_chunks;
lpAviHdr->AudioLengthOfFrames = avi->audio_avg_bytes;
memcpy(lpAviHdr->AudioExtraData, avi->a_extradata, avi->a_extradata_size);
lpAviHdr->AudioExtraDataSize = avi->a_extradata_size;
//file information
if( avi->fps )
lpAviHdr->TotalPlayTime = (DWORD)(avi->video_frames/avi->fps);
else
lpAviHdr->TotalPlayTime = 0;
lpAviHdr->FileSize = avi->filesize;
}
void CMediaPlayer::GetFileInfo(char *lpAviFileName, AVIHDR *lpAviHdr)
{
CAviReader aviReader;
if( lpAviFileName && (aviReader.OpenAviFile(lpAviFileName) < 0) )
{
lpAviHdr = NULL;
return;
}
avi_t *avi = aviReader.m_pAviFile;
lpAviHdr->NumberOfStreams = WORD(avi->audio_strn > avi->video_strn ? avi->audio_strn : avi->video_strn) + 1;
//video
lpAviHdr->VideoTag = MAKEFOURCC(avi->video_tag[0], avi->video_tag[1], avi->video_tag[2], avi->video_tag[3]);
lpAviHdr->Width = avi->width;
lpAviHdr->Height = avi->height;
lpAviHdr->FramePerSec = avi->fps;
lpAviHdr->VideoNumberOfFrames = avi->video_frames;
//audio
lpAviHdr->AudioTag = (WORD)avi->a_fmt;
lpAviHdr->SamplesPerSec = avi->a_rate;
lpAviHdr->Channels = (WORD)avi->a_chans;
lpAviHdr->AudioNumberOfFrames = avi->audio_chunks;
lpAviHdr->AudioLengthOfFrames = avi->audio_avg_bytes;
memcpy(lpAviHdr->AudioExtraData, avi->a_extradata, avi->a_extradata_size);
lpAviHdr->AudioExtraDataSize = avi->a_extradata_size;
//file information
if( avi->fps )
lpAviHdr->TotalPlayTime = (DWORD)(avi->video_frames/avi->fps);
else
lpAviHdr->TotalPlayTime = 0;
lpAviHdr->FileSize = avi->filesize;
aviReader.CloseAviFile();
}
//##ModelId=4753B7E903BB
BOOL CMediaPlayer::Play()
{
UINT nPercent;
if( m_PlayState == NONE )
return FALSE;
m_bStreaming = TRUE;
m_bEndStream = FALSE;
LogMsg(LOG_INFO, HCLN, "Startup MediaPlayer!");
m_pVidDecTask->StartDecTask();
m_pAudDecTask->StartDecTask();
//checking buffer state
if( IsBuffering(nPercent) )
{
LogMsg(LOG_INFO, HCLN, "stop MediaPlayer by buffering!");
m_PlayState = BUFFERING;
m_pAudioRender->Stop();
m_pVideoRender->Stop();
}
else
{
LogMsg(LOG_INFO, HCLN, "Start MediaPlayer by no buffering!");
m_pAudioRender->Play();
m_pVideoRender->Play();
m_PlayState = PLAY;
}
return TRUE;
}
//##ModelId=4753B7E903BD
BOOL CMediaPlayer::Pause()
{
if( m_PlayState == PLAY )
{
LogMsg(LOG_INFO, HCLN, "Paused MediaPlayer!");
m_pAudioRender->Stop();
m_pVideoRender->Stop();
m_PlayState = PAUSE;
return TRUE;
}
return FALSE;
}
BOOL CMediaPlayer::Seek(int nTime)
{
if( m_PlayState == PLAY )
{
Pause();
EmptyStream();
m_pAviReader->SetAviReaderPos((float)nTime);
Play();
return TRUE;
}
return FALSE;
}
//##ModelId=4753B7E903BE
BOOL CMediaPlayer::Stop()
{
if( m_PlayState == PLAY || m_PlayState == PAUSE )
{
m_bStreaming = FALSE;
//stop video and audio play
m_pAudioRender->Stop();
m_pVideoRender->Stop();
EmptyStream();
m_pVidDecTask->CodecReset();
m_pAudDecTask->CodecReset();
m_pAviReader->SetAviReaderPos(0);
m_PlayState = READY;
LogMsg(LOG_INFO, HCLN, "Stopped MediaPlayer!\n");
return TRUE;
}
return FALSE;
}
int CMediaPlayer::OnReadFrame(BYTE **lpData, DWORD &nTime)
{
return m_pAviReader->ReadVideo(lpData, nTime);
}
int CMediaPlayer::OnReadAudio(BYTE **lpData, DWORD &nTime)
{
return m_pAviReader->ReadAudioFrame(lpData, nTime);
}
DWORD CMediaPlayer::GetTotalPlayTime()
{
return (DWORD)(m_pAviReader->m_pAviFile->video_frames/m_pAviReader->m_pAviFile->fps);
}
//##ModelId=4753B7E903C8
BOOL CMediaPlayer::EmptyStream()
{
//decoder task stop
m_pVidDecTask->StopDecTask();
m_pAudDecTask->StopDecTask();
m_pAudioStream->Empty();
m_pAudioRender->EmptyWaveBuffer();
m_pVideoStream->Empty();
LogMsg(LOG_INFO, HCLN, "resumed rtp session!");
return TRUE;
}
//##ModelId=4753B7E903C9
BOOL CMediaPlayer::SetVolume(int nVol)
{
if( m_pAudioRender )
return m_pAudioRender->SetVolume(nVol);
return FALSE;
}
//check buffer state
//##ModelId=4753B7EA0002
BOOL CMediaPlayer::IsBuffering(UINT &nPercent)
{
BOOL bRet = FALSE;
UINT nVidPc, nAudPc;
BOOL bVidBuffering, bAudBuffering;
bAudBuffering = m_pAudioStream->CheckIsBuffering(nAudPc);
bVidBuffering = m_pVideoStream->CheckIsBuffering(nVidPc);
bRet = ( bVidBuffering || bAudBuffering );
nPercent = nVidPc > nAudPc ? nAudPc : nVidPc;
if( bRet )
LogMsg(LOG_DEBUG, HCLN, "buffering audio=%d vidoe=%d!", nAudPc, nVidPc);
return bRet;
}
//do monitoring buffer state
//##ModelId=4753B7EA0004
BOOL CMediaPlayer::BufferMonitor()
{
UINT nPercent;
LONG nPlayTime;
//check buffer state per 30ms
if( m_PlayState == BUFFERING )
{
if( !IsBuffering(nPercent) )
{
m_pAudioRender->Play();
m_pVideoRender->Play();
m_PlayState = PLAY;
LogMsg(LOG_INFO, HCLN, "resuming MediaPlayer on buffering state");
}
else
{
LONG nTotaltime = GetTotalPlayTime();
nPlayTime = m_pVideoStream->GetPopTime();
if( nTotaltime - 1 < nPlayTime / 1000)
{
LogMsg(LOG_INFO, HCLN, "resuming MediaPlayer by streaming end");
m_bEndStream = TRUE;
m_pAudioStream->SetEmptyJitterNum(1);
m_pVideoStream->SetEmptyJitterNum(1);
m_pAudioRender->Play();
m_pVideoRender->Play();
m_PlayState = PLAY;
}
}
}
else if( m_PlayState == PLAY )
{
if( IsBuffering(nPercent) && m_bStreaming )
{
Stop();
}
}
return TRUE;
}
//##ModelId=4753B7EA0005
BOOL CMediaPlayer::SyncCtrol()
{
DWORD nCurPlayTime = 0;
//get current time to audio player
nCurPlayTime = m_pAudioRender->GetCurPlayTime();
m_pVideoRender->SetCurPlayTime(nCurPlayTime);
return TRUE;
}
//##ModelId=4753B7E903DD
UINT WINAPI CMediaPlayer::ThreadEntry(void *lpParam)
{
((CMediaPlayer *) lpParam)->PlayMonitor();
return 0;
}
//##ModelId=4753B7EA0001
void CMediaPlayer::PlayMonitor()
{
LONG nPlayTime;
m_nCount = 1;
while( TRUE )
{
if( WaitForSingleObject(m_hStop, 0) == WAIT_OBJECT_0 )
break;
//check buffer state and exit if streaming is end.
if( !BufferMonitor() )
break;
//
if( (m_PlayState == PLAY) && m_nCount%25 == 0)
{
nPlayTime = m_pVideoRender->GetCurPlayTime();
}
if( m_PlayState == PLAY && (m_nCount%25 == 0) )//check synchronization per 500ms
{
SyncCtrol();
m_nCount = 1;
}
Sleep(20);
m_nCount++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -