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

  1. /* 
  2.  *  VideoWrapper.cpp 
  3.  *
  4.  *    Copyright (C) Alberto Vigata - January 2000  ultraflask@yahoo.com
  5.  *                 
  6.  *
  7.  *  This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
  8.  *    
  9.  *  FlasKMPEG is free software; you can redistribute it and/or modify
  10.  *  it under the terms of the GNU General Public License as published by
  11.  *  the Free Software Foundation; either version 2, or (at your option)
  12.  *  any later version.
  13.  *   
  14.  *  FlasKMPEG is distributed in the hope that it will be useful,
  15.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  *  GNU General Public License for more details.
  18.  *   
  19.  *  You should have received a copy of the GNU General Public License
  20.  *  along with GNU Make; see the file COPYING.  If not, write to
  21.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  22.  *
  23.  */
  24.  
  25.  
  26. #include "VideoWrapper.h"
  27. #include "..\Subpic\Subpic.h"
  28. #include "..\cpusupport.h"
  29. #include "..\flrandom.h"
  30. #include "debug.h"
  31.  
  32. extern "C"
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <ctype.h>
  36. #include <fcntl.h>
  37. #include <assert.h>
  38.  
  39. #define GLOBAL
  40. #include "config.h"
  41. #include "global.h"
  42. //#include "getbits.h"
  43. }
  44.  
  45.  
  46. #include "misc_tables.h"
  47.  
  48. //#define TRACK_FRAMEINFO
  49. #define ABS(x) ((x>0)? x:-x)
  50.  
  51. const i64 nJumpBackwards = 102400;
  52.  
  53. //Global variables for syncing with decoding thread
  54. VideoWrapper *myVideo;
  55. int             gopPOS;
  56. bool         closedGOP;
  57. bool         synced=false;
  58.  
  59.  
  60. // This function returns the position of the 
  61. // stream in offset bytes from the buffer
  62. // Defined in getbits.cpp
  63. extern          int Get_Buffer_Pos();
  64. extern          void Reset_Bits_Buffer();
  65. extern unsigned int Set_Buffer_State( ui8 *buffer, ui32 offset, ui32 buffersize );
  66. extern          void picture_data();
  67.  
  68. /* private prototypes */
  69. static int  video_sequence _ANSI_ARGS_((int *framenum));
  70. static int Decode_Bitstream _ANSI_ARGS_((void));
  71. static void Process_Options _ANSI_ARGS_((int argc, char *argv[]));
  72. static void InitClip();
  73. static void DeInitClip();
  74.  
  75. bool NextSequenceHeader(){
  76.  
  77.   ui32 nStartCode=Show_Bits(32);
  78.   while (nStartCode!=0x000001B3  && nStartCode!=0x000001B7)
  79.   { 
  80.     Flush_Buffer(8);
  81.     nStartCode = Show_Bits(32);
  82.   }
  83.   if(nStartCode!=0x000001B3)
  84.     return false;
  85.   else
  86.     return true;
  87. }
  88.  
  89.  
  90. VideoWrapper::VideoWrapper()
  91. {
  92.     time          = 0;
  93.     error         = 0;
  94.     pictureWidth  = 0;
  95.     pictureHeight = 0;
  96.     myVideo       = this;
  97.     stopDecoding  = false;
  98.   m_nLastDecodedPictureStart = 0;
  99.  
  100.  
  101.   m_bSequenceInitialized = false;
  102.   
  103.   
  104.   Idct          = NULL;
  105.   m_hModule     = NULL;
  106.  
  107. }
  108.  
  109. VideoWrapper::~VideoWrapper()
  110. {
  111.  
  112.     if(m_bSequenceInitialized)
  113.     {
  114.         
  115.         DeInitClip();
  116.         DeinitializeSequence();
  117.     }
  118.     if(m_hModule)
  119.         FreeLibrary( m_hModule );
  120. }
  121.  
  122. void VideoWrapper::LoadIdctModule( char *szTemp )
  123. {
  124.   FMpegIdct_PluginFunc iDctPlugFunc;
  125.   FMpegIdctInfo        iDctInfo;
  126.   fmGetPluginFuncPtr      getPluginFunc;
  127.  
  128.   long nSupportedExt = CPUGetSupportedExtensions();
  129.   long nSupportedExtIdct = 0;
  130.  
  131.   if( m_hModule = LoadLibrary( szTemp ) )
  132.   {
  133.     if( getPluginFunc = (fmGetPluginFuncPtr)GetProcAddress( m_hModule, "fmGetPluginFunc" ) )
  134.     {
  135.       getPluginFunc( &iDctPlugFunc );
  136.       if (iDctPlugFunc.GetIdct && iDctPlugFunc.GetIdctCount)
  137.       {
  138.         for( int i=0; i< iDctPlugFunc.GetIdctCount(); i++ )
  139.         {
  140.           iDctPlugFunc.GetIdct( i, &iDctInfo );
  141.           // Check that the CPU supports this iDCT
  142.           nSupportedExtIdct = 0;
  143.           // Adapt flags from CPU support to iDCT api conventions
  144.           nSupportedExtIdct |= nSupportedExt&CPU_SUPPORTS_MMX ? SUPPORTS_MMX : 0;
  145.           nSupportedExtIdct |= nSupportedExt&CPU_SUPPORTS_SSE ? SUPPORTS_SSE : 0;
  146.           nSupportedExtIdct |= nSupportedExt&CPU_SUPPORTS_SSE2 ? SUPPORTS_SSE2 : 0;
  147.           nSupportedExtIdct |= nSupportedExt&CPU_SUPPORTS_3DNOW ? SUPPORTS_3DNOW : 0;
  148.           nSupportedExtIdct |= nSupportedExt&CPU_SUPPORTS_3DNOW_EXT ? SUPPORTS_3DNOW_EXT : 0;
  149.           nSupportedExtIdct &= PROCESSOR_SUPPORT_MASK;
  150.  
  151.           // If all the CPU features are supported
  152.           if( (iDctInfo.dwFlags&PROCESSOR_SUPPORT_MASK) & nSupportedExtIdct)
  153.             m_vIdct.AddItem( &iDctInfo );
  154.           // If no special CPU features are required add it also
  155.           else if( !(iDctInfo.dwFlags&PROCESSOR_SUPPORT_MASK) )
  156.             m_vIdct.AddItem( &iDctInfo );
  157.         }
  158.       }
  159.     }
  160.   }
  161.  
  162. }
  163.  
  164.  
  165. bool VideoWrapper::IdctSpeedTest()
  166. {
  167.   FMpegIdctInfo        iDctInfo;
  168.   i64   nStartTime, nEndTime;
  169.   i64   nMinTime = MAXLONGLONG;
  170.   bool  bTimerError = false;
  171.   FlRandom *pRandGen = new FlRandom;
  172.  
  173.   CFrame frTestFrame(NULL);
  174.   // This will allocate a chunk of aligned memory 
  175.   // to 16bytes boundaries.
  176.   frTestFrame.Set( 8, 8*250, FRAME_RGB32 );
  177.   // Get the buffer
  178.   short *shortbuf = (short *)frTestFrame.GetBuffer();
  179.   // Randomize block
  180.   for(int k=0; k<(8*8*250); k++)
  181.     shortbuf[k] = (short)pRandGen->Random(0, 2048);
  182.   
  183.   for(int i=0; i<m_vIdct.GetCount(); i++)
  184.   {
  185.     iDctInfo = m_vIdct[i];
  186.  
  187.     void (* idct)(short *block) = iDctInfo.Idct;
  188.     
  189.     // Perform speed test
  190.     if(iDctInfo.InitIdct)
  191.       iDctInfo.InitIdct();
  192.  
  193.     short *block = shortbuf;
  194.     QueryPerformanceCounter( (LARGE_INTEGER *)&nStartTime );
  195.     for(int j=0; j<250; j++)
  196.     {
  197.       for(k=0; k<64;k++)
  198.         idct(block);
  199.       block+=64;
  200.     }
  201.     QueryPerformanceCounter( (LARGE_INTEGER *)&nEndTime );
  202.  
  203.     if(iDctInfo.DeInitIdct)
  204.       iDctInfo.DeInitIdct();    
  205.     
  206.     if(nEndTime==0)
  207.     {
  208.       bTimerError = true;
  209.       break;
  210.     }
  211.  
  212.  
  213.     i64 nTestTime = nEndTime - nStartTime;
  214.     if( nTestTime < nMinTime )
  215.     {
  216.       nMinTime = nTestTime;
  217.       SelectIdct(i);
  218.     }
  219.  
  220.   }
  221.   // If we couldnt use QueryPerformanceCounter
  222.   if(bTimerError)
  223.   {
  224.     // Look for one that supports MMX
  225.     for(int i=0; i<m_vIdct.GetCount(); i++)
  226.     {
  227.       iDctInfo = m_vIdct[i];
  228.       if(iDctInfo.dwFlags&SUPPORTS_MMX)
  229.       {
  230.         SelectIdct(i);
  231.         break;
  232.       }
  233.     }
  234.     if( i>=m_vIdct.GetCount() )
  235.       SelectIdct(0);
  236.   }
  237.   return true;
  238. }
  239.  
  240. bool VideoWrapper::LoadIDCTs()
  241. {
  242.   WIN32_FIND_DATA find_data;
  243.   char     directory[MAX_PATH], szTemp[MAX_PATH];
  244.   
  245.   HANDLE   search_handle;
  246.   int      i;
  247.   
  248.   
  249.   sprintf(directory, "%s\\*.idct.flask", program_directory );
  250.   
  251.   m_vIdct.EmptyArray();
  252.   
  253.   i=0;
  254.   search_handle = FindFirstFile(directory, &find_data);
  255.   if(search_handle==INVALID_HANDLE_VALUE){
  256.     m_vIdct.EmptyArray();
  257.   }
  258.   else{
  259.     sprintf(szTemp,"%s\\%s", program_directory, find_data.cFileName );
  260.     LoadIdctModule( szTemp );
  261.     
  262.     while( FindNextFile(search_handle, &find_data ) ){
  263.       sprintf(szTemp,"%s\\%s", program_directory, find_data.cFileName );
  264.       LoadIdctModule( szTemp );
  265.     }
  266.     FindClose(search_handle);
  267.   }
  268.   
  269.   IdctSpeedTest();
  270.  
  271.   return m_vIdct.GetCount() > 0;
  272. }
  273.  
  274. int VideoWrapper::Init(TVideoInit *pInitParams)
  275. {
  276.     int ret;
  277.  
  278.   strcpy( this->program_directory, pInitParams->ProgramDirectory );
  279.   // Try to load iDCTs from files
  280.   if(!LoadIDCTs())
  281.     return 0;
  282.   // testing
  283.  
  284.     VideoWrapper::streamID    = pInitParams->nStreamId;
  285.     VideoWrapper::subStreamID = pInitParams->nSubStreamId;
  286.  
  287.     VideoWrapper::subpic_streamID    = pInitParams->nSubpicStreamId;
  288.     VideoWrapper::subpic_substreamID = pInitParams->nSubpicSubstreamId;
  289.  
  290.  
  291.  
  292.     
  293.     //Start demuxer
  294.     if(!SetInput(pInitParams->pMismInfo))
  295.         return 0;
  296.  
  297.     InitClip();               /* Creating clipping vector */
  298.  
  299.   //MSSG decoder Initialization
  300.   ld               = &base; /* select base context */
  301.   Frame_Store_Flag = 1;     /* store full frames */
  302.   Output_Type=2;            /* YUV format output */
  303.   System_Stream_Flag = 0;
  304.   
  305.   FlushBuffer();
  306.  
  307.     m_pTempVideoBuffer     = NULL;
  308.  
  309.     //GET  SEQUENCE PROPERTIES
  310.     CDemux::SetStreamPos(0);
  311.     StartReadLPES();
  312.     Initialize_Buffer(); 
  313.   if(!NextSequenceHeader())
  314.     return 0;
  315.   
  316.     /* Headers returns when end of sequence (0) or picture
  317.        header has been parsed (1) */
  318.     ret = Get_Hdr();
  319.     if(ret==1)
  320.     {
  321.        //VIDEO SEQUENCE....
  322.       Sequence_Framenum=0;
  323.         InitializeSequence();
  324.         pictureWidth = Coded_Picture_Width;
  325.         pictureHeight= Coded_Picture_Height;
  326.  
  327.     m_bSequenceInitialized = true;
  328.     }
  329.   else
  330.     return 0;
  331.  
  332.   // Now, guess if this is 24fps 
  333.   detectedFrameRateCode = Is24Progressive() ? 1 : frame_rate_code;
  334.   updateVideoStats();
  335.  
  336.  
  337.     // Rewind stream
  338.     CDemux::SetStreamPos(0);
  339.     StartReadLPES();
  340.     Initialize_Buffer(); 
  341.     synced=true;
  342.   
  343.   // Store clut
  344.   pClut = pInitParams->clut;
  345.  
  346.     return 1;
  347. }
  348.  
  349. void VideoWrapper::FlushBuffer()
  350. {
  351.   m_pTempVideoBuffer     = NULL;
  352.   m_nTempVideoBufferPtr  = 0;
  353.   m_nTempVideoBufferSize = 0;
  354.   m_nPesPosState         = PesNotDefined;
  355.   Reset_Bits_Buffer();
  356. }
  357.  
  358. int VideoWrapper::Start(TVideoOptions *opt)
  359. {
  360.   
  361.  
  362.    m_bFronFrameIsReady = false;
  363.    m_pFrontFrame = m_pBackFrame = NULL;
  364.    m_pFrameBuffer = opt->pFrameBuffer;
  365. /*
  366.    // Output temporary YUV frame for adaptation to output
  367.    switch( m_nOutFormat )
  368.    {
  369.      case FRAME_RGB32:
  370.        m_oYuvFrame.Set( pictureWidth,  pictureHeight, FRAME_YUV444  );
  371.        m_oUtilFrame.Set( pictureWidth, pictureHeight, FRAME_RGB32 );
  372.        m_oYuvFrame.SetBuffer( (ui8*)&sYuvFrame );       
  373.        break;
  374.      case FRAME_YV12:
  375.        m_oYuvFrame.Set( pictureWidth,  pictureHeight, FRAME_YUV420 );
  376.        m_oUtilFrame.Set( pictureWidth, pictureHeight, FRAME_YV12 );
  377.        m_oYuvFrame.SetBuffer( (ui8*)&sYuvFrame );       
  378.        break;
  379.    }*/
  380.  
  381.  
  382.    m_bSyncedNotEnoughReferences = false;
  383.    m_bFirstPictureDecoded   = false;
  384.    m_bPreviousDirWasForward = false;
  385.  
  386.     time=0;
  387.     SelectIdct( opt->idctIndex ); 
  388.   /* IDCT */
  389.   if( myVideo->InitIdct )
  390.     myVideo->InitIdct();
  391.  
  392.     m_bTopFieldExpected = true;
  393.  
  394.     //Decoder Configuration
  395.     timeCode.frame=0;
  396.     timeCode.hour=0;
  397.     timeCode.minute=0;
  398.     timeCode.second=0;
  399.     stopDecoding=false;
  400.  
  401.   // Only allow recons_progressive flag if the frame rate is 29.97 or 30
  402.   if( frame_rate_code == 4 || frame_rate_code == 5 )
  403.     recons_progressive     = opt->recons_progressive;
  404.   else
  405.     recons_progressive = false;
  406.   
  407.   memset(&p, 0, sizeof(presTimes));
  408.     internalPTS=0;
  409.  
  410.     // Pull down stuff
  411.     pullDownDetected=false;
  412.     pulldown_state  = 3;
  413.     interlaced_field_delay = (__int64)(MPEG2_CLK_REF*(frameDelay))>>1;
  414.   progressive_frame_delay = (__int64)(MPEG2_CLK_REF*(1.25*frameDelay));
  415.  
  416.     Bitstream_Framenum = 0;
  417.     sequencePos=SEQ_FIRSTTIME;
  418.  
  419.  
  420.  
  421.   if( opt->bStartInSync )
  422.   {
  423.  
  424.     // During this start-stop sequence, only calls to GetFrame, can be performed
  425.     // Timestamps will be valid since the sync point.
  426.     // In the start part, we retrieve any possible references needed for the decoding
  427.     // of the first frame.
  428.     // We first set our position to the sync position
  429.     CDemux::SetStreamPos( opt->nSyncPoint );
  430.     // Flush the buffer
  431.     FlushBuffer();
  432.     // Now we decode the previous picture.
  433.     // This will retrieve any references needed.
  434.     // If there are not enough references available, inform about it
  435.     // (likely we're at the beginning of the file)
  436.     // First align the stream with the first picture to be decoded.
  437.     int nParams = SEARCH_P | SEARCH_I | SEARCH_B | SEARCH_FORWARD  | SEARCH_ALIGN_FIRST_FIELD;
  438.     // This shoudlnt fail
  439.     SearchPictureHeader( nParams );
  440.     // Now call DecodePictureEx that will decode the previous
  441.     // picture retrieving any references needed.
  442.     // Parse the start code so
  443.     ui32 dword;
  444.     GetFordDWord(&dword);
  445.     // Decode without forcing to retrieve the first availabe picture
  446.     DecodePictureEx(DECEX_PREV_PICTURE|DECEX_FORCEDECODING);
  447.  
  448.     // Reset the current timestamps because they are not valid at all.
  449.     p.forward.PTS = p.backward.PTS = 0;
  450.     p.forward.SCR = p.backward.SCR = 0;
  451.  
  452.     memset(&myPES, 0, sizeof(PESinfo));
  453.     // Now set the position back again to the sync point
  454.     CDemux::SetStreamPos( opt->nSyncPoint );
  455.     // Flag sync Decoding operation. i.e. only calls to getFrame can be performed.
  456.     m_bSyncedDecoding = true;
  457.     // Flush the buffer
  458.     FlushBuffer();
  459.     
  460.     //Read Linear PES init
  461.     StartReadLPES();
  462.     // Store the end point
  463.     m_nEndPoint = opt->nEndPoint;
  464.     if(m_nEndPoint <= opt->nSyncPoint)
  465.       m_nEndPoint = GetStreamSize();
  466.  
  467.     // That should do it!
  468.   }
  469.   else
  470.   {
  471.     m_bSyncedDecoding = false;
  472.   }
  473.     // Subpic init
  474.   if( subpic_streamID!=-1 )
  475.       subpic_init(pClut);
  476.  
  477.     return 1;
  478. }
  479.  
  480.  
  481. i64 inline VideoWrapper::get_time(int adjust_clock)
  482. {
  483.     i64    present;
  484.     i64    delay = (__int64)(MPEG2_CLK_REF*(frameDelay));
  485.     ui32  half_delay = (int)delay>>1;
  486.  
  487.  
  488.     if(p.image.PTS){
  489. #if DEBUG
  490.     if( ABS(internalPTS - p.image.PTS) > 900000 ) 
  491.       DBG_STR((str, "VideoWrapper::get_time() - Timestamp deviates from expected value by %I64d clock units or %I64d ms\n", internalPTS - p.image.PTS, (internalPTS - p.image.PTS)/27000));
  492. #endif
  493.         internalPTS = p.image.PTS;
  494.         switch( adjust_clock )
  495.         {
  496.             case EQUAL:
  497.                 present = internalPTS;
  498.                 break;
  499.             case PLUS:
  500.                 present = internalPTS = internalPTS + half_delay;
  501.                 break;
  502.             case MINUS:
  503.                 present = internalPTS = internalPTS - half_delay;
  504.                 break;
  505.         }
  506.  
  507.             internalPTS += i64(recons_progressive ? (1.25*(double)delay) : delay);    
  508.  
  509.     }
  510.     else{
  511.             present = internalPTS;
  512.             internalPTS += i64(recons_progressive ? (1.25*(double)delay) : delay);    
  513.     }
  514.     return present;
  515. }
  516.  
  517. // CFrame GetFrame
  518. // Frame source definition
  519. bool VideoWrapper::GetFrame(CFrame **pFrame)
  520. {
  521.   int nVal;
  522.   *pFrame = NULL;
  523.  
  524.   if( m_nLastDecodedPictureStart >= m_nEndPoint &&
  525.       m_bSyncedDecoding)
  526.     return false;  
  527.  
  528.     ui32  frame_delay = (ui32)(frameDelay * 10000.0);
  529.   ui32  progressive_frame_delay = (ui32)(1.25 * frameDelay * 10000.0);
  530.  
  531.  
  532.   if(!m_pFrontFrame)
  533.   {
  534.     m_pFrontFrame = m_pFrameBuffer->GetFreeFrame();
  535.     if(!m_pFrontFrame)
  536.       return false;
  537.   }
  538.  
  539.   if(!m_pBackFrame)
  540.   {
  541.     m_pBackFrame  = m_pFrameBuffer->GetFreeFrame();
  542.     if(!m_pBackFrame)
  543.       return false;
  544.   }
  545.  
  546.   
  547.   // If we already have a frame
  548.   // return it
  549.   if(m_bFronFrameIsReady)
  550.   {
  551.     *pFrame       = m_pFrontFrame;
  552.     m_pFrontFrame = m_pBackFrame;
  553.     m_pBackFrame  = NULL;
  554.     m_bFronFrameIsReady = false;
  555.     goto EndGetFrame;
  556.   }
  557.  
  558.   m_pFrontFrame->SetDuration( frame_delay );
  559.  
  560.   // Retrieve a frame
  561.   nVal = get_frame();
  562.   if(!nVal)
  563.     return false;
  564.  
  565.   
  566.   // Parse frame structure
  567.     if(progressive_sequence)
  568.   {
  569.         //Well, here MPEG2 standard defines 
  570.         // to output 1, 2 or 3 consecutive frames
  571.         // for 60 fps progressive output
  572.         // let's output just one
  573.         // This is the case of MPEG1 too
  574.     m_pFrontFrame->SetFrame(m_pDecoded);
  575.     m_pFrontFrame->SetPresTime( get_time(EQUAL) );
  576.     m_pFrontFrame->SetFlags( FRAME_PROGRESSIVE );
  577.  
  578.     *pFrame       = m_pFrontFrame;
  579.     m_pFrontFrame = m_pBackFrame;
  580.     m_pBackFrame  = NULL;
  581.     }
  582.   else
  583.   {
  584.         if(p.image.progressive_frame)
  585.         {
  586.             if(recons_progressive)
  587.       {
  588.         m_pFrontFrame->SetFrame(m_pDecoded);
  589.         m_pFrontFrame->SetPresTime( get_time(EQUAL) );
  590.         m_pFrontFrame->SetFlags( FRAME_PROGRESSIVE );
  591.         m_pFrontFrame->SetDuration( progressive_frame_delay );
  592.  
  593.         *pFrame       = m_pFrontFrame;
  594.         m_pFrontFrame = m_pBackFrame;
  595.         m_pBackFrame  = NULL;        
  596.         m_bTopFieldExpected = true;
  597.             }
  598.             else if(p.image.top_field_first)
  599.       {
  600.         m_pFrontFrame->SetFrame(m_pDecoded);
  601.         m_pFrontFrame->SetPresTime( get_time(EQUAL) );
  602.         m_pFrontFrame->SetFlags( FRAME_INTERLACED );
  603.  
  604.                 if(p.image.repeat_first_field )
  605.         {
  606.           m_pBackFrame->SetField(m_pDecoded, true);
  607.           m_pBackFrame->SetFlags( FRAME_TOPFIELD );
  608.           m_bTopFieldExpected = false;
  609.                 }
  610.         else
  611.           m_bTopFieldExpected = true;
  612.  
  613.         *pFrame       = m_pFrontFrame;
  614.         m_pFrontFrame = m_pBackFrame;
  615.         m_pBackFrame  = NULL;        
  616.       }
  617.             else //Bottom field first
  618.       {
  619.  
  620.         m_pFrontFrame->SetField(m_pDecoded, false);
  621.         m_pFrontFrame->SetPresTime( get_time(MINUS) );
  622.         m_pFrontFrame->SetFlags( FRAME_INTERLACED );
  623.  
  624.                 if(m_bTopFieldExpected)
  625.           m_pFrontFrame->SetField(m_pDecoded, true);
  626.  
  627.         m_pBackFrame->SetField(m_pDecoded, true);
  628.         if(p.image.repeat_first_field )
  629.         {
  630.           m_pBackFrame->SetField(m_pDecoded, false);
  631.           m_pBackFrame->SetPresTime( get_time(PLUS) );
  632.           m_bFronFrameIsReady = true;
  633.           m_bTopFieldExpected = true;
  634.         }
  635.         else
  636.           m_bTopFieldExpected = false;
  637.  
  638.         *pFrame       = m_pFrontFrame;
  639.         m_pFrontFrame = m_pBackFrame;
  640.         m_pBackFrame  = NULL;    
  641.             }
  642.     } 
  643.         else // Frame is interlaced
  644.     {
  645.             if( p.image.picture_structure == FRAME_PICTURE )
  646.       {
  647.                 if(p.image.top_field_first)
  648.         {
  649.           m_pFrontFrame->SetFrame(m_pDecoded);
  650.           m_pFrontFrame->SetPresTime( get_time(EQUAL) );
  651.           m_pFrontFrame->SetFlags( FRAME_INTERLACED );
  652.  
  653.           *pFrame       = m_pFrontFrame;
  654.           m_pFrontFrame = m_pBackFrame;
  655.           m_pBackFrame  = NULL; 
  656.           m_bTopFieldExpected = true;
  657.                 }
  658.                 else //bottom field first
  659.         {
  660.           m_pFrontFrame->SetField(m_pDecoded, false);
  661.           m_pFrontFrame->SetPresTime( get_time(MINUS) );
  662.           m_pFrontFrame->SetFlags( FRAME_INTERLACED );
  663.  
  664.           if(m_bTopFieldExpected)
  665.             m_pFrontFrame->SetField(m_pDecoded, true);
  666.           
  667.           m_pBackFrame->SetField(m_pDecoded, true);
  668.  
  669.           *pFrame       = m_pFrontFrame;
  670.           m_pFrontFrame = m_pBackFrame;
  671.           m_pBackFrame  = NULL; 
  672.           m_bTopFieldExpected = false;
  673.                 }
  674.             }
  675.             else // frames is reconstructed from field pictures
  676.       {
  677.         if(p.image.top_field_first)
  678.         {
  679.           m_pFrontFrame->SetFrame(m_pDecoded);
  680.           m_pFrontFrame->SetPresTime( get_time(EQUAL) );
  681.           m_pFrontFrame->SetFlags( FRAME_INTERLACED );
  682.           
  683.           *pFrame       = m_pFrontFrame;
  684.           m_pFrontFrame = m_pBackFrame;
  685.           m_pBackFrame  = NULL;
  686.           m_bTopFieldExpected = true;
  687.         }
  688.         else //bottom field first
  689.         {
  690.           m_pFrontFrame->SetField(m_pDecoded, false);
  691.           m_pFrontFrame->SetPresTime( get_time(MINUS) );
  692.           m_pFrontFrame->SetFlags( FRAME_INTERLACED );
  693.           
  694.           if(m_bTopFieldExpected)
  695.             m_pFrontFrame->SetField(m_pDecoded, true);
  696.           
  697.           m_pBackFrame->SetField(m_pDecoded, true);
  698.           
  699.           *pFrame       = m_pFrontFrame;
  700.           m_pFrontFrame = m_pBackFrame;
  701.           m_pBackFrame  = NULL; 
  702.           m_bTopFieldExpected = false;
  703.         }
  704.             }    
  705.         }
  706.     }
  707.  
  708. EndGetFrame:
  709.   // Apply subpictures
  710.   if( subpic_streamID!=-1 )
  711.     subpic_apply(*pFrame, (double)(*pFrame)->GetPresTime()/27000.0);
  712.  
  713. ;
  714.   return true;
  715. }
  716.  
  717. bool VideoWrapper::GetBackByte(ui8 *byte)
  718. {
  719.     bool bSuccess = true;
  720.   PESinfo dummyPES;
  721.  
  722.     // The offset has to be 
  723.     if( m_nTempVideoBufferPtr <= (i32)m_nTempVideoBufferSize )
  724.     {
  725.         // Grab previous PES if we're finished with this one
  726.         // or we don't have any data
  727.         if( m_nTempVideoBufferPtr <= 0 || !m_pTempVideoBuffer )
  728.         {
  729.             // The buffer has been underrun.
  730.             // Retrieve the previous buffer. This assumes that the position in the
  731.             // stream is exactly the byte after the latest PES.
  732.  
  733.             // Rewind PES
  734.             // If the pointer of the file is at the end
  735.             // of the Pes rewind this PES first
  736.             if( m_nPesPosState == PesEnd )
  737.                 bSuccess = RewindPreviousPES( streamID );
  738.             // Rewind again to find the real Pes
  739.             bSuccess = RewindPreviousPES( streamID );
  740.             ui64 PESpos = CDemux::GetStreamPos();
  741.  
  742.             if( bSuccess )
  743.             {
  744.                 // Read the PES
  745.                 // Invalid value for streamId
  746.                 dummyPES.streamID = 0xAA;
  747.                 while( bSuccess && dummyPES.streamID!=streamID )
  748.                 {
  749.                     bSuccess = ReadPES( (unsigned char **)&m_pTempVideoBuffer, &dummyPES );
  750.                     if( bSuccess )
  751.                     {
  752.                         m_nTempVideoBufferSize = dummyPES.payloadSize;
  753.                         m_nTempVideoBufferPtr  = dummyPES.payloadSize;
  754.                         // Update this two variables to be able to
  755.                         // reposition the stream after this.
  756.                         m_nPesPosState = PesBegin;
  757.                         m_nEndPesPosition = CDemux::GetStreamPos();
  758.                     }
  759.                 }
  760.                 // Because we want to emulate the going backwards 
  761.                 // behaviour, set the position to the beginning of the PES
  762.                 // again
  763.                 CDemux::SetStreamPos( PESpos );
  764.             }
  765.             else
  766.                 DBG_STR((str, "VideoWrapper::GetBackByte() - Couldnt rewind PES\n"));
  767.         }
  768.  
  769.         // There are still bytes in this buffer to gather.
  770.         if( bSuccess )
  771.         {    
  772.             m_nTempVideoBufferPtr--;
  773.             *byte = *(m_pTempVideoBuffer + m_nTempVideoBufferPtr);
  774.         }        
  775.     }
  776.     else
  777.     {
  778.         DBG_STR((str, "VideoWrapper::GetBackByte() - Buffer offset outside bounds\n"))
  779.         bSuccess = false;
  780.     }
  781.     return bSuccess;
  782. }
  783.  
  784. bool VideoWrapper::GetFordByte(ui8 *byte)
  785. {
  786.     bool    bSuccess = true;
  787.   PESinfo dummyPES;
  788.  
  789.     // The offset has to be minor than the buffer size
  790.     if( m_nTempVideoBufferPtr <= (i32)m_nTempVideoBufferSize )
  791.     {
  792.         // Grab previous PES if we're finished with this one
  793.         if( m_nTempVideoBufferPtr >= (i32)m_nTempVideoBufferSize || !m_pTempVideoBuffer)
  794.         {
  795.             // Read the PES
  796.             // If the pointer is a the beginning of the Pes
  797.             // We just read, read it again to parse it. 
  798.             if( m_nPesPosState == PesBegin )
  799.                 bSuccess = ReadPES( (unsigned char **)&m_pTempVideoBuffer, &dummyPES );
  800.  
  801.             // Invalid value for streamId
  802.             dummyPES.streamID = 0xAA;
  803.             while( bSuccess && dummyPES.streamID!=streamID )
  804.             {
  805.                 bSuccess = ReadPES( (unsigned char **)&m_pTempVideoBuffer, &dummyPES );
  806.                 if( bSuccess && dummyPES.streamID==streamID )
  807.                 {
  808.                     m_nPesPosState = PesEnd;
  809.                     m_nTempVideoBufferSize = dummyPES.payloadSize;
  810.                     m_nTempVideoBufferPtr  = 0;                    
  811.                 }
  812.             }
  813.         }
  814.         // There are still bytes in this buffer to gather.
  815.         if( bSuccess )
  816.         {
  817.             *byte = *(m_pTempVideoBuffer + m_nTempVideoBufferPtr);
  818.             m_nTempVideoBufferPtr++;            
  819.         }        
  820.     }
  821.     else
  822.     {
  823.         bSuccess = false;
  824.     }
  825.     return bSuccess;
  826.             
  827. }
  828. bool VideoWrapper::GetFordDWord(ui32 *dword)
  829. {
  830.     ui8 byte;
  831.  
  832.     *dword = 0;
  833.  
  834.     bool bSuccess = GetFordByte( &byte );
  835.     *dword = byte << 24;
  836.     if( bSuccess )
  837.         bSuccess = GetFordByte( &byte );
  838.     *dword |= byte << 16;
  839.     if( bSuccess )
  840.         bSuccess = GetFordByte( &byte );
  841.     *dword |= byte << 8;        
  842.     if( bSuccess )
  843.         bSuccess = GetFordByte( &byte );
  844.     *dword |= byte;    
  845.     
  846.     return bSuccess;
  847. }
  848.  
  849. bool VideoWrapper::SearchPictureHeader( int &nParams )
  850. {
  851.     bool bSuccess=true;
  852.     bool bFound = false;
  853.    i32 nParsedBytes;
  854.   ui32 nPictureType;
  855.   ui32 nPrevPictureType;
  856.   ui32 nTemporalReference;
  857.   ui64 nFirstFieldPictureStartPos=0;
  858.   bool bLookingSecondField=false;
  859.   ui32 nPrevTemporalReference;
  860.   ui16 nVBVDelay;
  861.   ui8  nPictureStructure;
  862.     
  863.     ui8  byte;
  864.     
  865.     while( !bFound && bSuccess )
  866.     {
  867.         ui32 nStartCode = 0xFFFFFFFF;
  868.         
  869.         // Select direccion of search
  870.         if( nParams&SEARCH_BACKWARDS )
  871.             while( nStartCode!=PICTURE_START_CODE && bSuccess )
  872.             {
  873.                 bSuccess = GetBackByte(&byte);
  874.                 nStartCode = (nStartCode>>8) | (byte<<24);
  875.             }
  876.             else
  877.                 while( nStartCode!=PICTURE_START_CODE && bSuccess )
  878.                 {
  879.                     bSuccess = GetFordByte(&byte);
  880.                     nStartCode = (nStartCode<<8) | byte;
  881.                 }
  882.                 
  883.                 if( bSuccess )
  884.                 {
  885.                     // We found a picture header and we are aligned with it
  886.                     // Get start code
  887.                     // Only parse the start code if we were reading
  888.                     // backwards
  889.  
  890.                     if( nParams&SEARCH_BACKWARDS )
  891.                         GetFordDWord(&nStartCode);
  892.  
  893.                     GetFordByte(&byte);
  894.           nTemporalReference = byte << 2;
  895.                     GetFordByte(&byte);
  896.           nTemporalReference |= (byte&0xC0)>>6;
  897.  
  898.           nParsedBytes = 6;
  899.                     nPictureType = (byte&0x3F)>>3;
  900.  
  901.           // If we're not interested in this type
  902.           // continue searching
  903.  
  904. #define FOUND_TYPE  ((nPictureType==P_TYPE && nParams&SEARCH_P) ||  \
  905.                      (nPictureType==B_TYPE && nParams&SEARCH_B) ||  \
  906.                      (nPictureType==I_TYPE && nParams&SEARCH_I) )
  907.  
  908. #if 0
  909.           char cTypes[] = {'X','I','P','B','X','X','X','X','X','X','X','X','X','X','X','X'};
  910.           DBG_STR((str, "VideoWrapper::SearchPictureHeader - %c picture found at %d\n", cTypes[nPictureType], GetStreamPos()-6))
  911. #endif
  912.         
  913.           if( nParams&SEARCH_ALIGN_FIRST_FIELD )
  914.           {
  915.             // parse the rest of the header
  916.             nVBVDelay  = (byte&0x07)<<13;
  917.             GetFordByte(&byte);
  918.             nVBVDelay |= byte<<5;
  919.             GetFordByte(&byte);
  920.             nVBVDelay |= (byte&0xF8)>>3;
  921.  
  922.             nParsedBytes += 2;
  923.             // Keep track of the bits remaining in 'byte'
  924.             // Now we have 3 bits remaining.
  925.             ui32 nBitsRemaining = 3;
  926.  
  927.  
  928. #define Rewind(x) { for(int i=0; i<x; i++) GetBackByte(&byte); }
  929.  
  930.             // Find next start code prefix
  931.             ui32 nStartCode = 0xFFFFFF00;
  932.             while( (nStartCode&0x00FFFFFF)!=1 && bSuccess )
  933.             {
  934.               bSuccess = GetFordByte(&byte);
  935.               nParsedBytes += 1;
  936.               nStartCode = (nStartCode<<8) | byte;
  937.             }
  938.  
  939.             if(!bSuccess) continue;
  940.             GetFordByte(&byte);
  941.             nParsedBytes += 1;
  942.             if(byte!=0xB5)
  943.             {
  944.               // Either this is MPEG1 or something wrong happened
  945.               goto validate;
  946.             }
  947.  
  948.             GetFordByte(&byte);
  949.             if((byte>>4)!=8) // The extension_start_code_identifier is 8 for picture
  950.               continue;      // something wrong happened
  951.  
  952.             nParsedBytes += 1;
  953.             GetFordByte(&byte); // parse some stuff
  954.             GetFordByte(&byte);
  955.             nParsedBytes += 2;
  956.             nPictureStructure = byte&0x03;
  957.  
  958.             bool bJumpToPos = false;
  959.             if(nPictureStructure==FRAME_PICTURE){
  960.               if(FOUND_TYPE)
  961.               {
  962.                 bFound = true;
  963.                 SetSearchType( nParams, nPictureType );
  964.               }
  965.             }
  966.             else{// we have a field picture
  967.               if( !bLookingSecondField ){
  968.                 nFirstFieldPictureStartPos = GetStreamPos() - nParsedBytes;
  969.                 nPrevTemporalReference = nTemporalReference;
  970.                 nPrevPictureType       = nPictureType;
  971.                 bLookingSecondField = true;
  972.               }
  973.               else
  974.               {
  975.                 // In this two field pictures, the temporal reference
  976.                 // matches. These two form the frame picture. Position
  977.                 // ourselves in the first one.                
  978.                 if( nPrevTemporalReference==nTemporalReference ){
  979.                   // If we're going forward, it was the previous one
  980.                   if(nParams&SEARCH_FORWARD)
  981.                   {
  982.                     bJumpToPos = true;
  983.                     nPictureType = nPrevPictureType;
  984.                   }
  985.                 }
  986.                 else{
  987.                   if(nParams&SEARCH_BACKWARDS)
  988.                   {
  989.                     bJumpToPos = true;
  990.                     nPictureType = nPrevPictureType;
  991.                   }
  992.                 }
  993.                 Second_Field = 0;
  994.                 if(FOUND_TYPE)
  995.                 {
  996.                   SetSearchType( nParams, nPictureType );                  
  997.                   bFound = true;
  998.                 }
  999.                 bLookingSecondField = false;
  1000.               }
  1001.             }
  1002.             if(bFound || nParams&SEARCH_BACKWARDS)
  1003.             {
  1004.               if(bJumpToPos)
  1005.                   SetStreamPos(nFirstFieldPictureStartPos);
  1006.               else
  1007.                   Rewind(nParsedBytes);
  1008.             }
  1009.  
  1010.           }
  1011.           else
  1012.           {
  1013. validate:
  1014.             if(FOUND_TYPE)
  1015.             {
  1016.               bFound = true;
  1017.               SetSearchType( nParams, nPictureType );
  1018.             }
  1019.             if( bFound || nParams&SEARCH_BACKWARDS )
  1020.             {
  1021.               Rewind(nParsedBytes);
  1022.             }              
  1023.           }
  1024.         }
  1025.     }
  1026.     return bSuccess;
  1027. }
  1028.  
  1029. bool VideoWrapper::EnterCoreContext()
  1030. {
  1031.     Set_Buffer_State( m_pTempVideoBuffer, 
  1032.                       m_nTempVideoBufferPtr, 
  1033.                       m_nTempVideoBufferSize );
  1034.     return true;
  1035. }
  1036.  
  1037. bool VideoWrapper::ExitCoreContext()
  1038. {
  1039.     m_nTempVideoBufferPtr = Get_Buffer_Pos();
  1040.   // If the pos is <0 means that the current position
  1041.   // of the video buffer belongs to a previous buffer
  1042.   // Rewind it
  1043.   if( m_nTempVideoBufferPtr<0 )
  1044.   {
  1045.     int nRewindBytes = -m_nTempVideoBufferPtr;
  1046.     // Set the beginning of the buffer
  1047.     m_nTempVideoBufferPtr = 0;
  1048.     // Rewind
  1049.     ui8 byte;
  1050.     for(int i=0; i<nRewindBytes; i++) 
  1051.       GetBackByte(&byte);
  1052.   }
  1053.     return true;
  1054. }
  1055.  
  1056.  
  1057. ////////////////////////////////////////////////////////////////////////////////
  1058. //
  1059. // Navigational retrieving methods. Timestamps are not valid within this context.
  1060. //
  1061. ////////////////////////////////////////////////////////////////////////////////
  1062.  
  1063. void VideoWrapper::UpdateDecodedPtr()
  1064. {
  1065.   unsigned char *pDecoded;
  1066.   pDecoded = p.actual.picture_coding_type==B_TYPE ? auxframe[0] : forward_reference_frame[0];
  1067.  
  1068.   for(int i=0; i<3; i++)
  1069.     if( pDecoded==(unsigned char *)m_frRef[i].GetBuffer() )
  1070.       break;
  1071.  
  1072.   m_pDecoded = &m_frRef[i];
  1073.  
  1074.   // Update picture info
  1075.   p.image = p.actual.picture_coding_type==B_TYPE ? p.actual : p.forward;
  1076. }
  1077.  
  1078. //-------------------------------------------------------------------
  1079. // GetSingleFrame - pFrame should be copied and not used directly.
  1080. //-------------------------------------------------------------------
  1081. inline bool VideoWrapper::GetSingleFrame(CFrame **pFrame, int nFlags)
  1082. {
  1083.  
  1084.   DecodePictureEx(nFlags);
  1085.   UpdateDecodedPtr();
  1086.  
  1087.   if(m_bReadError)
  1088.     error=END_OF_STREAM;
  1089.  
  1090.   bool bSuccess =!m_bReadError;
  1091.   if(!bSuccess)
  1092.   {
  1093.     *pFrame = NULL;
  1094.     return false;
  1095.   }
  1096.  
  1097.   *pFrame = m_pDecoded;
  1098.   return false;
  1099. }
  1100.  
  1101.  
  1102. bool VideoWrapper::GetNextFrame( CFrame **pFrame )
  1103.   return GetSingleFrame(pFrame, DECEX_NEXT_PICTURE);
  1104. }
  1105.  
  1106. bool VideoWrapper::GetPrevFrame( CFrame **pFrame )
  1107.   return GetSingleFrame(pFrame, DECEX_PREV_PICTURE);
  1108. }
  1109.  
  1110. bool VideoWrapper::GetNextIFrame(CFrame **pFrame)
  1111. {
  1112.   return GetSingleFrame(pFrame, DECEX_NEXT_PICTURE|DECEX_JUST_IPICTURE);
  1113. }
  1114.  
  1115. bool VideoWrapper::GetPrevIFrame(CFrame **pFrame)
  1116. {
  1117.   return GetSingleFrame(pFrame, DECEX_PREV_PICTURE|DECEX_JUST_IPICTURE);
  1118. }
  1119.  
  1120.  
  1121. int VideoWrapper::DecodePictureEx( int nDecExParams )
  1122. {
  1123.     int nRetValue=0;
  1124.     int nPictureTypes, nDecodingModes;
  1125.     int nParams;
  1126.     
  1127.     nPictureTypes = nDecExParams&DECEX_JUST_IPICTURE ? 
  1128.                     SEARCH_I : 
  1129.                     SEARCH_I | SEARCH_B | SEARCH_P;
  1130.  
  1131.     // If just I picture was demanded, skip references search
  1132.     nDecodingModes = nDecExParams&DECEX_JUST_IPICTURE ? 
  1133.                      SKIP_REF_SEARCH|DECODING_PICTURE : DECODING_PICTURE;
  1134.  
  1135.     if( nDecExParams&DECEX_NEXT_PICTURE )
  1136.     {
  1137.         nParams = nPictureTypes | SEARCH_FORWARD | SEARCH_ALIGN_FIRST_FIELD;
  1138.         if( SearchPictureHeader( nParams ) )
  1139.         {
  1140.             if( m_bFirstPictureDecoded )
  1141.             {
  1142.               nDecodingModes |= SKIP_REF_SEARCH;
  1143.               nRetValue = DecodePicture(nDecodingModes);
  1144.             }
  1145.             else
  1146.             {
  1147.                 m_bFirstPictureDecoded = true;
  1148.                 nRetValue = DecodePicture(nDecodingModes);
  1149.                 // This is here in the case of an I frame. Likely the first
  1150.                 // of the stream 
  1151.                 // Decode next picture. Should be a P.
  1152.                 while( nRetValue==DEC_NOTENOUGHREF && 
  1153.                        !m_bReadError &&
  1154.                        !(nDecExParams&DECEX_FORCEDECODING)) // this will return DEC_NOTENOUGHREF
  1155.                     nRetValue=DecodePicture(nDecodingModes);
  1156.             }
  1157.             m_bPreviousDirWasForward = true;
  1158.         }
  1159.     }
  1160.     else
  1161.     {
  1162.         // Now rewind picture just decoded
  1163.         nParams = nPictureTypes | SEARCH_BACKWARDS | SEARCH_ALIGN_FIRST_FIELD;
  1164.         SearchPictureHeader( nParams );
  1165.         
  1166.         nParams = nPictureTypes | SEARCH_BACKWARDS | SEARCH_ALIGN_FIRST_FIELD;
  1167.         DBG_STR((str, "VideoWrapper::DecodePictureEx - back decoding starting at %d\n", GetStreamPos()))        
  1168.         if( SearchPictureHeader( nParams ) )
  1169.         {
  1170.             m_bFirstPictureDecoded = false;
  1171.             nRetValue = DecodePicture(nDecodingModes);
  1172.             // This is here in the case of an I frame. Likely the first
  1173.             // of the stream 
  1174.             // Decode next picture. Should be a P.
  1175.             while( nRetValue==DEC_NOTENOUGHREF && 
  1176.                   !m_bReadError &&
  1177.                   !(nDecExParams&DECEX_FORCEDECODING)) // this will return DEC_NOTENOUGHREF
  1178.               nRetValue=DecodePicture(nDecodingModes);
  1179.         }
  1180.         //DBG_STR((str, "VideoWrapper::DecodePictureEx - back decoding stopping at %d\n", GetStreamPos()))
  1181.         m_bPreviousDirWasForward = false;
  1182.     }
  1183.     // If just and I picture was demanded, reposition the stream
  1184.     // to the frame after the next I or P picture, because DECEX_JUST_IPICTURE makes
  1185.     // the decoder to output the I picture without references.
  1186.     if( nDecExParams&DECEX_JUST_IPICTURE )
  1187.     {
  1188.       // Search the next I or P
  1189.       nParams = SEARCH_P | SEARCH_I | SEARCH_FORWARD | SEARCH_ALIGN_FIRST_FIELD;
  1190.       SearchPictureHeader( nParams );
  1191.       // Get one byte to avoid aligning to the I or P again
  1192.       ui8 byte;
  1193.       GetFordByte(&byte);
  1194.       // Align to the frame after it
  1195.       nParams = SEARCH_P | SEARCH_I | SEARCH_B | SEARCH_FORWARD | SEARCH_ALIGN_FIRST_FIELD;
  1196.       SearchPictureHeader( nParams );       
  1197.     }
  1198.  
  1199.     return nRetValue;
  1200. }
  1201.  
  1202. int VideoWrapper::DecodePicture(int nDecParams)
  1203. {
  1204.     ui64 nPicturePos;
  1205.     int  nParams, cc;
  1206.     unsigned char *tmp;  /* temporary swap pointer */
  1207.     bool bSuccess;
  1208.   int  nReturn = DEC_OK;
  1209.     
  1210.   // Our goal is to decode the picture that is this position.
  1211.   // Parse picture header
  1212.   nParams  = SEARCH_P | SEARCH_I | SEARCH_B | SEARCH_FORWARD | SEARCH_ALIGN_FIRST_FIELD;
  1213.   if(!(nDecParams&SKIP_REF_SEARCH))
  1214.   {
  1215.     if( SearchPictureHeader( nParams )  )
  1216.     {
  1217.       // If we are told NOT to search
  1218.       // for references skip this section.
  1219.       // This is flagged when we already have
  1220.       // the correct references.
  1221.       
  1222.       // Retrieve position of this picture
  1223.       nPicturePos = GetStreamPos();
  1224.       
  1225.       switch( GetSearchType( nParams ) )
  1226.       {
  1227.       case I_TYPE:
  1228.         // No references pictures needed. Decode picture right away.
  1229.         // However the output will be the previous I or P
  1230.         // Retrieve it only if we this is the first call to DecodePicture,
  1231.         // i.e. we're not doing recursive calls to DecodePicture to retrieve 
  1232.         // references.
  1233.         // Backward reference needed
  1234.         if( nDecParams&DECODING_PICTURE )
  1235.         {
  1236.           nParams = SEARCH_I | SEARCH_P | SEARCH_BACKWARDS | SEARCH_ALIGN_FIRST_FIELD;
  1237.           if( SearchPictureHeader( nParams ) )
  1238.             // We found the previous P or I picture. Decode it.
  1239.             nReturn = DecodePicture();
  1240.           else
  1241.             nReturn = DEC_NOTENOUGHREF;
  1242.         }
  1243.         break;            
  1244.       case P_TYPE:
  1245.         // Backward reference needed
  1246.         nParams = SEARCH_I | SEARCH_P | SEARCH_BACKWARDS  | SEARCH_ALIGN_FIRST_FIELD;
  1247.         if( SearchPictureHeader( nParams ) )
  1248.         {
  1249.           // We found the previous P or I picture. Decode it.
  1250.           nReturn = DecodePicture();
  1251.           // Put this P or I frame as reference 
  1252.         }
  1253.         else
  1254.           nReturn = DEC_NOTENOUGHREF;
  1255.         // Rewind stream to find previous I or P picture.
  1256.         // Decode it and put it as reference. Come back to this place.
  1257.         break;
  1258.       case B_TYPE:
  1259.         ui64 nFirstRefPos = -1;
  1260.         bool bFirstRefOk=false, bSecondRefOk=false;
  1261.         // Search for the previous I or P
  1262.         nParams = SEARCH_P | SEARCH_I | SEARCH_BACKWARDS  | SEARCH_ALIGN_FIRST_FIELD;
  1263.         bSuccess = SearchPictureHeader( nParams );
  1264.         if(bSuccess)
  1265.         {
  1266.           nFirstRefPos = GetStreamPos();
  1267.           
  1268.           // Search for the previous I or P picture again
  1269.           nParams = SEARCH_P | SEARCH_I | SEARCH_BACKWARDS  | SEARCH_ALIGN_FIRST_FIELD;
  1270.           bSuccess = SearchPictureHeader( nParams );
  1271.           if( bSuccess )
  1272.             bFirstRefOk = DecodePicture()!=DEC_NOTENOUGHREF;
  1273.         }
  1274.         // If we found the first reference decode it
  1275.         if( nFirstRefPos != -1 )
  1276.         {
  1277.           // Set the stream to the first reference
  1278.           // we found
  1279.           SetStreamPos( nFirstRefPos );
  1280.           // Decode it
  1281.           bSecondRefOk = DecodePicture()!=DEC_NOTENOUGHREF;
  1282.         }
  1283.         
  1284.         nReturn = ( bSuccess && bFirstRefOk && bSecondRefOk ) ? DEC_OK : DEC_NOTENOUGHREF;
  1285.         break;
  1286.       }
  1287.       
  1288.       // Restore position of the beginning of this picture
  1289.       SetStreamPos( nPicturePos );
  1290.     }
  1291.   } 
  1292.  
  1293.   if(!Second_Field)
  1294.     m_nLastDecodedPictureStart = GetStreamPos();
  1295.   
  1296.   // Don't enter and exit context if we are in continous reading mode!
  1297.   if(!(nDecParams&CONTINOUS_READING))  
  1298.     EnterCoreContext();
  1299.  
  1300.   // We should be align to the first field by now.
  1301.   Second_Field = 0;
  1302.   
  1303. start_decode:
  1304.   if(Get_Hdr())
  1305.   {
  1306.     if (picture_structure==FRAME_PICTURE && Second_Field)
  1307.     {
  1308.       DBG_STR((str, "VideoWrapper::DecodePicture - Odd number of field pictures\n"));
  1309.       Second_Field = 0;
  1310.     }            
  1311.  
  1312.     if( !(nDecParams&DONT_UPDATE_REF) )
  1313.     {
  1314.       // DBG_STR((str, "VideoWrapper::DecodePicture - pic type %d  sec field %d\n", picture_coding_type,Second_Field));
  1315.       // Update picture buffers
  1316.       for (cc=0; cc<3; cc++)
  1317.       {
  1318.         /* B pictures do not need to be saved for future reference */
  1319.         if (picture_coding_type==B_TYPE)
  1320.         {
  1321.           current_frame[cc] = auxframe[cc];
  1322.         }
  1323.         else
  1324.         {
  1325.           /* only update at the beginning of the coded frame */
  1326.           if (!Second_Field)
  1327.           {
  1328.             tmp = forward_reference_frame[cc];
  1329.             
  1330.             /* the previously decoded reference frame is stored
  1331.             coincident with the location where the backward 
  1332.             reference frame is stored (backwards prediction is not
  1333.             needed in P pictures) */
  1334.             forward_reference_frame[cc] = backward_reference_frame[cc];
  1335.             
  1336.             /* update pointer for potential future B pictures */
  1337.             backward_reference_frame[cc] = tmp;                
  1338.           }
  1339.           
  1340.           /* can erase over old backward reference frame since it is not used
  1341.           in a P picture, and since any subsequent B pictures will use the 
  1342.           previously decoded I or P frame as the backward_reference_frame */
  1343.           current_frame[cc] = backward_reference_frame[cc];
  1344.         }
  1345.         /* IMPLEMENTATION:
  1346.         one-time folding of a line offset into the pointer which stores the
  1347.         memory address of the current frame saves offsets and conditional 
  1348.         branches throughout the remainder of the picture processing loop */
  1349.         if (picture_structure==BOTTOM_FIELD)
  1350.           current_frame[cc]+= (cc==0) ? Coded_Picture_Width : Chroma_Width;
  1351.       }
  1352.     }
  1353.     // Finally decode the picture data
  1354.     picture_data();
  1355.     
  1356.     if (picture_structure!=FRAME_PICTURE)
  1357.       Second_Field = !Second_Field;
  1358.  
  1359.     if (picture_structure!=FRAME_PICTURE && Second_Field)
  1360.       goto start_decode;
  1361.  
  1362.   }
  1363.   else
  1364.   {
  1365.     DBG_STR((str, "VideoWrapper::DecodePicture - GetHdr() failed.\n"));    
  1366.   }
  1367.   // Don't enter and exit context if we are in continous reading mode!
  1368.   if(!(nDecParams&CONTINOUS_READING))    
  1369.     ExitCoreContext();
  1370.  
  1371.   return nReturn;
  1372. }
  1373.  
  1374.  
  1375.  
  1376. bool VideoWrapper::get_frame()
  1377. {  
  1378.     updateVideoStats();
  1379.     
  1380.     time= (ui32)(double(GetTime())/ (double)27000); //miliseconds
  1381.     //In case  there is a problem
  1382.     timeCode.hour= hour;
  1383.     timeCode.minute= minute;
  1384.     timeCode.second= sec;
  1385.     timeCode.frame=  frame;
  1386.     
  1387.     if(stopDecoding){
  1388.         error=PLAYER_STOPPED;
  1389.         return 0;
  1390.     }
  1391.     
  1392.     if(m_bSyncedDecoding)
  1393.     {
  1394.       int nDecodingModes = SKIP_REF_SEARCH|DECODING_PICTURE|CONTINOUS_READING;
  1395.       // Decode an extra picture if we don't have enough references
  1396.       DecodePicture(nDecodingModes);
  1397.  
  1398.     }
  1399.     else
  1400.     {
  1401.       DecodePictureEx(DECEX_NEXT_PICTURE);
  1402.     }
  1403.  
  1404. #ifdef TRACK_FRAMEINFO
  1405.     DBG_STR(( str, "Frame info: Type= %d, Int=%s, TS = %d\n", p.actual.picture_coding_type,
  1406.               p.actual.progressive_frame ? "Yes" : "No",
  1407.               p.actual.PTS / 300));
  1408. #endif
  1409.  
  1410.     UpdateDecodedPtr();
  1411.  
  1412.     if(m_bReadError)
  1413.         error=END_OF_STREAM;
  1414.  
  1415.     return !m_bReadError;
  1416. }
  1417.  
  1418.  
  1419. int VideoWrapper::Stop()
  1420. {
  1421.  
  1422.  
  1423.   if(m_pFrontFrame)
  1424.     m_pFrontFrame->Release();
  1425.   if(m_pBackFrame)  
  1426.     m_pBackFrame->Release();
  1427.  
  1428.     time=0;
  1429.   if( subpic_streamID!=-1 )
  1430.       subpic_free(); /* reset subpics */
  1431.  
  1432.   /* IDCT */
  1433.   if( myVideo->DeInitIdct )
  1434.     myVideo->DeInitIdct();
  1435.     return 0;
  1436. }
  1437.  
  1438. void DeInitClip(){
  1439.     free(Clip-384);
  1440. }
  1441. void InitClip(){
  1442.  
  1443.   int i;
  1444.  
  1445.   /* Clip table */
  1446.   if (!(Clip=(unsigned char *)malloc(1024)))
  1447.     Error("Clip[] malloc failed\n");
  1448.  
  1449.   Clip += 384;
  1450.  
  1451.   for (i=-384; i<640; i++)
  1452.     Clip[i] = (i<0) ? 0 : ((i>255) ? 255 : i);
  1453. }
  1454.  
  1455. /* mostly IMPLEMENTAION specific rouintes */
  1456. void VideoWrapper::InitializeSequence()
  1457. {
  1458.   int size, chroma_size, luma_size;
  1459.   static int Table_6_20[3] = {6,8,12};
  1460.  
  1461.   /* check scalability mode of enhancement layer */
  1462.   if (Two_Streams && (enhan.scalable_mode!=SC_SNR) && (base.scalable_mode!=SC_DP))
  1463.     Error("unsupported scalability mode\n");
  1464.  
  1465.   /* force MPEG-1 parameters for proper decoder behavior */
  1466.   /* see ISO/IEC 13818-2 section D.9.14 */
  1467.   if (!base.MPEG2_Flag)
  1468.   {
  1469.     progressive_sequence = 1;
  1470.     progressive_frame = 1;
  1471.     picture_structure = FRAME_PICTURE;
  1472.     frame_pred_frame_dct = 1;
  1473.     chroma_format = CHROMA420;
  1474.     matrix_coefficients = 5;
  1475.   }
  1476.  
  1477.   /* round to nearest multiple of coded macroblocks */
  1478.   /* ISO/IEC 13818-2 section 6.3.3 sequence_header() */
  1479.   mb_width = (horizontal_size+15)/16;
  1480.   mb_height = (base.MPEG2_Flag && !progressive_sequence) ? 2*((vertical_size+31)/32)
  1481.                                         : (vertical_size+15)/16;
  1482.  
  1483.   Coded_Picture_Width = 16*mb_width;
  1484.   Coded_Picture_Height = 16*mb_height;
  1485.  
  1486.     //Allocate space for Output Bitmap
  1487.    //DibArray=malloc(         Coded_Picture_Width * Coded_Picture_Height * 3 );  
  1488.     //DibArray = TempArray;
  1489.  
  1490.   /* ISO/IEC 13818-2 sections 6.1.1.8, 6.1.1.9, and 6.1.1.10 */
  1491.   Chroma_Width = (chroma_format==CHROMA444) ? Coded_Picture_Width
  1492.                                            : Coded_Picture_Width>>1;
  1493.   Chroma_Height = (chroma_format!=CHROMA420) ? Coded_Picture_Height
  1494.                                             : Coded_Picture_Height>>1;
  1495.   
  1496.   /* derived based on Table 6-20 in ISO/IEC 13818-2 section 6.3.17 */
  1497.   block_count = Table_6_20[chroma_format-1];
  1498.  
  1499.   /* Allocate buffers */
  1500.   chroma_size = Chroma_Width*Chroma_Height;
  1501.   luma_size = Coded_Picture_Width*Coded_Picture_Height;
  1502.   size =  luma_size + 2*(chroma_size);
  1503.  
  1504.   /* Set the format in our frames. This will allocate the space in them */
  1505.   for(int i=0; i<3; i++)
  1506.     m_frRef[i].Set( Coded_Picture_Width, Coded_Picture_Height, FRAME_YV12 );
  1507.  
  1508.   backward_reference_frame[0] = (unsigned char *)m_frRef[0].GetBuffer();
  1509.   forward_reference_frame[0]  = (unsigned char *)m_frRef[1].GetBuffer();
  1510.   auxframe[0]                 = (unsigned char *)m_frRef[2].GetBuffer();;
  1511.  
  1512.   /* Setup pointers */  
  1513.   backward_reference_frame[1] = backward_reference_frame[0] + luma_size + chroma_size;
  1514.   backward_reference_frame[2] = backward_reference_frame[0] + luma_size;
  1515.  
  1516.   forward_reference_frame[1] = forward_reference_frame[0] + luma_size + chroma_size;
  1517.   forward_reference_frame[2] = forward_reference_frame[0] + luma_size;
  1518.  
  1519.   auxframe[1] = auxframe[0] + luma_size + chroma_size;
  1520.   auxframe[2] = auxframe[0] + luma_size;
  1521.  
  1522.  
  1523.  
  1524.  
  1525. }
  1526.  
  1527. void Error(char *text)
  1528. {
  1529.   fprintf(stderr,text);
  1530. //  exit(1);
  1531. }
  1532.  
  1533. /* Trace_Flag output */
  1534. void Print_Bits(int code,int bits,int len)
  1535. {
  1536.   int i;
  1537.   for (i=0; i<len; i++)
  1538.     printf("%d",(code>>(bits-1-i))&1);
  1539. }
  1540.  
  1541.  
  1542. void VideoWrapper::DeinitializeSequence()
  1543. {
  1544.  
  1545.   /* clear flags */
  1546.   base.MPEG2_Flag=0;
  1547. }
  1548.  
  1549.  
  1550.  
  1551.  
  1552. bool VideoWrapper::SetStreamPos(ui64 pos)
  1553. {
  1554.     // Lock the decoder
  1555.     CAutoLock lock(&m_csLockSection);
  1556.   PESinfo   dummyPes;
  1557.  
  1558.     bool bSuccess = false;
  1559.  
  1560.     i64 nFirstJump = (i64)pos - nJumpBackwards;
  1561.     ui64 nCurrentPos;
  1562.  
  1563.     if( nFirstJump<=0 )
  1564.         nFirstJump = 0;
  1565.  
  1566.   // Align stream to the pack header near the first Jump
  1567.     CDemux::SetStreamPos( CDemux::GetSyncPoint(pos) );
  1568.     
  1569.   m_bReadSuccess = true;
  1570.     // Read a PES of video
  1571.     while( m_bReadSuccess && (pos >= CDemux::GetStreamPos()) )
  1572.     {
  1573.         while( (m_bReadSuccess = ReadPES((unsigned char **)&m_pTempVideoBuffer, &dummyPes)) &&
  1574.             (dummyPes.streamID == streamID) )
  1575.         {
  1576.             // Wet got a video PES.
  1577.             // Get current Position
  1578.             nCurrentPos = CDemux::GetStreamPos();
  1579.             
  1580.             // Is the position requested inside our PES?
  1581.             if( pos <   nCurrentPos &&
  1582.                 pos >=  (nCurrentPos - dummyPes.payloadSize) )
  1583.             {
  1584.                 //Yep, it is.
  1585.                 m_nTempVideoBufferSize = dummyPes.payloadSize;
  1586.                 m_nTempVideoBufferPtr  = (ui32)(dummyPes.payloadSize - (nCurrentPos - pos));
  1587.                 m_nPesPosState = PesEnd;
  1588.                 bSuccess = true;
  1589.                 break;
  1590.             }
  1591.             else if( pos < nCurrentPos )
  1592.             {
  1593.                 // we missed the position requested without
  1594.                 // finding an appropiate PES position
  1595.                 DBG_STR((str, "VideoWrapper::SetStreamPos - Position not found\n"))
  1596.                 m_nTempVideoBufferSize = dummyPes.payloadSize;
  1597.                 m_nTempVideoBufferPtr = 0;
  1598.                 bSuccess = false;
  1599.                 break;
  1600.             }
  1601.         }
  1602.     }
  1603.  
  1604.   // Because this was a seek operation and we didnt succeed
  1605.   // remove the present data in the buffer because its no longer valid.
  1606.   if( !bSuccess )
  1607.     FlushBuffer();
  1608.  
  1609.     return bSuccess;
  1610. }
  1611.  
  1612. ui64 VideoWrapper::GetStreamPos()
  1613. {
  1614.     // Lock the decoder object in this function
  1615.     CAutoLock lock(&m_csLockSection);
  1616.  
  1617.     // Get real current position
  1618.     // If this Pes was read backwards the
  1619.     // end position was already retrieved
  1620.     ui64 nCurrentPos = m_nPesPosState==PesBegin ? m_nEndPesPosition : CDemux::GetStreamPos();
  1621.  
  1622.     return nCurrentPos - (m_nTempVideoBufferSize - m_nTempVideoBufferPtr );
  1623. }
  1624.     
  1625.  
  1626.  
  1627. int VideoWrapper::GetError()
  1628. {
  1629.     int temp;
  1630.     temp=error;
  1631.     error=0;
  1632.     return temp;
  1633. }
  1634.  
  1635. void VideoWrapper::updateVideoStats()
  1636. {
  1637.  
  1638.         if(isMPEG2)
  1639.     {
  1640.             DAR = MPEG2aspect_ratio_Table[aspect_ratio_information];
  1641.         }
  1642.         else{
  1643.             DAR = (MPEG1aspect_ratio_Table[aspect_ratio_information]*(double)pictureHeight)/((double)pictureWidth);
  1644.         }
  1645.         
  1646.         frameRate=frameRateTable[frame_rate_code];
  1647.         
  1648.         detectedFrameDelay=1/frameRateTable[detectedFrameRateCode];
  1649.  
  1650.         frameDelay=1/frameRate;
  1651.  
  1652. }
  1653.  
  1654. // Stub for feeding data to MSSG video decoder
  1655. bool VideoWrapper::ReadVideoData( ui8** ppBuffer, ui32* pBufferSize )
  1656. {
  1657.     if( m_nPesPosState == PesBegin )
  1658.         CDemux::SetStreamPos( m_nEndPesPosition );
  1659.     do{
  1660.         m_bReadSuccess = ReadLPES((unsigned char **)&m_pTempVideoBuffer, &myPES);
  1661.         if(!m_bReadSuccess) break;
  1662.         if( myPES.streamID    == subpic_streamID &&
  1663.             myPES.subStreamID == subpic_substreamID ) {
  1664.             /* this is a subpic; parse it, and discard it so the video decoder
  1665.             * doesn't see it */
  1666.             
  1667.             subpic_decode((unsigned char *)m_pTempVideoBuffer, myVideo->myPES.payloadSize, (int)((double)myVideo->myPES.PTS/27000.0) );
  1668.             continue;
  1669.         }
  1670.     }while( myPES.streamID!=streamID);
  1671.     
  1672.     // We are feeding the video decoder
  1673.     //   set the offset to what we've read.
  1674.     m_nTempVideoBufferSize   = myPES.payloadSize;
  1675.     m_nTempVideoBufferPtr    = myPES.payloadSize;
  1676.     m_nPesPosState = PesEnd;
  1677.     
  1678.     // Update buffers
  1679.     *ppBuffer     = m_pTempVideoBuffer;
  1680.     *pBufferSize = myPES.payloadSize;
  1681.     return m_bReadSuccess;
  1682. }
  1683.  
  1684. bool VideoWrapper::Is24Progressive()
  1685. {
  1686.   //This megamatic function will try to detect
  1687.   // the framerate of a stream, just looking into
  1688.   // the PTS from the incoming pictures.
  1689.   // This is necessary to detect 24 fps progressive sequences
  1690.   // that have the frame_rate set to 29.97 and use repeat_first_field flag
  1691.   //
  1692.   bool bSuccess = false;
  1693.  
  1694.   ui64 nStreamSize = GetStreamSize();
  1695.   // Jump to the middle
  1696.   CDemux::SetStreamPos(nStreamSize>>1);
  1697.     Initialize_Buffer();
  1698.   int nFramesToTry = 10;
  1699.   while( Get_Hdr() && nFramesToTry-- )
  1700.   {
  1701.     if(picture_structure!=FRAME_PICTURE)
  1702.       break;
  1703.     // If its not 29.97
  1704.     if( frame_rate_code!= 4 )
  1705.       break;
  1706.     if(repeat_first_field){
  1707.       bSuccess = true;
  1708.       break;
  1709.     }
  1710.   }
  1711.   return bSuccess;
  1712. }
  1713.  
  1714. bool VideoWrapper::BuildFrameDB()
  1715. {
  1716.   // Set stream to the beginning.
  1717.   SetStreamPos(0);
  1718.   bool bSuccess = true;
  1719.   ui8 byte;
  1720.   ui32 nTemporalReference;
  1721.  
  1722.   while(bSuccess)
  1723.   {
  1724.     // Find next startcode prefix
  1725.     ui32 nStartCode = 0xFFFFFF00;
  1726.     while( (nStartCode&0x00FFFFFF)!=1 && bSuccess )
  1727.     {
  1728.       bSuccess = GetFordByte(&byte);
  1729.       nStartCode = (nStartCode<<8) | byte;
  1730.     }
  1731.     GetFordByte(&byte);
  1732.     switch(byte)
  1733.     {
  1734.       case 0: // Picture start code
  1735.         // Get Start position
  1736.         m_sTempFrameInfo.nStartPos = GetStreamPos() - 4;
  1737.  
  1738.         
  1739.         GetFordByte(&byte);
  1740.         nTemporalReference = byte << 2;
  1741.         GetFordByte(&byte);
  1742.         nTemporalReference |= (byte&0xC0)>>6;
  1743.           
  1744.         // Get picture coding type
  1745.         m_sTempFrameInfo.picture_coding_type = (byte&0x3F)>>3;
  1746.         // If mpeg one, we're finished
  1747.         if(!isMPEG2)
  1748.           m_vFrames.push_back(m_sTempFrameInfo);
  1749.         break;
  1750.       case 0xB5: // extension start code
  1751.         GetFordByte(&byte);
  1752.         switch(byte>>4)
  1753.         {
  1754.         case 0x08: // picture extension
  1755.           GetFordByte(&byte);
  1756.           GetFordByte(&byte); // two last bits are picture_structure
  1757.           m_sTempFrameInfo.picture_structure = byte& 0x03;
  1758.           GetFordByte(&byte); // tff:8 bit    rff:2nd bit
  1759.           m_sTempFrameInfo.top_field_first    = byte & 0x80;
  1760.           m_sTempFrameInfo.repeat_first_field = byte & 0x02;
  1761.           GetFordByte(&byte); // progressive frame:8th bit
  1762.           m_sTempFrameInfo.progressive_frame  = byte & 0x80;
  1763.           break;
  1764.         }
  1765.           m_vFrames.push_back(m_sTempFrameInfo);
  1766.         break;
  1767.     }
  1768.   }
  1769.   int size = m_vFrames.size();
  1770.  
  1771.   return true;
  1772. }
  1773.  
  1774. TMPGVideoInfo * VideoWrapper::GetVideoInfo()
  1775. {
  1776.     video_info.width                    = Coded_Picture_Width;
  1777.     video_info.height                   = Coded_Picture_Height;
  1778.     video_info.aspect_ratio_information = aspect_ratio_information;
  1779.     video_info.bit_rate_value           = bit_rate_value;
  1780.     video_info.detected_frame_rate_code = detectedFrameRateCode;
  1781.     video_info.frame_rate_code          = frame_rate_code;
  1782.     video_info.isMPEG2                  = isMPEG2;
  1783.     video_info.progressive_frame        = progressive_frame;
  1784.     video_info.progressive_sequence     = progressive_sequence;
  1785.  
  1786.     return &video_info;
  1787. }
  1788.  
  1789.