⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mediaplayer.cpp

📁 播放被H264_AAC所压缩的avi文件的播放器。
💻 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 + -