home *** CD-ROM | disk | FTP | other *** search
- /*
- * Player.cpp
- *
- * Copyright (C) Alberto Vigata - July 2000 - ultraflask@yahoo.com
- *
- * This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
- *
- * FlasKMPEG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * FlasKMPEG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-
-
- #include "FlasKMPEG.h"
- #include "auxiliary.h"
- #include "resource.h"
- #include "Player.h"
- #include "debug.h"
- #include "AudioProperties.h"
- #include "PlayerThread.h"
- #include "OutputPad.h"
- #include "./Misc/StatsStrings.h"
- #include "./Video/VideoWrapper.h"
- #include "./RunState.h"
- #include "flppreceiver.h"
- #include <string>
-
- // Extern globals
- extern TRunState rs;
- extern HINSTANCE hInst;
-
- extern HWND hMainWnd;
- extern BITMAPINFO DibInfo;
- extern BOOL playerStopped; //Needed for main window to redraw
- // FlasKMPEG logo.
-
- // Local variables
- static HWND hPlayerDlg;
-
- static CRITICAL_SECTION GlobalCriticalSection;
- static bool SeekInProgress;
- static i64 diferencia;
- static TStatsStrings stats; //This is a big one
- DWORD play_start_time;
- unsigned play_frame_count;
-
-
- // This is the profile we will work on in
- // the control
- // initialized on ShowPlayer()
- TProfile pprof;
- static TPPost pps; // we store locally the current post processing settings
-
-
- const int nTrackBarRange = 1000;
-
- void ShowPlayer( TProfile *prof )
- {
-
- // Don't start player if bad post processing parameters
- pprof = *prof;
- TPPost pp;
- FromConfigToPPost(&pprof, &pp,
- rs.video->GetWidth(),
- rs.video->GetHeight(),
- rs.video->DAR,
- FRAME_YV12 );
-
-
- if( CheckVideoParameters( &pp ) ) {
- if(!rs.hPlayerWnd)
- {
- rs.hPlayerWnd = CreateDialog(hInst,MAKEINTRESOURCE(IDD_PLAYER), hMainWnd, (DLGPROC) PlayerDlg);
- ShowWindow(rs.hPlayerWnd, SW_SHOW);
- }
- }
- }
-
- static CFlEvent evPlayerEnded;
-
- TProfile *GetCurrentPlayerSettings()
- {
- FromPPostToConfig( &pprof, &pps );
- return &pprof;
- }
-
- TProfile *HidePlayer()
- {
- TProfile *prof = NULL;
- if(rs.hPlayerWnd)
- {
- prof = &pprof;
- evPlayerEnded.Reset();
- SendMessage( rs.hPlayerWnd, WM_COMMAND, MAKEWPARAM(IDOK,0), 0);
- evPlayerEnded.Wait();
- DestroyWindow(rs.hPlayerWnd);
- rs.hPlayerWnd = NULL;
- }
- return prof;
- }
-
- void Localize(HWND hDlg)
- {
- DlgSetText(hDlg, R_PLAYER_PLAY_BUTTON, GS(R_PLAYER_PLAY_BUTTON) );
- DlgSetText(hDlg, R_PLAYER_STOP_BUTTON, GS(R_PLAYER_STOP_BUTTON) );
- DlgSetText(hDlg, R_PLAYER_VIDEOSTATS_BOX, GS(R_PLAYER_VIDEOSTATS_BOX) );
- DlgSetText(hDlg, R_PLAYER_FILETIME_TITLE, GS(R_PLAYER_FILETIME_TITLE) );
- DlgSetText(hDlg, R_PLAYER_FILE_TITLE, GS(R_PLAYER_FILE_TITLE) );
- DlgSetText(hDlg, R_PLAYER_VIDEOSIZE_TITLE, GS(R_PLAYER_VIDEOSIZE_TITLE) );
- DlgSetText(hDlg, R_PLAYER_FPS_TITLE, GS(R_PLAYER_FPS_TITLE) );
- DlgSetText(hDlg, R_PLAYER_TOTALFILESIZE_TITLE, GS(R_PLAYER_TOTALFILESIZE_TITLE) );
- DlgSetText(hDlg, R_PLAYER_ASPECTRATIO_TITLE, GS(R_PLAYER_ASPECTRATIO_TITLE) );
- DlgSetText(hDlg, R_PLAYER_BITRATE_TITLE, GS(R_PLAYER_BITRATE_TITLE) );
- DlgSetText(hDlg, R_PLAYER_VIDEOSTRUCTURE_TITLE, GS(R_PLAYER_VIDEOSTRUCTURE_TITLE) );
- DlgSetText(hDlg, R_PLAYER_SEEKFIRST_BUTTON, GS(R_PLAYER_SEEKFIRST_BUTTON) );
- DlgSetText(hDlg, R_PLAYER_DETECTEDFPS_TITLE, GS(R_PLAYER_DETECTEDFPS_TITLE) );
- DlgSetText(hDlg, R_PLAYER_VIDEOFORMAT_TITLE, GS(R_PLAYER_VIDEOFORMAT_TITLE) );
-
- return;
- }
-
-
-
- #define OUTPUT_POPUP_BASE 10000
- static void ShowOutputPopup(HWND hDlg, HWND hButton)
- {
- HMENU hPopup = CreatePopupMenu();
- for(int i=0; i<rs.plugs.OutPluginCount; i++)
- {
- MenuAddItem( hPopup, i, OUTPUT_POPUP_BASE+i, rs.plugs.outPlugs[i].ID );
- }
- CheckMenuItem(hPopup,rs.selected_out_plug, MF_BYPOSITION|MF_CHECKED);
- MenuAddSeparator(hPopup, i);
- MenuAddItem(hPopup, i+1, OUTPUT_POPUP_BASE+i+1, "Configure Output Module");
-
- // Get the rect of the button
- RECT rcButton;
- GetWindowRect(hButton, &rcButton);
- // Now show the popup
- TrackPopupMenu( hPopup,
- TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON,
- rcButton.right, rcButton.top,
- 0, hDlg, NULL);
- // thats it
- }
-
- void CreateDefaultJob()
- {
- // If there are no jobs create one
- if(!rs.vBatchList.size())
- {
- CFrame *pDummyFrame;
-
- TBatchListElement el;
- // Calculate start position
- // Go to the beginning
- rs.video->SetStreamPos(0);
- // Decode the first frame available
- TVideoOptions sStartOpt;
- memset( &sStartOpt, 0, sizeof(TVideoOptions));
- sStartOpt.bStartInSync = false;
- sStartOpt.idctIndex = rs.conf.idctIndex;
- sStartOpt.pFrameBuffer = NULL;
-
- rs.video->Start(&sStartOpt);
- rs.video->GetNextFrame(&pDummyFrame);
- rs.video->Stop();
-
- el.nStart = rs.video->GetLastDecodedFrameStart();
- el.nEnd = rs.video->GetStreamSize();
- rs.vBatchList.push_back(el);
- }
- }
-
- static void DeInitializePlayer(HWND hDlg, CPlayerThread * &pPlayer,
- CAudioThread * &pAudioPlayer,
- CMasterClock * &pMasterClock )
- {
-
- if( !pMasterClock || !pAudioPlayer || !pPlayer )
- return;
-
- // Stop playing thread
- pPlayer->Exit();
- pPlayer=NULL;
-
- // Create default job
- CreateDefaultJob();
-
- KillTimer( hDlg, 2);
- // SetWindowSize();
- // InvalidateRect(hMainWnd, NULL, true);
-
- // Stop the audio thread
- pAudioPlayer->Exit();
- delete pAudioPlayer;
- pAudioPlayer = NULL;
-
- // Delete de master clock
- delete pMasterClock;
- pMasterClock = NULL;
-
- // Set end dialog event to wake anyone waiting on HidePlayer
- evPlayerEnded.Set();
-
-
- }
-
- void RenderBatchList( HWND hList )
- {
- int i, nSize = rs.vBatchList.size();
- char str[256];
-
- SendMessage(hList, LB_RESETCONTENT, 0, 0);
- for(i=0; i<nSize; i++)
- {
- int nJobSize = (rs.vBatchList[i].nEnd - rs.vBatchList[i].nStart)>>20;
- sprintf( str, "Job %d. size %d MB.", i+1, nJobSize );
- SendMessage(hList, LB_ADDSTRING, 0, (WPARAM)str);
- }
- }
-
- void RenderTrackbarSel( HWND hTrackbar , TBatchListElement *pItem )
- {
- LONG start = (LONG)(((double)pItem->nStart/(double)rs.video->GetStreamSize()) * (double)nTrackBarRange);
- LONG end = (LONG)(((double)pItem->nEnd /(double)rs.video->GetStreamSize()) * (double)nTrackBarRange);
-
- SendMessage( hTrackbar, TBM_SETSEL, (WPARAM)(BOOL)true, (LPARAM)MAKELONG(start, end) );
- }
-
- void SetupTooltips(HWND hDlg)
- {
- HINSTANCE hInst = rs.hInst;
-
- #define ATTACH(id, title, text){ DlgAttachToolTip( hInst, hDlg, id, title, text); }
-
-
- // Play controls
- ATTACH( IDC_SEEKFIRST, "Seek Beginning", "Sets cursor at the \n\rbeginning." )
- ATTACH( IDC_PLAYBACK, "Play Backwards", "Plays video backwards." )
- ATTACH( IDC_PLAY, "Play", "Plays video." )
- ATTACH( IDC_STOP, "Stop", "Stops current action." )
- ATTACH( IDC_PREVFRAME, "Previous Frame", "Displays previous frame." )
- ATTACH( IDC_NEXTFRAME, "Next Frame", "Displays next frame." )
- ATTACH( IDC_FASTBACK, "Fast Rewind", "Rewinds video backwards." )
- ATTACH( IDC_FASTFOR, "Fast Forward", "Fast forwards video." )
- ATTACH( IDC_SEEKEND, "Seek End", "Goes to the end of \n\r the video." )
-
- // Selection Controls
- ATTACH( IDC_STARTMARKER, "Start Marker", "Start of selection" )
- ATTACH( IDC_ENDMARKER, "End Marker", "End of selection" )
- ATTACH( IDC_GOSTARTMARKER, "Jump Start Marker", "Jumps to wherever\n\r the start marker is \n\rplaced." )
- ATTACH( IDC_GOENDMARKER, "Jump End Marker", "Jumps to wherever\n\r the end marker is \n\rplaced." )
-
- ATTACH( IDC_LIST, "Job List", "List of jobs\n\r currently created." )
-
-
- #undef ATTACH
- }
-
-
- // Define an the report class for our dialog
- // The class will send the WM_NEWFRAMEINFO message
- // to the dialog every time there is new info about
- // a frame
- #define WM_NEWPPSETTINGS WM_USER + 1
-
- class CPlayerListener: public FlPPReceiver
- {
- public:
- CPlayerListener(HWND hDlg)
- {
- m_hDlg = hDlg;
- }
-
- int PutPPSettings( TPPost *pp )
- {
- if(m_hDlg)
- PostMessage(m_hDlg, WM_NEWPPSETTINGS, (WPARAM)pp, (LPARAM)0);
-
- return 0;
- }
- void SetDlg( HWND hDlg ){ m_hDlg = hDlg; }
-
- private:
- HWND m_hDlg;
-
- };
-
-
- LRESULT CALLBACK PlayerDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
- {
- static HANDLE hPlayer;
- i64 nFilePos;
- int nSel;
- static int playerTimer;
- int fPosition, lPosition;
- static bool userIsTracking;
- char szTemp[1024];
- static CPlayerThread *pPlayer;
- static CAudioThread *pAudioPlayer;
- static CMasterClock *pMasterClock;
- static COutputPadDlg vidPanel(hMainWnd, hDlg, hInst);
- static TBatchListElement trackBarSpan;
- CPlayerThread::playerStates nState;
- static CPlayerListener listener(hDlg);
- static FlPostProcess pp;
- static TStatsStrings stats;
- string title;
-
-
- switch (message)
- {
- case WM_TIMER:
- // Total frames
- // Total file size
- sprintf( szTemp, "%d Mbytes", (unsigned)(rs.video->GetStreamSize() >> 20));
- SetDlgItemText(hDlg, IDC_FILESIZE, szTemp);
- // Video size
- DlgSetText(hDlg,IDC_VIDEOSIZE ,stats.InMedia.video_size);
- // Frame rate
- DlgSetText(hDlg,IDC_FRAMERATE ,stats.InMedia.video_frame_rate);
- //Detected FPS
- DlgSetText(hDlg,IDC_DETECTEDFPS ,stats.InMedia.video_detected_frame_rate);
- // Aspect Ratio
- DlgSetText(hDlg,IDC_ASPECTRATIO ,stats.InMedia.video_aspect_ratio_information);
- // Bitrate
- DlgSetText(hDlg,IDC_BITRATE ,stats.InMedia.video_bit_rate);
- // Progressive sequence
- DlgSetText(hDlg,IDC_PROGRESSIVE ,stats.InMedia.video_structure);
- //DlgSetText(hDlg,IDC_PROGRESSIVE ,video->internalPTS/27000.0);
- //DlgSetText(hDlg,IDC_BITRATE ,diferencia);
-
- nState = pPlayer->GetState();
- fPosition=true;
- lPosition= (int)(((double)(i64)(rs.video->GetStreamPos())/(double)(i64)(rs.video->GetStreamSize()))*nTrackBarRange);
- if( !userIsTracking &&
- nState!=CPlayerThread::stNextFrame &&
- nState!=CPlayerThread::stPrevFrame )
- SendDlgItemMessage(hDlg, IDC_SLIDER, TBM_SETPOS, (WPARAM) (BOOL) fPosition,(LPARAM) (LONG) lPosition);
-
- break;
- case WM_INITDIALOG:
- RenderStatsStrings(&stats);
-
- title ="Control Panel - ";
- title += rs.video->GetFileName();
- SetText( hDlg, (char *)title.c_str() );
-
- vidPanel.SetWindows( hMainWnd, hDlg );
-
- SetWindowLong( hDlg, GWL_EXSTYLE, WS_EX_TOOLWINDOW );
-
- SetupTooltips( hDlg );
-
- Localize(hDlg);
-
- // put the audio in place
- rs.video->SetStreamPos(rs.startFilePos);
- if(rs.audio)
- rs.audio->SetStreamPos(rs.startFilePos);
-
-
- // Get post processing options from config
- FromConfigToPPost(&pprof, &pps,
- rs.video->GetWidth(),
- rs.video->GetHeight(),
- rs.video->DAR,
- FRAME_YV12 );
-
-
- if( !pp.Set( &pps ) ) {
- DBG_STR((str, "Player - Settings in profile are not valid\n"))
- return FALSE;
- }
-
- WindowClientResize( hMainWnd, pp.GetWidth() , pp.GetHeight() );
-
- // Create Master Clock
- pMasterClock = new CMasterClock(ClkSystem);
- if( !pMasterClock->Initialize() )
- {
- delete pMasterClock;
- pMasterClock = NULL;
- }
-
-
-
- hPlayerDlg=hDlg;
- SeekInProgress=false;
- userIsTracking=false;
- EnableWindow( GetDlgItem(hDlg, IDC_PLAY), true);
- EnableWindow( GetDlgItem(hDlg, IDOK), true);
- EnableWindow( GetDlgItem(hDlg, IDC_SEEKFIRST), true);
- EnableWindow( GetDlgItem(hDlg, IDC_SLIDER), true);
- EnableWindow( GetDlgItem(hDlg, IDC_STOP), true);
- SendDlgItemMessage(hDlg, IDC_SLIDER, TBM_SETRANGE, (WPARAM) TRUE,(LPARAM) MAKELONG(0, nTrackBarRange));
-
-
- play_frame_count = 0;
- play_start_time = GetTickCount();
-
- playerTimer= SetTimer(hDlg, // handle of window for timer messages
- 2, // timer identifier
- 500, // time-out value
- NULL // address of timer procedure
- );
-
- // Snap the player at the botton of the main window
- RECT rcMain;
- GetWindowRect( hMainWnd, &rcMain );
- WindowMove( hDlg, rcMain.left, rcMain.bottom );
-
-
-
- // Create default job
- CreateDefaultJob();
-
- // Render list
- RenderBatchList(GetDlgItem(hDlg, IDC_LIST));
-
-
- // listener
- listener.SetDlg( hDlg );
-
- // Create player thread
- FLASSERT(pMasterClock!=NULL);
-
-
- // Create video player thread
- pPlayer = new CPlayerThread( rs.video, hMainWnd, pMasterClock, pp.Get(),
- rs.conf.idctIndex, pprof.recons_progressive, &vidPanel );
- pPlayer->Create();
-
- // Create audio player thread
- pAudioPlayer = new CAudioThread( pMasterClock );
- pAudioPlayer->Create();
-
- // If there are jobs select jump to the first one.
- if(rs.vBatchList.size())
- {
- trackBarSpan = rs.vBatchList[0];
- pPlayer->Seek( trackBarSpan.nStart );
- RenderTrackbarSel(GetDlgItem(hDlg, IDC_SLIDER), &trackBarSpan );
- }
-
- return TRUE;
- case WM_HSCROLL:
- int nPos;
- switch(LOWORD(wParam)){
- case TB_THUMBTRACK:
- // Get position
- // No need to serialize this.
- userIsTracking = true;
-
- pAudioPlayer->Stop();
-
- nPos = SendDlgItemMessage(hDlg, IDC_SLIDER, TBM_GETPOS, 0, 0);
-
- nFilePos=(i64)(((double)nPos/1000.0)*(double)(i64)(rs.video->GetStreamSize()));
-
- // Seek the player to that position
- pPlayer->SeekKeyFrame( nFilePos );
-
- play_frame_count = 0;
- play_start_time = GetTickCount();
-
- break;
- case TB_THUMBPOSITION :
- userIsTracking = false;
- break;
- }
- break;
- case WM_NEWPPSETTINGS:
- pps = *(TPPost *)wParam;
- pPlayer->SetPPSettings( &pps );
- pp.Set( &pps );
- WindowClientResize( hMainWnd, pp.GetWidth() , pp.GetHeight() );
- break;
- case WM_COMMAND:
- {
- if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
- {
- DeInitializePlayer(hDlg, pPlayer, pAudioPlayer, pMasterClock);
- DestroyWindow(rs.hPlayerWnd);
- rs.hPlayerWnd = NULL;
- return TRUE;
- }
- WORD wmId = LOWORD(wParam);
- // Customized menues
- if(wmId>=OUTPUT_POPUP_BASE && wmId<(OUTPUT_POPUP_BASE+MAX_OUT_PLUGINS+2))
- {
- if((wmId - OUTPUT_POPUP_BASE) < rs.plugs.OutPluginCount)
- rs.selected_out_plug = wmId - 10000;
- else if( (wmId - OUTPUT_POPUP_BASE) == rs.plugs.OutPluginCount + 1 ){
- SendMessage( hMainWnd, WM_COMMAND, MAKEWPARAM(IDM_MPEG1OPTIONS,0), 0 );
- }
- }
-
- switch( LOWORD(wParam)){
- case IDC_FLASKIT:
- SendMessage( hMainWnd, WM_COMMAND, MAKEWPARAM(IDM_START2,0), 0 );
- break;
- case IDC_AUDIOPLAYER:
- ShowAudioPanel(pAudioPlayer);
- break;
- case IDC_VIDEOPANEL:
- vidPanel.Show(pp.Get(), &listener );
- break;
- case IDC_SELECTOUTPUT:
- ShowOutputPopup(hDlg, GetDlgItem(hDlg, IDC_SELECTOUTPUT));
- break;
- case IDC_SEEKFIRST:
- pAudioPlayer->Stop();
- pPlayer->SeekBeginning();
- break;
- case IDC_SEEKEND:
- pAudioPlayer->Stop();
- pPlayer->SeekEnd();
- break;
- case IDC_PLAYBACK:
- pAudioPlayer->Stop();
- pPlayer->PlayBack();
- break;
- case IDC_PLAY:
- pAudioPlayer->Stop();
- pPlayer->Stop();
-
- pMasterClock->Set(0);
- pAudioPlayer->Seek( rs.video->GetSyncPoint( pPlayer->GetFrameStartPos() ));
-
- pPlayer->Play();
- pAudioPlayer->Play();
- break;
- case IDC_STOP:
- pAudioPlayer->Stop();
- pPlayer->Stop();
- break;
- case IDC_NEXTFRAME:
- pAudioPlayer->Stop();
- pPlayer->NextFrame();
- break;
- case IDC_PREVFRAME:
- pAudioPlayer->Stop();
- pPlayer->PrevFrame();
- break;
- case IDC_FASTFOR:
- pAudioPlayer->Stop();
- pPlayer->FastForward();
- break;
- case IDC_FASTBACK:
- pAudioPlayer->Stop();
- pPlayer->FastRewind();
- break;
- case IDC_STARTMARKER:
- {
- bool bWasPlaying;
-
- bWasPlaying = pPlayer->GetState() == CPlayerThread::stPlaying;
-
- if(bWasPlaying)
- {
- pAudioPlayer->Stop();
- pPlayer->Stop();
- }
-
- trackBarSpan.nStart = pPlayer->GetFrameStartPos();
-
- if(bWasPlaying)
- {
- pMasterClock->Set(0);
- pAudioPlayer->Seek( rs.video->GetSyncPoint( trackBarSpan.nStart ));
-
- pPlayer->Play();
- pAudioPlayer->Play();
- }
-
- if(trackBarSpan.nStart > trackBarSpan.nEnd)
- trackBarSpan.nEnd = rs.video->GetStreamSize();
- RenderTrackbarSel(GetDlgItem(hDlg, IDC_SLIDER), &trackBarSpan );
-
- }
- break;
- case IDC_ENDMARKER:
- trackBarSpan.nEnd = rs.video->GetStreamPos();
- if(trackBarSpan.nEnd < trackBarSpan.nStart)
- trackBarSpan.nStart = 0;
-
- RenderTrackbarSel(GetDlgItem(hDlg, IDC_SLIDER), &trackBarSpan );
- break;
- case IDC_GOSTARTMARKER:
- pAudioPlayer->Stop();
- pPlayer->Seek( trackBarSpan.nStart );
- break;
- case IDC_GOENDMARKER:
- pAudioPlayer->Stop();
- pPlayer->Seek( trackBarSpan.nEnd );
- break;
- case IDC_LISTADD:
- rs.vBatchList.push_back(trackBarSpan);
- RenderBatchList(GetDlgItem(hDlg, IDC_LIST));
- break;
- case IDC_LISTDELETEALL:
- rs.vBatchList.clear();
- RenderBatchList(GetDlgItem(hDlg, IDC_LIST));
- break;
- case IDC_LISTDELETE:
- nSel = SendMessage(GetDlgItem(hDlg, IDC_LIST), LB_GETCURSEL, 0, 0 );
- if(nSel!=LB_ERR)
- {
- rs.vBatchList.erase( rs.vBatchList.begin() + nSel );
- RenderBatchList(GetDlgItem(hDlg, IDC_LIST));
- }
- break;
- case IDC_LIST:
- if(HIWORD(wParam)==LBN_SELCHANGE)
- {
- pAudioPlayer->Stop();
- nSel = SendMessage(GetDlgItem(hDlg, IDC_LIST), LB_GETCURSEL, 0, 0 );
- trackBarSpan = rs.vBatchList[nSel];
- RenderTrackbarSel(GetDlgItem(hDlg, IDC_SLIDER), &trackBarSpan);
- pPlayer->Seek( trackBarSpan.nStart );
- }
- break;
- }
- }
- break;
-
- case WM_DESTROY:
-
- vidPanel.Hide();
- // return the settings to the current profile
- FromPPostToConfig( &pprof, &pps );
-
- DeInitializePlayer(hDlg, pPlayer, pAudioPlayer, pMasterClock);
- rs.hPlayerWnd = NULL;
- break;
- }
- return FALSE;
- }
-
-
-