home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / viscobv6.zip / vac22os2 / ibmcobol / samples / toolkit / mm / asymrec / asymrec.c next >
Text File  |  1996-11-19  |  65KB  |  1,258 lines

  1. Copyright (C) IBM 1993
  2. /******************************************************************/
  3. /* Name: Asymrec.scr                                              */
  4. /*                                                                */
  5. /* This sample source code illustrates some of functions that     */
  6. /* could be used when creating a asymmetric recorder application  */
  7. /* or a application that uses asymmetric recording.               */
  8. /*                                                                */
  9. /* This sample code has been extracted from the Recorder          */
  10. /* Application.  It needs to be noted that this is functional     */
  11. /* code but the functions have been altered to be strictly sample */
  12. /* code without alot of error checking and additional code that a */
  13. /* complete application may need to have.                         */
  14. /*                                                                */
  15. /* Note: Because this is complex sample code most error checking  */
  16. /*       has been removed.                                        */
  17. /*                                                                */
  18. /* Refer to the Asymrec.h file for header information.            */
  19. /*                                                                */
  20. /*                                                                */
  21. /* Functions :  OpenMMIO                                          */
  22. /*              IdentifyIOProc                                    */
  23. /*              AssociateCodec                                    */
  24. /*              InitiateFrameStepRecord                           */
  25. /*              CompressBuffer                                    */
  26. /*              StartVideoThread                                  */
  27. /*                                                                */
  28. /******************************************************************/
  29.  
  30. /******************************************************************/
  31. /* Name : OpenMMIO                                                */
  32. /*                                                                */
  33. /* This function initializes the environment for frame step       */
  34. /* record.                                                        */
  35. /*                                                                */
  36. /******************************************************************/
  37.  
  38. RC OpenMMIO(PSWVRCB pCB) /* pCB is a pointer to the PSWVRCB which is */
  39.                          /* a structure in the asymrec.h.  This is   */
  40.                          /* a user defined structure and may be      */
  41.                          /* altered to a users needs.                */
  42. {
  43.   /**********************************************************************/
  44.   /*  Do an MMIOOpen                                                    */
  45.   /*  Save the mmio handle into our SWVRCB.  Use this handle later      */
  46.   /*  to do MMIO_COMPRESS.                                              */
  47.   /**********************************************************************/
  48.    MMMOVIEHEADER     mmMovieHdr;                /* Movie header structure   */
  49.                                                 /* contains general info    */
  50.                                                 /* about the movie.         */
  51.    MMVIDEOHEADER     mmVideoHdr;                /* Video header structure   */
  52.                                                 /* contains info specific to*/
  53.                                                 /* the track(video or audio)*/
  54.    MMAUDIOHEADER     mmAudioHdr;                /* Audio header structure   */
  55.    LONG              lBytesWritten;             /* Number of bytes to write */
  56.    ULONG             ulReserved=0;              /* Reserved                 */
  57.    ULONG             ulFlags=0;                 /* Flags                    */
  58.    USHORT            rc=0;                      /* Return code              */
  59.    MMIOINFO          mmioinfo;                  /* MMIO info structure      */
  60.  
  61.  
  62.   /**********************************************************************/
  63.   /* Identify and load the IO Proc for creating a new movie file        */
  64.   /**********************************************************************/
  65.  
  66.    rc = IdentifyIOProc( (PSZ) TEMP_VIDEO_FILENAME,
  67.                          &pCB->hmmioTemp,
  68.                          MMIO_READWRITE |
  69.                          MMIO_CREATE |
  70.                          MMIO_TRANSLATEHEADER,
  71.                          &mmioinfo );
  72.  
  73. /****************************************************************************/
  74. /* The values chosen for the following structures are values that have been */
  75. /* specifically tweaked for the  Recorder Application or are default.       */
  76. /* These values could change depending on a applications implementation.    */
  77. /* Values that have been changed to default are noted as such.              */
  78. /****************************************************************************/
  79. /****************************************************************************/
  80. /* Set up the movie header structure with appropriate params for the movie. */
  81. /* Once the structure is filled in, we'll go to the video header and set    */
  82. /* that information up.                                                     */
  83. /****************************************************************************/
  84.                                                 /* Length of this structure */
  85.    mmMovieHdr.ulStructLen           = sizeof(MMMOVIEHEADER);
  86.  
  87.    mmMovieHdr.ulContentType         = 0L;       /* Reserved for future use  */
  88.                                                 /* Video Media Type         */
  89.    mmMovieHdr.ulMediaType           = MMIO_MEDIATYPE_MOVIE;
  90.  
  91.    mmMovieHdr.ulMovieCapsFlags      = MOVIE_HAS_VIDEO |
  92.                                       MOVIE_HAS_AUDIO |
  93.                                       MOVIE_CAN_SEEK  |
  94.                                       MOVIE_CAN_SCAN;   /* Capabilities     */
  95.  
  96.    mmMovieHdr.ulMaxBytesPerSec      = 0L;     /* Maximum transfer rate      */
  97.  
  98.    mmMovieHdr.ulPaddingGranularity  = 4096;/* Pad to a multiple of this size*/
  99.  
  100.    mmMovieHdr.ulSuggestedBufferSize = 4096;                 /* Buffer sizer */
  101.  
  102.    mmMovieHdr.ulStart               = 0L;
  103.  
  104.    mmMovieHdr.ulLength              = 100L;      /* Length of movie         */
  105.  
  106.    mmMovieHdr.ulNextTrackID         = 0L;        /* Next available track id */
  107.  
  108.    mmMovieHdr.ulNumEntries          = 2L;        /* Number of track entries */
  109.  
  110.    mmMovieHdr.pmmTrackInfoList      = NULL;      /* Track information       */
  111.  
  112.    mmMovieHdr.ulCountry             = 0L;  /* Country code for title string */
  113.  
  114.                                       /* Country code page for title string */
  115.    mmMovieHdr.ulCodePage            = 0L;
  116.  
  117.   /***************************************************************/
  118.   /* This function is called to set the track and to setup       */
  119.   /* extended file information for the movie.  For movie         */
  120.   /* information we reset to -1.                                 */
  121.   /***************************************************************/
  122.    SetActiveTrack ( pCB->hmmioTemp, MMIO_RESETTRACKS );
  123.                                                     /* MMIO_RESETTRACKS = -1 */
  124.  
  125.   /****************************************************************/
  126.   /* Once we have setup the movie information and set the track   */
  127.   /* for the extended file information we need to set the movie   */
  128.   /* header information.  Track -1 will contain the movie info.   */
  129.   /****************************************************************/
  130.    mmioSetHeader( pCB->hmmioTemp, &mmMovieHdr, sizeof(MMMOVIEHEADER),
  131.                   &lBytesWritten, ulReserved, ulFlags );
  132.   /****************************************************************/
  133.   /* Set up the video header structure with appropriate params    */
  134.   /* for the video.                                               */
  135.   /****************************************************************/
  136.  
  137.                                                /* length of this structure  */
  138.    mmVideoHdr.ulStructLen        = sizeof(MMVIDEOHEADER);
  139.                                                      /* video content type  */
  140.    mmVideoHdr.ulContentType      = MMIO_VIDEO_DATA;
  141.                                                        /* video media type  */
  142.    mmVideoHdr.ulMediaType        = MMIO_MEDIATYPE_DIGITALVIDEO;
  143.                                                        /* capabilities      */
  144.    mmVideoHdr.ulVideoCapsFlags   = 0L;
  145.                                                     /* video width in pels  */
  146.    mmVideoHdr.ulWidth            = pCB->recopts.usMovieSizeX;
  147.                                                    /* video height in pels  */
  148.    mmVideoHdr.ulHeight           = pCB->recopts.usMovieSizeY;
  149.                                                    /* Scale                 */
  150.    mmVideoHdr.ulScale            = 01L;
  151.                                            /* Rate / Scale == frames/second */
  152.    mmVideoHdr.ulRate             = pCB->recopts.MovieFPS;
  153.    mmVideoHdr.ulStart            = 0L;
  154.  
  155.                                          /* total number of frames * MMTIME */
  156.    mmVideoHdr.ulLength           = 0L;   /* per frame                       */
  157.  
  158.    mmVideoHdr.ulTotalFrames      = 0L;      /* total number of video frames */
  159.    mmVideoHdr.ulInitialFrames    = 0L;
  160.                                                 /* frame display time or 0L */
  161.    mmVideoHdr.mmtimePerFrame     = 3000/pCB->recopts.MovieFPS;
  162.    mmVideoHdr.genpalVideo.ulStartIndex    = 0L;              /* Start index */
  163.    mmVideoHdr.genpalVideo.ulNumColors     = 0L;                  /* palette */
  164.    mmVideoHdr.genpalVideo.prgb2Entries    = NULL;
  165.                                            /* windows DIB compatible header */
  166.    mmVideoHdr.pmmXDIBHeader               = 0L;
  167.  
  168.   /***************************************************************/
  169.   /* This function is called to set the track and to setup       */
  170.   /* extended file information for the video.  For video         */
  171.   /* information we set to 0.                                    */
  172.   /***************************************************************/
  173.    SetActiveTrack ( pCB->hmmioTemp, 0L );
  174.  
  175.   /****************************************************************/
  176.   /* Once we have setup the video information and set the track   */
  177.   /* for the extended file information we need to set the video   */
  178.   /* header information.  Track 0 will contain the video info.    */
  179.   /****************************************************************/
  180.    mmioSetHeader( pCB->hmmioTemp, &mmVideoHdr, sizeof(MMVIDEOHEADER),
  181.                 &lBytesWritten, ulReserved, ulFlags );
  182.  
  183.  
  184.   /****************************************************************/
  185.   /* Update/create audio header information.  It is being shown   */
  186.   /* in this sample but it is assumed that audio data is recorded */
  187.   /* at the time of interleaving.  This audio header information  */
  188.   /* is provided only for initial setup and reference when opening*/
  189.   /* mmio.                                                        */
  190.   /****************************************************************/
  191.    mmAudioHdr.dwHeaderLength  = sizeof(MMAUDIOHEADER);
  192.    mmAudioHdr.dwContentType   = MMIO_AUDIO_MUSIC;
  193.    mmAudioHdr.dwMediaType     = MMIO_MEDIATYPE_AUDIO;
  194.  
  195.   /*********************************************************/
  196.   /* Assign values to - mmAudioHdr.mmXWAVHeader.WAVRHeader */
  197.   /*********************************************************/
  198.    mmAudioHdr.mmXWAVHeader.WAVEHeader.usFormatTag      = 01L;
  199.                                                            /* Stero vs mono */
  200.    mmAudioHdr.mmXWAVHeader.WAVEHeader.usChannels       = 02L;
  201.  
  202.                                                            /* Sampling size */
  203.    mmAudioHdr.mmXWAVHeader.WAVEHeader.ulSamplesPerSec  = 22050L;
  204.  
  205.                                                       /* Avg bytest per sec */
  206.    mmAudioHdr.mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec = 0L;
  207.  
  208.                                                 /* Block alignment in bytes */
  209.    mmAudioHdr.mmXWAVHeader.WAVEHeader.usBlockAlign     = 02L;
  210.  
  211.                                                          /* Bits per sample */
  212.    mmAudioHdr.mmXWAVHeader.WAVEHeader.usBitsPerSample  = 16L;
  213.  
  214.   /***************************************************************/
  215.   /* Assign values to - mmAudioHdr.mmXWAVHeader.XWAVEHeaderInfo  */
  216.   /***************************************************************/
  217.  
  218.    mmAudioHdr.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS    = 0L;
  219.    mmAudioHdr.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes = 0L;
  220.    mmAudioHdr.mmXWAVHeader.XWAVHeaderInfo.ulReserved           = 0L;
  221.  
  222.   /***************************************************************/
  223.   /* This function is called to set the track and to setup       */
  224.   /* extended file information for the audio.  For audio         */
  225.   /* information we set to 1.                                    */
  226.   /***************************************************************/
  227.    SetActiveTrack ( pCB->hmmioTemp, 1L );
  228.  
  229.  
  230.   /****************************************************************/
  231.   /* Once we have setup the audio information and set the track   */
  232.   /* for the extended file information we need to set the audio   */
  233.   /* header information.  Track 1 will contain the audio info.    */
  234.   /****************************************************************/
  235.    rc = mmioSetHeader( pCB->hmmioTemp, &mmAudioHdr, sizeof(MMAUDIOHEADER),
  236.                        &lBytesWritten, ulReserved, ulFlags );
  237.  
  238.   /***************************************************************/
  239.   /* This function is called to reset the track and to setup     */
  240.   /* extended file information.                                  */
  241.   /***************************************************************/
  242.    SetActiveTrack ( pCB->hmmioTemp, MMIO_RESETTRACKS );
  243.                                                     /* MMIO_RESETTRACKS = -1*/
  244.    return(rc);
  245.  
  246. }  /* OpenMMIO */
  247.  
  248. /******************************************************************/
  249. /* Name : IdentifyIOProc                                          */
  250. /*                                                                */
  251. /* This function identifies the AVIO procedure.                   */
  252. /*                                                                */
  253. /******************************************************************/
  254. RC   IdentifyIOProc( PSZ       fname,             /* File name              */
  255.                      HMMIO    *phmmio,            /* Handle to open file    */
  256.                      ULONG     ulOpenFlags,       /* Flags                  */
  257.                      MMIOINFO *pmmioinfo )        /* mmio info structure    */
  258. {
  259.   APIRET             rc = MCIERR_SUCCESS;
  260.   MMIOINFO           mmioinfo;
  261.   LPMMIOPROC         pAnswer = 0;
  262.   CHAR               LoadError[100];
  263.   FOURCC             fcc;
  264.   ULONG              ulrc;
  265.   HMODULE            hmod;
  266.  
  267.   /***********************************/
  268.   /* Open/Identify IOProc to install */
  269.   /***********************************/
  270.   memset(pmmioinfo, '\0', sizeof(MMIOINFO));  /* Reset mmioinfo area      */
  271.  
  272.  
  273.   /******************************************/
  274.   /* Extract from the file header and place */
  275.   /* in the appropriate fileds.              */
  276.   /******************************************/
  277.   pmmioinfo->dwTranslate = MMIO_TRANSLATEHEADER;
  278.  
  279.   /******************************************/
  280.   /* Media type is Movie.                   */
  281.   /******************************************/
  282.   pmmioinfo->adwInfo[3] = MMIO_MEDIATYPE_MOVIE;
  283.  
  284.   rc = 0;  /* reset DosLoadModule call */
  285.  
  286.   /*************************************************************************/
  287.   /* Check to see if it is a known IO proc if not then load AVIO straight  */
  288.   /*************************************************************************/
  289.   fcc = mmioStringToFOURCC( (PSZ) "AVI ", MMIO_TOUPPER);
  290.   if (!(pAnswer = mmioInstallIOProc(fcc, NULL, MMIO_FINDPROC)))
  291.     {
  292.     /********************************************/
  293.     /* Load The IO Proc                         */
  294.     /********************************************/
  295.     rc = DosLoadModule( (PSZ)LoadError, sizeof(LoadError), (PSZ) "AVIO", &hmod);
  296.  
  297.     /********************************************/
  298.     /* Obtain Procedure Entry Point             */
  299.     /********************************************/
  300.     if (rc = DosQueryProcAddr(hmod, 0L, (PSZ) "IOProc_Entry",
  301.                               (PFN *)&(pmmioinfo->pIOProc)))
  302.       {
  303.       ulrc = DosFreeModule(hmod);
  304.       return(rc);
  305.       }
  306.  
  307.     /********************************************/
  308.     /* Install the IO Proc                      */
  309.     /********************************************/
  310.     pAnswer = mmioInstallIOProc(fcc,
  311.                                 pmmioinfo->pIOProc,
  312.                                 MMIO_INSTALLPROC);
  313.     if ((pAnswer != pmmioinfo->pIOProc) || (!pAnswer))
  314.       {
  315.       ulrc = DosFreeModule(hmod);
  316.       return (MCIERR_CANNOT_LOAD_DRIVER);
  317.       }
  318.     } /* FindProc */
  319.  
  320.    /**************************************************/
  321.    /* Try to Open a new Movie file using this IOProc */
  322.    /**************************************************/
  323.   pmmioinfo->pIOProc = pAnswer;  /* Install worked! */
  324.   pmmioinfo->fccIOProc = 0;
  325.   pmmioinfo->dwTranslate = MMIO_TRANSLATEHEADER;
  326.   pmmioinfo->hmmio = *phmmio;
  327.   *phmmio = mmioOpen((PSZ) fname, pmmioinfo, ulOpenFlags );
  328.   if (!*phmmio)
  329.      rc = MCIERR_CANNOT_LOAD_DRIVER;
  330.   return(rc);
  331.  
  332. }  /* end: IdentifyIOProc               */
  333.  
  334. /**********************************************************************/
  335. /* Name : AssociateCodec                                              */
  336. /*                                                                    */
  337. /* This function gets the selected codec and tells MMIO to associate  */
  338. /* it to the IOPROC for later use in the compression. Sets up color   */
  339. /* coding from the card and various structures for initial association*/
  340. /* of codec.                                                          */
  341. /**********************************************************************/
  342. LONG AssociateCodec( HMMIO              hmmio,   /* Handle to open file     */
  343.                      PSWVRCB            pCB,     /* Pointer to control block*/
  344.                      CODECINIFILEINFO  *pcifi,/* Pointer to codec file info */
  345.                      PVOID              pControlHdr,
  346.                      ULONG              ulCODECFlags )   /* Flags           */
  347. {
  348.    RC                rc;
  349.  
  350.    MMEXTENDINFO      mmextendinfo;
  351.    MMVIDEOOPEN       mmvideoopen;
  352.  
  353.   /*****************************************************************/
  354.   /* The following structures are used by the codec during the     */
  355.   /* recording process.                                            */
  356.   /*****************************************************************/
  357.    CODECASSOC        codecassoc;
  358.    CODECOPEN         codecopen;
  359.    CODECVIDEOHEADER  cvhSrc;
  360.    CODECVIDEOHEADER  cvhDst;
  361.  
  362.    MCI_STATUS_PARMS  mciStatusParms;
  363.    ULONG             ulSrcColorEncoding = MMIO_RGB_5_6_5;
  364.  
  365.   /*****************************************************************/
  366.   /* Get the color encoding of the video capture card              */
  367.   /* otherwise hardcode to RGB                                     */
  368.   /*****************************************************************/
  369.    memset(&mciStatusParms, 0, sizeof(MCI_STATUS_PARMS));
  370.    mciStatusParms.dwCallback   = 0;
  371.    mciStatusParms.dwItem       = MCI_DGV_STATUS_IMAGE_PELFORMAT;
  372.    rc = mciSendCommand (pCB->OutputMovie.wDeviceID,     /* Device ID        */
  373.                         MCI_STATUS,                     /* Command          */
  374.                         MCI_WAIT | MCI_STATUS_ITEM,     /* dwFlags          */
  375.                         (ULONG) (&mciStatusParms),      /* In/Out Parameters*/
  376.                          0 );                           /* User Parameter   */
  377.    rc &= 0x0000FFFF ;                  /* Mask out the high (device ID) word*/
  378.    if (!rc)
  379.      ulSrcColorEncoding = mciStatusParms.dwReturn;
  380.  
  381.   /*****************************************************************/
  382.   /* Initialize source codec video header                          */
  383.   /* This structure is used later in this routine as a field       */
  384.   /* in the codecopen structure.                                   */
  385.   /*****************************************************************/
  386.    cvhSrc.ulStructLen      = sizeof(CODECVIDEOHEADER);
  387.    cvhSrc.cx               = pCB->recopts.usMovieSizeX;  /* 320 Default     */
  388.    cvhSrc.cy               = pCB->recopts.usMovieSizeY;  /* 240 Default     */
  389.    cvhSrc.cPlanes          = 1;
  390.    cvhSrc.cBitCount        = 16;
  391.    cvhSrc.ulColorEncoding  = ulSrcColorEncoding;
  392.  
  393.   /*****************************************************************/
  394.   /* Initialize destination codec video header                     */
  395.   /* This structure is used later in this routine as a field       */
  396.   /* in the codecopen structure.                                   */
  397.   /*****************************************************************/
  398.    cvhDst.ulStructLen      = sizeof(CODECVIDEOHEADER);
  399.    cvhDst.cx               = pCB->recopts.usMovieSizeX;
  400.    cvhDst.cy               = pCB->recopts.usMovieSizeY;
  401.    cvhDst.cPlanes          = 1;
  402.    cvhDst.cBitCount        = 16;
  403.    cvhDst.ulColorEncoding  = MMIO_COMPRESSED;
  404.  
  405.   /*****************************************************************/
  406.   /* Initialize mmvideoopen structure                              */
  407.   /* This structure is used later in this routine as a field       */
  408.   /* in the codecopen structure.                                   */
  409.   /*****************************************************************/
  410.    mmvideoopen.ulStructLen = sizeof(MMVIDEOOPEN);
  411.  
  412.   /*****************************************************************/
  413.   /* This is max quality derived from quality slider               */
  414.   /* in options notebook. 10,000 for high quality.                 */
  415.   /* Some codecs do not support setting quality a max              */
  416.   /* data rate.                                                    */
  417.   /*****************************************************************/
  418.    mmvideoopen.ulQuality   = pCB->recopts.usQuality;
  419.  
  420.    if ( pCB->recopts.fInsertRefFrames )  /* Is the reference frame flag set*/
  421.    /*****************************************/
  422.    /* Maximum refresh time = 30 for default */
  423.    /*****************************************/
  424.       mmvideoopen.ulKeyFrameRate    = pCB->recopts.usMaxRefreshTime;
  425.    else
  426.       mmvideoopen.ulKeyFrameRate    = 0;
  427.    mmvideoopen.ulScale              = 1;
  428.    /****************************************/
  429.    /* MovieFPS = input 15 output 15.       */
  430.    /* This is to compensate frame rate for */
  431.    /* difference in input and output.      */
  432.    /****************************************/
  433.    mmvideoopen.ulRate               = pCB->recopts.MovieFPS;
  434.    /****************************************/
  435.    /* MaxDataRate = 1000 bytes/sec         */
  436.    /****************************************/
  437.    mmvideoopen.ulDataConstraint     = pCB->recopts.usMaxDataRate << 10;
  438.    mmvideoopen.ulConstraintInterval = pCB->recopts.MovieFPS;
  439.  
  440.   /****************************************************************/
  441.   /* Initialize codec open structure                              */
  442.   /****************************************************************/
  443.    memset((PVOID)&codecopen,'\0', sizeof(CODECOPEN));
  444.  
  445.   /****************************************************************/
  446.   /* Codec - ulFlags need to be specific if the codec supports    */
  447.   /* compress and decompress.                                     */
  448.   /****************************************************************/
  449.                /* flags & events - Refer to ulCapsFlags in CODECINIFILEINFO   */
  450.  
  451.   /****************************************************************/
  452.   /* Initialize the codecopen and codecassoc structure with the   */
  453.   /* the following information.                                   */
  454.   /****************************************************************/
  455.  
  456.    codecopen.ulFlags                = ulCODECFlags;
  457.                                        /* control header - (codec specific)   */
  458.    codecopen.pControlHdr            = pControlHdr;
  459.                                           /* source header information from   */
  460.                                           /* the CODECVIDEOHEADER             */
  461.    codecopen.pSrcHdr                = (PVOID)&cvhSrc;
  462.                                      /* destination header information from   */
  463.                                      /* the CODECVIDEOHEADER                  */
  464.    codecopen.pDstHdr                = (PVOID)&cvhDst;
  465.                                            /* other information MMVIDEOOPEN   */
  466.    codecopen.pOtherInfo             = (PVOID)&mmvideoopen;
  467.                                               /* Codec specific open header   */
  468.    codecassoc.pCodecOpen            = &codecopen;
  469.                                               /* Codecinifileinfo             */
  470.    codecassoc.pCODECIniFileInfo     = pcifi;
  471.  
  472.   /****************************************************************/
  473.   /* Initialize mmextedinfo structure for MMIO_SET                */
  474.   /****************************************************************/
  475.    memset((PVOID)&mmextendinfo,'\0', sizeof(MMEXTENDINFO));
  476.    mmextendinfo.ulStructLen         = sizeof(MMEXTENDINFO);
  477.    mmextendinfo.ulFlags             = MMIO_CODEC_ASSOC;
  478.    mmextendinfo.ulNumCODECs         = 1;
  479.    mmextendinfo.pCODECAssoc         = &codecassoc;
  480.  
  481.   /****************************************************************/
  482.   /* Send MIOM_SET to IOproc to associate the codec               */
  483.   /****************************************************************/
  484.    rc =  mmioSendMessage( hmmio,
  485.                           MMIOM_SET,
  486.                           (LONG)&mmextendinfo,
  487.                           MMIO_SET_EXTENDEDINFO);
  488.    return(rc);
  489.  
  490. } /* AssociateCodec */
  491.  
  492. /******************************************************************/
  493. /* Name : InitiateFrameStepRecord                                 */
  494. /*                                                                */
  495. /* This function initializes the environment for frame step       */
  496. /* record.                                                        */
  497. /*                                                                */
  498. /******************************************************************/
  499. LONG InitiateFrameStepRecord( PSWVRCB pswvrcb)
  500. {
  501.   ULONG    rc;                           /* return code for random usage   */
  502.   BOOL     fInitErr = FALSE;
  503.   PRECCB   pRecCB;                       /* ptr to a recording cb structure*/
  504.   ULONG    ulBufferSize;
  505.  
  506.  
  507.  /********************************************************************/
  508.  /* save a global pointer to the control block                       */
  509.  /********************************************************************/
  510.   threadpointer = pswvrcb;
  511.  
  512.  /********************************************************************/
  513.  /* Allocate record control if it doesn't exist and set it           */
  514.  /* into our control block.  Then clear it out before we start       */
  515.  /* using it.                                                        */
  516.  /********************************************************************/
  517.   if (!pswvrcb->pRecCB)
  518.  
  519.   {
  520.     pswvrcb->pRecCB = malloc( sizeof(RECCB));       /* Allocate record CB  */
  521.   } /* endif */
  522.   pRecCB = pswvrcb->pRecCB;
  523.  
  524.   memset(pRecCB, '\0', sizeof(RECCB));
  525.  
  526.  /********************************************************************/
  527.  /* Set the threads running state as ok.  This flag is check in      */
  528.  /* StartVideoThread routine.                                        */
  529.  /********************************************************************/
  530.   pRecCB->fStillRunning= TRUE;
  531.  
  532.  /********************************************************************/
  533.  /* Create an event semaphore to indicate paused recording           */
  534.  /* Set error flag for failure                                       */
  535.  /********************************************************************/
  536.   rc = DosCreateEventSem((PSZ) "\\SEM32\\ASYM\\RECPAUSE", /*semaphore name   */
  537.                          &pRecCB->hevRecordPaused,        /*semaphore handle */
  538.                          (ULONG) 0,                    /* attribute - unused */
  539.                          (ULONG) 0);                   /* initial state set  */
  540.  
  541.   if (rc) fInitErr = TRUE;
  542.  
  543.  /********************************************************************/
  544.  /* Create an event semaphore to signal frame step complete          */
  545.  /* Set error flag for failure                                       */
  546.  /********************************************************************/
  547.   rc = DosCreateEventSem((PSZ) "\\SEM32\\ASYM\\FRMSTEP",  /* semaphore name  */
  548.                          &pRecCB->hevFrameStep,           /* semaphore handle*/
  549.                          (ULONG) 0,                    /* attribute - unused */
  550.                          (ULONG) 0);                   /* initial state set  */
  551.  
  552.   if (rc) fInitErr = TRUE;
  553.  
  554.  /********************************************************************/
  555.  /* Get a buffer for capturing the raw image.  Set error flag for    */
  556.  /* failure.  The value we are using for the multiply represents     */
  557.  /* 16 bit.  1 = 8 bit, 2 = 16 bit, 3 = 24 bit.                      */
  558.  /********************************************************************/
  559.   ulBufferSize = pswvrcb->recopts[pswvrcb->usCurrProf].usMovieSizeX *
  560.                  pswvrcb->recopts[pswvrcb->usCurrProf].usMovieSizeY * 2;
  561.  
  562.   rc = DosAllocMem ( (PPVOID) &pRecCB->rawimagebuf,
  563.                      ulBufferSize,
  564.                      (ULONG) PAG_COMMIT | PAG_READ | PAG_WRITE);
  565.  
  566.   if (rc) fInitErr = TRUE;
  567.  
  568.  /********************************************************************/
  569.  /* Get a buffer for holding the compressed image                    */
  570.  /* Set error flag for failure                                       */
  571.  /********************************************************************/
  572.   rc = DosAllocMem ( (PPVOID) &pRecCB->compimagebuf, ulBufferSize,
  573.                      (ULONG) PAG_COMMIT | PAG_READ | PAG_WRITE);
  574.  
  575.   if (rc) fInitErr = TRUE;
  576.  
  577.  /*********************************************************************/
  578.  /* If an error occured return error, so that recording will not start*/
  579.  /*********************************************************************/
  580.   if (fInitErr) {
  581.      return(1);
  582.   } /* endif */
  583.  
  584.  /******************************************************************/
  585.  /* Save the Wave file that was previously recorded if it has not  */
  586.  /* been saved.                                                    */
  587.  /******************************************************************/
  588.   lpWaveSave.dwCallback = 0;
  589.   lpWaveSave.lpFileName = 0;
  590.   rcode =
  591.           mciSendCommand (
  592.           pswvrcb->wWaveDID,       /* Device ID returned from OPEN */
  593.           MCI_SAVE,                /* Command                      */
  594.           MCI_WAIT,                /* dwFlags                      */
  595.          (ULONG)&lpWaveSave,       /* In/Out Parameters            */
  596.            0 );                    /* User Parameter               */
  597.  
  598.  /******************************************************************/
  599.  /* We need to close the waveaudio so we can open digitalvideo02.  */
  600.  /* This is done because some audio adapters do not support        */
  601.  /* multiple instances.                                            */
  602.  /******************************************************************/
  603.   rcode = mciSendCommand( pswvrcb->wWaveDID,
  604.                           MCI_CLOSE,
  605.                           MCI_WAIT,
  606.                           (ULONG) &lpGenparms, 0 );
  607.  
  608.   if (SendString ((PSZ) "OPEN",
  609.                         (PSZ) pswvrcb->OutputMovie.szDeviceName,
  610.                         (PSZ) "ALIAS",
  611.                         (PSZ) pswvrcb->OutputMovie.szDeviceAlias,
  612.                         (PSZ) "WAIT",
  613.                          NULL,
  614.                          NULL))
  615.     {
  616.        WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,
  617.           (PSZ) "error opening MCD",
  618.           (PSZ) errnostr, 0, MB_OK | MB_MOVEABLE);
  619.     }
  620.     else
  621.     {
  622.      pswvrcb->OutputMovie.wDeviceID =
  623.                    mciGetDeviceID( (LPSTR) pswvrcb->OutputMovie.szDeviceAlias);
  624.     }
  625.  /*********************************************************************/
  626.  /* If we have any problems with the codec data, initializing our     */
  627.  /* environment for frame step recording or associating the codec     */
  628.  /* then return.  We cannot proceed with recording.                   */
  629.  /*********************************************************************/
  630.   if (!pswvrcb->pCODECData      ||
  631.       (rc = OpenMMIO(pswvrcb)) ||
  632.       (rc =  AssociateCodec( pswvrcb->hmmioTemp,
  633.                              pswvrcb,
  634.                              &pswvrcb->pCODECData->cifi,
  635.                              (PVOID)NULL,
  636.                              CODEC_COMPRESS )));
  637.   {
  638.   return(rc);
  639.   }
  640.  
  641.  /********************************************************************/
  642.  /* Everything is ok so far, start the frame step recording thread   */
  643.  /********************************************************************/
  644.   rc = DosCreateThread ((PTID) &pRecCB->RecordThreadID,   /* Thread ID       */
  645.                         (PFNTHREAD) StartVideoThread,     /* Thread addr     */
  646.                         (ULONG) pswvrcb,
  647.                         (ULONG) 0,                        /* Flags           */
  648.                         (ULONG) RecordThreadStackSize);   /* stack size      */
  649.  
  650.  /********************************************************************/
  651.  /* Change record thread to regular class, delta = -4.               */
  652.  /* Set error flag for failure                                       */
  653.  /********************************************************************/
  654.   rc = DosSetPriority ( 2L, 2L, -4L, pRecCB->RecordThreadID);
  655.  
  656.   if (rc)
  657.   {
  658.      fInitErr = TRUE;
  659.      return(rc);
  660.   }
  661.  
  662.   return(0L);
  663. } /* end: InitiateFrameStepRecord      */
  664.  
  665. /*********************************************************************/
  666. /* Name : CompressBuffer                                             */
  667. /*                                                                   */
  668. /* This function calls the IO proc to compress a raw image buffer    */
  669. /*                                                                   */
  670. /*********************************************************************/
  671. RC CompressBuffer (HMMIO         hmmio        /* Handle to open file */
  672.                    PSWVRCB       pCB,       /* Control block pointer */
  673.                    PRECCB        pRecCB)  /* Pointer to record block */
  674. {
  675.  /********************************************************************/
  676.  /* Compression variables                                            */
  677.  /********************************************************************/
  678.   RC                        rcode = NO_ERROR;
  679.   MMCOMPRESS                CompressInfo;
  680.   MMVIDEOCOMPRESS           VideoCompressInfo;
  681.  
  682.   /*******************************************************************/
  683.   /* Initialize the compression information                          */
  684.   /*******************************************************************/
  685.    memset( &VideoCompressInfo, 0, sizeof(MMVIDEOCOMPRESS));
  686.  
  687.    CompressInfo.ulStructLen   = sizeof( MMCOMPRESS );
  688.  
  689.    CompressInfo.pRunTimeInfo  = &VideoCompressInfo;
  690.  
  691.    CompressInfo.ulSrcBufLen   = pswrcb->recopts.usMovieSizeX *
  692.                                 pswrcb->recopts.usMovieSizeY * 2;
  693.  
  694.    CompressInfo.pSrcBuf       = pRecCB->rawimagebuf;
  695.  
  696.    CompressInfo.ulDstBufLen   = pswrcb->recopts.usMovieSizeX *
  697.                                 pswrcb->recopts.usMovieSizeY * 2;
  698.  
  699.    CompressInfo.pDstBuf       = pRecCB->compimagebuf;
  700.  
  701.   /*******************************************************************/
  702.   /* If we are inserting reference frames, check to see if it's now. */
  703.   /* If its the 15th frame or 1st frame insert a reference frame.    */
  704.   /*******************************************************************/
  705.    if ( pCB->recopts.fInsertRefFrames )
  706.       if ( !( pRecCB->FramesCounted % pCB->recopts.usMaxRefreshTime ) )
  707.       {
  708.         /**************************************************************/
  709.         /* Compress a reference frame                                 */
  710.         /**************************************************************/
  711.          CompressInfo.ulFlags = MMIO_IS_KEY_FRAME;
  712.          rcode = mmioSendMessage( pCB->hmmioTemp, MMIOM_COMPRESS,
  713.                                (ULONG)&CompressInfo, 0L);
  714.       }
  715.       else
  716.       {
  717.         /**************************************************************/
  718.         /* Compress a delta frame                                     */
  719.         /**************************************************************/
  720.          CompressInfo.ulFlags = 0;
  721.          rcode = mmioSendMessage( pCB->hmmioTemp, MMIOM_COMPRESS,
  722.                                (ULONG)&CompressInfo, 0L);
  723.       }
  724.   /**************************************************************/
  725.   /* Increment our frame counter                                */
  726.   /**************************************************************/
  727.    pRecCB->FramesCounted++;
  728.  
  729.   /**************************************************************/
  730.   /* Determine total data rate written for this frame           */
  731.   /**************************************************************/
  732.    pRecCB->outbuflen  = CompressInfo.ulDstBufLen;
  733.  
  734.    return(rcode);
  735.  
  736. } /* Compress Buffer */
  737.  
  738. /***************************************************************************/
  739. /* Name : StartVideoThread                                                 */
  740. /*                                                                         */
  741. /* Function: Recording thread for frame step.  This function is assuming   */
  742. /* that we have previously recorded the audio to a temporary file that     */
  743. /* will be used in this function.  We also create a temporary file that    */
  744. /* is used for the data after it has been interleaved with the audio.      */
  745. /*                                                                         */
  746. /* InputMovie is referencing the laser disk device and OutputMovie is      */
  747. /* referencing the digitalvideo02 adapter.                                 */
  748. /*                                                                         */
  749. /* Once everything is setup, compress the video then send the              */
  750. /* MMIOM_MULTITRACKWRITE message to interleave the audio and video data    */
  751. /* and create a movie file.  Since this is only a sample we are only       */
  752. /* writing out 1 frame of video and whatever audio that goes with that     */
  753. /* video.  This structure may be set up for multiple records of video and  */
  754. /* audio.                                                                  */
  755. /*                                                                         */
  756. /***************************************************************************/
  757. VOID StartVideoThread( VOID )
  758. {
  759.  /*****************************************************************/
  760.  /* Various return code variables and strings                     */
  761.  /*****************************************************************/
  762.   ULONG                  rcode = NO_ERROR;
  763.   ULONG                  rc;
  764.   char                   errnostr[20];
  765.  
  766.  /*****************************************************************/
  767.  /* Semaphore variables                                           */
  768.  /*****************************************************************/
  769.   ULONG                  Postcount;
  770.   HMQ                    hmq = WinCreateMsgQueue( hab, 0 );
  771.  
  772.  /******************************************************************/
  773.  /* External device mci variables structs for mcisendcommand       */
  774.  /******************************************************************/
  775.   MCI_SEEK_PARMS         lpExtdevSeek;
  776.   MCI_STEP_PARMS         lpExtdevStep;
  777.   MCI_STATUS_PARMS       lpStatusParms;
  778.  
  779.  /******************************************************************/
  780.  /* Audio device mci variables structs for mcisendcommand          */
  781.  /******************************************************************/
  782.   MCI_SAVE_PARMS         lpWaveSave;
  783.   MCI_GENERIC_PARMS      lpGenparms;
  784.  
  785.  /******************************************************************/
  786.  /* Variables for maintaining data rate requested.                 */
  787.  /* Must use for skipping frames to maintain desired data rate     */
  788.  /******************************************************************/
  789.   ULONG                  ulCurrentSkipPct,
  790.                          ulSkipPercentage;
  791.   ULONG                  ulFrames;
  792.  
  793.  /******************************************************************/
  794.  /* Compression variables                                          */
  795.  /******************************************************************/
  796.   MCI_IMAGE_PARMS        mciImageParms;
  797.   IRECT                  dest_rect;
  798.   IRECT                  source_rect;
  799.  
  800.  /******************************************************************/
  801.  /* Varibles needed to frame step record video and interleave      */
  802.  /* the audio.                                                     */
  803.  /******************************************************************/
  804.   MMMULTITRACKWRITE      MMMultiTrackWrite; /* MMMULTITRACKWRITE Structure */
  805.  
  806.   TRACKMAP               TrackMap[2];           /* TRACKMAP Structure      */
  807.  
  808.   RECORDTAB              Aud;      /* Audio RECORDTAB Structure            */
  809.  
  810.   RECORDTABWRITE         Vid;      /* Video RECORDTAB Structure            */
  811.  
  812.  /******************************************************************/
  813.  /* Varibles needed to break up Audio into 1 frame chunks.         */
  814.  /******************************************************************/
  815.   HMMIO                  hmmiowav;
  816.   PMMAUDIOHEADER         pMMAudioHeader;
  817.   LONG                   lBytes;
  818.   LONG                   lBytesRead;
  819.   LONG                   lSize;
  820.   ULONG                  ulAudioBytesPerFrame;
  821.   ULONG                  ulReserved;
  822.   ULONG                  ulFlags;
  823.   PSZ                    pAudioBuffer;
  824.  
  825.  /******************************************************************/
  826.  /* Main control block and record control block                    */
  827.  /* Get main from global threadpointer since it can't be passed in */
  828.  /******************************************************************/
  829.   PRECCB                 pRecCB;
  830.   PSWVRCB                pswvrcb = threadpointer;
  831.  
  832.  /******************************************************************/
  833.  /* Get record control block off of main control block             */
  834.  /******************************************************************/
  835.   pRecCB = pswvrcb->pRecCB;
  836.  
  837.  
  838.  /******************************************************************/
  839.  /* Get exclusive control of the Output device now.  We want       */
  840.  /* exclusive use so we don't loose control in the middle of       */
  841.  /* recording.                                                     */
  842.  /******************************************************************/
  843.   lpGenparms.dwCallback = 0;
  844.   rcode = mciSendCommand( pswvrcb->OutputMovie.wDeviceID,
  845.                           MCI_ACQUIREDEVICE,
  846.                           MCI_WAIT | MCI_EXCLUSIVE,
  847.                           (ULONG) &lpGenparms, 0 );
  848.  
  849.  /******************************************************************/
  850.  /* Get exclusive control of the Input device now if we have one   */
  851.  /******************************************************************/
  852.   if (!rcode && pswvrcb->InputMovie.wDeviceID)
  853.   {
  854.     lpGenparms.dwCallback = 0;
  855.     rcode = mciSendCommand( pswvrcb->InputMovie.wDeviceID,
  856.                             MCI_ACQUIREDEVICE,
  857.                             MCI_WAIT | MCI_EXCLUSIVE,
  858.                             (ULONG) &lpGenparms, 0 );
  859.   }
  860.  
  861.  /******************************************************************/
  862.  /* Initialize current input positions (laser disk)                */
  863.  /******************************************************************/
  864.   if (!rcode)
  865.   {
  866.     pRecCB->dwSrcCurrentPosition   = pswvrcb->dwSrcRecordFrom;
  867.     pRecCB->dwMovieRecordFrom      = 0;
  868.     pRecCB->dwMovieCurrentPosition = 0;
  869.  
  870.   } /* endif */
  871.  
  872.  /*******************************************************************/
  873.  /* Set the time format on external video device to MMTIME format   */
  874.  /*******************************************************************/
  875.   lpExtdevSet.dwCallback   = 0;
  876.   lpExtdevSet.dwTimeFormat = MCI_FORMAT_MMTIME;
  877.   rcode = mciSendCommand (pswvrcb->InputMovie.wDeviceID,     /* Device ID */
  878.                           MCI_SET,                           /* Command   */
  879.                           MCI_WAIT | MCI_SET_TIME_FORMAT,    /* dwFlags   */
  880.                           (ULONG) (&lpExtdevSet),    /* In/Out Parameters */
  881.                           0 );                       /* User Parameter    */
  882.  
  883.  /******************************************************************/
  884.  /*    Seek external video device to first frame                   */
  885.  /******************************************************************/
  886.   lpExtdevSeek.dwCallback = 0;
  887.   lpExtdevSeek.dwTo       = pswvrcb->dwSrcRecordFrom;
  888.   rcode = mciSendCommand ( pswvrcb->InputMovie.wDeviceID,  /* Device ID      */
  889.                            MCI_SEEK,                       /* Command        */
  890.                            MCI_WAIT | MCI_TO,              /* dwFlags        */
  891.                            (ULONG) (&lpExtdevSeek), /* In/Out Parameters     */
  892.                            0 );                     /* User Parameter        */
  893.  
  894.  
  895.   if (!rcode)
  896.     {
  897.     /******************************************************************/
  898.     /* Calculate the number of frames on the source device we need to */
  899.     /* skip per movie frame to maintain the desired capture frame rate*/
  900.     /******************************************************************/
  901.     ulCurrentSkipPct = 0L;
  902.     ulSkipPercentage = (((pswvrcb->recopts.SrcFPS -
  903.                           pswvrcb->recopts.MovieFPS) * 1000 ) +
  904.                           pswvrcb->recopts.MovieFPS - 1 ) /
  905.                           pswvrcb->recopts.MovieFPS;
  906.  
  907.     /******************************************************************/
  908.     /* Set the source rectangle size for the capture.                 */
  909.     /* This is for how much we are capturing.                         */
  910.     /******************************************************************/
  911.     source_rect.X_left   =  pswvrcb->recopts.usCapPosX; /* Default 0         */
  912.     source_rect.Y_top    =  pswvrcb->recopts.usCapPosY; /* Default 0         */
  913.     source_rect.X_width  =  pswvrcb->recopts.usCapSizeX;/* Default 640       */
  914.     source_rect.Y_height =  pswvrcb->recopts.usCapSizeY;/* Default 480       */
  915.  
  916.     /******************************************************************/
  917.     /* Set the destination rectangle size to the desired movie size   */
  918.     /******************************************************************/
  919.     dest_rect.X_left   = 0;
  920.     dest_rect.Y_top    = 0;
  921.                                   /* Destination rectangle width for capture */
  922.     dest_rect.X_width  = pswvrcb->recopts.usMovieSizeX;  /* default 320      */
  923.                                  /* Destination rectangle height for capture */
  924.     dest_rect.Y_height = pswvrcb->recopts.usMovieSizeY;  /* default 240      */
  925.   } /* endif */
  926.  
  927.  /******************************************************************/
  928.  /* Open up the Audio file.                                        */
  929.  /******************************************************************/
  930.    hmmiowav = mmioOpen( TempAudioFilename,
  931.                         NULL,
  932.                         0);
  933.  
  934.  /******************************************************************/
  935.  /* Query header length from audio file.                           */
  936.  /******************************************************************/
  937.   if (!rcode)
  938.     rcode = mmioQueryHeaderLength(hmmiowav,&lSize,0L,0L);
  939.  
  940.   if (!rcode)
  941.     pMMAudioHeader = malloc(lSize);
  942.  
  943.  /***********************************************************************/
  944.  /***********************************************************************/
  945.  /* Get main header information from the previously recorded audio file.*/
  946.  /* This information will be set into the new movie files audio track   */
  947.  /* header.                                                             */
  948.  /***********************************************************************/
  949.   if (!rcode)
  950.     rcode = mmioGetHeader(hmmiowav,
  951.                           (PVOID)(pMMAudioHeader),
  952.                           lSize, &lBytesRead, 0L, 0L);
  953.  
  954.   /***************************************************************/
  955.   /* This function is called to set the track and to setup       */
  956.   /* extended file information for the audio.  For audio         */
  957.   /* information we set to 1.                                    */
  958.   /***************************************************************/
  959.    SetActiveTrack ( pswvrcb->hmmioTemp, 1L );
  960.  
  961.   /******************************************************************/
  962.   /* Set the audio header information in the new movie file.        */
  963.   /******************************************************************/
  964.    rc = mmioSetHeader( pswvrcb->hmmioTemp,
  965.                                 pMMAudioHeader,
  966.                                 sizeof(MMAUDIOHEADER),
  967.                                 &lBytes,
  968.                                 ulReserved,
  969.                                 ulFlags );
  970.  
  971.   /***************************************************************/
  972.   /* This function is called to reset the track and to setup     */
  973.   /* extended file information for the audio.                    */
  974.   /***************************************************************/
  975.    SetActiveTrack ( pswvrcb->hmmioTemp, MMIO_RESETTRACKS );
  976.                                                     /* MMIO_RESETTRACKS = -1 */
  977.  
  978.   /******************************************************************/
  979.   /* Calculate Number of Audio Bytes Per Frame of Video because     */
  980.   /* we will be interleaving the audio and video at 1 to 1.         */
  981.   /******************************************************************/
  982.    ulAudioBytesPerFrame = pMMAudioHeader->mmXWAVHeader.
  983.                                           WAVEHeader.
  984.                                           ulAvgBytesPerSec /
  985.                                           pswvrcb->recopts.MovieFPS;
  986.    pAudioBuffer = malloc(ulAudioBytesPerFrame);
  987.    memset(pAudioBuffer, 0, ulAudioBytesPerFrame);
  988.  
  989.    free(pMMAudioHeader);
  990.  
  991.  /******************************************************************/
  992.  /* This is the frame step recording loop                          */
  993.  /* Recording continues until we reach the recording end point     */
  994.  /* on the source device, or until the user presses stop.          */
  995.  /******************************************************************/
  996.  
  997.   /***************************************************************/
  998.   /* This function is called to reset the track and to setup     */
  999.   /* extended file information.                                  */
  1000.   /***************************************************************/
  1001.   rcode = SetActiveTrack(pswvrcb->hmmioTemp, MMIO_RESETTRACKS);
  1002.                                                     /* MMIO_RESETTRACKS = -1 */
  1003.  
  1004.   while (!rcode &&
  1005.           pswvrcb->fRecordActive &&
  1006.          (pswvrcb->InputMovie.wDeviceID ?
  1007.          (pRecCB->dwSrcCurrentPosition <= pswvrcb->dwSrcRecordTo) : TRUE) )
  1008.   {
  1009.    /******************************************************************/
  1010.    /*    Block at this point if record operation is paused           */
  1011.    /******************************************************************/
  1012.      while ( pswvrcb->fRecordPaused && pRecCB->fStillRunning )
  1013.      {
  1014.         rc = DosResetEventSem( pRecCB->hevRecordPaused, &Postcount);
  1015.         rc = DosWaitEventSem( pRecCB->hevRecordPaused, (ULONG) -1);
  1016.      } /* endwhile */
  1017.  
  1018.      /******************************************************************/
  1019.      /* make sure we were not stopped while we were paused             */
  1020.      /******************************************************************/
  1021.      if ( pswvrcb->fRecordActive && !pswvrcb->fRecordPaused )
  1022.      {
  1023.  
  1024.         if (pswvrcb->recopts.fCompress)
  1025.         {
  1026.  
  1027.           /*****************************************************************/
  1028.           /* Initialize mciImageParm variable before sending to MCD        */
  1029.           /*****************************************************************/
  1030.            memset( &mciImageParms, 0, sizeof(mciImageParms));
  1031.            mciImageParms.dwBufLen = pswvrcb->recopts.usMovieSizeX *
  1032.                                     pswvrcb->recopts.usMovieSizeY * 2;
  1033.           /*****************************************************************/
  1034.           /* rawimagebuf is where we put our output from the GetImageBuffer*/
  1035.           /*****************************************************************/
  1036.            mciImageParms.pPelBuffer=(PVOID *)pRecCB->rawimagebuf;
  1037.            mciImageParms.rect.xLeft        = source_rect.X_left;
  1038.            mciImageParms.rect.yBottom      = source_rect.Y_top;
  1039.            mciImageParms.rect.xRight       = source_rect.X_left +
  1040.                                              source_rect.X_width;
  1041.            mciImageParms.rect.yTop         = source_rect.Y_top  +
  1042.                                              source_rect.Y_height;
  1043.            mciImageParms.dwPelBufferWidth  = pswvrcb->recopts.usMovieSizeX;
  1044.            mciImageParms.dwPelBufferHeight = pswvrcb->recopts.usMovieSizeY;
  1045.  
  1046.           /*****************************************************************/
  1047.           /* Get image data for this frame into raw image buffer           */
  1048.           /*****************************************************************/
  1049.            rcode = mciSendCommand( pswvrcb->OutputMovie.wDeviceID,
  1050.                                    MCI_GETIMAGEBUFFER,
  1051.                                    MCI_WAIT | MCI_USE_HW_BUFFER,
  1052.                                    (ULONG)&mciImageParms,
  1053.                                    0);
  1054.  
  1055.         }
  1056.  
  1057.        /*******************************************************************/
  1058.        /* Figure out how many frames to advance the external video device */
  1059.        /* to maintain desired data rate                                   */
  1060.        /*******************************************************************/
  1061.         ulCurrentSkipPct           += ulSkipPercentage;
  1062.         ulFrames                    = ulCurrentSkipPct / 1000L;
  1063.         ulCurrentSkipPct           -= ulFrames * 1000L;
  1064.         if ( ulCurrentSkipPct < 50L )
  1065.            ulCurrentSkipPct = 0L;
  1066.  
  1067.        /********************************************************************/
  1068.        /* Advance the input device.                                        */
  1069.        /* If device is not controllable, ask the user to do it.            */
  1070.        /********************************************************************/
  1071.         if (!rcode && pswvrcb->InputMovie.wDeviceID)
  1072.         {
  1073.  
  1074.           /*****************************************************************/
  1075.           /* Clear the semaphore that signals the external device          */
  1076.           /* frame step complete                                           */
  1077.           /*****************************************************************/
  1078.            rc = DosResetEventSem( pRecCB->hevFrameStep, &Postcount);
  1079.  
  1080.           /*****************************************************************/
  1081.           /* Send STEP to external video device.  This is stepping the     */
  1082.           /* input device (laser disk).                                    */
  1083.           /*****************************************************************/
  1084.            lpExtdevStep.dwCallback = vhwndPlayerDialog;
  1085.            ulFrames++;
  1086.            lpExtdevStep.dwStep     = ulFrames * 3000/pswvrcb->recopts.SrcFPS;
  1087.            mciSendCommand ( pswvrcb->InputMovie.wDeviceID,
  1088.                             MCI_STEP,
  1089.                             MCI_NOTIFY | MCI_STEP_FRAMES,
  1090.                             (ULONG) (&lpExtdevStep),
  1091.                             lpExtdevStep.dwStep );
  1092.         }
  1093.  
  1094.        /*****************************************************************/
  1095.        /* Since we are compressing during record,                       */
  1096.        /* compress the image contained in rawimagebuf and put the       */
  1097.        /* compressed output into the stream buffer                      */
  1098.        /*****************************************************************/
  1099.         if (!rcode && pswvrcb->recopts.fCompress)
  1100.         {
  1101.  
  1102.            /*****************************************************************/
  1103.            /* Compress - Input raw image buffer is in pRecCB->rawimagebuf.  */
  1104.            /*****************************************************************/
  1105.             rcode = CompressBuffer (pswvrcb->hmmioTemp,
  1106.                                     pswvrcb,
  1107.                                     pRecCB);
  1108.  
  1109.            /*****************************************************/
  1110.            /* Get a chunk of Audio data                         */
  1111.            /*****************************************************/
  1112.             lBytes = mmioRead( hmmiowav,
  1113.                              (PSZ)pAudioBuffer,
  1114.                              ulAudioBytesPerFrame);
  1115.  
  1116.            /*****************************************************/
  1117.            /* Initialize these MMMultiTrackWrite fields for     */
  1118.            /* later use in the mmioSendMessage.                 */
  1119.            /*****************************************************/
  1120.  
  1121.             MMMultiTrackWrite.ulFlags = 0L;
  1122.  
  1123.             MMMultiTrackWrite.Reserved = 0L;
  1124.  
  1125.           /****************************************************************/
  1126.           /* Specifies the number of TRACKMAP entries in pTrackMapList on */
  1127.           /* output.  Currently we have audio and video                   */
  1128.           /****************************************************************/
  1129.             MMMultiTrackWrite.ulNumTracks = 2;
  1130.  
  1131.            /*****************************************************************/
  1132.            /* We do not need to assign/specify the next element.  Using     */
  1133.            /* the MMMULTITRACKWRITE the IO proc handles this.               */
  1134.            /* The MMMULTITRACKWRITE does the interleaving of the video data */
  1135.            /* and audio data for you.                                       */
  1136.            /*****************************************************************/
  1137.  
  1138.             MMMultiTrackWrite.pTrackMapList = &TrackMap[0];
  1139.  
  1140.            /**********************************************************/
  1141.            /* Initialize the TRACKMAP entries for video data         */
  1142.            /* before sending the MMMultiTrackWrite message.          */
  1143.            /**********************************************************/
  1144.  
  1145.             TrackMap[0].ulTrackID = 0;      /* video data                */
  1146.  
  1147.             TrackMap[0].ulNumEntries = 1;   /* Number of video entries   */
  1148.  
  1149.             TrackMap[0].pRecordTabList = &Vid; /* Point to the RECORDTAB */
  1150.                                                /* for video              */
  1151.  
  1152.             /*******************************************************/
  1153.             /* Initialize the RECORDTAB table entries for video    */
  1154.             /* before sending the MMMultiTrackWrite message.       */
  1155.             /*******************************************************/
  1156.  
  1157.             Vid.pRecord = pRecCB->compimagebuf;
  1158.  
  1159.             Vid.ulLength = pRecCB->outbuflen;
  1160.  
  1161.             Vid.ulParm1 = 0L;
  1162.  
  1163.             Vid.ulParm2 = 0L;
  1164.  
  1165.             /***************************************************/
  1166.             /* Initialize the TRACKMAP entries for audio data */
  1167.             /* before sending the MMMultiTrackWrite message.   */
  1168.             /***************************************************/
  1169.  
  1170.             TrackMap[1].ulTrackID = 1;      /* audio data                */
  1171.  
  1172.             TrackMap[1].ulNumEntries = 1;   /* Number of audio entries   */
  1173.  
  1174.  
  1175.             TrackMap[1].pRecordTabList = &Aud; /* Point to the RECORDTAB */
  1176.                                                /* for audio              */
  1177.  
  1178.             /*******************************************************/
  1179.             /* Initialize the RECORDTAB table entries for audio    */
  1180.             /* before sending the MMMultiTrackWrite message.       */
  1181.             /*******************************************************/
  1182.  
  1183.             Aud.pRecord = pAudioBuffer;
  1184.  
  1185.             Aud.ulLength = ulAudioBytesPerFrame;
  1186.  
  1187.             Aud.ulParm1 = 0L;
  1188.  
  1189.             Aud.ulParm2 = 0L;
  1190.  
  1191.             /***************************************************************/
  1192.             /* Once everything is setup,send the message to interleave and */
  1193.             /* compress the video and audio data                           */
  1194.             /***************************************************************/
  1195.  
  1196.              rcode = mmioSendMessage(pswvrcb->hmmioTemp,
  1197.                                      MMIOM_MULTITRACKWRITE,
  1198.                                      (LONG)&MMMultiTrackWrite,
  1199.                                      sizeof(MMMultiTrackWrite));
  1200.  
  1201.         } /* End if - if compressing during record */
  1202.  
  1203.          /******************************************************************/
  1204.          /* Wait here until the external video device completes the        */
  1205.          /* frame step                                                     */
  1206.          /******************************************************************/
  1207.           DosWaitEventSem ( pRecCB->hevFrameStep, (ULONG)-1 );
  1208.  
  1209.      } /* End - if not stopped while paused */
  1210.  
  1211.   }   /* End while - frame step recording frame loop */
  1212.  
  1213.   free(pAudioBuffer);
  1214.  /*****************************************************************/
  1215.  /* Close the temp video output file since                        */
  1216.  /* recording is finished                                         */
  1217.  /*****************************************************************/
  1218.   mmioClose( pswvrcb->hmmioTemp, 0);    /* Close the final file   */
  1219.   mmioClose( hmmiowav, 0);              /* Close the audio file   */
  1220.  
  1221.  /*****************************************************************/
  1222.  /* Close event semaphore to signal frame step complete           */
  1223.  /*****************************************************************/
  1224.   DosCloseEventSem ( pRecCB->hevFrameStep );
  1225.  
  1226.  /*****************************************************************/
  1227.  /* Close event semaphore to signal recording paused              */
  1228.  /*****************************************************************/
  1229.   DosCloseEventSem ( pRecCB->hevRecordPaused );
  1230.  
  1231.  /*****************************************************************/
  1232.  /* Free buffer for capturing the raw image                       */
  1233.  /*****************************************************************/
  1234.   DosFreeMem ( pRecCB->rawimagebuf );
  1235.  
  1236.  /*****************************************************************/
  1237.  /* Free buffer for capturing the compressed image                */
  1238.  /*****************************************************************/
  1239.   DosFreeMem ( pRecCB->compimagebuf );
  1240.  
  1241.  /******************************************************************/
  1242.  /* Send a message back to our window so it knows recording is done*/
  1243.  /******************************************************************/
  1244.   WinSendMsg( vhwndPlayerDialog, WM_FINISHEDRECORDING,
  1245.               (MPARAM) rcode, (MPARAM) 0);
  1246.  
  1247.  /*****************************************************************/
  1248.  /* Destroy message queue                                         */
  1249.  /*****************************************************************/
  1250.   WinDestroyMsgQueue( hmq );
  1251.  
  1252.  /*****************************************************************/
  1253.  /* Exit thread                                                   */
  1254.  /*****************************************************************/
  1255.   DosExit( (ULONG) 0, (ULONG) 0);
  1256.  
  1257. } /* end: StartVideoThread          */
  1258.