device/wolf/smdk6410/BoardConfig.mk
USE_CAMERA_STUB := false
hardware建立Camera HAL目录
hardware/wolf/libcamera
CannedJpeg.h
Ov965xCamera.cpp
Ov965xCamera.h
S3C6410CameraHardware.cpp
S3C6410CameraHareware.h
USBCamera.cpp
USBCamera.h
编写Android.mk文件
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
USBCamera.cpp \
Ov965xCamera.cpp \
S3C6410CameraHardware.cpp
LOCAL_SHARED_LIBRARIES:= \
libui \
libutils \
libbinder \
liblog \
libcamera_client
LOCAL_MODULE:= libcamera
LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += \
frameworks/base/libs
include $(BUILD_SHARED_LIBRARY)
2 android2.3.4_32bit$ source ./build/envsetup.sh
3 android2.3.4_32bit$ choosecombo
Build for the simulator or the device?
1. Device
2. Simulator
1
1
Which product would you like? [smdk6410]
回车
eng
4 make libcamera编译特定模块
开始编译摄像头模块,动态连接库文件*.so存放在
Install: out/target/product/smdk6410/system/lib/libcamera.so
用adb push把libcamera.so推到目标机/system/lib/中
cd D:\software\android-sdk-windows\tools
d:
adb push libcamera.so /system/lib/
5 目标机上
export ANDROID_LOG_TAGS="CameraHardware:D CameraHardware:E *:S"
logcat -d
6 问题
拍照
E/AudioService( 1902): Media server died.
解决:在init.c中添加
chmod 0777 /dev/video0
二 CAMERA 系统
Camera系统分成以下几个部分
1)摄像头驱动程序:通常基于linux的video for linux视频驱动框架
2)Camera硬件抽象层
接口的代码路径:frameworks/base/include/camera/
主要文件为CameraHardwareInterfacd.h,需要各个系统根据自己的情况实现
3)Camera服务部分
代码路径:frameworks/base/include/camera
Camera服务是Android系统中一个单独部分,通过调用Camera硬件抽象层来实现
4)Camera的本地框架代码
代码路径:frameworks/base/include/camera
5)Camera的JNI代码
代码路径:frameworks/base/core/jni/android_hardware_Camera.cpp
提供给Java类的本地支持,也包含了反向调用java传递信息和数据功能
6)Camera系统的Java类
代码路径:frameworks/base/core/java/android/hardware/Camera.java
Camera对Java层次的类为android.hardware.Camera,自Java应用程序提供接口
可用于在Java应用程序层构建照相机和扫描类的程序
-----------------------------------------------------------------------
移植的内容
在Android系统中,照相机系统的标准化部分是硬件抽象层的接口,因此
针对特定平台Camera系统的移植包括Camera驱动程序和Camera硬件抽象层
在Linux系统中,Camera的驱动程序都是用Linux标准的Video for Linux 2(V4L2)
驱动程序,从内核空间到用户空间,主要的数据流和控制类的均由V4L2驱动程序
的框架来定义,在Android系统的实现中,一般也都使用标准的V4L2驱动程序作为
照相机部分的驱动程序
Camera硬件抽象层主要实现取景器,视频录制,拍摄相片三个方面功能。V4L2驱动
程序一般只提供的Video数据的获得,而如何实现视频预览,如何向上层发送数据等
功用,这些都是Camera的硬件抽象层需要负责的方面了。
三 硬件抽象层
1. Camera硬件抽象层
frameworks/base/include/camera/
主要文件为CameraHardwareInterface.h,需要各个系统根据自己的情况实现
2. Camera服务部分
frameworks/base/services/camera/libcameraservice
Camera服务是Andriod系统中一个单独的部分,通过调用camera硬件抽象层
来实现。
3. Camera 的本地框架代码
frameworks/base/libs/camera/
4. Camera的硬件抽象层
是位于V4L2驱动程序和CameraService之间的部分,这是
一个C++的接口类,需要具体的实现者继承这个类,并实现其中的各个纯虚函数。
纯虚函数可以让类先具有一个操作名称,而没有操作内容,让派生类在继承时
再去具体地给出定义。
硬件抽象层的主要的头文件为CameraHardwareInterface.h,定义了C++的接口类
需要根据系统的情况继承实现。
camera.h 这是Camera系统本地对上层的接口
CameraParameters.h定义Camera系统的参数,在本地代码的各个层次中使用。
Camera硬件抽象层的实现通常需要生成动态库libcamera.so
5. CameraHardwareInterface中定义了几种回调函数
typedef void (*notify_callback)(int32_t msgType, //通知回调
int32_t ext1,
int32_t ext2,
void* user);
typedef void (*data_callback)(int32_t msgType, //数据回调
const sp<IMemory>& dataPtr,
void* user);
typedef void (*data_callback_timestamp)(nsecs_t timestamp,//带有时间的数据回调
int32_t msgType,
const sp<IMemory>& dataPtr,
void* user);
消息类型mstType 数据IMemory
回调函数由setCallbacks(),enableMsgType()函数统一处理。
setCallbacks()可以设置三个类型的回调函数指针
/** Set the notification and data callbacks */
virtual void setCallbacks(notify_callback notify_cb,
data_callback data_cb,
data_callback_timestamp data_cb_timestamp,
void* user) = 0;
6. Camera硬件抽象层的三种业务
A 取景器preview(使用YUV原始数据格式,发送到视频输出设备)
S3C6410CameraHardware.cpp中
- 1)在初始化过程中,建立preview的内存队列
- void CameraHardware::initHeapLocked()
- {
-
- int picture_width, picture_height;
- mParameters.getPictureSize(&picture_width, &picture_height);
- mRawHeap = new MemoryHeapBase(picture_width * picture_height * 2);
-
- int preview_width, preview_height;
- mParameters.getPreviewSize(&preview_width, &preview_height);
-
- int how_big = preview_width * preview_height*2;
- }
-
- void CameraHardware::initDefaultParameters()
- {
- CameraParameters p;
-
- p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");
- p.setPreviewSize(320, 240);
- p.setPreviewFrameRate(15);
-
- p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_RGB565);
- p.set(CameraParameters::KEY_ROTATION, 0);
-
- p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
- p.setPictureSize(320, 240);
- p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
-
- if (setParameters(p) != NO_ERROR) {
- LOGE("Failed to set default parameters?!");
- }
-
- }
- 2) 在startPreview()的实现中,建立preview线程
- status_t CameraHardware::startPreview()
- {
- Mutex::Autolock lock(mLock);
- if (mPreviewThread != 0) {
- return INVALID_OPERATION;
- }
- mPreviewThread = new PreviewThread(this);
- return NO_ERROR;
- }
- 3)在preview线程的循环中,等待视频数据的到达
- int CameraHardware::previewThread()
- {
- if(mCamType == CAMTYPE_CMOS)
- Ov965xCamera->getNextFrameAsRgb565((uint16_t *)frame);
- 4)视频帧到达后使用preview回调的机制CAMERA_MSG_PREVIEW_FRAME,将视频
- 帧向上层传送
-
- if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
- mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
- B拍摄照片(可以使用原始数据或者压缩图像数据)
- 1) takePicture()函数表示开始拍摄,可以建立单独的线程来处理
- status_t CameraHardware::takePicture()
- {
- stopPreview();
- if (createThread(beginPictureThread, this) == false)
- return UNKNOWN_ERROR;
- return NO_ERROR;
- }
-
- int CameraHardware::beginPictureThread(void *cookie)
- {
- CameraHardware *c = (CameraHardware *)cookie;
- return c->pictureThread();
- }
-
- int CameraHardware::pictureThread()
- {
- if (mMsgEnabled & CAMERA_MSG_SHUTTER)
- mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
-
- if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
-
-
- int w, h;
- mParameters.getPictureSize(&w, &h);
- sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 2);
-
- Ov965xCamera cam(w, h);
-
-
- if(mCamType == CAMTYPE_CMOS)
- {
- cam.getNextFrameAsRgb565((uint16_t *)mRawHeap->base());
- }
- else if (mCamType == CAMTYPE_USB)
- {
-
- LOGE("%s, Taking picure using USB CAM", LOG_TAG);
-
-
- }
- mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
- }
-
-
-
-
- if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
- LOGE("%s, COMPRESSED IMAGE", LOG_TAG);
- int w, h;
- unsigned int DATA_OFFSET = 54;
- uint16_t WIDTH = w;
- uint16_t HEIGHT = h;
-
- mParameters.getPictureSize(&w, &h);
- Ov965xCamera* Ov965xCamera = mOv965xCamera;
- sp<MemoryHeapBase> heap = new MemoryHeapBase(DATA_OFFSET+w * h* 2);
- sp<MemoryBase> mem = new MemoryBase(heap, 0, DATA_OFFSET+w * h* 2);
-
-
-
- uint8_t header[54] = { 0x42,
- 0x4d,
- 0, 0, 0, 0,
- 0, 0,
- 0, 0,
- 54, 0, 0, 0,
- 40, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 0,
- 16, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0
- };
-
-
- uint16_t file_size = WIDTH * HEIGHT * 2 + DATA_OFFSET;
- header[2] = (uint8_t)(file_size & 0x000000ff);
- header[3] = (file_size >> 8) & 0x000000ff;
- header[4] = (file_size >> 16) & 0x000000ff;
- header[5] = (file_size >> 24) & 0x000000ff;
-
-
- header[18] = HEIGHT & 0x000000ff;
- header[19] = (HEIGHT >> 8) & 0x000000ff;
- header[20] = (HEIGHT >> 16) & 0x000000ff;
- header[21] = (HEIGHT >> 24) & 0x000000ff;
-
-
- header[22] = WIDTH & 0x000000ff;
- header[23] = (WIDTH >> 8) & 0x000000ff;
- header[24] = (WIDTH >> 16) & 0x000000ff;
- header[25] = (WIDTH >> 24) & 0x000000ff;
-
- LOGE("%s, Header Ready", LOG_TAG);
-
- unsigned int i;
- for(i=0;i<DATA_OFFSET;i++){
- *((uint8_t*)heap->base()+i)=header[i];
- }
-
- Ov965xCamera->getNextFrameAsRgb565((uint16_t*)heap->base()+DATA_OFFSET/2);
-
- uint16_t *heap_base = (uint16_t*)heap->base();
- uint16_t pixel_data;
- uint8_t tail_data;
- for(i=DATA_OFFSET/2;i<DATA_OFFSET/2+WIDTH*HEIGHT;i++){
- pixel_data = *(heap_base+i);
- tail_data = (uint8_t)(pixel_data & 0x001f);
- pixel_data = (pixel_data & 0xffc0)>>1 | tail_data;
- *(heap_base+i)=pixel_data;
- }
-
-
- mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
- heap=NULL;
- LOGE("%s, IMAGE SAVED!", LOG_TAG);
- }
- return NO_ERROR;
- }
2)使用回调机制传送数据:如果得原始格式(通常是YUV的格式,如yuv422sp,这里是RGB565)
的数据,使用CAMERA_MSG_RAW_IMAGE将数据传送;如果得到压缩图像(通常JPEG格式,这里是BMP)
使用CAMERA_MSG_COMPRESSED_IMAGE将数据传送
C 视频录制(将数据传送给视频编码器程序)
1)在startRecording()的实现中,开始录制的准备,录制视频可以使用自己的线程,也可以使用
preview线程
2)当一个视频帧到来的时候,通过录制回调机制(使用CAMERA_MSG_VIDEO_FRAME)将视频帧向上
发送
3)releaseRecordingFrame()被调用后,表示上层通知Camera硬件抽象层,这一帧的内存已经用完
可以进行下一次的处理。
四 、 android camera HAL的改写
- 1. 修改BoardConfig.mk
- USE_CAMERA_STUB := false
- 2. hardware下建立Camera HAL目录
- /hardware/ego/libcamera
- 复制几个文件
- cp ../../../frameworks/base/services/camera/libcameraservice/CameraHardwareStub.cpp
- S3C6410CameraHardware.cpp
- cp ../../../frameworks/base/services/camera/rks/base/services/camera/libcameraservice/CameraHardwareStub.h
- S3C6410CameraHardware.h
- cp ../../../frameworks/base/services/camera/libcameraservice/FakeCamera.cpp Ov965xCamera.cpp
- cp ../../../frameworks/base/services/camera/libcameraservice/FakeCamera.h Ov965xCamera.h
- 3. 编译Android.mk文件
- LOCAL_PATH:= $(call my-dir)
- include $(CLEAR_VARS)
-
- LOCAL_SRC_FILES:= \
- S3C6410CameraHardware.cpp \
- Ov965xCamera.cpp
-
- LOCAL_SHARED_LIBRARIES:= \
- libui \
- libutils \
- libbinder \
- liblog \
- libcamera_client
-
- LOCAL_MODULE:= libcamera
- LOCAL_MODULE_TAGS:= eng
-
- LOCAL_C_INCLUDES += \
- frameworks/base/libs
-
- include $(BUILD_SHARED_LIBRARY)
-
- 根据这个脚本可编译出libcamera.so
- 4. 修改Ov965xCamera.cpp,该文件可以按照V4L2流程来写
- 1)构造函数中进行初始化
-
- Ov965xCamera::Ov965xCamera(int width, int height)
- : mTmpRgb16Buffer(0)
- {
- struct v4l2_format fmt;
- int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- v4l2_fd = open("/dev/video0", O_RDWR | O_SYNC);
- LOGE("open /dev/video0 fd is %d", v4l2_fd);
-
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = width;
- fmt.fmt.pix.height = height;
- fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-
- ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt);
- ioctl(v4l2_fd, VIDIOC_STREAMON, &type);
- setSize(width, height);
- }
- -------->调用setSize()
-
- 5. 修改S3C6410CameraHardware.cpp
-
- void CameraHardware::initDefaultParameters()
- {
-
- CameraParameters p;
-
- p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");
- p.setPreviewSize(320, 240);
-
- p.setPreviewFrameRate(15);
- p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_RGB565);
- p.set(CameraParameters::KEY_ROTATION, 0);
-
- p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
- p.setPictureSize(320, 240);
- p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
-
- if (setParameters(p) != NO_ERROR) {
- LOGE("Failed to set default parameters!");
- }
- }
-
- 调用----->setParameters(p)
- status_t CameraHardware::setParameters(const CameraParameters& params)
- {
- Mutex::Autolock lock(mLock);
-
- if (strcmp(params.getPreviewFormat(),
- CameraParameters::PIXEL_FORMAT_RGB565) != 0) {
- LOGE("Only rgb565 preview is supported");
- return -1;
- }
-
- if (strcmp(params.getPictureFormat(),
- CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
- LOGE("Only jpeg still pictures are supported");
- return -1;
- }
-
- int w, h;
- params.getPictureSize(&w, &h);
-
- mParameters = params;
- initHeapLocked();
-
- return NO_ERROR;
- }
-
- 调用----->initHeapLocked();
- void CameraHardware::initHeapLocked()
- {
- int picture_width, picture_height;
- mParameters.getPictureSize(&picture_width, &picture_height);
-
- mRawHeap = new MemoryHeapBase(picture_width * picture_height * 2);
-
-
- int preview_width, preview_height;
- mParameters.getPreviewSize(&preview_width, &preview_height);
- LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);
-
- int how_big = preview_width * preview_height * 2;
- mPreviewFrameSize = how_big;
-
- mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);
-
- for (int i = 0; i < kBufferCount; i++) {
- mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize);
-
- }
-
- if (mOv965xCamera != 0)
- {
- LOGD("delete mOv965xCamera");
- delete mOv965xCamera;
- mOv965xCamera = 0;
- }
- else if(mCamType == CAMTYPE_CMOS)
- {
- LOGD("new mOv965xCamera");
- mOv965xCamera = new Ov965xCamera(preview_width, preview_height);
- }
- }
- 在这个过程中,建立了两块内存(MemoryHeapBase): mRawHeap 表示一个拍照照片的内存
- mPreviewHeap表示取景preview的内存,由于取景器preview的内容是一个队列,因此在
- mPreviewHeap中建立kBufferCount(为4个)MemoryBase
- new Ov965xCamera作为摄像头输入数据的来源
-
- CameraService.cpp调用----------->startPreview()
- status_t CameraHardware::startPreview()
- {
- Mutex::Autolock lock(mLock);
- if (mPreviewThread != 0) {
- return INVALID_OPERATION;
- }
-
-
- mPreviewThread = new PreviewThread(this);
-
- return NO_ERROR;
- }
-
- 调用----------->PreviewThread()
- 在PreviewThread线程中通过调用preview的回调机制,实现preview
- 数据的数据传递给上层就是CameraService
- int CameraHardware::previewThread()
- {
- mLock.lock();
-
- int previewFrameRate = mParameters.getPreviewFrameRate();
-
- ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
- sp<MemoryHeapBase> heap = mPreviewHeap;
-
-
- Ov965xCamera* Ov965xCamera = mOv965xCamera;
-
- sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
-
- mLock.unlock();
-
- if (buffer != 0) {
-
- int delay = (int)(1000000.0f / float(previewFrameRate));
-
- void *base = heap->base();
-
- uint8_t *frame = ((uint8_t *)base) + offset;
-
-
- Ov965xCamera->getNextFrameAsRgb565((uint16_t *)frame);
-
- if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
- mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
-
- mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
-
- usleep(delay);
- }
- return NO_ERROR;
- }
- 硬件抽象层实现的取景器数据来自 Ov965xCamera,可以得到数据,并使用
- 回调函数CAMERA_MSG_PREVIEW_FRAME宏为参数将数据送向上层,这里使用
- mDataCb是上层CameraService,通过setCallbacks()函数设置。
- 其中mPreviewHeap存储着n个帧的缓冲,这块区域被分割为n个mBuffers。
- buffer为当前帧的引用,通过mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie)
- 就可以将buffer输出到屏幕。那每一个帧是怎么存到mPreviewHeap上的呢?
- 关键的一句就是Ov965xCamera->getNextFrameAsRgb565((uint16_t *)frame) ,
- 通过看它的实现可以知道(在Ov96xCamera.app中),一个帧的数据以16位的格式写入frame中,
- 这里的frame即是对mPreviewHeap上某个mBuffer的引用
- 调用--------->getNextFrameAsRgb565((uint16_t *)frame)
- void Ov965xCamera::getNextFrameAsRgb565(uint16_t *buffer)
- {
- int ret;
- unsigned long len;
- if (v4l2_fd != -1)
- {
- len = mWidth * mHeight*2;
- ret = read(v4l2_fd, buffer, len);
- }
- }
- --------------------------------------------------------
- setCallbacks()函数的实现
- void CameraHardware::setCallbacks(notify_callback notify_cb,
- data_callback data_cb,
- data_callback_timestamp data_cb_timestamp,
- void* user)
- {
- Mutex::Autolock lock(mLock);
- mNotifyCb = notify_cb;
- mDataCb = data_cb;
- mDataCbTimestamp = data_cb_timestamp;
- mCallbackCookie = user;
- }
-
- --------------->takePicture()函数在拍摄照片时被调用,它也保存了回调函数的指针,并建立了拍摄照片
- 的线程
- status_t CameraHardware::takePicture()
- {
- stopPreview();
- if (createThread(beginPictureThread, this) == false)
- return UNKNOWN_ERROR;
-
- return NO_ERROR;
- }
- 调用----------------->beginPictureThread()
- int CameraHardware::beginPictureThread(void *cookie)
- {
- CameraHardware *c = (CameraHardware *)cookie;
- return c->pictureThread();
- }
- 调用----------------->pictureThread()
- int CameraHardware::pictureThread()
- {
-
-
- if (mMsgEnabled & CAMERA_MSG_SHUTTER)
- mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
-
-
- if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
- int w, h;
- mParameters.getPictureSize(&w, &h);
- sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 2);
-
- Ov965xCamera cam(w, h);
- if (mCamType == CAMTYPE_CMOS)
- {
-
- cam.getNextFrameAsRgb565((uint16_t *)mRawHeap->base());
- LOGD("----------Taking picture using OV9650 CAM------");
- }
-
- mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
- }
-
-
- if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
- LOGE("%s, --------COMPRESSD IMAGE------", LOG_TAG);
-
- int w, h;
- unsigned int DATA_OFFSET = 54;
- uint16_t WIDTH = w;
- uint16_t HEIGHT = h;
-
- mParameters.getPictureSize(&w, &h);
- Ov965xCamera* Ov965xCamera = mOv965xCamera;
- sp<MemoryHeapBase> heap = new MemoryHeapBase(DATA_OFFSET + w * h * 2);
-
- sp<MemoryBase> mem = new MemoryBase(heap, 0, DATA_OFFSET + w * h * 2);
-
-
- uint8_t header[54] = {
- 0x42, 0x4d,
- 0, 0, 0, 0,
- 0, 0,
- 0, 0,
- 54, 0, 0, 0,
- 40, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 0,
- 16, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0
- };
-
-
- uint16_t file_size = WIDTH * HEIGHT * 2 + DATA_OFFSET;
- header[2] = (uint8_t)(file_size & 0x000000ff);
- header[3] = (file_size >> 8) & 0x000000ff;
- header[4] = (file_size >> 16) & 0x000000ff;
- header[5] = (file_size >> 24) & 0x000000ff;
-
-
- header[18] = HEIGHT & 0x000000ff;
- header[19] = (HEIGHT >> 8) & 0x000000ff;
- header[20] = (HEIGHT >> 16) & 0x000000ff;
- header[21] = (HEIGHT >> 24) & 0x000000ff;
-
-
- header[22] = WIDTH & 0x000000ff;
- header[23] = (WIDTH >> 8 ) & 0x000000ff;
- header[24] = (WIDTH >> 16) & 0x000000ff;
- header[25] = (WIDTH >> 24) & 0x000000ff;
-
-
-
- unsigned int i;
- for (i=0; i< DATA_OFFSET; i++){
- *((uint8_t *)heap->base() + i) = header[i];
- }
-
- Ov965xCamera->getNextFrameAsRgb565((uint16_t *)heap->base() + DATA_OFFSET/2);
-
- uint16_t *heap_base = (uint16_t *)heap->base();
- uint16_t pixel_data;
- uint8_t tail_data;
- for(i=DATA_OFFSET/2; i<DATA_OFFSET/2+WIDTH*HEIGHT; i++) {
- pixel_data = *(heap_base + i);
- tail_data = (uint8_t)(pixel_data & 0x001f);
- pixel_data = (pixel_data & 0xffc0)>>1 | tail_data;
- *(heap_base + i) = pixel_data;
- }
-
-
- mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
- heap = NULL;
- LOGE("%s, -----IMAGE SAVED-----", LOG_TAG);
- }
-
- return NO_ERROR;
- }
- -----------------------------------------------------------
- ---------------->autoFocus()
- status_t CameraHardware::autoFocus()
- {
- Mutex::Autolock lock(mLock);
- if (createThread(beginAutoFocusThread, this) == false)
- return UNKNOWN_ERROR;
- return NO_ERROR;
- }
- 调用-------------->beginAutoFocusThread()
- int CameraHardware::beginAutoFocusThread(void *cookie)
- {
- CameraHardware *c = (CameraHardware *)cookie;
- return c->autoFocusThread();
- }
- 调用-------------->autoFocusThread()
- int CameraHardware::autoFocusThread()
- {
- if (mMsgEnabled & CAMERA_MSG_FOCUS)
- mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
- return NO_ERROR;
- }
- ----------------------------------------------------------------
- 上面是实现的RGB565写成BMP格式的