Saturday, December 11, 2004

ICamera Interface - Preview Mode

The preview mode is well documented in the documentation provided along with the QualComm SDK. I prefer using the API documentation provided in the PDF format rather than the compiled help in .chm format. The sample code provided in the .chm file that came with my copy of the SDK(2.1) had some errors in it specially the ICAMERA_GetFrame() function.
To implement it in my applet I just the took the code from the SDK documentation to get started. I added a pointer to the ICamera interface in my Applet structure. I prefer not to have a AEEDeviceInfo structure in my applet so I just include the width and height of the screen in the applet.





typedef struct _cameratest{
AEEApplet a;// First element of this structure must be AEEApplet
IDisplay *pIDisplay;
IShell *pIShell;
EAppStateType m_eAppState; // Current Application State
EAppStateType m_ePrevState;
uint16 cxScreen;// Width of the handset screen
uint16 cyScreen;// Height of the handset screen
IMenuCtl *m_pMainMenu;
ICamera *m_pICamera; // ptr to the camera
} cameratest;

To Start the Camera I use a function that will initialize the parameters and start the camera in the preview mode. Most important thing is to initialize a callback and pass the AEECameraNotify structure. Since Camera access is done asynchronously in BREW (very much like other platforms) the callback serves an important role.




static void cameratest_DisplayCameraPreview(cameratest * pMe)
{
int nErr;
AEESize az;
pMe->m_eAppState = APP_STATE_CAM_PREVIEW;
if (ISHELL_CreateInstance(pMe->pIShell, AEECLSID_CAMERA , (void**)(&pMe->m_pICamera)) != SUCCESS)
return;
// Register callback notification function.
nErr = ICAMERA_RegisterNotify(pMe->m_pICamera, cameratest_CameraNotify, pMe);
if (nErr)
{
DBGPRINTF("ERROR IN REGISTERING CALL BACK %d", nErr);
Cameratest_goBack(pMe->m_eAppState);
return;
}
az.cx = pMe->cxScreen;
az.cy = pMe->cyScreen;
ICAMERA_SetDisplaySize(pMe->m_pICamera, &az);
nErr = ICAMERA_Preview(pMe->m_pICamera);
if (nErr)
{
DBGPRINTF("ERROR in initiating preview %d", nErr);
return;
}
}

Every display function must have a hide function. To stop the Preview mode all we need to do is call the ICAMERA_Stop() function.





static void cameratest_HideCameraPreview(cameratest * pMe)
{
if(ICAMERA_Stop(pMe->m_pICamera) == SUCCESS)
DBGPRINTF("STOP COMMAND ACCEPTED");
}

The call back function is where the real stuff happens. Once the Camera is ready the OS will call the callback function that we had registered earlier. The AEECameraNotify structure contains a bunch of info about the callback. In the preview mode the first callback will have the status CAM_STATUS_START with nCmd = CAM_CMD_START and nSubCmd = CAM_MODE_PREVIEW. The frames captured from the camera are sent to the callback at regular intervals ( depends on the fps) and you can capture the frame of data using ICAMERA_GetFrame() function. The interface does not display the frames on the screen much like the API in series 60 so you have to display them yourself.




static void cameratest_CameraNotify(void * pUser, AEECameraNotify * pn)
{
cameratest * pMe = (cameratest *)pUser;
if (!pMe !pn)
return;
switch (pn->nStatus)
{
case CAM_STATUS_START:
// Preview has begun...
break;
case CAM_STATUS_FRAME:
{
IBitmap * pFrame;
AEEBitmapInfo bi; // // IMPORTANT NOTE: You need to do IBITMAP_Release(pFrame) after you're done with pFrame.
pFrame = ICAMERA_GetFrame(pMe->m_pICamera, &pFrame);
if (!pFrame)
{
DBGPRINTF("DID not get FRAME");
break;
}
// Get the bitmap info...this can be saved in app global structure.
IBITMAP_GetInfo(pFrame, &bi, sizeof(bi));
// Display the frame at (0, 0) location of the screen
IDISPLAY_BitBlt(pMe->pIDisplay, 2, 2, bi.cx, bi.cy, pFrame, 0, 0, AEE_RO_COPY);
IBITMAP_Release(pFrame);
IDISPLAY_Update(pMe->pIDisplay);
}
break;
case CAM_STATUS_DONE:
break;
case CAM_STATUS_ABORT:
// Preview got aborted.
break;
}
}

Off course in the production version of the code you will have to take care of some additional things. The documentation advises to make sure that when the applet receives a EVT_PAUSE event – make sure you shut down the preview mode. Also it would be a wise move to put in some code for the other status codes in the callback like CAM_STATUS_ABORT, CAM_STATUS_DATA_IO_DELAY etc.

No comments:

Post a Comment