home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2004 March / PCWELT_3_2004.ISO / pcwsoft / flaskmpeg_078_39_src.z.exe / flaskmpeg / playerthread.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-28  |  10.9 KB  |  363 lines

  1. /* 
  2.  *  Player.cpp 
  3.  *
  4.  *    Copyright (C) Alberto Vigata - July 2000 - ultraflask@yahoo.com
  5.  *
  6.  *  This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
  7.  *    
  8.  *  FlasKMPEG is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published by
  10.  *  the Free Software Foundation; either version 2, or (at your option)
  11.  *  any later version.
  12.  *   
  13.  *  FlasKMPEG is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *   
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with GNU Make; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  21.  *
  22.  */
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29. #include "playerthread.h"
  30. #include "debug.h"
  31. #include "runstate.h"
  32.  
  33. extern TRunState rs;
  34.  
  35.  
  36. // Actual running thread
  37. DWORD CPlayerThread::ThreadProc()
  38. {
  39.   m_nState = stStopped;
  40.   TCommand sCommand;
  41.  
  42.   ui64 size, nCommandResult;
  43.   tick tkPresTime, tkWaitTime, tkCurrentTime, tkFrameDelay;
  44.   
  45.     TVideoOptions video_opt;
  46.   CFrame *pDecodedFrame = NULL;
  47.   CFrame frProcessedFrame(NULL);
  48.   CFrame frDisplay;
  49.   FlPostProcess pp;
  50.  
  51.   enum {perfNormal =0, perfIOnly, perfSkip} perfState;
  52.  
  53.   perfState  = perfNormal;
  54.  
  55.   // Post processing
  56.   // Start Post processing
  57.   m_pp.nInHeight = rs.video->GetHeight();
  58.   m_pp.nInWidth  = rs.video->GetWidth();
  59.   m_pp.nProcessingFormat = rs.conf.nProcessingFormat;
  60.   pp.Set(&m_pp);
  61.   
  62.   if( pp.Start() == false ) {
  63.     DBG_STR(( str, "CPlayerThread::ThreadProc - Couldnt start post processing. Exiting thread\n"))
  64.     return 0;
  65.   }
  66.  
  67.   // FIXME :  the buffer size of post processed frames has to be larger than the final size
  68.   frProcessedFrame.Set( pp.GetWidth(), pp.GetHeight(), FRAME_YV12 );
  69.  
  70.   // Update video options
  71.   video_opt.idctIndex            = m_nIdctIndex;
  72.     video_opt.recons_progressive   = m_bReconsProgressive;
  73.   video_opt.bStartInSync         = false;
  74.   video_opt.nSyncPoint           = 0;
  75.   video_opt.nEndPoint            = rs.video->GetStreamSize();
  76.   video_opt.pFrameBuffer         = new CListFrameBuffer( rs.video->pictureWidth,
  77.                                                            rs.video->pictureHeight,
  78.                                                            FRAME_YV12,
  79.                                                            3); 
  80.  
  81.   tkFrameDelay = (mmtick)(rs.video->GetFrameDelay() * 10000);
  82.   pDecodedFrame  = NULL;
  83.   while(1)
  84.   {
  85.  
  86.     // open scope to lock command
  87.     if(GetCommand(&sCommand))
  88.     {
  89.       nCommandResult = 0;
  90.       switch( sCommand.nCommand )
  91.       {
  92.       case noCommand:
  93.         break;
  94.       case seek:
  95.         // Stop if necessary
  96.         if(m_nState!=stStopped)
  97.           m_pVideoDecoder->Stop();
  98.         m_pVideoDecoder->SetStreamPos(sCommand.nParam);
  99.         m_pVideoDecoder->Start(&video_opt);
  100.         m_nState = stNextFrame;
  101.         break;
  102.       case seekKeyFrame:
  103.         // Stop if necessary
  104.         if(m_nState!=stStopped)
  105.           m_pVideoDecoder->Stop();
  106.         m_pVideoDecoder->SetStreamPos(sCommand.nParam);
  107.         m_pVideoDecoder->Start(&video_opt);
  108.         m_nState = stNextKeyFrame;
  109.         break;
  110.       case seekBeginning:
  111.         // Stop if necessary
  112.         if(m_nState!=stStopped)
  113.           m_pVideoDecoder->Stop();
  114.         m_pVideoDecoder->SetStreamPos(0);
  115.         m_pVideoDecoder->Start(&video_opt);
  116.         m_nState = stNextFrame;
  117.         break;
  118.       case seekEnd:
  119.         // Stop if necessary
  120.         if(m_nState!=stStopped)
  121.           m_pVideoDecoder->Stop();
  122.         // Go to end
  123.         size = m_pVideoDecoder->GetStreamSize();
  124.         m_pVideoDecoder->SetStreamPos( size );
  125.         // Start video
  126.         m_pVideoDecoder->Start(&video_opt);
  127.         m_nState = stPrevFrame;
  128.         break;
  129.       case nextFrame:
  130.         // Stop if necessary
  131.         if(m_nState!=stStopped)
  132.           m_pVideoDecoder->Stop();
  133.         // Start video
  134.         m_pVideoDecoder->Start(&video_opt);
  135.           m_nState = stNextFrame;
  136.         break;
  137.       case prevFrame:
  138.         // Stop if necessary
  139.         if(m_nState!=stStopped)
  140.           m_pVideoDecoder->Stop();
  141.         // Start video
  142.         m_pVideoDecoder->Start(&video_opt);
  143.           m_nState = stPrevFrame;
  144.         break;
  145.       case nextKeyFrame:
  146.         // Stop if necessary
  147.         if(m_nState!=stStopped)
  148.           m_pVideoDecoder->Stop();
  149.         // Start video
  150.         m_pVideoDecoder->Start(&video_opt);
  151.           m_nState = stNextKeyFrame;
  152.         break;
  153.       case prevKeyFrame:
  154.         // Stop if necessary
  155.         if(m_nState!=stStopped)
  156.           m_pVideoDecoder->Stop();
  157.         // Start video
  158.         m_pVideoDecoder->Start(&video_opt);
  159.           m_nState = stPrevKeyFrame;
  160.         break;
  161.       case fastForward:
  162.         // Stop if necessary
  163.         if(m_nState!=stStopped)
  164.           m_pVideoDecoder->Stop();
  165.         // Start video
  166.         m_pVideoDecoder->Start(&video_opt);
  167.           m_nState = stFastForward;
  168.         break;    
  169.       case fastRewind:
  170.         // Stop if necessary
  171.         if(m_nState!=stStopped)
  172.           m_pVideoDecoder->Stop();
  173.         // Start video
  174.         m_pVideoDecoder->Start(&video_opt);
  175.           m_nState = stFastRewind;
  176.         break;
  177.       case getFrameStartPos:
  178.         // Stop if necessary
  179.         if(m_nState!=stStopped)
  180.           m_pVideoDecoder->Stop();
  181.         m_nState = stStopped;
  182.         nCommandResult = m_pVideoDecoder->GetLastDecodedFrameStart();
  183.         break;
  184.       case play: 
  185.         // Stop if necessary
  186.         if(m_nState!=stStopped)
  187.           m_pVideoDecoder->Stop();
  188.         
  189.         // Set the sync point
  190.         video_opt.bStartInSync = true;
  191.         video_opt.nSyncPoint = m_pVideoDecoder->GetSyncPoint( m_pVideoDecoder->GetLastDecodedFrameStart() );
  192.  
  193.         // Start video
  194.         m_pVideoDecoder->Start(&video_opt);
  195.         DBG_STR((str, "Starting Video Playing at %I64d ms\n", m_pMasterClock->GetTickCount()/10 ))
  196.  
  197.         // Set this to false for all the rest of modes
  198.         video_opt.bStartInSync = false;
  199.  
  200.         perfState = perfNormal;
  201.  
  202.         m_nState = stPlaying;
  203.         m_lPlayFrameCount = 0;
  204.         break;
  205.       case playBack:
  206.         // Stop if necessary
  207.         if(m_nState!=stStopped)
  208.           m_pVideoDecoder->Stop();
  209.  
  210.         // Start video
  211.         m_pVideoDecoder->Start(&video_opt);
  212.         m_nState = stPlayingBack;
  213.         break;
  214.       case ppChange:
  215.         pp.Stop();
  216.         m_pp = *((TPPost *)(sCommand.nParam));
  217.         pp.Set(&m_pp);
  218.         pp.Start();
  219.         frProcessedFrame.Set( pp.GetWidth(), pp.GetHeight(), FRAME_YV12 );
  220.         break;
  221.       case stop:
  222.         // Stop if necessary
  223.         if(m_nState!=stStopped)
  224.           m_pVideoDecoder->Stop();
  225.         m_nState = stStopped;
  226.         break;
  227.       case exit:
  228.         if(m_nState!=stStopped)
  229.           m_pVideoDecoder->Stop();
  230.         
  231.         if(video_opt.pFrameBuffer)
  232.           delete video_opt.pFrameBuffer;
  233.  
  234.         // Reply the command
  235.         ReplyCommand(&sCommand);
  236.         // Exit
  237.         return 0;
  238.         break;
  239.       }
  240.       ReplyCommand(&sCommand, nCommandResult);
  241.     }
  242.     else // No command. Wait if stopped
  243.     {
  244.       if(m_nState==stStopped)
  245.         WaitCommand();
  246.     }
  247.  
  248. // Perform action according the state of the playe
  249.  
  250.  
  251.     switch(m_nState)
  252.     {
  253.     case stStopped:
  254.       break;
  255.     case stPlaying:
  256.       if( !m_pVideoDecoder->GetFrame(&pDecodedFrame) )
  257.         Stop();
  258.  
  259.       // If there is a frame to display
  260.       // time it
  261.       if( pDecodedFrame )
  262.       {
  263.         // Timing
  264.         tkFrameDelay  = pDecodedFrame->GetDuration();
  265.         tkPresTime    = pDecodedFrame->GetPresTime()/2700;
  266.         tkCurrentTime = m_pMasterClock->GetTickCount();
  267.         
  268.         if ( !tkPresTime )// If we dont have presentation time wait the frame delay
  269.         { 
  270.           // FIXME
  271.           // THIS IS NOT CORRECT given that the decoding time is not
  272.           // instantaneous. You should wait less than the frame delay here.
  273.           m_pMasterClock->Wait( tkFrameDelay , tkFrameDelay );
  274.           DBG_STR((str, "NO TIMESTAMP. Waiting %I64d ms\n", tkFrameDelay/10))
  275.         }
  276.         else if ( tkPresTime >= tkCurrentTime )
  277.         {
  278.           perfState = perfNormal;
  279.           tkWaitTime = tkPresTime - tkCurrentTime;
  280.           m_pMasterClock->Wait( tkWaitTime, tkFrameDelay*4 );
  281.           // DBG_STR((str, "Presenting frame: DR:%I64d ms PTS:%I64d CT:%I64d ms\n", tkWaitTime/10, tkPresTime/10, tkCurrentTime/10))
  282.         }
  283.         else if ( (tkCurrentTime-tkPresTime) >= 2500 )
  284.         {
  285.           // If its late by 1000 ms or more, probably
  286.           // the video is lagging behind
  287.           // set the master clock back
  288.           
  289.           // tkPresTime is < tkCurrentTime
  290.           
  291.           // m_pMasterClock->Set(tkPresTime);
  292.           //DBG_STR((str, "Video lagging. Setting time to %I64d ms. Current Time was %I64d ms\n", 
  293.           //  tkPresTime/10, tkCurrentTime/10))
  294.           DBG_STR((str, "Video lagging behind.\n"));
  295.           perfState = perfIOnly;
  296.         }
  297.  
  298.         
  299.       }            
  300.  
  301.       m_lPlayFrameCount++;
  302.       break;
  303.     case stPlayingBack:
  304.       m_pVideoDecoder->GetPrevFrame(&pDecodedFrame);
  305.       break;
  306.     case stNextFrame:
  307.       m_pVideoDecoder->GetNextFrame(&pDecodedFrame);
  308.       m_pVideoDecoder->Stop();
  309.       m_nState = stStopped;
  310.       break;
  311.     case stPrevFrame:
  312.       m_pVideoDecoder->GetPrevFrame(&pDecodedFrame);
  313.       m_pVideoDecoder->Stop();
  314.       m_nState = stStopped;
  315.       break;
  316.     case stNextKeyFrame:
  317.       m_pVideoDecoder->GetNextIFrame(&pDecodedFrame);
  318.       m_pVideoDecoder->Stop();
  319.       m_nState = stStopped;
  320.       break;
  321.     case stPrevKeyFrame:
  322.       m_pVideoDecoder->GetPrevIFrame(&pDecodedFrame);
  323.       m_pVideoDecoder->Stop();
  324.       m_nState = stStopped;      
  325.       break;
  326.     case stFastForward:
  327.       m_pVideoDecoder->GetNextIFrame(&pDecodedFrame);  
  328.       break;
  329.     case stFastRewind:
  330.       m_pVideoDecoder->GetPrevIFrame(&pDecodedFrame);
  331.       break;    
  332.     }
  333.  
  334.     // If something to draw, draw it
  335.     if(pDecodedFrame)
  336.     {    
  337.       if( perfState == perfNormal || (m_lPlayFrameCount%20 == 0) || m_nState!=stPlaying )
  338.       {
  339.         // If there is a video sink, pass the frame over
  340.         if(m_pVidSink)
  341.           m_pVidSink->PutFrame(pDecodedFrame);
  342.  
  343.         // Continue regular renderer
  344.         pp.Process(pDecodedFrame, &frProcessedFrame);
  345.  
  346.        
  347.         rs.pVideoRenderer->Draw(&frProcessedFrame);        
  348.       }
  349.       pDecodedFrame->Release();
  350.     }
  351.  
  352.     // If we're going to stopeed, pause the video renderer
  353.     if(m_nState==stStopped)
  354.     {
  355.       rs.pVideoRenderer->StopPlaying();
  356.       if( pDecodedFrame ) rs.pVideoRenderer->SetStaticFrame(&frProcessedFrame);
  357.     }
  358.     else
  359.       rs.pVideoRenderer->StartPlaying();
  360.   }
  361.  
  362.   pp.Stop();
  363. }