Android Camera Subsystem 架构(Binder机制)及显示分析(5)

Step3:获取JPEG Image,并存储JPEG Image,生成JPEG Image的缩略图显示在Camera窗口的右上角。在GrabRawFrame函数的基础上,我们需要将获取的原始数据转化成JPEG格式的数据,所以我们将之前GrabRawFrame获得的原始数据传给GrabJpegFrame(void * buffer)函数,返回满足要求的JPEG格式的数据。随后通过回调函数,向CameraService发送CAMERA_MSG_COMPRESSED_IMAGE消息,CameraService收到该消息之后调用JPEG Image处理函数handleCompressedPicture。

void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem)

{

sp<ICameraClient> c = mCameraClient;

if (c != NULL) {

c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);

}

mHardware->disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);

}

 

handleCompressedPicture和之前的处理函数不同,而是将消息和数据直接(其实是间接,还要通过Camera Client端,Camera JNI, Android.hardware.Camera)交给上层AP来处理。包括JPEG Image Storage和 Create Image Thumbnail。

在定义的延迟时间内,在Preview Layout中显示Capture image,之后通过调用restartPreview,恢复到Preview Mode状态下。

(3)VideoCamera Preview Display

当由Capture Preview状态切换到VideoPreview状态进入VideoCamera模式时,首先VideoCamera模式提供给用户的是Preview Display,这部分同Camera Preview Display。

int CameraHardware::previewThread()

{

mLock.lock();

int previewFrameRate = mParameters.getPreviewFrameRate();

mLock.unlock();

Mutex::Autolock lock(mPreviewLock);

if (!previewStopped && mPreviewBuffer != 0

&& mRawBuffer !=0 && mDataFn) {

int delay = (int)(1000000.0f / float(previewFrameRate));

①mCamera.GrabRawFrame(mHeap->getBase());

if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME){

②mCamera.GrabPreviewFrame(mHeap->getBase(),

mPreviewHeap->getBase());

③mDataFn(CAMERA_MSG_PREVIEW_FRAME,

mPreviewBuffer, mUser);

delay-=100;

}

①mRecordingLock.lock();

if ((mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)

&& mRecordBuffer != 0 && mTimestampFn) {

②mCamera.GrabRecordFrame(mHeap->getBase(),

mRecordHeap->getBase());

③nsecs_t timeStamp = systemTime(SYSTEM_TIME_MONOTONIC);

④mTimestampFn(timeStamp,

CAMERA_MSG_VIDEO_FRAME, mRecordBuffer, mUser);

delay-=100;

}

mRecordingLock.unlock();

usleep(delay);

}

return NO_ERROR;

}

 
 

在VideoCamera模式下,当用户通过ClickShutterButton进入Camera Recording状态时,用户看到的是Camera Recording Preview Display,从数据的显示过程同Camera Preview Display,但在此状态下,需要考虑到向Opencore框架,也就是CameraInput模块投递由Camera硬件采集的Record数据。CameraHardware不仅需要向Preview缓冲区投递数据,同时还要向CameraInput传送数据。如上图所示。

在Camera Recording状态下,libcamera_client.so端的回调函数(也就是CameraListener类定义的回调函数)不再由JNICameraContext类来实现,而是由AndroidCameraInputListener实现,换句话说,在CameraInput中的mListener成员变量是由AndroidCameraInputListener来初始化的。

Location:frameworks/base/include/camera/Camera.h

class CameraListener: virtual public RefBase

{

public:

virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;

virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr) = 0;

virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType,

const sp<IMemory>& dataPtr) = 0;

};

 
 

在整个Androi系统中,总共有三个类来分别实现这个抽象类,他们分别是JNICameraContext、AndroidCameraInputListener、CameraSourceListener类。

①Location:frameworks/base/core/jni/android_hardware_Camera.cpp

class JNICameraContext: public CameraListener

②Location:external/opencore/android/author/Android_camera_input.h

class AndroidCameraInputListener: public CameraListener

③Location:frameworks/base/core/jni/android_hardware_Camera.cpp

class CameraSourceListener: public CameraListener

 
 

而具体实现上,由于CameraInput只需要带时间戳的数据,所以AndroidCameraInputListener只实现了postDataTimestamp回调函数。

void AndroidCameraInputListener::postDataTimestamp(nsecs_t timestamp,

int32_t msgType, const sp<IMemory>& dataPtr)

{

if ((mCameraInput != NULL)

&& (msgType == CAMERA_MSG_VIDEO_FRAME)) {

mCameraInput->postWriteAsync(timestamp, dataPtr);

}

}

 
 

根据Opencore框架中CameraInput中的实现,CameraInput可以作为CameraClient端得一个实例,通过Camera和CameraService架构实现包括预览,录像在内的所有功能。

但在目前的Camera子系统中,Camera Recording模式与Camera Capture模式共享同一个CameraDevice实例,Camera Recording的预览是通过使用Camera Capture模式下的Surface实现的,即Camera Recording通过调用Camera Capture中的setPreviewDisplay和底层CameraHardware层的previewThread线程实现Camera Recording预览。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwgysw.html