打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
android camera HAL

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 pushlibcamera.so推到目标机/system/lib/

cd D:\software\android-sdk-windows\tools

d:

adb push libcamera.so /system/lib/

目标机上

export ANDROID_LOG_TAGS="CameraHardware:D CameraHardware:E *:S"

logcat -d

问题

拍照

E/AudioService( 1902): Media server died.

解决:在init.c中添加

chmod 0777 /dev/video0

二 CAMERA 系统

Camera系统分成以下几个部分

1)摄像头驱动程序:通常基于linuxvideo for linux视频驱动框架

2Camera硬件抽象层

接口的代码路径:frameworks/base/include/camera/

主要文件为CameraHardwareInterfacd.h,需要各个系统根据自己的情况实现

3)Camera服务部分

代码路径:frameworks/base/include/camera

Camera服务是Android系统中一个单独部分,通过调用Camera硬件抽象层来实现

4Camera的本地框架代码

代码路径:frameworks/base/include/camera

5CameraJNI代码

代码路径:frameworks/base/core/jni/android_hardware_Camera.cpp

提供给Java类的本地支持,也包含了反向调用java传递信息和数据功能

6Camera系统的Java

代码路径:frameworks/base/core/java/android/hardware/Camera.java

CameraJava层次的类为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硬件抽象层的三种业务

取景器preview(使用YUV原始数据格式,发送到视频输出设备)

S3C6410CameraHardware.cpp

  1. 1)在初始化过程中,建立preview的内存队列  
  2. void CameraHardware::initHeapLocked()  
  3. {  
  4.     // Create raw heap.  
  5.     int picture_width, picture_height;  
  6.     mParameters.getPictureSize(&picture_width, &picture_height);  
  7.     mRawHeap = new MemoryHeapBase(picture_width * picture_height * 2);  
  8.   
  9.     int preview_width, preview_height;  
  10.     mParameters.getPreviewSize(&preview_width, &preview_height);  
  11.      
  12.     int how_big = preview_width * preview_height*2;  
  13. }  
  14.   
  15. void CameraHardware::initDefaultParameters()  
  16. {  
  17.     CameraParameters p;  
  18.   
  19.     p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");  
  20.     p.setPreviewSize(320, 240);//大小为320*240  
  21.     p.setPreviewFrameRate(15);//帧率为15bps  
  22.   
  23.     p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_RGB565);//preview 的格式为RGB565  
  24.     p.set(CameraParameters::KEY_ROTATION, 0);//90  
  25.   
  26.     p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");  
  27.     p.setPictureSize(320, 240);  
  28.     p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);// SET OUTPUT PIC TO BMP FORMAT  
  29.   
  30.     if (setParameters(p) != NO_ERROR) {  
  31.         LOGE("Failed to set default parameters?!");  
  32.     }  
  33.       
  34. }  
  35. 2) 在startPreview()的实现中,建立preview线程  
  36. status_t CameraHardware::startPreview()  
  37. {  
  38.     Mutex::Autolock lock(mLock);  
  39.     if (mPreviewThread != 0) {  
  40.         return INVALID_OPERATION;  
  41.     }  
  42.     mPreviewThread = new PreviewThread(this);  
  43.     return NO_ERROR;  
  44. }  
  45. 3)在preview线程的循环中,等待视频数据的到达  
  46. int CameraHardware::previewThread()  
  47. {  
  48.     if(mCamType == CAMTYPE_CMOS)   
  49.             Ov965xCamera->getNextFrameAsRgb565((uint16_t *)frame);  
  50. 4)视频帧到达后使用preview回调的机制CAMERA_MSG_PREVIEW_FRAME,将视频  
  51. 帧向上层传送  
  52.  // Notify the client of a new frame.  
  53.         if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)  
  54.             mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);  
  55. B拍摄照片(可以使用原始数据或者压缩图像数据)  
  56. 1) takePicture()函数表示开始拍摄,可以建立单独的线程来处理  
  57. status_t CameraHardware::takePicture()  
  58. {  
  59.     stopPreview();  
  60.     if (createThread(beginPictureThread, this) == false)  
  61.         return UNKNOWN_ERROR;  
  62.     return NO_ERROR;  
  63. }  
  64.   
  65.  int CameraHardware::beginPictureThread(void *cookie)  
  66. {  
  67.     CameraHardware *c = (CameraHardware *)cookie;  
  68.     return c->pictureThread();  
  69. }  
  70.   
  71. int CameraHardware::pictureThread()  
  72. {  
  73.     if (mMsgEnabled & CAMERA_MSG_SHUTTER)  
  74.         mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);  
  75.   
  76.     if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {  
  77.         //FIXME: use a canned YUV image!  
  78.         // In the meantime just make another fake camera picture.  
  79.         int w, h;  
  80.         mParameters.getPictureSize(&w, &h);  
  81.         sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 2);  
  82.           
  83.         Ov965xCamera cam(w, h);  
  84.         //cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());  
  85.   
  86.         if(mCamType == CAMTYPE_CMOS)  
  87.         {  
  88.         cam.getNextFrameAsRgb565((uint16_t *)mRawHeap->base());        
  89.         }         
  90.         else if (mCamType == CAMTYPE_USB)  
  91.         {  
  92.             //USBCamera cam1(w, h);  
  93.         LOGE("%s, Taking picure using USB CAM", LOG_TAG);  
  94.         //cam.getNextFrameAsRgb565((uint16_t *)mRawHeap->base());              
  95.         //cam1.getNextFrameAsYuv420((uint16_t *)mRawHeap->base());         
  96.         }  
  97.         mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);  
  98.     }  
  99.   
  100.     // ToDo: Release MemoryHeapBase  
  101.     // ToDo: Convert BMP to JPEG  
  102.     // Todo: Higher Resultion Support  
  103.     if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {  
  104.     LOGE("%s, COMPRESSED IMAGE", LOG_TAG);  
  105.         int w, h;  
  106.     unsigned int DATA_OFFSET = 54;  
  107.         uint16_t WIDTH = w;  
  108.     uint16_t HEIGHT = h;  
  109.   
  110.         mParameters.getPictureSize(&w, &h);  
  111.     Ov965xCamera* Ov965xCamera = mOv965xCamera;   
  112.     sp<MemoryHeapBase> heap = new MemoryHeapBase(DATA_OFFSET+w * h* 2);  
  113.     sp<MemoryBase> mem = new MemoryBase(heap, 0, DATA_OFFSET+w * h* 2); //16 bits for one pixel  
  114.       
  115.       
  116.          
  117.         uint8_t header[54] = { 0x42, // identity : B  
  118.         0x4d, // identity : M  
  119.         0, 0, 0, 0, // file size  
  120.         0, 0, // reserved1  
  121.         0, 0, // reserved2  
  122.         54, 0, 0, 0, // RGB data offset  
  123.         40, 0, 0, 0, // struct BITMAPINFOHEADER size  
  124.         0, 0, 0, 0, // bmp height  
  125.         0, 0, 0, 0, // bmp width  
  126.         1, 0, // planes  
  127.         16, 0, // bit per pixel  
  128.         0, 0, 0, 0, // compression  
  129.         0, 0, 0, 0, // data size  
  130.         0, 0, 0, 0, // h resolution  
  131.         0, 0, 0, 0, // v resolution  
  132.         0, 0, 0, 0, // used colors  
  133.         0, 0, 0, 0 // important colors  
  134.         };  
  135.   
  136.         // file size offset 54  
  137.     uint16_t file_size = WIDTH * HEIGHT * 2 + DATA_OFFSET;  
  138.     header[2] = (uint8_t)(file_size & 0x000000ff);  
  139.     header[3] = (file_size >> 8) & 0x000000ff;  
  140.     header[4] = (file_size >> 16) & 0x000000ff;  
  141.     header[5] = (file_size >> 24) & 0x000000ff;  
  142.   
  143.     // height  
  144.     header[18] = HEIGHT & 0x000000ff;  
  145.     header[19] = (HEIGHT >> 8) & 0x000000ff;  
  146.     header[20] = (HEIGHT >> 16) & 0x000000ff;  
  147.     header[21] = (HEIGHT >> 24) & 0x000000ff;  
  148.   
  149.     // width  
  150.     header[22] = WIDTH & 0x000000ff;  
  151.     header[23] = (WIDTH >> 8) & 0x000000ff;  
  152.     header[24] = (WIDTH >> 16) & 0x000000ff;  
  153.     header[25] = (WIDTH >> 24) & 0x000000ff;  
  154.       
  155.     LOGE("%s, Header Ready", LOG_TAG);  
  156.   
  157.     unsigned int i;  
  158.     for(i=0;i<DATA_OFFSET;i++){  
  159.       *((uint8_t*)heap->base()+i)=header[i];  
  160.     }  
  161.       
  162.     Ov965xCamera->getNextFrameAsRgb565((uint16_t*)heap->base()+DATA_OFFSET/2);  
  163.       
  164.     uint16_t *heap_base = (uint16_t*)heap->base();  
  165.     uint16_t pixel_data;  
  166.     uint8_t tail_data;  
  167.     for(i=DATA_OFFSET/2;i<DATA_OFFSET/2+WIDTH*HEIGHT;i++){  
  168.       pixel_data = *(heap_base+i);  
  169.       tail_data = (uint8_t)(pixel_data & 0x001f);  
  170.       pixel_data = (pixel_data & 0xffc0)>>1 | tail_data;  
  171.       *(heap_base+i)=pixel_data;  
  172.     }  
  173.   
  174.   
  175.         mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);  
  176.     heap=NULL;  
  177.     LOGE("%s, IMAGE SAVED!", LOG_TAG);  
  178.     }  
  179.     return NO_ERROR;  
  180. }  

2)使用回调机制传送数据:如果得原始格式(通常是YUV的格式,如yuv422sp,这里是RGB565

的数据,使用CAMERA_MSG_RAW_IMAGE将数据传送;如果得到压缩图像(通常JPEG格式,这里是BMP

使用CAMERA_MSG_COMPRESSED_IMAGE将数据传送

视频录制(将数据传送给视频编码器程序)

1)在startRecording()的实现中,开始录制的准备,录制视频可以使用自己的线程,也可以使用

preview线程

2)当一个视频帧到来的时候,通过录制回调机制(使用CAMERA_MSG_VIDEO_FRAME)将视频帧向上

发送

3)releaseRecordingFrame()被调用后,表示上层通知Camera硬件抽象层,这一帧的内存已经用完

可以进行下一次的处理。

四 、 android camera HAL的改写

  1. 1. 修改BoardConfig.mk  
  2. USE_CAMERA_STUB := false  
  3. 2. hardware下建立Camera HAL目录  
  4. /hardware/ego/libcamera  
  5. 复制几个文件  
  6. cp ../../../frameworks/base/services/camera/libcameraservice/CameraHardwareStub.cpp  
  7. S3C6410CameraHardware.cpp  
  8. cp ../../../frameworks/base/services/camera/rks/base/services/camera/libcameraservice/CameraHardwareStub.h   
  9. S3C6410CameraHardware.h   
  10. cp ../../../frameworks/base/services/camera/libcameraservice/FakeCamera.cpp Ov965xCamera.cpp              
  11. cp ../../../frameworks/base/services/camera/libcameraservice/FakeCamera.h Ov965xCamera.h     
  12. 3. 编译Android.mk文件  
  13. LOCAL_PATH:= $(call my-dir)  
  14. include $(CLEAR_VARS)  
  15.   
  16. LOCAL_SRC_FILES:= \  
  17.     S3C6410CameraHardware.cpp   \  
  18.     Ov965xCamera.cpp  
  19.   
  20. LOCAL_SHARED_LIBRARIES:= \  
  21.     libui   \  
  22.     libutils    \  
  23.     libbinder   \  
  24.     liblog  \  
  25.     libcamera_client  
  26.   
  27. LOCAL_MODULE:= libcamera  
  28. LOCAL_MODULE_TAGS:= eng  
  29.   
  30. LOCAL_C_INCLUDES += \  
  31.     frameworks/base/libs  
  32.   
  33. include $(BUILD_SHARED_LIBRARY)  
  34.   
  35. 根据这个脚本可编译出libcamera.so  
  36. 4. 修改Ov965xCamera.cpp,该文件可以按照V4L2流程来写  
  37. 1)构造函数中进行初始化  
  38.   
  39. Ov965xCamera::Ov965xCamera(int width, int height)  
  40.           : mTmpRgb16Buffer(0)  
  41. {  
  42.     struct v4l2_format fmt;  
  43.     int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  44.       
  45.     v4l2_fd = open("/dev/video0", O_RDWR | O_SYNC);  
  46.     LOGE("open /dev/video0 fd is %d", v4l2_fd);  
  47.       
  48.     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  49.     fmt.fmt.pix.width = width;  
  50.     fmt.fmt.pix.height = height;  
  51.     fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;  
  52.       
  53.     ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt);  
  54.     ioctl(v4l2_fd, VIDIOC_STREAMON, &type);  
  55.     setSize(width, height);  
  56. }  
  57. -------->调用setSize()  
  58.   
  59. 5. 修改S3C6410CameraHardware.cpp  
  60. //参数设置  
  61. void CameraHardware::initDefaultParameters()  
  62. {  
  63.       
  64.     CameraParameters p;  
  65.     //设置preview大小  
  66.     p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");  
  67.     p.setPreviewSize(320, 240);  
  68.     //设置帧率  
  69.     p.setPreviewFrameRate(15);  
  70.     p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_RGB565);  
  71.     p.set(CameraParameters::KEY_ROTATION, 0);  
  72.       
  73.     p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");  
  74.     p.setPictureSize(320, 240);  
  75.     p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);  
  76.       
  77.     if (setParameters(p) != NO_ERROR) {  
  78.         LOGE("Failed to set default parameters!");  
  79.     }  
  80. }  
  81.   
  82. 调用----->setParameters(p)  
  83. status_t CameraHardware::setParameters(const CameraParameters& params)  
  84. {  
  85.     Mutex::Autolock lock(mLock);  
  86.       
  87.     if (strcmp(params.getPreviewFormat(),  
  88.             CameraParameters::PIXEL_FORMAT_RGB565) != 0) {  
  89.             LOGE("Only rgb565 preview is supported");  
  90.             return -1;  
  91.             }  
  92.               
  93.     if (strcmp(params.getPictureFormat(),  
  94.             CameraParameters::PIXEL_FORMAT_JPEG) != 0) {  
  95.             LOGE("Only jpeg still pictures are supported");  
  96.             return -1;  
  97.             }  
  98.       
  99.     int w, h;  
  100.     params.getPictureSize(&w, &h);  
  101.       
  102.     mParameters = params;  
  103.     initHeapLocked();  
  104.       
  105.     return NO_ERROR;  
  106. }  
  107.   
  108. 调用----->initHeapLocked();  
  109. void CameraHardware::initHeapLocked()  
  110. {  
  111.     int picture_width, picture_height;  
  112.     mParameters.getPictureSize(&picture_width, &picture_height);  
  113.     //建立内存堆  
  114.     mRawHeap = new MemoryHeapBase(picture_width * picture_height * 2);  
  115.       
  116.     //从参数中获取信息  
  117.     int preview_width, preview_height;  
  118.     mParameters.getPreviewSize(&preview_width, &preview_height);  
  119.     LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);  
  120.       
  121.     int how_big = preview_width * preview_height * 2;  
  122.     mPreviewFrameSize = how_big;  
  123.     //制作新mmap'ed的堆,可以跨进程共享。  
  124.     mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);  
  125.     //建立内存队列kBufferCount 4个  
  126.     for (int i = 0; i < kBufferCount; i++) {  
  127.         mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize);  
  128.           
  129.     }  
  130.       
  131.     if (mOv965xCamera != 0)  
  132.     {  
  133.         LOGD("delete mOv965xCamera");  
  134.         delete mOv965xCamera;  
  135.         mOv965xCamera = 0;  
  136.     }  
  137.     else if(mCamType == CAMTYPE_CMOS)  
  138.     {  
  139.         LOGD("new mOv965xCamera");  
  140.         mOv965xCamera = new Ov965xCamera(preview_width, preview_height);  
  141.     }  
  142. }  
  143. 在这个过程中,建立了两块内存(MemoryHeapBase): mRawHeap 表示一个拍照照片的内存  
  144. mPreviewHeap表示取景preview的内存,由于取景器preview的内容是一个队列,因此在  
  145. mPreviewHeap中建立kBufferCount(为4个)MemoryBase  
  146. new Ov965xCamera作为摄像头输入数据的来源  
  147.   
  148. CameraService.cpp调用----------->startPreview()  
  149. status_t CameraHardware::startPreview()  
  150. {  
  151.     Mutex::Autolock lock(mLock);  
  152.     if (mPreviewThread != 0) {  
  153.         return INVALID_OPERATION;  
  154.     }  
  155.       
  156.     //建立视频preview的线程  
  157.     mPreviewThread = new PreviewThread(this);  
  158.       
  159.     return NO_ERROR;  
  160. }  
  161.   
  162. 调用----------->PreviewThread()  
  163. 在PreviewThread线程中通过调用preview的回调机制,实现preview  
  164. 数据的数据传递给上层就是CameraService  
  165. int CameraHardware::previewThread()  
  166. {  
  167.     mLock.lock();  
  168.       
  169.     int previewFrameRate = mParameters.getPreviewFrameRate();  
  170.     //获取内存偏移  
  171.     ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;  
  172.     sp<MemoryHeapBase> heap = mPreviewHeap;  
  173.       
  174.     //获得Ov965xCamera类  
  175.     Ov965xCamera* Ov965xCamera = mOv965xCamera;  
  176.       
  177.     sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];  
  178.       
  179.     mLock.unlock();  
  180.       
  181.     if (buffer != 0) {  
  182.         //计算帧之间等待多久  
  183.         int delay = (int)(1000000.0f / float(previewFrameRate));  
  184.         //获得内存地址  
  185.         void *base = heap->base();  
  186.         //获得视频帧  
  187.         uint8_t *frame = ((uint8_t *)base) + offset;  
  188.   
  189.         //获取一个帧的数据,放入frame  
  190.         Ov965xCamera->getNextFrameAsRgb565((uint16_t *)frame);  
  191.         //通知客户端的一个新的一帧,调用Callback向上层发送数据  
  192.         if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)  
  193.             mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);  
  194.         //推进缓冲区指针     
  195.         mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;  
  196.           
  197.         usleep(delay);  
  198.     }  
  199.     return NO_ERROR;  
  200. }  
  201. 硬件抽象层实现的取景器数据来自 Ov965xCamera,可以得到数据,并使用  
  202. 回调函数CAMERA_MSG_PREVIEW_FRAME宏为参数将数据送向上层,这里使用  
  203. mDataCb是上层CameraService,通过setCallbacks()函数设置。  
  204. 其中mPreviewHeap存储着n个帧的缓冲,这块区域被分割为n个mBuffers。  
  205. buffer为当前帧的引用,通过mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie)  
  206. 就可以将buffer输出到屏幕。那每一个帧是怎么存到mPreviewHeap上的呢?  
  207. 关键的一句就是Ov965xCamera->getNextFrameAsRgb565((uint16_t *)frame) ,  
  208. 通过看它的实现可以知道(在Ov96xCamera.app中),一个帧的数据以16位的格式写入frame中,  
  209. 这里的frame即是对mPreviewHeap上某个mBuffer的引用  
  210. 调用--------->getNextFrameAsRgb565((uint16_t *)frame)  
  211. void Ov965xCamera::getNextFrameAsRgb565(uint16_t *buffer)  
  212. {  
  213.     int ret;  
  214.     unsigned long len;  
  215.     if (v4l2_fd != -1)  
  216.     {  
  217.         len = mWidth * mHeight*2;  
  218.         ret = read(v4l2_fd, buffer, len);  
  219.     }  
  220. }  
  221. --------------------------------------------------------  
  222. setCallbacks()函数的实现  
  223. void CameraHardware::setCallbacks(notify_callback notify_cb,  
  224.                                     data_callback data_cb,  
  225.                                     data_callback_timestamp data_cb_timestamp,  
  226.                                     void* user)  
  227. {  
  228.     Mutex::Autolock lock(mLock);  
  229.     mNotifyCb = notify_cb;//通知回调  
  230.     mDataCb = data_cb;//数据回调  
  231.     mDataCbTimestamp = data_cb_timestamp;  
  232.     mCallbackCookie = user;  
  233. }  
  234.   
  235. --------------->takePicture()函数在拍摄照片时被调用,它也保存了回调函数的指针,并建立了拍摄照片  
  236. 的线程  
  237. status_t CameraHardware::takePicture()  
  238. {  
  239.     stopPreview();  
  240.     if (createThread(beginPictureThread, this) == false)  
  241.         return UNKNOWN_ERROR;  
  242.       
  243.     return NO_ERROR;  
  244. }  
  245. 调用----------------->beginPictureThread()  
  246. int CameraHardware::beginPictureThread(void *cookie)  
  247. {  
  248.     CameraHardware *c = (CameraHardware *)cookie;  
  249.     return c->pictureThread();  
  250. }  
  251. 调用----------------->pictureThread()  
  252. int CameraHardware::pictureThread()  
  253. {  
  254.   
  255.     //快门回调机制  
  256.     if (mMsgEnabled & CAMERA_MSG_SHUTTER)  
  257.         mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);  
  258.       
  259.     //传送原始数据的处理  
  260.     if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {  
  261.         int w, h;  
  262.         mParameters.getPictureSize(&w, &h);  
  263.         sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 2);  
  264.           
  265.         Ov965xCamera cam(w, h);  
  266.         if (mCamType == CAMTYPE_CMOS)  
  267.         {  
  268.             //获得指针  
  269.             cam.getNextFrameAsRgb565((uint16_t *)mRawHeap->base());  
  270.             LOGD("----------Taking picture using OV9650 CAM------");  
  271.         }  
  272.         //传送数据  
  273.         mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);  
  274.     }  
  275.       
  276.     //传送JPEG数据的处理  
  277.     if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {  
  278.         LOGE("%s, --------COMPRESSD IMAGE------", LOG_TAG);  
  279.         //step1 首先申请BMP暂存区:  
  280.         int w, h;  
  281.         unsigned int DATA_OFFSET = 54;  
  282.         uint16_t WIDTH  = w;  
  283.         uint16_t HEIGHT = h;  
  284.           
  285.         mParameters.getPictureSize(&w, &h);  
  286.         Ov965xCamera* Ov965xCamera = mOv965xCamera;  
  287.         sp<MemoryHeapBase> heap = new MemoryHeapBase(DATA_OFFSET + w * h * 2);  
  288.         //一个像素6位  
  289.         sp<MemoryBase> mem = new MemoryBase(heap, 0, DATA_OFFSET + w * h * 2);  
  290.           
  291.         //写BMP文件头  
  292.         uint8_t header[54] = {  
  293.         0x42, 0x4d,//BM  
  294.         0, 0, 0, 0, //file size  
  295.         0, 0, //reserved1  
  296.         0, 0, //reserved2  
  297.         54, 0, 0, 0, //RGB data offset  
  298.         40, 0, 0, 0, //struct BITMAPINFOHEADER size  
  299.         0, 0, 0, 0,//bmp height  
  300.         0, 0, 0, 0, //bmp width  
  301.         1, 0, //planes  
  302.         16, 0, //一个像素16位  
  303.         0, 0, 0, 0,//压缩  
  304.         0, 0, 0, 0,//data size  
  305.         0, 0, 0, 0,//h resolution  
  306.         0, 0, 0, 0,//v resolution  
  307.         0, 0, 0, 0,//used colors  
  308.         0, 0, 0, 0//important colors  
  309.         };  
  310.       
  311.     //file size offset 54  
  312.     uint16_t file_size = WIDTH * HEIGHT * 2 + DATA_OFFSET;  
  313.     header[2] = (uint8_t)(file_size & 0x000000ff);  
  314.     header[3] = (file_size >> 8)  & 0x000000ff;  
  315.     header[4] = (file_size >> 16) & 0x000000ff;  
  316.     header[5] = (file_size >> 24) & 0x000000ff;  
  317.       
  318.     //height  
  319.     header[18] = HEIGHT & 0x000000ff;  
  320.     header[19] = (HEIGHT >> 8) & 0x000000ff;  
  321.     header[20] = (HEIGHT >> 16) & 0x000000ff;  
  322.     header[21] = (HEIGHT >> 24) & 0x000000ff;  
  323.       
  324.     //width  
  325.     header[22] = WIDTH & 0x000000ff;  
  326.     header[23] = (WIDTH >> 8 ) & 0x000000ff;  
  327.     header[24] = (WIDTH >> 16) & 0x000000ff;  
  328.     header[25] = (WIDTH >> 24) & 0x000000ff;  
  329.       
  330.     //step2 获取当前帧,进行RGB565到RGB555的转换,将转换后的  
  331.     //数据放入MemoryHeap中  
  332.     unsigned int i;  
  333.     for (i=0; i< DATA_OFFSET; i++){  
  334.         *((uint8_t *)heap->base() + i) = header[i];  
  335.     }  
  336.       
  337.     Ov965xCamera->getNextFrameAsRgb565((uint16_t *)heap->base() + DATA_OFFSET/2);  
  338.       
  339.     uint16_t *heap_base = (uint16_t *)heap->base();  
  340.     uint16_t pixel_data;  
  341.     uint8_t tail_data;  
  342.     for(i=DATA_OFFSET/2; i<DATA_OFFSET/2+WIDTH*HEIGHT; i++) {  
  343.         pixel_data = *(heap_base + i);  
  344.         tail_data = (uint8_t)(pixel_data & 0x001f);  
  345.         pixel_data = (pixel_data & 0xffc0)>>1 | tail_data;  
  346.         *(heap_base + i) = pixel_data;  
  347.     }  
  348.     //step3 调用callback,将数据存储到设备,并释放MemoryHeap  
  349.       
  350.     mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);  
  351.     heap = NULL;  
  352.     LOGE("%s, -----IMAGE SAVED-----", LOG_TAG);  
  353.     }  
  354.   
  355.     return NO_ERROR;  
  356. }  
  357. -----------------------------------------------------------  
  358. ---------------->autoFocus()  
  359. status_t CameraHardware::autoFocus()  
  360. {  
  361.     Mutex::Autolock lock(mLock);  
  362.     if (createThread(beginAutoFocusThread, this) == false)  
  363.         return UNKNOWN_ERROR;  
  364.     return NO_ERROR;  
  365. }  
  366. 调用-------------->beginAutoFocusThread()  
  367. int CameraHardware::beginAutoFocusThread(void *cookie)  
  368. {  
  369.     CameraHardware *c = (CameraHardware *)cookie;  
  370.     return c->autoFocusThread();  
  371. }  
  372. 调用-------------->autoFocusThread()  
  373. int CameraHardware::autoFocusThread()  
  374. {  
  375.     if (mMsgEnabled & CAMERA_MSG_FOCUS)  
  376.         mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);  
  377.     return NO_ERROR;  
  378. }  
  379. ----------------------------------------------------------------  
  380. 上面是实现的RGB565写成BMP格式的 
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Android照相功能驱动层中HAL的实现(基于OK6410开发板+OV9650摄像头)
【转】Android Camera架构浅析
Android Camera 架构简析2
Android Camera Subsystem 架构(Binder机制)及显示分析
camerahalportingrecorder131204.txt
Android Camera HAL设计初步
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服