/****************************************************************************/
/*                                                                          */
/* SAMPLUTG.C: Sample Codec Color Lookup table/converter generation.        */
/*                                                                          */
/* Copyright (c) IBM Corporation 1991,1992,1993        All Rights Reserved  */
/*                                                                          */
/****************************************************************************/

/* OS/2 and Multimedia Includes */
#define INCL_WIN
#define INCL_GPI
#define INCL_DOSSEMAPHORES
#define INCL_DOSEXCEPTIONS
#define INCL_DOSERRORS
#define INCL_DOSPROCESS
#define INCL_OS2MM
#define INCL_MMIO_CODEC
#include <os2.h>
#include <stdio.h>
#include <string.h>
#include <os2me.h>
#include <video.h>
#include "svsh.h"
#include "hhpheap.h"
#include "codecsrv.h"
#include "samplutg.h"


/* This is an external declaration to the color conversion table that we    */
/* statically defined in the SAMPGDAT.C global process data section.        */
extern aColorConv[512];



/****************************************************************************/
/*                                                                          */
/* SUBROUTINE NAME: Make16bitTable                                          */
/*     This procedure will make the lookup table convert from an 8-bit      */
/*     luminance value to a 16 bit RGB565 value.  Since RGB565 is a         */
/*     direct color mode, this will be called once during initialization    */
/*     and not again (unlike the 8-bit palette scenerio).                   */
/*                                                                          */
/****************************************************************************/

VOID Make16bitTable ( VOID )
   {
   ULONG ulLum;
   PUSHORT pusTable= (PUSHORT)aColorConv;

   for ( ulLum=0; ulLum<256; ulLum++ )
      *pusTable++= ((ulLum>>3)<<11) + ((ulLum>>2)<<5) + (ulLum>>3);

   return;
   }




/****************************************************************************/
/*                                                                          */
/* SUBROUTINE NAME: MakeNbitTable                                           */
/*     This procedure will make the lookup table convert from an 8-bit      */
/*     luminance value to an 8-bit palette entry.  Note that this procedure */
/*     will be called once at open time and every time the physical         */
/*     palette changes *even during the playback of a move*.  Since this    */
/*     example is rather slow, there will be a significant (undesired)      */
/*     delay.  One suggestion is to use lookup tables to assist in the      */
/*     conversion, the other is to use 32-bit assembly as much as possible. */
/*                                                                          */
/****************************************************************************/

VOID MakeNbitTable ( PULONG pulThePal, ULONG ulNumEntries )
   {
   ULONG ulPal;
   LONG  lLum;
   PBYTE pbTable= (PBYTE)aColorConv, tpbPal;
   LONG  lLowestError, lError, lY, lU, lV;
   BYTE  bBestEntry;

   /* Find the best entry for each of the 256 possible luminances.          */
   for ( lLum=0; lLum<256; lLum++ )
      {
      /* Initilaize the best found entry to one over the maximum error      */
      /* insuring that we find a better match.                              */
      lLowestError= 1537L;

      /* Search through the entire palette looking for the best match.      */
      tpbPal= (PBYTE)pulThePal;
      for ( ulPal=0; ulPal<ulNumEntries; ulPal++ )
         {
         /* Convert to YUV24 without using floating point arithmetic.       */
         lY= ( (LONG)*tpbPal     *  117 +                 /* Blue Content.  */
               (LONG)*(tpbPal+1) *  601 +                 /* Green Content. */
               (LONG)*(tpbPal+2) *  306 ) >> 10;          /* Red Content.   */
         lU= ( (LONG)*tpbPal     *  512 +                 /* Blue Content.  */
               (LONG)*(tpbPal+1) * -339 +                 /* Green Content. */
               (LONG)*(tpbPal+2) * -173 ) >> 10;          /* Red Content.   */
         lV= ( (LONG)*tpbPal     *  -83 +                 /* Blue Content.  */
               (LONG)*(tpbPal+1) * -428 +                 /* Green Content. */
               (LONG)*(tpbPal+2) *  512 ) >> 10;          /* Red Content.   */

         /* Find the error that would be generated if we used this color    */
         /* for the luminance in question, with a weighting towards the lum.*/
         lError= ( ( lLum >= lY ? lLum - lY : lY - lLum ) << 2 ) +
                 (lU >= 0 ? lU : -lU)  +  (lV >= 0 ? lV : - lV);

         /* Is this the least error to date (true 1st time through)?        */
         if ( lError < lLowestError )
            {
            lLowestError= lError;
            bBestEntry= (BYTE)ulPal;
            }

         /* Increment the palette pointer past this RGB2 entry.             */
         tpbPal+= 4;
         }

      /* Save the best entry in the table.                                  */
      *pbTable++= bBestEntry;
      }

   return;
   }




/****************************************************************************/
/*                                                                          */
/* SUBROUTINE NAME: PaletteHandler                                          */
/*     This procedure will take the palette change notification calls and   */
/*     route them to the appropriate lut generation routine.                */
/*                                                                          */
/****************************************************************************/

ULONG PaletteHandler ( PGENPAL pgenpalPhysical )
   {
   /* Based on number of destination colors, figure out how to make lut.    */
   switch ( pgenpalPhysical->ulNumColors )
      {
      case 16:
         if ( pgenpalPhysical->prgb2Entries )
            {
            MakeNbitTable ( (PULONG)pgenpalPhysical->prgb2Entries, 16L );
            return MMIO_SUCCESS;
            }
         else
            return MMIOERR_INVALID_PARAMETER;

      case 256:
         if ( pgenpalPhysical->prgb2Entries )
            {
            MakeNbitTable ( (PULONG)pgenpalPhysical->prgb2Entries, 256L );
            return MMIO_SUCCESS;
            }
         else
            return MMIOERR_INVALID_PARAMETER;

      case 65536:
         Make16bitTable ();
         return MMIO_SUCCESS;

      default:
         return MMIOERR_INVALID_BUFFER_LENGTH;
      }

   /* We don't make it here, but it'll keep the compiler warnings down.     */
   return MMIO_SUCCESS;
   }
