📄 mediaplayback.cpp
字号:
playback->buffering = TRUE;
while(size < sizeI + playback->input->GetBufferingSize() && !(playback->input->GetBufferSize() >= playback->input->GetSize())) {
Sleep(10);
size = playback->input->GetBufferSize();
playback->bufferingProgress = (size - sizeI) * 100 / playback->input->GetBufferingSize();
}
playback->buffering = FALSE;
playback->hasToBuffer = FALSE;
playback->decaps->UpdateForSize();
RECT rect;
GetClientRect(playback->hwndPlayback, &rect);
InvalidateRect(playback->hwndPlayback, &rect, TRUE);
UpdateWindow(playback->hwndPlayback);
if(playback->audioRenderer->paused)
playback->audioRenderer->Pause();
}
}
startPlayingWAudio:
frame = NULL;
if(!playback->paused) {
if(playback->fastForward) {
playback->decaps->SeekNextKeyFrame(0);
}
else {
if(playback->rewind) {
playback->decaps->SeekPreviousKeyFrame(0);
}
}
/*
* 同步
*
*/
if(!playback->fastForward && !playback->rewind) {
timeDiff = playback->GetVideoTime() - playback->GetAudioTime();
if(timeDiff == 0) {
/*
* 什么也不做
*/
}
else {
if(timeDiff > 10) {
Sleep(timeDiff/2);
}
if(timeDiff < -150) {
/*
* 跳过,不进行补偿
*/
playback->videoBuffer->DropOneFrame();
playback->videoFrames++;
}
if(timeDiff < -230) {
/*
* 跳过,不进行补偿
*/
playback->videoBuffer->DropOneFrame();
playback->videoFrames++;
}
}
}
else {
Sleep(120);
}
frame = playback->videoBuffer->GetOneFrame();
playback->videoFrames++;
if(frame == NULL) {
/*
* 在文件或缓冲末尾
*/
if(playback->input->GetCaps() & MEDIA_CAPS_BUFFERIZE) {
if(playback->input->GetBufferSize() < playback->input->GetSize()) {
goto startBufferingWAudio;
}
else {
if(!playback->audioRenderer->paused)
playback->audioRenderer->Pause();
playback->decaps->UpdateForSize();
frame = playback->videoBuffer->GetOneFrame();
if(playback->audioRenderer->paused)
playback->audioRenderer->Pause();
}
}
}
if(frame == NULL) {
if(!playback->loop) {
SendMessage(playback->hwndPlayback, WM_PLAYA_PLAYBACK_END, 0, 0);
playback->Stop(TRUE);
}
else {
playback->decaps->Rewind(0, 0);
if(!playback->fastForward && !playback->rewind) {
if(playback->hasAudio)
playback->audioRenderer->Stop();
if(playback->hasAudio)
playback->audioDecoder->EmptyAudioBuffer();
}
playback->audioBytes = 0;
playback->videoFrames = 0;
playback->videoBuffer->StopBuffering();
playback->videoBuffer->StartBuffering(playback->decaps->GetVideoWidth(0));
if(!playback->fastForward && !playback->rewind) {
if(playback->hasAudio)
playback->audioRenderer->Start();
}
goto startPlayingWAudio;
}
break;
}
WaitForSingleObject(playback->playbackMutex, INFINITE);
if(!playback->paused) {
if(playback->fullscreen) {
playback->videoRenderer->DrawFullscreen(frame, playback->decaps->GetCurrentVideoFrame(0), playback->videoDecoder->GetInvertFlag(), playback->desktopMode);
}
else {
playback->videoRenderer->Draw(frame, playback->videoRect, playback->decaps->GetCurrentVideoFrame(0), playback->videoDecoder->GetInvertFlag());
}
}
ReleaseMutex(playback->playbackMutex);
}
}
}
return 0;
}
/*
* 图形设备接口(GDI)方法
*
*/
MP_RESULT MediaPlayback::FlipToGDI()
{
return MP_RESULT_OK;
}
/**************************************************************
* *
* 视频回调方法 *
* ------------------------ *
* *
**************************************************************/
MP_RESULT MediaPlayback::Play()
{
if(this->HasAudio() || this->HasVideo()) {
if(this->fastForward) {
this->fastForward = FALSE;
this->baseTime = GetTickCount();
this->videoFrames = 0;
this->audioBytes = 0;
if(this->decaps) {
this->decaps->ReSeekAudio(0);
}
if(this->hasAudio) {
this->audioDecoder->EmptyAudioBuffer();
this->audioRenderer->SetVolume(this->volume);
this->audioRenderer->Stop();
this->audioRenderer->Start();
}
}
else {
if(this->rewind) {
this->rewind = FALSE;
this->baseTime = GetTickCount();
this->videoFrames = 0;
this->audioBytes = 0;
if(this->decaps) {
this->decaps->ReSeekAudio(0);
}
if(this->hasAudio) {
this->audioDecoder->EmptyAudioBuffer();
this->audioRenderer->SetVolume(this->volume);
this->audioRenderer->Stop();
this->audioRenderer->Start();
}
}
else {
if(this->paused) {
this->Pause();
return MP_RESULT_OK;
}
if(this->playing)
return MP_RESULT_ERROR;
this->playing = TRUE;
this->paused = FALSE;
this->videoFrames = 0;
this->audioBytes = 0;
this->decaps->Rewind(0, 0);
if(this->HasAudio()) {
this->audioDecoder->EmptyAudioBuffer();
this->audioRenderer->SetVolume(this->volume);
this->videoBuffer->StartBuffering(this->decaps->GetVideoWidth(0));
if(this->audioRenderer->paused && (this->input->GetCaps() & MEDIA_CAPS_BUFFERIZE)) {
this->audioRenderer->Pause();
this->audioRenderer->Stop();
this->audioRenderer->Start();
}
else {
this->audioRenderer->Start();
}
this->videoThread = CreateThread( NULL, 0, PlaybackVideoAndAudioThreadFunc, (LPVOID) this, 0, &this->videoThreadId );
return MP_RESULT_OK;
}
else {
if(this->HasVideo()) {
this->videoBuffer->StartBuffering(this->decaps->GetVideoWidth(0));
this->videoThread = CreateThread( NULL, 0, PlaybackVideoOnlyThreadFunc, (LPVOID) this, 0, &this->videoThreadId );
return MP_RESULT_OK;
}
}
}
}
}
return MP_RESULT_ERROR;
}
MP_RESULT MediaPlayback::Pause()
{
if(this->playing) {
if(this->paused) {
if(this->hasAudio) {
this->audioRenderer->Pause();
}
this->paused = FALSE;
ReleaseMutex(this->playbackMutex);
this->baseTime += (GetTickCount() - this->stopTime);
ResumeThread(this->videoThread);
}
else {
WaitForSingleObject(this->playbackMutex, INFINITE);
if(!this->fastForward && !this->rewind) {
if(this->hasAudio) {
this->audioRenderer->Pause();
}
}
else {
this->videoFrames = 0;
if(this->hasAudio) {
this->decaps->ReSeekAudio(0);
this->audioDecoder->EmptyAudioBuffer();
this->audioBytes = 0;
this->audioRenderer->Stop();
this->audioRenderer->Start();
this->audioRenderer->Pause();
}
}
this->fastForward = FALSE;
this->rewind = FALSE;
this->stopTime = GetTickCount();
SuspendThread(this->videoThread);
this->paused = TRUE;
}
}
return MP_RESULT_ERROR;
}
MP_RESULT MediaPlayback::NextFrame()
{
return MP_RESULT_ERROR;
}
MP_RESULT MediaPlayback::Stop(int redrawWindow)
{
if(this->paused)
this->Pause();
if(this->playing) {
WaitForSingleObject(this->playbackMutex, INFINITE);
if(this->hasAudio) {
this->audioRenderer->Stop();
}
this->playing = FALSE;
this->buffering = FALSE;
this->bufferingProgress = 0;
if(this->HasVideo()) {
this->videoBuffer->StopBuffering();
}
ReleaseMutex(this->playbackMutex);
}
this->fastForward = FALSE;
this->rewind = FALSE;
this->playing = FALSE;
this->paused = FALSE;
this->audioBytes = 0;
this->videoFrames = 0;
this->decaps->Rewind(0, 0);
if(this->hasAudio)
this->audioDecoder->EmptyAudioBuffer();
if(this->videoRenderer)
this->videoRenderer->Stop();
/*
* 刷新
*/
RECT rect;
if(redrawWindow) {
GetClientRect(this->hwndPlayback, &rect);
InvalidateRect(this->hwndPlayback, &rect, TRUE);
UpdateWindow(this->hwndPlayback);
}
TerminateThread(this->videoThread, 0);
return MP_RESULT_ERROR;
}
MP_RESULT MediaPlayback::FastForward()
{
if(this->paused) {
this->fastForward = TRUE;
this->paused = FALSE;
ReleaseMutex(this->playbackMutex);
this->baseTime += (GetTickCount() - this->stopTime);
ResumeThread(this->videoThread);
return MP_RESULT_OK;
}
if(this->playing && !this->rewind && !this->fastForward) {
if(this->hasAudio) {
this->audioRenderer->Stop();
}
this->stopTime = GetTickCount();
this->fastForward = TRUE;
}
return MP_RESULT_OK;
}
MP_RESULT MediaPlayback::Rewind()
{
if(this->paused) {
this->rewind = TRUE;
this->paused = FALSE;
ReleaseMutex(this->playbackMutex);
this->baseTime += (GetTickCount() - this->stopTime);
ResumeThread(this->videoThread);
return MP_RESULT_OK;
}
if(this->playing && !this->fastForward && !this->rewind) {
if(this->hasAudio) {
this->audioRenderer->Stop();
}
this->stopTime = GetTickCount();
this->rewind = TRUE;
}
return MP_RESULT_OK;
}
MP_RESULT MediaPlayback::MaintainImage()
{
if(this->HasVideo()) {
if(this->fullscreen) {
this->videoRenderer->DrawFullscreen(this->videoBuffer->GetLastFrame(), 0, this->videoDecoder->GetInvertFlag(), this->desktopMode);
}
else {
this->videoRenderer->Draw(this->videoBuffer->GetLastFrame(), this->videoRect, 0, this->videoDecoder->GetInvertFlag());
}
}
return MP_RESULT_OK;
}
MP_RESULT MediaPlayback::Seek(int percent)
{
int has_to_play = 0;
RECT rect;
if(this->HasAudio() || this->HasVideo()) {
if(this->playing) {
Stop(FALSE);
has_to_play = 1;
}
this->decaps->Seek(0, 0, percent);
if(this->input->GetCaps() & MEDIA_CAPS_BUFFERIZE) {
this->decaps->UpdateForSize();
}
if(this->hasAudio)
this->audioDecoder->EmptyAudioBuffer();
if(has_to_play) {
this->playing = TRUE;
this->paused = FALSE;
this->videoFrames = 0;
this->audioBytes = 0;
if(this->HasAudio()) {
this->audioRenderer->Start();
this->videoThread = CreateThread( NULL, 0, PlaybackVideoAndAudioThreadFunc, (LPVOID) this, 0, &this->videoThreadId );
}
else {
this->videoThread = CreateThread( NULL, 0, PlaybackVideoOnlyThreadFunc, (LPVOID) this, 0, &this->videoThreadId );
}
}
GetClientRect(this->hwndPlayback, &rect);
InvalidateRect(this->hwndPlayback, &rect, TRUE);
UpdateWindow(this->hwndPlayback);
}
return MP_RESULT_ERROR;
}
MP_RESULT MediaPlayback::SetFullscreen(int active, HWND hwnd)
{
if(active && !this->fullscreen) {
int has_to_play = 0;
if(this->playing && !this->paused) {
this->Pause();
has_to_play = 1;
}
this->fullscreen = TRUE;
if(this->videoRenderer->InitFullscreen(hwnd, this->decaps->GetVideoWidth(0), this->decaps->GetVideoHeight(0)) != MP_RESULT_OK) {
this->videoRenderer->Init(hwnd, this->decaps->GetVideoWidth(0), this->decaps->GetVideoHeight(0));
this->fullscreen = FALSE;
return MP_RESULT_ERROR;
}
if(has_to_play) {
this->Pause();
}
}
else {
if(this->fullscreen) {
int has_to_play = 0;
if(this->playing && !this->paused) {
this->Pause();
has_to_play = 1;
}
this->videoRenderer->Init(hwnd, this->decaps->GetVideoWidth(0), this->decaps->GetVideoHeight(0));
this->fullscreen = FALSE;
if(has_to_play) {
this->Pause();
}
}
}
return MP_RESULT_ERROR;
}
MP_RESULT MediaPlayback::SetVolume(int volume)
{
this->volume = volume;
if(this->hasAudio) {
this->audioRenderer->SetVolume(this->volume);
}
return MP_RESULT_OK;
}
MP_RESULT MediaPlayback::SetLoop(int loop)
{
this->loop = loop;
return MP_RESULT_OK;
}
MP_RESULT MediaPlayback::SetDesktopMode(BOOL on)
{
this->desktopMode = on;
return MP_RESULT_OK;
}
MP_RESULT MediaPlayback::SetVideoRect(RECT *rect)
{
this->videoRect = rect;
return MP_RESULT_OK;
}
MP_RESULT MediaPlayback::Close()
{
if(this->input)
this->input->Close();
if(this->HasVideo()) {
/*
* 清除视频
*
*/
this->Stop(FALSE);
this->videoRenderer->Close();
this->videoBuffer->StopBuffering();
this->videoBuffer->ReleaseConnections();
this->videoDecoder->ReleaseConnections();
this->decaps->ReleaseConnections();
}
if(this->HasAudio()) {
/*
* 清除音频
*
*/
this->audioRenderer->Close();
this->audioDecoder->ReleaseConnections();
}
if(this->hasSubtitles) {
this->subtitler->ReleaseConnections();
this->subtitler->Close();
}
return MP_RESULT_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -