home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / warptlk3.zip / TOOLKIT / SAMPLES / MM / CODEC / SAMPMAIN.C < prev   
C/C++ Source or Header  |  1995-08-24  |  17KB  |  383 lines

  1. /*****************************************************************************/
  2. /*                                                                           */
  3. /* SAMPMAIN.C: Sample Codec Main entry point and instance handling.          */
  4. /*                                                                           */
  5. /* Copyright (c) IBM Corporation 1991,1994             All Rights Reserved   */
  6. /*                                                                           */
  7. /*****************************************************************************/
  8.  
  9. #define  INCL_WIN
  10. #define  INCL_GPI
  11. #define  INCL_DOS
  12. #define  INCL_OS2MM
  13. #define  INCL_MMIO_CODEC
  14. #include <os2.h>
  15. #include <os2me.h>
  16. #include <string.h>
  17. #include "sampinst.h"
  18. #include "sampdeco.h"
  19. #include "sampenco.h"
  20.  
  21. /*****************************************************************************/
  22. /*                                                                           */
  23. /* Below defines the DLL shared global data (only one copy of this exists... */
  24. /* regardless of the number of processes or instances using it).             */
  25. /* The data must be initialized or it won't be placed in this segment.       */
  26. /* Note that if you have significant information in your instance array,     */
  27. /* you may want to make this global array pointers and allocate the          */
  28. /* instances on a required basis.  As it exists here, all 16 instances       */
  29. /* fit in one 4KB page of memory (the minimum allocatable memory without     */
  30. /* a heap manager).  It's also a good idea to put static conversion tables   */
  31. /* here so that if more than one process is open at a time, there's only     */
  32. /* one copy of the tables (see the bottom of sampenco.c).                    */
  33. /*                                                                           */
  34. /*****************************************************************************/
  35.  
  36. #pragma data_seg (PROCESS_SHARED_DATA_SEGMENT)
  37.  
  38. #define   MAX_INSTANCES 16
  39.  
  40. MAIN_INST amiInst[MAX_INSTANCES] = {0};
  41.  
  42. HMTX      hmtxInstanceArray = 0;
  43.  
  44. ULONG     ulInitCount = 0;
  45.  
  46. #pragma data_seg ()
  47.  
  48.  
  49.  
  50.  
  51. /*****************************************************************************/
  52. /*                                                                           */
  53. /* SUBROUTINE NAME: OpenCodecInstance                                        */
  54. /*     This routine is called once per instance allocation.  Here is where   */
  55. /*     you initialize either your compression parameters, your               */
  56. /*     decompression parameters, or both (one instance can do both at        */
  57. /*     once) based on the passed open flags.                                 */
  58. /*                                                                           */
  59. /*****************************************************************************/
  60.  
  61. LONG OpenCodecInstance ( PULONG pulInstNumber, PCODECOPEN pCodecOpen )
  62.    {
  63.    PMAIN_INST pMainInst;
  64.    PCODECVIDEOHEADER pCodecDst;
  65.    PCODECVIDEOHEADER pCodecSrc;
  66.    ULONG ulInstIndex;
  67.  
  68.    /* Check to make sure that the instance pointer is non-zero.              */
  69.    if ( !pulInstNumber )
  70.       return ( MMIO_ERROR );
  71.  
  72.    /* Check to make sure that the instance isn't already allocated.          */
  73.    if ( *pulInstNumber )
  74.       return ( MMIO_ERROR );
  75.  
  76.    /* Search for a spot in the instance array for this pointer.              */
  77.    ulInstIndex = 0;
  78.    while ( ulInstIndex < MAX_INSTANCES ) {
  79.       /* If we've found an open instance location, use it.                   */
  80.       if ( !amiInst[ulInstIndex].fInstanceInUse )
  81.          break;
  82.       ulInstIndex ++;
  83.       }
  84.  
  85.    /* Check if we are out of instance space.                                 */
  86.    if ( ulInstIndex == MAX_INSTANCES )
  87.       return ( ERROR_ALLOC_RESOURCES );
  88.  
  89.    /* Setup a pointer to point to the instance.                              */
  90.    pMainInst = &amiInst[ulInstIndex];
  91.  
  92.    /* Initialize the instance to all zeros.                                  */
  93.    memset ( pMainInst, 0, sizeof ( MAIN_INST ) );
  94.  
  95.    /* Grab local copys of the codec open dst and src structure pointers.     */
  96.    pCodecDst = (PCODECVIDEOHEADER) pCodecOpen->pDstHdr;
  97.    pCodecSrc = (PCODECVIDEOHEADER) pCodecOpen->pSrcHdr;
  98.  
  99.    /* Check if we are opening a decompression instance.                      */
  100.    if ( pCodecOpen->ulFlags & CODEC_DECOMPRESS ) {
  101.  
  102.       /* Grab a copy of the width and height.                                */
  103.       pMainInst->ulWidth = pCodecSrc->cx;
  104.       pMainInst->ulHeight = pCodecSrc->cy;
  105.       }
  106.  
  107.    /* Check if we are opening a compression instance.                        */
  108.    if ( pCodecOpen->ulFlags & CODEC_COMPRESS ) {
  109.  
  110.       /* We don't do any scaling, make sure we're not asked to.  Also check  */
  111.       /* the source color format to see if we support that, and check that   */
  112.       /* the destination is actually supposed to be compressed.              */
  113.       if ( pCodecSrc->cx != pCodecDst->cx || pCodecSrc->cy != pCodecDst->cy ||
  114.            ( pCodecSrc->ulColorEncoding != MMIO_RGB_5_6_5 &&
  115.              pCodecSrc->ulColorEncoding != MMIO_YUV_4_1_1 ) ||
  116.              pCodecDst->ulColorEncoding != MMIO_COMPRESSED )
  117.          return ( MMIO_ERROR );
  118.  
  119.       /* Grab a copy of the source width, height, and color encoding.        */
  120.       pMainInst->ulWidth= pCodecSrc->cx;
  121.       pMainInst->ulHeight= pCodecSrc->cy;
  122.       pMainInst->ulColorEncoding= pCodecSrc->ulColorEncoding;
  123.       }
  124.  
  125.    /* Mark that this instance is now in use.                                 */
  126.    pMainInst->fInstanceInUse = TRUE;
  127.  
  128.    /* Return the instance number that we created, and we are done.  Note     */
  129.    /* that we'll add 1 to it just so we don't return a 0 as a vaild instance */
  130.    /* number.  Therefore we'll return instance numbers in the 1 to 16 range. */
  131.    /* Remember that when they come back, they'll be one larger!              */
  132.    *pulInstNumber = ulInstIndex + 1;
  133.  
  134.    return ( MMIO_SUCCESS );
  135.    }
  136.  
  137.  
  138.  
  139.  
  140. /*****************************************************************************/
  141. /*                                                                           */
  142. /* SUBROUTINE NAME: CompressBuffer                                           */
  143. /*     This routine will be called once per frame to compress.  This may     */
  144. /*     be a symmetric call or an asymmetric call (or even an asymmetric      */
  145. /*     call to a symmetric algorithm) if your compression has set the        */
  146. /*     symmetric flag.  Otherwise the asymmetric flag must be set and        */
  147. /*     the call to the compression can take as long as desired.              */
  148. /*                                                                           */
  149. /*****************************************************************************/
  150.  
  151. ULONG CompressBuffer ( PULONG pulInstNumber, PMMCOMPRESS pmmCompress )
  152.    {
  153.    PMAIN_INST pMainInst;
  154.  
  155.    /* Check to make sure that the instance pointer is valid                  */
  156.    if ( !pulInstNumber )
  157.       return ( MMIOERR_INVALID_PARAMETER );
  158.  
  159.    /* Check to make sure that the instance number is valid.                  */
  160.    if ( !*pulInstNumber || *pulInstNumber > MAX_INSTANCES )
  161.       return ( MMIOERR_INVALID_PARAMETER );
  162.  
  163.    /* Grab a pointer to the instance and make sure it's okay.                */
  164.    pMainInst = &amiInst[*pulInstNumber-1];
  165.    if ( !pMainInst->fInstanceInUse )
  166.       return ( MMIOERR_INVALID_PARAMETER );
  167.  
  168.    /* Check to see that the pmmCompress pointer is non-zero.                 */
  169.    if ( !pmmCompress )
  170.       return ( MMIOERR_INVALID_PARAMETER );
  171.  
  172.    /* Call to the compressor.                                                */
  173.    pmmCompress->ulDstBufLen = CompressFrame ( pMainInst,
  174.                                  pmmCompress->pSrcBuf, pmmCompress->pDstBuf );
  175.  
  176.    /* If we actually compressed something, return that it worked.            */
  177.    if ( pmmCompress->ulDstBufLen )
  178.       return ( MMIO_SUCCESS );
  179.    else
  180.       return ( MMIO_ERROR );
  181.    }
  182.  
  183.  
  184.  
  185.  
  186. /*****************************************************************************/
  187. /*                                                                           */
  188. /* SUBROUTINE NAME: DecompressBuffer                                         */
  189. /*     This routine is called once per frame to be decompressed.             */
  190. /*                                                                           */
  191. /*****************************************************************************/
  192.  
  193. ULONG DecompressBuffer ( PULONG pulInstNumber, PMMDECOMPRESS pmmDecompress )
  194.    {
  195.    PMAIN_INST pMainInst;
  196.  
  197.    /* Check to make sure that the instance pointer is valid                  */
  198.    if ( !pulInstNumber )
  199.       return ( MMIOERR_INVALID_PARAMETER );
  200.  
  201.    /* Check to make sure that the instance number is valid.                  */
  202.    if ( !*pulInstNumber || *pulInstNumber > MAX_INSTANCES )
  203.       return ( MMIOERR_INVALID_PARAMETER );
  204.  
  205.    /* Grab a pointer to the instance and make sure it's okay.                */
  206.    pMainInst = &amiInst[*pulInstNumber-1];
  207.    if ( !pMainInst->fInstanceInUse )
  208.       return ( MMIOERR_INVALID_PARAMETER );
  209.  
  210.    /* Check the videodecompress parameter for validity.                      */
  211.    if ( !pmmDecompress->pRunTimeInfo )
  212.       return ( MMIOERR_INVALID_PARAMETER );
  213.  
  214.    /* Here is where we check to see if the software video stream handler     */
  215.    /* is requesting that we drop this frame to keep synchronization with     */
  216.    /* the audio.  It is not recommended that this flag be ignored.  If it    */
  217.    /* is ignored, the audio stream could starve waiting on the video stream  */
  218.    /* and the audio will "break up"-- seemingly stopping and starting.       */
  219.    /* The MMIO_DROP_FRAME_DECODE means don't do the decompression on this    */
  220.    /* frame (but we're getting called in case we need to do clean-up).       */
  221.    if ( pmmDecompress->ulFlags & MMIO_DROP_DELTA_FRAME )
  222.       pmmDecompress->ulFlags &= ~MMIO_DROP_DELTA_FRAME;
  223.    else
  224.       /* Decompress the frame.                                               */
  225.       DecompressFrame ( pMainInst, pmmDecompress->pSrcBuf,
  226.                                        pmmDecompress->pDstBuf );
  227.  
  228.    /* The frame has be completely decoded, tell the subsystem we're done.    */
  229.    pmmDecompress->pSrcBuf = 0;
  230.    pmmDecompress->ulSrcBufLen = 0;
  231.    return ( MMIO_SUCCESS );
  232.    }
  233.  
  234.  
  235.  
  236.  
  237. /*****************************************************************************/
  238. /*                                                                           */
  239. /* SUBROUTINE NAME: CloseCodecInstance                                       */
  240. /*     This routine will be called once per instance at deallocation time.   */
  241. /*     Be sure to deallocate any private RAM allocated from the heap or      */
  242. /*     through DosAllocMem in either a compression instance, decompression   */
  243. /*     instance, or both.                                                    */
  244. /*                                                                           */
  245. /*****************************************************************************/
  246.  
  247. LONG CloseCodecInstance ( PULONG pulInstNumber )
  248.    {
  249.    PMAIN_INST pMainInst;
  250.  
  251.    /* Check to make sure the instance pointer is non-zero.                   */
  252.    if ( pulInstNumber )
  253.  
  254.       /* Check to make sure the instance number itself is valid.             */
  255.       if ( *pulInstNumber && *pulInstNumber <= MAX_INSTANCES ) {
  256.  
  257.          /* Grab a pointer to the instance.                                  */
  258.          pMainInst = &amiInst[*pulInstNumber-1];
  259.  
  260.          /* Check to see if the instance is actually in use.                 */
  261.          if ( pMainInst->fInstanceInUse ) {
  262.  
  263.             /* Okay, everything checks out.  Mark it as no longer in use and */
  264.             /* Free up the compression buffer if it was allocated.           */
  265.             pMainInst->fInstanceInUse = FALSE;
  266.  
  267.             /* Null the instance data pointer.                               */
  268.             *pulInstNumber = 0;
  269.  
  270.             /* Return that everything was okay.                              */
  271.             return ( MMIO_SUCCESS );
  272.             }
  273.          }
  274.  
  275.    /* There was something wrong with the passed instance number pointer.     */
  276.    return ( MMIOERR_INVALID_PARAMETER );
  277.    }
  278.  
  279.  
  280.  
  281.  
  282. /*****************************************************************************/
  283. /*                                                                           */
  284. /* SUBROUTINE NAME: SampleCodecEntry                                         */
  285. /*     This routine is where all messages to the codec come in.              */
  286. /*     This is the routine name that goes into the MMPMMMIO.INI file,        */
  287. /*     specified in the install scrupt.                                      */
  288. /*                                                                           */
  289. /*****************************************************************************/
  290.  
  291. LONG APIENTRY SampleCodecEntry ( PULONG pulInstNumber, LONG lMMIOmessage,
  292.                                  LONG lParam1, LONG lParam2 )
  293.    {
  294.    /* Switch to the appropriate routine based on the message.                */
  295.    switch ( lMMIOmessage )
  296.       {
  297.       case MMIOM_CODEC_OPEN:
  298.  
  299.          /* During an open call, pulInstNumber is the address of where       */
  300.          /* to put the instance number.  This location must contain          */
  301.          /* a zero or the call should fail.                                  */
  302.          return ( OpenCodecInstance ( pulInstNumber, (PCODECOPEN)lParam1 ) );
  303.  
  304.       case MMIOM_CODEC_CLOSE:
  305.  
  306.          /* During a close call, pulInstNumber is the address of the         */
  307.          /* instance number to close.                                        */
  308.          return ( CloseCodecInstance ( pulInstNumber ) );
  309.  
  310.       case MMIOM_CODEC_COMPRESS:
  311.  
  312.          /* During a decompress call, pulInstNumber is actually the instance */
  313.          /* number and NOT a pointer.  Do the appropriate cast here.         */
  314.          return ( CompressBuffer ( pulInstNumber, (PMMCOMPRESS)lParam1 ) );
  315.  
  316.       case MMIOM_CODEC_DECOMPRESS:
  317.  
  318.          /* During a decompress call, pulInstNumber is actually the instance */
  319.          /* number and NOT a pointer.  Do the appropriate cast here.         */
  320.          return ( DecompressBuffer ( pulInstNumber, (PMMDECOMPRESS)lParam1 ) );
  321.  
  322.       case MMIOM_CODEC_QUERYNAMELENGTH:
  323.  
  324.          /* Put codec name length here, plus 1 for the terminating char.     */
  325.          /* Example: "Sample Codec" is 6+1+5+1= 13;                          */
  326.          *(PULONG)lParam1= 13L;
  327.          return ( MMIO_SUCCESS );
  328.  
  329.       case MMIOM_CODEC_QUERYNAME:
  330.  
  331.          /* Use standard string function "strcpy" to copy over codec name.   */
  332.          strcpy ( (PSZ)lParam1, (PSZ)"Sample Codec" );
  333.  
  334.          /* Put codec name length here, plus 1 for the terminating chars.    */
  335.          /* Example: "Sample Codec" is 6+1+5+1= 13;                          */
  336.          *(PULONG)lParam2= 13L;
  337.          return ( MMIO_SUCCESS );
  338.  
  339.       /* The rest of the messages are unsupported.                           */
  340.       default:
  341.          return ( MMIOERR_UNSUPPORTED_MESSAGE );
  342.       }
  343.    }
  344.  
  345.  
  346.  
  347.  
  348. /*****************************************************************************/
  349. /*                                                                           */
  350. /* This is called by the system when the .DLL is being accessed by a new     */
  351. /* process for the first and last time.  Here is where we create a semaphore */
  352. /* to protect instances and processes from each other.                       */
  353. /*                                                                           */
  354. /*****************************************************************************/
  355.  
  356. ULONG _CRT_init ( VOID );
  357.  
  358. ULONG _DLL_InitTerm ( ULONG hmod, ULONG fTerm )
  359.    {
  360.    /* Check if we are initializing or terminating.                           */
  361.    if ( fTerm )
  362.       /* We are terminating.                                                 */
  363.       {
  364.       ulInitCount--;
  365.       if ( !ulInitCount )
  366.          DosCloseMutexSem ( hmtxInstanceArray );
  367.       return ( TRUE );
  368.       }
  369.    else
  370.       {
  371.       /* We are initializing.  Call to init the "C" run-time library,        */
  372.       /* and create a mutex semaphore for accessing the global data.         */
  373.       ulInitCount++;
  374.       if ( !(_CRT_init()) )
  375.          if ( !DosCreateMutexSem ( NULL, &hmtxInstanceArray,
  376.                                              DC_SEM_SHARED, FALSE ) )
  377.             return ( TRUE );
  378.       }
  379.  
  380.    /* The initialization or termination has failed for some reason.          */
  381.    return ( FALSE );
  382.    }
  383.