在Android中,當(dāng)Camera原生服務(wù)有數(shù)據(jù)上傳給客戶端時,在ICameraClient的數(shù)據(jù)回調(diào)函數(shù)中會收到數(shù)據(jù),具體如下:
代碼:客戶端的數(shù)據(jù)回調(diào)處理
void CameraService::Client::dataCallback(int32_t msgType, const sp< IMemory>& dataPtr, void* user)
{
LOGV("dataCallback(%d)", msgType);
sp< Client> client=getClientFromCookie(user); //獲取客戶端
if (client==0) {
return;
}
sp< ICameraClient> c=client->mCameraClient; //獲取ICameraClient
if (dataPtr==NULL) { //如果沒有數(shù)據(jù)
LOGE("Null data returned in data callback");
if (c != NULL) {
c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
c->dataCallback(msgType, NULL);
}
return;
}
switch (msgType) {
case CAMERA_MSG_PREVIEW_FRAME: //預(yù)覽數(shù)據(jù)幀
client->handlePreviewData(dataPtr);
break;
case CAMERA_MSG_POSTVIEW_FRAME: //準(zhǔn)備預(yù)覽
client->handlePostview(dataPtr);
break;
case CAMERA_MSG_RAW_IMAGE: //原始圖像
client->handleRawPicture(dataPtr);
break;
case CAMERA_MSG_COMPRESSED_IMAGE: //壓縮圖像
client->handleCompressedPicture(dataPtr);
break;
default:
if (c !=NULL) {
c->dataCallback(msgType, dataPtr);
}
break;
}
#if DEBUG_CLIENT_REFERENCES
if (client->getStrongCount()==1) {
LOGE("++++++++++++++++ (DATA CALLBACK) THIS WILL CAUSE A LOCKUP!");
client->printRefs();
}
#endif
}
當(dāng)客戶端的數(shù)據(jù)回調(diào)函數(shù)收到的消息類型為CAMERA_MSG_PREVIEW_FRAME時,客戶端通過handlePreviewData()方法進(jìn)行處理;當(dāng)消息類型為CAMERA_MSG_ POSTVIEW_FRAME時,客戶端通過handlePostview()方法進(jìn)行處理,然后向上層應(yīng)用傳遞CAMERA_MSG_PREVIEW_FRAME消息;當(dāng)消息類型為CAMERA_MSG_RAW_IMAGE時,客戶端通過handleRawPicture()方法進(jìn)行處理,將拍攝的圖像渲染在屏幕上;當(dāng)消息類型為CAMERA_MSG_COMPRESSED_IMAGE時,客戶端通過handleCompressedPicture()方法進(jìn)行處理,將JPG數(shù)據(jù)傳遞給上層應(yīng)用。
在handlePreviewData()方法中,會將收到的數(shù)據(jù)進(jìn)行屏幕渲染,下面是handlePreviewData()方法的實現(xiàn):
代碼:預(yù)覽數(shù)據(jù)處理
void CameraService::Client::handlePreviewData(const sp< IMemory>& mem)
{
ssize_t offset;
size_t size;
//獲取偏移地址和大小,格式為YUV
sp< IMemoryHeap> heap=mem->getMemory(&offset, &size);
#if DEBUG_HEAP_LEAKS && 0 // debugging
if (gWeakHeap==NULL) {
if (gWeakHeap != heap) {
LOGD("SETTING PREVIEW HEAP");
heap->trackMe(true, true);
gWeakHeap=heap;
}
}
#endif
if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
{
if (debug_frame_cnt++==DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
dump_to_file("/data/preview.yuv", //調(diào)試用
uint8_t *)heap->base() + offset, size);
}
}
#endif
if (!mUseOverlay)
{
Mutex::Autolock surfaceLock(mSurfaceLock);
if (mSurface !=NULL) {
mSurface->postBuffer(offset); //傳遞給Surface
}
}
int flags=mPreviewCallbackFlag;
if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
LOGV("frame callback is diabled");
return;
}
sp< ICameraClient> c=mCameraClient;
if ((c==NULL) || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
LOGV("Disable preview callback");
mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASKFRAME_CALLBACK_FLAG_COPY_OUT_MASK|
FRAME_CALLBACK_FLAG_ENABLE_MASK);
if (mUseOverlay)
mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
}
if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
LOGV("frame is copied");
copyFrameAndPostCopiedFrame(c, heap, offset, size); //將數(shù)據(jù)存入預(yù)覽緩沖
} else {
LOGV("frame is forwarded");
c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem); //向上層傳遞消息
}
}
當(dāng)上層收到數(shù)據(jù)時,執(zhí)行保持?jǐn)?shù)據(jù)的方法為ImageCapture:: storeImage()。