/*===========================================================================

FILE: OEMCamera.c

SERVICES: ICamera interface implementation

DESCRIPTION
   This file implements BREW ICamera. ICamera controls the device camera
   and allows recording of snapshot or movie.

PUBLIC CLASSES:  Not Applicable

INITIALIZATION AND SEQUENCING REQUIREMENTS:  Not Applicable

        Copyright © 1999-2002 QUALCOMM Incorporated.
               All Rights Reserved.
            QUALCOMM Proprietary/GTDR
===========================================================================*/
/*===========================================================================

                     INCLUDE FILES FOR MODULE

===========================================================================*/
#include "OEMFeatures.h"

#if defined(FEATURE_BREW_CAMERA)

#include "OEMCameraDMSS.h"
#include "OEMCriticalSection.h"
#include "OEMFS.h"
#include "AEE_OEMFile.h"
#include "AEEMediaFormats.h"
#include "AEEPosDet.h"
#include "AEEBridle.h"
#include "AEEStdLib.h"

/*===========================================================================

                      MACRO DEFINITIONS

===========================================================================*/
#define OEMCamera_ISREADY(pme)        ((pme)->m_nMode == CAM_MODE_READY)
#define OEMCamera_ISPREVIEW(pme)      ((pme)->m_nMode == CAM_MODE_PREVIEW)
#define OEMCamera_ISSNAPSHOT(pme)     ((pme)->m_nMode == CAM_MODE_SNAPSHOT)
#define OEMCamera_ISMOVIE(pme)        ((pme)->m_nMode == CAM_MODE_MOVIE)
#define OEMCamera_STATECHANGING(pme)  ((pme)->m_bStateChanging)
#define OEMCamera_ISPAUSED(pme)       ((pme)->m_bPaused)

#define OEMCamera_CAMERAREADY(pme)    (OEMCamera_ISREADY(pme) && !OEMCamera_STATECHANGING(pme))
#define OEMCamera_STARTOK(pme)        OEMCamera_CAMERAREADY(pme)
#define OEMCamera_STOPOK(pme)         (!OEMCamera_ISREADY(pme))

#define OEMCamera_ISMOVINGMODE(pme)   (OEMCamera_ISPREVIEW(pme) || OEMCamera_ISMOVIE(pme))
#define OEMCamera_PAUSEOK(pme)        (OEMCamera_ISMOVINGMODE(pme) && !OEMCamera_ISPAUSED(pme) && !OEMCamera_STATECHANGING(pme))
#define OEMCamera_RESUMEOK(pme)       (OEMCamera_ISMOVINGMODE(pme) && OEMCamera_ISPAUSED(pme) && !OEMCamera_STATECHANGING(pme))
#define OEMCamera_ENCODESNAPSHOTOK(pme) (1)

#define OEMCAMERA_ENTER_CRITICAL_SECTION()          OEMCriticalSection_Enter(&gOEMCameraCriticalSection); {
#define OEMCAMERA_LEAVE_CRITICAL_SECTION()        ;} OEMCriticalSection_Leave(&gOEMCameraCriticalSection);

/*===========================================================================

                      CameraDevice DECLARATIONS

===========================================================================*/
typedef struct CameraDevice   CameraDevice;
struct CameraDevice
{
   int   nRefs;
};

static int  CameraDevice_Open(void);
static int  CameraDevice_Close(void);

static CameraDevice     gCameraDevice = { 0 };
static camera_info_type gCameraInfo;

/*===========================================================================

                      ICamera DECLARATIONS

===========================================================================*/
static boolean       OEMCamera_FilePath(OEMCamera * pme, void * pData);
static void          OEMCamera_InitCameraRsp(OEMCamera * pme, int16 nCmd);
static CameraRsp *   OEMCamera_AllocStartCameraRsp(OEMCamera * pme, int16 nSubCmd);
static void          OEMCamera_FreeStartCameraRsp(OEMCamera * pme);
static CameraRsp *   OEMCamera_GetStartCameraRsp(OEMCamera * pme);
static void          OEMCamera_FreeCameraRsp(CameraRsp * pRsp);
static int           OEMCamera_Preview(OEMCamera * pme, CameraRsp * pRsp);
static int           OEMCamera_RecordMovie(OEMCamera * pme, CameraRsp * pRsp);
static int           OEMCamera_RecordSnapshot(OEMCamera * pme, CameraRsp * pRsp);
static boolean       OEMCamera_SaveFrameInfo(OEMCamera * pme, camera_frame_type * pf);
static int           OEMCamera_AddOverlay(OEMCamera * pme, IDIB * pb);
static void          OEMCamera_SetReadyMode(OEMCamera * pme);
static int16         OEMCamera_AudioStreamType(uint32 clsAudio, uint32 dwSubAudio);

#define OEMCamera_FreeCmdCameraRsp             OEMCamera_FreeCameraRsp
#define OEMCamera_UngetCameraRsp(pRsp)    {(pRsp)->bInUse = FALSE;}

// CameraLayer related...

#if defined(FEATURE_VIDEO_ENCODE)
static int  OEMCamera_SetMovieDestination(OEMCamera * pme, video_handle_type * ph);
#endif // defined(FEATURE_VIDEO_ENCODE)

static void OEMCamera_CallbackNotify(CameraRsp * pRsp);

//
// BRIDLE specific...
//
#if __ARMCC_VERSION >= 120000 // ADS 1.2
#pragma arm section zidata = "bridle_critical_section_zi"
#endif // __ARMCC_VERSION >= 120000 // ADS 1.2
static OEMCriticalSection gOEMCameraCriticalSection;
#if __ARMCC_VERSION >= 120000 // ADS 1.2
#pragma arm section zidata
#endif // __ARMCC_VERSION >= 120000 // ADS 1.2

/*===============================================================================

                     CameraDevice Function Definitions

===============================================================================*/
static int CameraDevice_Open(void)
{
   if (gCameraDevice.nRefs > 0)
   {
      ++gCameraDevice.nRefs;
   }
   else
   {
      // Initialize the phrase device
      if (camera_start(NULL, NULL))
         return EFAILED;

      gCameraDevice.nRefs = 1;
      camera_get_info(&gCameraInfo);
   }

   return SUCCESS;
}

static int CameraDevice_Close(void)
{
   if (gCameraDevice.nRefs <= 0)
      return EFAILED;

   if (--gCameraDevice.nRefs == 0)
   {
      camera_stop(NULL, NULL);
   }

   return SUCCESS;
}

/*===============================================================================

                     ICamera Function Definitions

===============================================================================*/
/*==================================================================

==================================================================*/
void OEMCamera_Init(void)
{
   // Empty
}

/*==================================================================

==================================================================*/
int OEMCamera_New(AEECLSID cls, IBitmap * pFrame, uint16 wSize, OEMINSTANCE * ph)
{
   OEMCamera *   pme;
   int         nRet = SUCCESS;

   if (!ph)
      return EBADPARM;

   // Alloc memory for the object
   pme = (OEMCamera *)MALLOC(sizeof(OEMCamera));
   if (!pme)
   {
      nRet = ENOMEMORY;
   }
   else
   {
      // Open the camera device, if necessary
      if (CameraDevice_Open())
      {
         nRet = EFAILED;
         goto Done;
      }

      pme->m_nMode = CAM_MODE_READY;
      pme->m_clsVideo = AEECLSID_JPEG;

      pme->m_pFrame = (FrameBitmap *)pFrame;
      
      pme->m_sizeFrame.cx = 176;
      pme->m_sizeFrame.cy = 144;
      // By default, file size is disabled by setting param to zero
      pme->m_nFileSize = OEMCAMERA_FILE_SIZE_DISABLED;
      pme->m_nFPS = (byte)gCameraInfo.fps;
      // Assume we will be using Snapshot mode
      pme->m_nQuality = OEMCAMERA_QUALITY_HIGH;
      pme->m_nPreviewType = CAM_PREVIEW_SNAPSHOT;

      OEMCamera_InitCameraRsp(pme, CAM_CMD_START);
      OEMCamera_InitCameraRsp(pme, CAM_CMD_SETPARM);
      OEMCamera_InitCameraRsp(pme, CAM_CMD_ENCODESNAPSHOT);

#if defined(FEATURE_BREWAPI_SPECIFIC)
      // PNG
      OEMCamera_InitCameraRsp(pme, CAM_CMD_OVERLAY_IMAGE);
#endif //defined(FEATURE_BREWAPI_SPECIFIC)
   }

   *ph = (OEMINSTANCE)pme;
   return nRet;
   
Done:
   if (ph)
      *ph = NULL;
   FREE(pme);
   return nRet;
}

/*==================================================================

==================================================================*/
void OEMCamera_Delete(OEMINSTANCE h)
{
   int         i;
   OEMCamera * pme = (OEMCamera *)h;

   // Delete all the Rsps...
   OEMCamera_FreeStartCameraRsp(pme);
   for (i = 0; i < OEMCAMERA_RSP_COMMAND_MAX; i++)
      OEMCamera_FreeCameraRsp(&pme->m_rspCommand[i]);

   for (i = 0; i < OEMCAMERA_RSP_ENCODESNAPSHOT_MAX; i++)
      OEMCamera_FreeCameraRsp(&pme->m_rspEncodeSnapshot[i]);

#if defined(FEATURE_BREWAPI_SPECIFIC)
   for (i = 0; i < OEMCAMERA_RSP_COMMAND_MAX; i++)
      OEMCamera_FreeCameraRsp(&pme->m_pngCommand[i]);
#endif // defined(FEATURE_BREWAPI_SPECIFIC)
   
   CameraDevice_Close();

   FREEIF(pme->m_pszMIME);
   FREEIF(pme->m_pszFile);

   FREE(pme);
}

/*==================================================================

==================================================================*/
int OEMCamera_RegisterNotify(OEMINSTANCE h, PFNCAMERANOTIFY pfnNotify, void * pUser)
{
   OEMCamera * pme = (OEMCamera *)h;

   pme->m_pfnNotify = pfnNotify;
   pme->m_pUser = pUser;

   return SUCCESS;
}

/*==================================================================

==================================================================*/
int OEMCamera_SetParm(OEMINSTANCE h, int16 nParmID, int32 p1, int32 p2)
{
   int               nRet = SUCCESS;
   camera_parm_type  eParm = CAMERA_PARM_MAX;
   CameraData        *pCData = NULL;
   OEMCamera *       pme = (OEMCamera *)h;

   switch (nParmID)
   {
      case CAM_PARM_MEDIA_DATA:
         if (p1)
         {
            MEMCPY(&pme->m_md, (void *)p1, sizeof(AEEMediaData));
            if (pme->m_md.clsData == MMD_FILE_NAME)
            { 
               if (!OEMCamera_FilePath(pme, pme->m_md.pData))
                  return EBADPARM;
            }
            else if (pme->m_md.clsData == MMD_BUFFER)
            {
               if (!pme->m_md.pData || !pme->m_md.dwSize)
                  return EBADPARM;
            }
            else
               return EUNSUPPORTED;

         }
         if (p2)
         {
            char *   psz = (char *)p2;

            FREEIF(pme->m_pszMIME);
            pme->m_pszMIME = STRDUP(psz);
         }
         break;

      case CAM_PARM_VIDEO_ENCODE:
		 switch(p1)
		 {case CAM_ENCODE_SHORT_HEADER:
		  if(p2){ 
		  pCData = (CameraData *) p2;
		  MEMCPY(&(pme->m_wShortHeader), pCData->pData, pCData->dwBytes);
		  }
         break;
         case CAM_ENCODE_UUID:
         if(p2){
		   pCData = (CameraData *) p2;
		   pme->m_pUuid_cpgd = MALLOC(pCData->dwBytes);
		   MEMCPY(pme->m_pUuid_cpgd, pCData->pData, pCData->dwBytes);
		  }
		  else{
			  pme->m_pUuid_cpgd = NULL;
		  }
         break;
		 case CAM_ENCODE_UUID_DATA:
		  if(p2){
		   pCData = (CameraData *) p2;
		   pme->m_pCpgd = MALLOC(pCData->dwBytes);
		   MEMCPY(pme->m_pCpgd, pCData->pData, pCData->dwBytes);
  	       pme->m_nszpCpgd = (uint32)  pCData->dwBytes;
		  }
		  else
		  {pme->m_pCpgd = NULL;
		  pme->m_nszpCpgd =0;
		  }		
         break;
		 default:
		  pme->m_clsVideo = (AEECLSID)p1;
           pme->m_dwSubVideo = (uint32)p2;
         break;
		 }
		 break;

      case CAM_PARM_AUDIO_ENCODE:
         pme->m_clsAudio = (AEECLSID)p1;
         pme->m_dwSubAudio = (uint32)p2;
         eParm = CAMERA_PARM_AUDIO_FMT;
         p1 = (int32)OEMCamera_AudioStreamType(pme->m_clsAudio, pme->m_dwSubAudio);
         if (-1 != p1)
            eParm = CAMERA_PARM_AUDIO_FMT;
         break;
	  case CAM_PARM_REFLECT:
	    eParm = CAMERA_PARM_REFLECT;
          break;
	  case CAM_PARM_PREVIEW_TYPE:
	    eParm = CAMERA_PARM_PREVIEW_MODE;
         if ((p1 == CAM_PREVIEW_SNAPSHOT) || 
             (p1 == CAM_PREVIEW_MOVIE))
            pme->m_nPreviewType = (int16)p1;
         else
            nRet = EBADPARM;
	    break;

      case CAM_PARM_SIZE:
         if (p1)
         {
            MEMCPY(&pme->m_sizeFrame, (AEESize *)p1, sizeof(AEESize));
            nRet = (int)camera_set_dimensions((uint16)pme->m_sizeFrame.cx, (uint16)pme->m_sizeFrame.cy, (uint16)pme->m_sizeDisplay.cx, NULL, NULL);
            nRet = OEMCamera_AEEError(nRet);
         }
         break;

      case CAM_PARM_QUALITY:
         // File size will take precedence over Quality if it is non zero
         // so clear file size here.
         pme->m_nFileSize = OEMCAMERA_FILE_SIZE_DISABLED;
         // Quality is treated differenty for snapshot VS movie modes
         if (pme->m_nPreviewType == CAM_PREVIEW_SNAPSHOT) 
         {
            // Valid range for snapshot quality param is 1 to 100
            // equal the quality percent (for snapshot camera only).
            if ((p1 >= OEMCAMERA_QUALITY_MIN_VALUE) && 
                (p1 <= OEMCAMERA_QUALITY_MAX_VALUE))
               pme->m_nQuality = (int16)p1;
            else
               nRet = EBADPARM;
         }
         else if (pme->m_nPreviewType == CAM_PREVIEW_MOVIE) 
         {

            if ((p1 >= OEMCAMCORDER_QUALITY_MIN_VALUE) && 
                (p1 <= OEMCAMCORDER_QUALITY_MAX_VALUE))
               pme->m_nQuality = (int16)p1;
            else
               nRet = EBADPARM;
         }
         break;


      case CAM_PARM_FPS:
//         if (gCameraInfo.fps != (uint16)pme->m_nFPS)
//            nRet = EBADPARM;
         if (p1)
         {
            pme->m_nFPS = (byte)p1;
            eParm = CAMERA_PARM_FPS;
         }
         else
            nRet = EBADPARM;
         break;

      case CAM_PARM_CONTRAST:
         eParm = CAMERA_PARM_CONTRAST;
         break;

      case CAM_PARM_BRIGHTNESS:
         eParm = CAMERA_PARM_BRIGHTNESS;
         break;

      case CAM_PARM_SHARPNESS:
         eParm = CAMERA_PARM_SHARPNESS;
         break;

      case CAM_PARM_ZOOM:
         eParm = CAMERA_PARM_ZOOM;
         break;

      case CAM_PARM_NIGHTSHOT_MODE:
         eParm = CAMERA_PARM_NIGHTSHOT_MODE;
         break;

      case CAM_PARM_ANTIBANDING:
         eParm = CAMERA_PARM_ANTIBANDING;
         break;

      case CAM_PARM_ROTATE_PREVIEW:
         eParm = CAMERA_PARM_SENSOR_POSITION;
         if (p1 == 0)
            p1 = CAMERA_SP_NORMAL;
         else if (p1 == 180)
            p1 = CAMERA_SP_REVERSE;
         else
            nRet = EBADPARM;
         break;

      case CAM_PARM_ROTATE_ENCODE:
         eParm = CAMERA_PARM_ENCODE_ROTATION;
         break;

      case CAM_PARM_OVERLAY:
         nRet = OEMCamera_AddOverlay(pme, (IDIB *)p1);
         break;

      case CAM_PARM_DISPLAY_SIZE:
         if (p1)
         {
            MEMCPY(&pme->m_sizeDisplay, (void *)p1, sizeof(AEESize));
            nRet = (int)camera_set_dimensions((uint16)pme->m_sizeFrame.cx, (uint16)pme->m_sizeFrame.cy, (uint16)pme->m_sizeDisplay.cx, NULL, NULL);
            nRet = OEMCamera_AEEError(nRet);
         }
         break;

      case CAM_PARM_DEFER_ENCODE:
         if (OEMCamera_CAMERAREADY(pme))
            pme->m_bDeferEncode = (boolean)p1;
         else
            nRet = EBADSTATE;
         break;

      case CAM_PARM_THUMBNAIL_INFO:
         if(p1)
         {
            CameraThumbnailInfo *         cti = (CameraThumbnailInfo*)p1;
            AEESize   tsize = {0};
            uint32    quality = 0;
  
            if(cti)
            {
              tsize = cti->size;
              quality = cti->nQuality;
            }
            else
              nRet = EBADPARM;

            if((tsize.cx > 0)  || (tsize.cy > 0) || (quality > 0))
            {
              nRet = camera_set_thumbnail_properties(tsize.cx,tsize.cy,quality);
              nRet = OEMCamera_AEEError(nRet);
            }
            else
              nRet = EBADPARM;
         }
         break;

      case CAM_PARM_GPSINFO:
         if (p1)
         {
            AEEGPSInfo *         pgi = (AEEGPSInfo *)p1;
            camera_position_type pt;

            pt.timestamp = pgi->dwTimeStamp;
            pt.altitude = pgi->wAltitude;
            pt.latitude = pgi->dwLat;
            pt.longitude = pgi->dwLon;

            nRet = camera_set_position(&pt, NULL, NULL);
            nRet = OEMCamera_AEEError(nRet);
         }
         break;

      case CAM_PARM_EXIF_IFDTAG:
         if (p1)
         {
            CameraExifTagInfo *     pti = (CameraExifTagInfo *)p1;
            camera_exif_tag_type    tt;

            tt.tag_id = pti->wTagID;
            tt.type = (tiff_data_type)pti->wTagType;
            tt.value = pti->pTagData;
            tt.count = (uint16)pti->dwBytes;
            tt.ifd = (camera_ifd_type)(pti->wIFDID == CAM_EXIF_IFD_DEFAULT ? DEFAULT_IFD : pti->wIFDID);
            nRet = camera_set_exif_tag(&tt, NULL, NULL);
            nRet = OEMCamera_AEEError(nRet);
         }
         break;

      case CAM_PARM_EXPOSURE:
         if (p1)
            eParm = CAMERA_PARM_EXPOSURE;
         else
            nRet = EBADPARM;
         break;

      case CAM_PARM_WHITE_BALANCE:
         if (p1)
            eParm = CAMERA_PARM_WB;
         else
            nRet = EBADPARM;
         break;

      case CAM_PARM_EFFECT:
         if (p1)
            eParm = CAMERA_PARM_EFFECT;
         else
            nRet = EBADPARM;
         break;

      case CAM_PARM_FLASH:
         eParm = CAMERA_PARM_FLASH;
         break;

      case CAM_PARM_RED_EYE_REDUCTION:
         eParm = CAMERA_PARM_RED_EYE_REDUCTION;
         break;
      
      case CAM_PARM_FILE_SIZE:
         // File size will take precidence over Quality if it is non zero
         // Units are Kilobytes for this param
         if ((p1 >= OEMCAMERA_FILE_SIZE_MIN_VALUE) &&
             (p1 <= OEMCAMERA_FILE_SIZE_MAX_VALUE))
          pme->m_nFileSize = (int32)p1;
         else
            nRet = EBADPARM;
         break;


      case CAM_PARM_IS_SUPPORT:  // Fall through...
      case CAM_PARM_IS_MOVIE:
      case CAM_PARM_PIXEL_COUNT:
      case CAM_PARM_VIDEO_ENCODE_LIST:
      case CAM_PARM_AUDIO_ENCODE_LIST:
      case CAM_PARM_SIZE_LIST:
      case CAM_PARM_FPS_LIST:
      default:
         nRet = EUNSUPPORTED;
         break;
   }

   if (SUCCESS == nRet && eParm != CAMERA_PARM_MAX)
   {
      int         nCamRet;
      CameraRsp * pRsp;

      pRsp = OEMCamera_AllocCmdCameraRsp(pme, CAM_CMD_SETPARM, nParmID);
      if (!pRsp)
         nRet = EITEMBUSY;
      else
      {
         nCamRet = (int)camera_set_parm(eParm, p1, OEMCamera_CameraLayerCB, (void *)pRsp->hObject);
         if (!nCamRet)
            nRet = CAM_PENDING;
         else
         {
            OEMCamera_FreeCameraRsp(pRsp);
            nRet = OEMCamera_AEEError(nCamRet);
         }
      }
   }

   return nRet;
}

/*==================================================================

==================================================================*/
int OEMCamera_GetParm(OEMINSTANCE h, int16 nParmID, int32 * pP1, int32 * pP2)
{
   OEMCamera *       pme = (OEMCamera *)h;
   int               nRet = SUCCESS;
   camera_parm_type  eParm = CAMERA_PARM_MAX;

   switch (nParmID)
   {
      case CAM_PARM_MEDIA_DATA:
         if (pP1)
            MEMCPY(pP1, &pme->m_md, sizeof(AEEMediaData));
         if (pP2)
            *pP2 = (int32)&pme->m_pszMIME;
         break;

      case CAM_PARM_VIDEO_ENCODE:
         if (pP1)
            *pP1 = (int32)pme->m_clsVideo;
         if (pP2)
            *pP2 = (int32)pme->m_dwSubVideo;
         break;

      case CAM_PARM_AUDIO_ENCODE:
         if (pP1)
            *pP1 = (int32)pme->m_clsAudio;
         if (pP2)
            *pP2 = (int32)pme->m_dwSubAudio;
         break;

      case CAM_PARM_SIZE:
         if (pP1)
            MEMCPY(pP1, &pme->m_sizeFrame, sizeof(AEESize));
         break;

      case CAM_PARM_QUALITY:
         if (pP1)
            *pP1 = (int32)pme->m_nQuality;
         if (pP2)
         {
            AEEParmInfo pi;

            pi.nCurrent = pme->m_nQuality;
            

            if (pme->m_nPreviewType == CAM_PREVIEW_SNAPSHOT) 
            {
               pi.nDefault = OEMCAMERA_QUALITY_HIGH;
               pi.nMin = OEMCAMERA_QUALITY_MIN_VALUE;
               pi.nMax = OEMCAMERA_QUALITY_MAX_VALUE;
               pi.nStep = (int32)1;
            }
            else if (pme->m_nPreviewType == CAM_PREVIEW_SNAPSHOT) 
            {
               pi.nDefault = OEMCAMCORDER_QUALITY_HIGH;
               pi.nMin = OEMCAMCORDER_QUALITY_MIN_VALUE;
               pi.nMax = OEMCAMCORDER_QUALITY_MAX_VALUE;
               pi.nStep = (int32)1;
            }


            MEMCPY(pP2, &pi, sizeof(AEEParmInfo));
         }
         break;

      case CAM_PARM_FPS:
         eParm = CAMERA_PARM_FPS;
         break;


      case CAM_PARM_CONTRAST:
         eParm = CAMERA_PARM_CONTRAST;
         break;

      case CAM_PARM_BRIGHTNESS:
         eParm = CAMERA_PARM_BRIGHTNESS;
         break;

      case CAM_PARM_SHARPNESS:
         eParm = CAMERA_PARM_SHARPNESS;
         break;

      case CAM_PARM_ZOOM:
         eParm = CAMERA_PARM_ZOOM;
         break;

      case CAM_PARM_NIGHTSHOT_MODE:
         eParm = CAMERA_PARM_NIGHTSHOT_MODE;
         break;

      case CAM_PARM_ANTIBANDING:
         eParm = CAMERA_PARM_ANTIBANDING;
         break;

      case CAM_PARM_ROTATE_PREVIEW:
         eParm = CAMERA_PARM_SENSOR_POSITION;
         break;

      case CAM_PARM_ROTATE_ENCODE:
         eParm = CAMERA_PARM_ENCODE_ROTATION;
         break;

      case CAM_PARM_OVERLAY:
         nRet = EUNSUPPORTED;
         break;

      case CAM_PARM_DISPLAY_SIZE:
         if (pP1)
            MEMCPY((void *)pP1, &pme->m_sizeDisplay, sizeof(AEESize));
         break;

      case CAM_PARM_DEFER_ENCODE:
         if (pP1)
            *pP1 = (int32)pme->m_bDeferEncode;
         break;

      case CAM_PARM_MODE:
         if (pP1)
            *(int16 *)pP1 = pme->m_nMode;
         if (pP2)
            *(boolean *)pP2 = pme->m_bPaused;
         break;

      case CAM_PARM_EXPOSURE:
         eParm = CAMERA_PARM_EXPOSURE;
         break;

      case CAM_PARM_WHITE_BALANCE:
         eParm = CAMERA_PARM_WB;
         break;

      case CAM_PARM_EFFECT:
         eParm = CAMERA_PARM_EFFECT;
         break;

      case CAM_PARM_THUMBNAIL_INFO:
         if(pP1)
         {
            CameraThumbnailInfo cti={0};
            uint32 height;
            uint32 width;
            uint32 quality;

            nRet = camera_get_thumbnail_properties(&width, &height, &quality);
            nRet = OEMCamera_AEEError(nRet);
            
            if(nRet == SUCCESS)
            {
              cti.nStructSize = sizeof(CameraThumbnailInfo);
              cti.size.cx = width;
              cti.size.cy = height;
              cti.nQuality = (int16)quality;
              MEMCPY(pP1,&cti,sizeof(CameraThumbnailInfo));
            }
         }           

      case CAM_PARM_FILE_SIZE:
         // Units are Kilobytes for this param
         if (pP1)
            *pP1 = (int32)pme->m_nFileSize;
         if (pP2)
         {
            AEEParmInfo pi;

            pi.nCurrent = pme->m_nFileSize;
            pi.nDefault = OEMCAMERA_FILE_SIZE_MIN_VALUE;
            pi.nMin = OEMCAMERA_FILE_SIZE_MIN_VALUE;
            pi.nMax = OEMCAMERA_FILE_SIZE_MAX_VALUE;
            pi.nStep = (int32)1;

            MEMCPY(pP2, &pi, sizeof(AEEParmInfo));
         }
         break;

      case CAM_PARM_PREVIEW_TYPE:
         if (pP1)
            *pP1 = (int32)pme->m_nPreviewType;
         break;

      case CAM_PARM_IS_SUPPORT:  // Fall through...
      case CAM_PARM_IS_MOVIE:
      case CAM_PARM_PIXEL_COUNT:
      case CAM_PARM_VIDEO_ENCODE_LIST:
      case CAM_PARM_AUDIO_ENCODE_LIST:
      case CAM_PARM_SIZE_LIST:
      case CAM_PARM_FPS_LIST:
      default:
         nRet = EUNSUPPORTED;
         break;
   }

   if ((pP1 || pP2) && eParm != CAMERA_PARM_MAX && SUCCESS == nRet)
   {
      int         nCamRet;
      AEEParmInfo pi;

      MEMSET(&pi, (int)0, sizeof(AEEParmInfo));
      nCamRet = (int)camera_get_parm(eParm, (camera_parm_info_type *)&pi);
      if (!nCamRet)
      {
         // Handle some exceptions...this can be done in a function if the list gets big.
         // Convert sensor position to rotate-angle...
         if (nParmID == CAM_PARM_ROTATE_PREVIEW)
         {
            if (pP1)
               *pP1 = pi.nCurrent ? 180 : 0;
            if (pP2)
            {
               pi.nMin = 0;
               pi.nMax = 180;
               pi.nStep = 180;
               MEMCPY(pP2, &pi, sizeof(AEEParmInfo));
            }
         }
         else
         {
            if (pP1)
               *pP1 = pi.nCurrent;
            if (pP2)
               MEMCPY(pP2, &pi, sizeof(AEEParmInfo));
         }

      }
      else
         nRet = OEMCamera_AEEError(nCamRet);
   }

   return nRet;
}

/*==================================================================

==================================================================*/
int OEMCamera_Start(OEMINSTANCE h, int16 nMode, uint32 dwParam)
{
   OEMCamera * pme = (OEMCamera *)h;
   int         nRet = EFAILED;
   CameraRsp * pRsp;

   if (!OEMCamera_STARTOK(pme))
      return EBADSTATE;

   pRsp = OEMCamera_AllocStartCameraRsp(pme, nMode);
   if (!pRsp)
      return EITEMBUSY;

   if (nMode == CAM_MODE_PREVIEW)
      nRet = OEMCamera_Preview(pme, pRsp);
   else if (nMode == CAM_MODE_SNAPSHOT)
      nRet = OEMCamera_RecordSnapshot(pme, pRsp);
   else if (nMode == CAM_MODE_MOVIE)
      nRet = OEMCamera_RecordMovie(pme, pRsp);
   else
      nRet = EBADPARM;

   if (nRet)
      OEMCamera_FreeCameraRsp(pRsp);
   else
      pme->m_bStateChanging = TRUE;

   return nRet;
}

/*==================================================================

==================================================================*/
int OEMCamera_Stop(OEMINSTANCE h)
{
   OEMCamera * pme = (OEMCamera *)h;
   int         nCamRet = -1;

   if (!OEMCamera_STOPOK(pme))
      return EBADSTATE;

   if (OEMCamera_ISPREVIEW(pme))
      nCamRet = (int)camera_stop_preview();
   else if (OEMCamera_ISSNAPSHOT(pme))
   {
      nCamRet = camera_release_picture();
/*
      CameraRsp * pRsp = OEMCamera_GetStartCameraRsp(pme);
      if (!pRsp)
         pRsp = &pme->m_rspStart[0];
      pRsp->camNotify.nStatus = CAM_STATUS_DONE;
      OEMCamera_SetReadyMode(pme);
      OEMCamera_Resume(pme, pRsp);
      nCamRet = 0;
*/
   }
#if defined(FEATURE_VIDEO_ENCODE)
   else if (OEMCamera_ISMOVIE(pme))
      nCamRet = (int)camera_stop_record();
#endif // defined(FEATURE_VIDEO_ENCODE)
   
   return OEMCamera_AEEError(nCamRet);
}  

/*==================================================================

==================================================================*/
int OEMCamera_Pause(OEMINSTANCE h, boolean bPause)
{
   OEMCamera * pme = (OEMCamera *)h;
   int         nCamRet;

   if ( ( bPause && !OEMCamera_PAUSEOK(pme) ) || 
        (!bPause && !OEMCamera_RESUMEOK(pme)) )
      return EBADSTATE;

   pme->m_bPaused = bPause;

   if (bPause)
   {
      if (OEMCamera_ISPREVIEW(pme))
         nCamRet = camera_disable_frame_callback();
#if defined(FEATURE_VIDEO_ENCODE)
      else if (OEMCamera_ISMOVIE(pme))
         nCamRet = camera_pause_record();
#endif // defined(FEATURE_VIDEO_ENCODE)
      else
         nCamRet = CAMERA_RET_CODE_MAX;
   }
   else
   {
      if (OEMCamera_ISPREVIEW(pme))
         nCamRet = camera_enable_frame_callback();
#if defined(FEATURE_VIDEO_ENCODE)
      else if (OEMCamera_ISMOVIE(pme))
         nCamRet = camera_resume_record();
#endif // defined(FEATURE_VIDEO_ENCODE)
      else
         nCamRet = CAMERA_RET_CODE_MAX;
   }

   return OEMCamera_AEEError(nCamRet);
}

/*==================================================================

==================================================================*/
int OEMCamera_EncodeSnapshot(OEMINSTANCE hInstance)
{
   OEMCamera *          pme = (OEMCamera *)hInstance;
   int                  nRet;
   camera_handle_type   h;
   CameraRsp *          pRsp;

   if (!OEMCamera_ENCODESNAPSHOTOK(pme))
      return EBADSTATE;

   if (!pme->m_pFrame || !pme->m_pFrame->m_dib.pBmp)
      return EFAILED;

   pRsp = OEMCamera_AllocCmdCameraRsp(pme, CAM_CMD_ENCODESNAPSHOT, 0);
   if (!pRsp)
      nRet = EITEMBUSY;

   nRet = OEMCamera_SetSnapshotDestination(pme, &h);
   
   if (SUCCESS != nRet)
      return nRet;
   // If File Size Param was given a positive, non zero value,
   // then call API to encode (JPEG only) upto the specified
   // size which is in K bytes.
   // Only applicable to JPEG mode.
   if ((pme->m_nFileSize > 0) && ((pme->m_clsVideo) == AEECLSID_JPEG))
   {
     nRet = camera_encode_picture_size_limit(pme->m_nFileSize, &pme->m_rawFrame, &h, OEMCamera_CameraLayerCB, (void *)pRsp->hObject);
   }
   else
   {
     nRet = camera_encode_picture(&pme->m_rawFrame, &h, OEMCamera_CameraLayerCB, (void *)pRsp->hObject);
   }

   return OEMCamera_AEEError(nRet);
}

/*==================================================================

==================================================================*/
void OEMCamera_ReleaseFrame(OEMINSTANCE h)
{
   // Release the frame buffer after the frame is delivered to the user.
   camera_release_frame();
}

/*===============================================================================

                     LOCAL FUNCTIONS

===============================================================================*/
static boolean OEMCamera_FilePath(OEMCamera * pme, void * pData)
{
   const char *cpszFile = (const char *)pData;
   char *      pszFS = 0;
   int         nLen;
   int         bRet = FALSE;

   if (!cpszFile) 
      goto Done;

   FREEIF(pme->m_pszFile);

   // Get resolved fs:/ path length
   if (SUCCESS != AEE_ResolvePath(cpszFile, NULL, &nLen))
      goto Done;

   pszFS = MALLOC(nLen);
   if (!pszFS)
      goto Done;

   // Resolve path to fs:/
   if (SUCCESS != AEE_ResolvePath(cpszFile, pszFS, &nLen))
      goto Done;

   // Check for access
   if (SUCCESS != AEE_CheckPathAccess(pszFS, AEEFP_CREATE,0)) 
      goto Done;

   /* measure native path */
   if (SUCCESS != OEMFS_GetNativePath(pszFS,0, &nLen))
      goto Done;

   pme->m_pszFile = MALLOC(nLen);
   if (!pme->m_pszFile) 
      goto Done;

   /* get native path */   
   if (SUCCESS != OEMFS_GetNativePath(pszFS,pme->m_pszFile,&nLen))
      goto Done;

   bRet = TRUE;

Done:
   FREEIF(pszFS);
   return bRet;
}

/*==================================================================

==================================================================*/
static void OEMCamera_InitCameraRsp(OEMCamera * pme, int16 nCmd)
{
   CameraRsp * pList;
   int         nLen;
   int         i;

   switch (nCmd)
   {
      case CAM_CMD_START:
         pList = pme->m_rspStart;
         nLen = OEMCAMERA_RSP_START_MAX;
         break;

      case CAM_CMD_SETPARM:
         pList = pme->m_rspCommand;
         nLen = OEMCAMERA_RSP_COMMAND_MAX;
         break;

      case CAM_CMD_ENCODESNAPSHOT:
         pList = pme->m_rspEncodeSnapshot;
         nLen = OEMCAMERA_RSP_ENCODESNAPSHOT_MAX;
         break;

#if defined(FEATURE_BREWAPI_SPECIFIC)
      case CAM_CMD_OVERLAY_IMAGE:
         pList = pme->m_pngCommand;
         nLen = OEMCAMERA_RSP_COMMAND_MAX;
         break;
#endif // defined(FEATURE_BREWAPI_SPECIFIC)

      default:
         pList = NULL;
         nLen = 0;
   }

   for (i = 0; i < nLen; i++)
   {
      pList[i].camNotify.nCmd = nCmd;
      pList[i].camNotify.pCam = NULL;
      pList[i].bInUse = FALSE;
      pList[i].pOwner = pme;
   }
}

/*==================================================================
   For CAM_CMD_START, alloc all cbs
==================================================================*/
static CameraRsp * OEMCamera_AllocStartCameraRsp(OEMCamera * pme, int16 nSubCmd)
{
   CameraRsp * pcb = NULL;

   OEMCAMERA_ENTER_CRITICAL_SECTION()

   CameraRsp * pList = pme->m_rspStart;
   int         nLen = OEMCAMERA_RSP_START_MAX;
   int         i;

   if (!pList[0].hObject)
   {
      // Just register the first rsp and use it in all Start() related API...
      if (AEEObjectMgr_Register(&pList[0], &pList[0].hObject))
         goto Done;

      for (i = 0; i < nLen; i++)
      {
         pList[i].bInUse = FALSE;
         pList[i].camNotify.nSubCmd = nSubCmd;
      }
   }

   pcb = &pList[0];

Done:
   OEMCAMERA_LEAVE_CRITICAL_SECTION()

   return pcb;
}

/*==================================================================
   For CAM_CMD_START, free all cbs
==================================================================*/
static void OEMCamera_FreeStartCameraRsp(OEMCamera * pme)
{
   CameraRsp * pList = pme->m_rspStart;
   int         nLen = OEMCAMERA_RSP_START_MAX;
   int         i;

   for (i = 0; i < nLen; i++)
      OEMCamera_FreeCameraRsp(&pList[i]);
}

/*==================================================================
   
==================================================================*/
static CameraRsp * OEMCamera_GetStartCameraRsp(OEMCamera * pme)
{
   CameraRsp * pcb;

   OEMCAMERA_ENTER_CRITICAL_SECTION()

   CameraRsp * pList = pme->m_rspStart;
   int         nLen = OEMCAMERA_RSP_START_MAX;
   int         i;

   for (i = 0; i < nLen && pList[i].bInUse; i++)
      ;

   if (i < nLen)
   {
      pList[i].bInUse = TRUE;
      pcb = &pList[i];
   }
   else
      pcb = NULL;

   OEMCAMERA_LEAVE_CRITICAL_SECTION()

   return pcb;
}

/*==================================================================
   Alloc and Get
==================================================================*/
CameraRsp * OEMCamera_AllocCmdCameraRsp(OEMCamera * pme, int16 nCmd, int16 nSubCmd)
{
   CameraRsp * pcb = NULL;

   OEMCAMERA_ENTER_CRITICAL_SECTION()

   CameraRsp * pList = pme->m_rspCommand;
   int         nLen = OEMCAMERA_RSP_COMMAND_MAX;
   int         i;

   switch (nCmd)
   {
      case CAM_CMD_SETPARM:
         pList = pme->m_rspCommand;
         break;

      case CAM_CMD_ENCODESNAPSHOT:
         pList = pme->m_rspEncodeSnapshot;
         break;

#if defined(FEATURE_BREWAPI_SPECIFIC)
      case CAM_CMD_OVERLAY_IMAGE:
         pList = pme->m_pngCommand;
         break;
#endif // defined(FEATURE_BREWAPI_SPECIFIC)

      default:
         goto Done;
   }

   for (i = 0; i < nLen && pList[i].bInUse; i++)
      ;
   
   if (i < nLen)
   {
      if (AEEObjectMgr_Register(&pList[i], &pList[i].hObject))
         goto Done;

      pList[i].bInUse = TRUE;
      pList[i].camNotify.nSubCmd = nSubCmd;
      pcb = &pList[i];
   }

Done:
   OEMCAMERA_LEAVE_CRITICAL_SECTION()

   return pcb;
}

/*==================================================================

==================================================================*/
static void OEMCamera_FreeCameraRsp(CameraRsp * pRsp)
{
   OEMCAMERA_ENTER_CRITICAL_SECTION()
//   CALLBACK_Cancel((AEECallback *)pRsp);
   AEEObjectMgr_Unregister(pRsp->hObject);
   pRsp->hObject = 0;
   pRsp->bInUse = FALSE;
   OEMCAMERA_LEAVE_CRITICAL_SECTION()
}

/*==================================================================
   
==================================================================*/
static int OEMCamera_Preview(OEMCamera * pme, CameraRsp * pRsp)
{
   int      nRet;

   nRet = (int)camera_start_preview(OEMCamera_CameraLayerCB, (void *)pRsp->hObject);
   return OEMCamera_AEEError(nRet);
}

/*==================================================================
   
==================================================================*/
static int OEMCamera_RecordSnapshot(OEMCamera * pme, CameraRsp * pRsp)
{
   int                  nRet;

   nRet = (int)camera_take_picture(OEMCamera_CameraLayerCB, (void *)pRsp->hObject);
   return OEMCamera_AEEError(nRet);
}

/*==================================================================
   
==================================================================*/
static int OEMCamera_RecordMovie(OEMCamera * pme, CameraRsp * pRsp)
{
#if !defined(FEATURE_VIDEO_ENCODE)
   return EUNSUPPORTED;
#else
   int                           nRet;
   video_handle_type             h;
   video_fmt_stream_audio_type   eAudioType = VIDEO_FMT_STREAM_AUDIO_INVALID;
   int32 wFileFormat = CAM_FILE_BRAND_3G2;
   int nVideoFormat = VIDEO_FMT_STREAM_VIDEO_MPEG4;
   int nSh = FALSE; 
   nRet = OEMCamera_SetMovieDestination(pme, &h);
   if (SUCCESS != nRet)
      return nRet;

   eAudioType = (video_fmt_stream_audio_type)OEMCamera_AudioStreamType(pme->m_clsAudio, pme->m_dwSubAudio);
   if (eAudioType == VIDEO_FMT_STREAM_AUDIO_INVALID || -1 == eAudioType)
      return EBADPARM;

   // Note: 
   // (1) MP4 format is hard-coded. When more video container formats
   //     are supported, the container type must be detected using the MIME
   //     string specified via ICAMERA_SetMediaData().
   // (2) MP4 stream type is hard-coded. When more video container formats
   //     are supported, then the container type must be derived using the 
   //     pme->m_clsVideo and pme->m_dwSubVideo.
   // (3) pme->m_nQuality is cast to video_profile_type as camera_quality_type matches
   //     video_profile_type.
 
   

   if(pme->m_pszMIME)
   { if(STRCMP(pme->m_pszMIME, CAM_FILE_FORMAT_MPG4) ==0)
      {wFileFormat = CAM_FILE_BRAND_MP4;
      }
   else if(STRCMP(pme->m_pszMIME, CAM_FILE_FORMAT_AMC) ==0)
      {wFileFormat = CAM_FILE_BRAND_AMC;
      }
   else if(STRCMP(pme->m_pszMIME, CAM_FILE_FORMAT_3GP) ==0)
      {wFileFormat = CAM_FILE_BRAND_3GP;
      }
   else if(STRCMP(pme->m_pszMIME, CAM_FILE_FORMAT_3G2) ==0)
      {wFileFormat = CAM_FILE_BRAND_3G2;
      }
   }

 


   switch(wFileFormat)
   {case CAM_FILE_BRAND_MP4://MPEG4
    case CAM_FILE_BRAND_AMC://AMC
    nVideoFormat = VIDEO_FMT_STREAM_VIDEO_MPEG4;
         switch(pme->m_wShortHeader)
		 { case CAM_SHORT_HEADER_DISABLED:
		     nSh = FALSE;
			 break;
		 case CAM_SHORT_HEADER_ENABLED: 
			 nVideoFormat = VIDEO_FMT_STREAM_VIDEO_MPEG4;
			 nSh = TRUE;
			 break;
		 }
       break;
    case CAM_FILE_BRAND_3GP://3GP
    	nSh = FALSE;
		switch(pme->m_wShortHeader)
		 { case CAM_SHORT_HEADER_DISABLED:
			 nVideoFormat = VIDEO_FMT_STREAM_VIDEO_MPEG4;
		   break;
		 case CAM_SHORT_HEADER_ENABLED: 
			 nVideoFormat = VIDEO_FMT_STREAM_VIDEO_H263;
			 break;
		 }
	   break;
    case CAM_FILE_BRAND_3G2_FRAG:
    case CAM_FILE_BRAND_3G2://3G2	
	    nSh = FALSE; 
		switch(pme->m_wShortHeader)
		 { case CAM_SHORT_HEADER_DISABLED:
			nVideoFormat = VIDEO_FMT_STREAM_VIDEO_MPEG4;		    
		   break;
		 case CAM_SHORT_HEADER_ENABLED: 
		    nVideoFormat = VIDEO_FMT_STREAM_VIDEO_H263;
  		   break;
		 case CAM_SHORT_HEADER_TEST:
            nVideoFormat = VIDEO_FMT_STREAM_VIDEO_H263;
			nSh = TRUE;
		   break;
		 }
   	   break;
   }
   nRet = (int)camera_start_record(VIDEO_FMT_MP4, 
                                   nVideoFormat,
								   wFileFormat,
								   nSh,
                                   eAudioType,
				                   pme->m_pCpgd, 
				                   pme->m_nszpCpgd, 
				                   pme->m_pUuid_cpgd, 
                                   (video_profile_type)pme->m_nQuality,
                                   &h, 
                                   OEMCamera_CameraLayerCB, (void *)pRsp->hObject);

   
   
//   nRet = (int)camera_start_record(VIDEO_FMT_MP4, 
 //                                  VIDEO_FMT_STREAM_VIDEO_MPEG4,
  //                                 eAudioType,
   //                                (video_profile_type)pme->m_nQuality,
    //                               &h, 
     //                              OEMCamera_CameraLayerCB, (void *)pRsp->hObject);

   return OEMCamera_AEEError(nRet);
#endif // defined(FEATURE_VIDEO_ENCODE)
}

/*==================================================================
   Called, in system mode, from AEECamera_CallbackSignal() to get
   the callback info.
==================================================================*/
static void OEMCamera_CallbackNotify(CameraRsp * pRsp)
{
   OEMCamera * pme = pRsp->pOwner;
   int16       nStatus = pRsp->camNotify.nStatus;
   CameraRsp   rspCopy;

   MEMCPY(&rspCopy, pRsp, sizeof(CameraRsp));

   if (pRsp->camNotify.nCmd == CAM_CMD_START)
   {
      if (nStatus == CAM_STATUS_DONE || nStatus == CAM_STATUS_ABORT)
         OEMCamera_FreeStartCameraRsp(pme);
      else
         OEMCamera_UngetCameraRsp(pRsp);
   }
   else if (pRsp->camNotify.nCmd == CAM_CMD_SETPARM)
      OEMCamera_FreeCmdCameraRsp(pRsp);
   else
      OEMCamera_UngetCameraRsp(pRsp);

   if (pme->m_pfnNotify) {
      BRIDLE_ASSERT_SAFE_PFN(pme->m_pfnNotify);
      pme->m_pfnNotify(pme->m_pUser, (void *)&rspCopy.camNotify);
   }

//rr Camera frame will be released later when the callback is delivered.
//   // Release the frame buffer after the frame is delivered to the user.
//   if (nStatus == CAM_STATUS_FRAME)
//      camera_release_frame();
}

/*==================================================================
   Map camera error code to AEE error code
==================================================================*/
int OEMCamera_AEEError(int nRet)
{
   if (nRet < 0)
      return EFAILED;

   switch ((camera_ret_code_type)nRet)
   {
      case CAMERA_SUCCESS:       nRet = SUCCESS;         break;
      case CAMERA_INVALID_STATE: nRet = EBADSTATE;       break;
      case CAMERA_INVALID_PARM:  nRet = EBADPARM;        break;
      case CAMERA_INVALID_FORMAT:nRet = EBADPARM;        break;
      case CAMERA_NO_SENSOR:     nRet = EFAILED;         break;
      case CAMERA_NO_MEMORY:     nRet = ENOMEMORY;       break;
      case CAMERA_NOT_SUPPORTED: nRet = EUNSUPPORTED;    break;
      case CAMERA_FAILED:        nRet = EFAILED;         break;
      default:                   nRet = EFAILED;         break;
   }

   return nRet;
}

/*==================================================================

==================================================================*/
int OEMCamera_SetSnapshotDestination(OEMCamera * pme, camera_handle_type * ph)
{
   AEEMediaData *       pmd = &pme->m_md;
   int                  nRet = SUCCESS;
   camera_encode_type   eFormat;

   if (!pmd || !pmd->pData)
      return EFAILED;

   switch (pme->m_clsVideo)
   {
      case AEECLSID_JPEG:
         eFormat = CAMERA_JPEG;
         break;

	  case AEECLSID_PNG:
         eFormat = CAMERA_PNG;
         break;

      case CAM_ENCODE_RAW:
         eFormat = CAMERA_RAW;
         break;

      default:
         eFormat  = CAMERA_JPEG;
         break;
   }

   if (pmd->clsData == MMD_FILE_NAME)
   {
      ph->device = ph->efs.device = CAMERA_DEVICE_EFS;
      ph->efs.quality = pme->m_nQuality;
      ph->efs.format = eFormat;
      if (pmd->pData)
         STRNCPY(ph->efs.filename, pme->m_pszFile, sizeof(ph->efs.filename));
      else
         nRet = EBADPARM;
   }
   else if (pmd->clsData == MMD_BUFFER)
   {
      ph->device = ph->mem.device = CAMERA_DEVICE_MEM;
      ph->mem.quality = pme->m_nQuality;
      ph->mem.format = eFormat;
      if (pmd->pData)
      {
         ph->mem.buffer = (byte *)pmd->pData;
         ph->mem.length = pmd->dwSize;
      }
      else
         nRet = EBADPARM;
   }
   else if (pmd->clsData >= MMD_ISOURCE)
   {
      // Perform streaming....
      nRet = EUNSUPPORTED;
   }

   return nRet;
}

/*==================================================================

==================================================================*/
#if defined(FEATURE_VIDEO_ENCODE)
static int OEMCamera_SetMovieDestination(OEMCamera * pme, video_handle_type * ph)
{
   AEEMediaData * pmd = &pme->m_md;
   int            nRet = SUCCESS;

   if (!pmd || !pmd->pData)
      return EFAILED;

   if (pmd->clsData == MMD_FILE_NAME)
   {
      ph->method = ph->efs.method = VIDEO_METHOD_EFS;
      if (pmd->pData)
         STRNCPY((char *)ph->efs.filename, pme->m_pszFile, sizeof(ph->efs.filename));
      else
         nRet = EBADPARM;
   }
   else if (pmd->clsData == MMD_BUFFER)
   {
      ph->method = ph->efs.method = VIDEO_METHOD_MEM;
      if (pmd->pData)
      {
         ph->mem.buf = (uint8 *)pmd->pData;
         ph->mem.len = pmd->dwSize;
      }
      else
         nRet = EBADPARM;
   }
   else if (pmd->clsData >= MMD_ISOURCE)
   {
      // Perform streaming....
      nRet = EUNSUPPORTED;
   }

   return nRet;
}
#endif // defined(FEATURE_VIDEO_ENCODE)

/*==================================================================
   CameraLayer callback called in CameraLayer context
==================================================================*/
void OEMCamera_CameraLayerCB(camera_cb_type cb, const void *client_data, camera_func_type func, int32 parm4)
{
   CameraRsp * pRsp = (CameraRsp *)AEEObjectMgr_GetObject((AEEObjectHandle)client_data);
   OEMCamera * pme;
   CameraRsp   rspCopy;

   if (!pRsp || !pRsp->pOwner)
      return;

   pme = pRsp->pOwner;

   MEMSET(&rspCopy, (int)0, sizeof(rspCopy));

   OEMCAMERA_ENTER_CRITICAL_SECTION()

   int         nStatus = 0;
   uint32      dwData = SUCCESS;

   // Common status handling...
   switch (cb)
   {
      case CAMERA_EXIT_CB_DSP_IDLE:    // Fall through...
      case CAMERA_EXIT_CB_DSP_ABORT:   // Fall through...
      case CAMERA_EXIT_CB_ABORT:       // Fall through...
      case CAMERA_EXIT_CB_ERROR:       
         nStatus = CAM_STATUS_ABORT; 
         switch(parm4)
         {
            case CAMERA_ERROR_EFS_SPACE_EXHAUSTED:
			   nStatus = CAM_STATUS_SPACE_ERROR;
               break;

            case CAMERA_ERROR_EFS_FILE_OPEN:
               nStatus = CAM_STATUS_IO_ERROR;
               dwData = CAM_ERR_ALREADY_OPEN;
               break;

            case CAMERA_ERROR_EFS_FILE_NOT_OPEN:
               nStatus = CAM_STATUS_IO_ERROR;
               dwData = CAM_ERR_OPEN;
               break;

            case CAMERA_ERROR_EFS_FILE_ALREADY_EXISTS:
               nStatus = CAM_STATUS_IO_ERROR;
               dwData = CAM_ERR_ALREADY_EXIST;
               break;

            case CAMERA_ERROR_EFS_NONEXISTENT_DIR:
            case CAMERA_ERROR_EFS_NONEXISTENT_FILE:
               nStatus = CAM_STATUS_IO_ERROR;
               dwData = CAM_ERR_NOT_EXIST;
               break;

            case CAMERA_ERROR_EFS_BAD_FILE_NAME:
               nStatus = CAM_STATUS_IO_ERROR;
               dwData = CAM_ERR_BAD_NAME;
               break;

            case CAMERA_ERROR_EFS_BAD_FILE_HANDLE:
               nStatus = CAM_STATUS_IO_ERROR;
               dwData = CAM_ERR_BAD_HANDLE;
               break;

            case CAMERA_ERROR_EFS_OTHER_ERROR:
            case CAMERA_ERROR_EFS_OPEN_TABLE_FULL:
               nStatus = CAM_STATUS_IO_ERROR;
               dwData = CAM_ERR_FS;
               break;
            default:
               nStatus = CAM_STATUS_ABORT; 
               break;
         }

         if (pRsp->camNotify.nCmd == CAM_CMD_START)
            OEMCamera_SetReadyMode(pme);
         goto Resume;
         break;

      case CAMERA_EVT_CB_FRAME:
         if (func == CAMERA_FUNC_START_PREVIEW || func == CAMERA_FUNC_START_RECORD)
         {
            OEMCamera_SaveFrameInfo(pme, (camera_frame_type *)parm4);
            nStatus = CAM_STATUS_FRAME;
         }
         goto Resume;
         break;
   }

   switch (func)
   {
      case CAMERA_FUNC_START: // Fall through...
      case CAMERA_FUNC_STOP:
         break;

      case CAMERA_FUNC_START_PREVIEW:
      {
         switch (cb)
         {
            case CAMERA_RSP_CB_SUCCESS:   
               pme->m_nMode = CAM_MODE_PREVIEW;
               nStatus = CAM_STATUS_START; 
               pme->m_bStateChanging = FALSE; 
               break;

            case CAMERA_EXIT_CB_FAILED:    
               nStatus = CAM_STATUS_FAIL; 
               dwData = CAM_EPREVIEWFAIL; 
               OEMCamera_SetReadyMode(pme);
               break;

            case CAMERA_EXIT_CB_DONE:     
               nStatus = CAM_STATUS_DONE;
               OEMCamera_SetReadyMode(pme);
               break;
         }
         break;
      }

      case CAMERA_FUNC_STOP_PREVIEW:
         break;

      case CAMERA_FUNC_TAKE_PICTURE:
      {
         switch (cb)
         {
            case CAMERA_RSP_CB_SUCCESS:   
               pme->m_nMode = CAM_MODE_SNAPSHOT;
               nStatus = CAM_STATUS_START; 
               pme->m_bStateChanging = FALSE; 
               break;

            case CAMERA_EXIT_CB_DONE:
               nStatus = CAM_STATUS_DONE;
               dwData = pme->m_bDeferEncode;
               // Save the frame info.
               OEMCamera_SaveFrameInfo(pme, (camera_frame_type *)parm4);
               // If encoding is not deferred, then encode the snapshot right away.
               if (!pme->m_bDeferEncode)
                  OEMCamera_EncodeSnapshot(pme);
               OEMCamera_SetReadyMode(pme);
               break;

            case CAMERA_EXIT_CB_FAILED:   
               nStatus = CAM_STATUS_FAIL; 
               dwData = CAM_ESNAPSHOTFAIL; 
               OEMCamera_SetReadyMode(pme);
               break;
         }
         break;
      }
       
      case CAMERA_FUNC_ENCODE_PICTURE:
      {
         switch (cb)
         {
            case CAMERA_EXIT_CB_DONE:     
               nStatus = CAM_STATUS_DONE;
               break;

            case CAMERA_EXIT_CB_FAILED:  
               nStatus = CAM_STATUS_FAIL; 
               dwData = CAM_ESNAPSHOTFAIL; 
               break;

            case CAMERA_EXIT_CB_FILE_SIZE_EXCEEDED:
               nStatus = CAM_STATUS_FILE_SIZE_EXCEEDED; 
               break;

         }
         break;
      }

      case CAMERA_FUNC_START_RECORD:
      {
         switch (cb)
         {
            case CAMERA_RSP_CB_SUCCESS:   
               pme->m_nMode = CAM_MODE_MOVIE;
               nStatus = CAM_STATUS_START; 
               pme->m_bStateChanging = FALSE; 
               break;

            case CAMERA_EXIT_CB_FAILED:    
               nStatus = CAM_STATUS_FAIL; 
               dwData = CAM_EMOVIEFAIL; 
               OEMCamera_SetReadyMode(pme);
               break;

            case CAMERA_EXIT_CB_DONE:     
               nStatus = CAM_STATUS_DONE;
               OEMCamera_SetReadyMode(pme);
               break;

#if defined(FEATURE_VIDEO_ENCODE)
            case CAMERA_STATUS_CB:
	       if ((parm4 == VIDEO_LIMIT_NEAR) || (parm4 == VIDEO_LIMIT_IMMINENT))
                  nStatus = CAM_STATUS_SPACE_WARNING;
               else if (parm4 == VIDEO_LIMIT_REACHED)
                  nStatus = CAM_STATUS_SPACE_ERROR;
               break;
#endif // FEATURE_VIDEO_ENCODE 
         }
         break;
      }

      case CAMERA_FUNC_DISABLE_FRAME_CALLBACK: // Fall through...
      case CAMERA_FUNC_PAUSE_RECORD:
      {
         switch (cb)
         {
            case CAMERA_RSP_CB_SUCCESS:   
               nStatus = CAM_STATUS_PAUSE; 
               break;

            case CAMERA_EXIT_CB_FAILED:    
               nStatus = CAM_STATUS_FAIL; 
               dwData = CAM_EPAUSEFAIL; 
               break;
         }
         break;
      }

      case CAMERA_FUNC_ENABLE_FRAME_CALLBACK: // Fall through...
      case CAMERA_FUNC_RESUME_RECORD:
      {
         switch (cb)
         {
            case CAMERA_RSP_CB_SUCCESS:   
               nStatus = CAM_STATUS_RESUME; 
               break;

            case CAMERA_EXIT_CB_FAILED:    
               nStatus = CAM_STATUS_FAIL; 
               dwData = CAM_ERESUMEFAIL; 
               break;
         }
         break;
      }

      case CAMERA_FUNC_STOP_RECORD:
         break;

      case CAMERA_FUNC_SET_PARM:
      {
         switch (cb)
         {
            case CAMERA_EXIT_CB_DONE:     
               nStatus = CAM_STATUS_DONE;
               break;

            case CAMERA_EXIT_CB_FAILED:  
               nStatus = CAM_STATUS_FAIL; 
               dwData = CAM_ESETPARMFAIL; 
               break;
         }
         break;
      }
   }

Resume:
   if (nStatus)
   {
      if (pRsp->camNotify.nCmd == CAM_CMD_START)
      {
         pRsp = OEMCamera_GetStartCameraRsp(pme);
         if (!pRsp)
            goto CBExit;
      }

      pRsp->camNotify.nStatus = nStatus;
      pRsp->camNotify.pData = (void *)dwData;

      MEMCPY(&rspCopy, pRsp, sizeof(CameraRsp));

      if (pRsp->camNotify.nCmd == CAM_CMD_START)
      {
         if (nStatus == CAM_STATUS_DONE || nStatus == CAM_STATUS_ABORT)
            OEMCamera_FreeStartCameraRsp(pme);
         else
            OEMCamera_UngetCameraRsp(pRsp);
      }
      else if (pRsp->camNotify.nCmd == CAM_CMD_SETPARM)
         OEMCamera_FreeCmdCameraRsp(pRsp);
      else
         OEMCamera_UngetCameraRsp(pRsp);
   }

CBExit:
   OEMCAMERA_LEAVE_CRITICAL_SECTION()

   if (rspCopy.bInUse && pme->m_pfnNotify) 
   {
      BRIDLE_ASSERT_SAFE_PFN(pme->m_pfnNotify);
      pme->m_pfnNotify(pme->m_pUser, (void *)&rspCopy.camNotify);
   }
}

/*==================================================================

==================================================================*/
static boolean OEMCamera_SaveFrameInfo(OEMCamera * pme, camera_frame_type * pf)
{
   if (!pf || !pf->buffer)
   {
      pme->m_pFrame->m_dib.cx = pme->m_pFrame->m_dib.cy = 0;
      pme->m_pFrame->m_dib.pBmp = NULL;
      return FALSE;
   }

   // Save the frame.
   MEMCPY(&pme->m_rawFrame, pf, sizeof(camera_frame_type));

   // Save it in the bitmap. Check write access.
   BRIDLE_COPY_TO_USER(&pme->m_pFrame->m_rawFrame, pf, sizeof(camera_frame_type));
//   MEMCPY(&pme->m_pFrame->m_rawFrame, pf, sizeof(camera_frame_type));
   // Set frame DIB info -- this is not complete info.
   if ((pf->rotation == 0) || (pf->rotation == 180))
   {
     pme->m_pFrame->m_dib.cx = pf->dx;
     pme->m_pFrame->m_dib.cy = pf->dy;
   }
   else
   {
     pme->m_pFrame->m_dib.cx = pf->dy;
     pme->m_pFrame->m_dib.cy = pf->dx;
   }
	pme->m_pFrame->m_dib.pBmp = pf->buffer;

   return TRUE;
}

/*==================================================================

==================================================================*/
static int OEMCamera_AddOverlay(OEMCamera * pme, IDIB * pDIB)
{
   int   nRet;

   if (pDIB)
      nRet = camera_set_overlay(pDIB->cx, pDIB->cy, pDIB->ncTransparent, pDIB->pBmp, NULL, NULL);
   else
      nRet = camera_clr_overlay(NULL, NULL);
   
   return OEMCamera_AEEError(nRet);
}

/*==================================================================

==================================================================*/
static void OEMCamera_SetReadyMode(OEMCamera * pme)
{
   pme->m_nMode = CAM_MODE_READY;
   pme->m_bPaused = FALSE;
   pme->m_bStateChanging = FALSE;
}

/*==================================================================

==================================================================*/
static int16 OEMCamera_AudioStreamType(uint32 clsAudio, uint32 dwSubAudio)
{
#if !defined(FEATURE_VIDEO_ENCODE)
   return -1;
#else
   int   nFmt;

   if (clsAudio == 0)
      nFmt = VIDEO_FMT_STREAM_AUDIO_NONE;
   else if (clsAudio == AEECLSID_MEDIAQCP)
   {
      switch (dwSubAudio)
      {
         case MM_QCP_FORMAT_FIXED_FULL_13K:
         case MM_QCP_FORMAT_VAR_FULL_13K:
            nFmt = VIDEO_FMT_STREAM_AUDIO_QCELP13K_FULL;
            break;

         case MM_QCP_FORMAT_VAR_HALF_13K:
         case MM_QCP_FORMAT_FIXED_HALF_13K:
            nFmt = VIDEO_FMT_STREAM_AUDIO_QCELP13K_HALF;
            break;

         case MM_QCP_FORMAT_EVRC:
         case MM_QCP_FORMAT_FIXED_FULL_EVRC:
            nFmt = VIDEO_FMT_STREAM_AUDIO_EVRC;
            break;

         case MM_QCP_FORMAT_FIXED_4_75_AMR:
         case MM_QCP_FORMAT_FIXED_5_15_AMR:
         case MM_QCP_FORMAT_FIXED_5_9_AMR :
         case MM_QCP_FORMAT_FIXED_6_7_AMR :
         case MM_QCP_FORMAT_FIXED_7_4_AMR :
         case MM_QCP_FORMAT_FIXED_7_95_AMR:
         case MM_QCP_FORMAT_FIXED_10_2_AMR:
         case MM_QCP_FORMAT_FIXED_12_2_AMR:
            nFmt = VIDEO_FMT_STREAM_AUDIO_AMR;
            break;

         default:
            nFmt = VIDEO_FMT_STREAM_AUDIO_INVALID;
            break;
      } // switch
   }
   else
      nFmt = VIDEO_FMT_STREAM_AUDIO_INVALID;

   return nFmt;
#endif // FEATURE_VIDEO_ENCODE
}

/*==================================================================

==================================================================*/
int OEMCamera_FrameBlt(void * pDst, uint32 dwDstSize, int xDst, int yDst, int cxDst, int cyDst,
                       void * pSrc, uint32 dwSrcSize, int xSrc, int ySrc, AEERasterOp rop)
{
   camera_frame_type *  pRawFrame = (camera_frame_type *)pSrc;
   IBitmap *            pDstBmp = (IBitmap *)pDst;
   IDIB *               pDstDIB;
   int      nRet;
   AEERect  rc;
   
#if defined(AEE_SIMULATOR)
   if (SUCCESS != IBITMAP_QueryInterface(pDstBmp, AEECLSID_DIB, (void **)&pDstDIB))
      return EFAILED;

   nRet = camera_blt(pRawFrame, (uint16)xSrc, (uint16)ySrc, (void *)pDst/*pDstDIB->pBmp*/, (uint16)xDst, (uint16)yDst, (uint16)cxDst, (uint16)cyDst);
   rc.x = xDst;
   rc.y = yDst;
   rc.dx = cxDst;
   rc.dy = cyDst;
   IBITMAP_Invalidate(pDst, &rc);

   IBITMAP_Release((IBitmap *)pDstDIB);
   
   return OEMCamera_AEEError(nRet);
#else
   //
   // QCT-specific code:
   //
#if !defined(OEM_PIXEL_SIZE)
#define OEM_PIXEL_SIZE   2
#endif
   uint8    nColorScheme;
   uint16   nPixelSize;

   if (SUCCESS != IBITMAP_QueryInterface(pDstBmp, AEECLSID_DIB, (void **)&pDstDIB))
      return EFAILED;

   switch (pDstDIB->nColorScheme)
   {
       case IDIB_COLORSCHEME_666: 
         nColorScheme = CAMERA_RGB666;
         nPixelSize = 4;
         break;
       case IDIB_COLORSCHEME_444: 
         nColorScheme = CAMERA_RGB444;
         nPixelSize = 2;
         break;
       default:                   
         nColorScheme = CAMERA_RGB565; 
         nPixelSize = 2;
         break;
   }

   nRet = camera_blt_ext(pRawFrame, (uint16)(pDstDIB->nPitch / nPixelSize), pDstDIB->cy, (void *)pDstDIB->pBmp, (uint16)xDst, (uint16)yDst, (uint16)cxDst, (uint16)cyDst, nColorScheme);
	  

   //nRet = camera_blt(pRawFrame, (uint16)(pDstDIB->nPitch / OEM_PIXEL_SIZE), pDstDIB->cy, (void *)pDstDIB->pBmp, (uint16)xDst, (uint16)cxDst, (uint16)cyDst);
   //nRet = camera_blt_ext(pRawFrame, (uint16)(pDstDIB->nPitch / OEM_PIXEL_SIZE), pDstDIB->cy, (void *)pDstDIB->pBmp, (uint16)xDst, (uint16)yDst, (uint16)cxDst, (uint16)cyDst, nColorScheme);
   rc.x = xDst;
   rc.y = yDst;
   rc.dx = cxDst;
   rc.dy = cyDst;
   IBITMAP_Invalidate(pDst, &rc);

   IBITMAP_Release((IBitmap *)pDstDIB);

   return OEMCamera_AEEError(nRet);
#endif // defined(AEE_SIMULATOR)
}

#endif // defined(FEATURE_BREW_CAMERA)

