camera小結

 
今年這兩個月,一直都在搞camera。android的camera模塊應該是比較熟悉了,剛好項目搞完,這裏做一下總結。
 
camera是相機或平板必備的一個功能模塊,拍照,錄像確實很實用。
android 的 camera 分驅動層,HAL層,APP層。
底層一般都用V4L2封裝,這樣HAL可以通過V4L2標準接口對底層進行調用,讀取數據。然後傳給APP。
 
USB接口的camera module 一般都會支持UVC標準,UVC- USB Video Class。這種模塊一般都由一個感光sensor + controller 組成。 這個controller 一般都會自帶firmware。
 
拍照和錄像裏面有很多parameter setting. white balance, color effect, picture quality, video quality 等等。 這些都可以通過V4L2的標準IOCTL接口實現。
 
previewthread() 這個線程最重要,所有的功能都圍繞這個線程工作。
 
camera模塊不算太難,也不深,感覺還是挺簡單的。這是我做android的第一個模塊,下個項目要搞PMIC了,這模塊會比較難,也比較深,涉及東西很多,搞懂了應該就成牛人了~

take picture 過程分析

這兩天一直在調拍照,由於之前拍照照片的格式只支持VGA以下的,我拿我的pad一看,居然可以支持5M和1.3M,也就是前後攝像頭的最大分辨率。這讓我想到肯定是軟件沒做好,有待改善,然後這兩天有空,就調了調。終於調出來了,一直卡在死鎖狀態。
由於軟件功底不夠,對於鎖,沒什麼概念,還好最後還是搞出來了,過程真是痛苦啊。。


流程如下:
首先cameraservice 會調用  takepicture()。

  1. status_t CameraHardwareStub::takePicture()  
  2. {  
  3.     disableMsgType(CAMERA_MSG_PREVIEW_FRAME);  
  4.     if (createThread(beginPictureThread, this) == false)  
  5.         return UNKNOWN_ERROR;  
  6.     return NO_ERROR;  
  7. }  
status_t CameraHardwareStub::takePicture()
{
    disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
    if (createThread(beginPictureThread, this) == false)
        return UNKNOWN_ERROR;
    return NO_ERROR;
}
  1. /*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)  
  2. {  
  3.     CameraHardwareStub *c = (CameraHardwareStub *)cookie;  
  4.     return c->pictureThread();  
  5. }  
/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
{
    CameraHardwareStub *c = (CameraHardwareStub *)cookie;
    return c->pictureThread();
}
  1. int CameraHardwareStub::pictureThread()  
  2. {  
  3.     int picture_width, picture_height;  
  4.     mParameters.getPictureSize(&picture_width, &picture_height);  
  5.     LOGD("picture size=%dx%d", picture_width, picture_height);  
  6.   
  7.     if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {  
  8.         LOGE("Take Picture COMPRESSED IMAGE");  
  9.   
  10.         /* 
  11.          * The takePicture() function called by the CameraService 
  12.          * must return synchronously without attempting to wait 
  13.          * for any locks, to prevent circular deadlocking in 
  14.          * attempting to call CameraService callbacks to deliver 
  15.          * frames. This includes waiting for the preview thread 
  16.          * to finish cleanly. So stopping the preview thread 
  17.          * is done in this separate pictureThread 
  18.          */  
  19.   
  20.         sp<PreviewThread> previewThread;  
  21.   
  22.         {  
  23.             Mutex::Autolock lock(mLock);  
  24.             previewThread = mPreviewThread;  
  25.         }  
  26.   
  27.         if (previewThread != 0) {  
  28.             previewThread->requestExitAndWait();  
  29.             Mutex::Autolock lock(mLock);  
  30.             mPreviewThread.clear();  
  31.         }  
  32.           
  33.         mFakeCamera->Uninit();  
  34.         mFakeCamera->StopStreaming(); //卸載掉preview 內存。   
  35.           
  36.         {  
  37.             mPictureLock.lock();  
  38.             mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mFakeCamera->GrabJpegFrame(picture_width, picture_height), mCallbackCookie);  
  39.             mPictureLock.unlock();  
  40.         }  
  41.     }  
  42.     return NO_ERROR;  
  43. }  
int CameraHardwareStub::pictureThread()
{
    int picture_width, picture_height;
    mParameters.getPictureSize(&picture_width, &picture_height);
    LOGD("picture size=%dx%d", picture_width, picture_height);

    if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
        LOGE("Take Picture COMPRESSED IMAGE");

        /*
         * The takePicture() function called by the CameraService
         * must return synchronously without attempting to wait
         * for any locks, to prevent circular deadlocking in
         * attempting to call CameraService callbacks to deliver
         * frames. This includes waiting for the preview thread
         * to finish cleanly. So stopping the preview thread
         * is done in this separate pictureThread
         */

        sp<PreviewThread> previewThread;

        {
            Mutex::Autolock lock(mLock);
            previewThread = mPreviewThread;
        }

        if (previewThread != 0) {
            previewThread->requestExitAndWait();
            Mutex::Autolock lock(mLock);
            mPreviewThread.clear();
        }
        
        mFakeCamera->Uninit();
        mFakeCamera->StopStreaming(); //卸載掉preview 內存。
        
        {
            mPictureLock.lock();
            mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mFakeCamera->GrabJpegFrame(picture_width, picture_height), mCallbackCookie);
            mPictureLock.unlock();
        }
    }
    return NO_ERROR;
}
GrabJpegFrame 會具體執行拍照功能。

  1. sp<IMemory> V4L2Camera::GrabJpegFrame (int pic_width, int pic_height)  
  2. {  
  3.     FILE *output;  
  4.     FILE *input;  
  5.     int fileSize;  
  6.     int ret, i;  
  7.   
  8.     int w, h;  
  9.     struct v4l2_buffer v4l2_buf_picture;  
  10.     struct v4l2_format format;  
  11.     struct v4l2_streamparm parm;  
  12.     struct v4l2_requestbuffers reqbuf;  
  13.     sp<MemoryHeapBase> rawPictureHeap;  
  14.     sp<MemoryHeapBase> mjpegPictureHeap;  
  15.     sp<MemoryBase> jpegMemBase;  
  16.   
  17.     /* VIDIOC_S_FMT */  
  18.     memset(&format, 0, sizeof(format));  
  19.     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  20.     format.fmt.pix.width = pic_width;  
  21.     format.fmt.pix.height = pic_height;  
  22.     format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;  
  23.     if (ioctl(fd, VIDIOC_S_FMT, &format) < 0)  
  24.     {  
  25.         LOGE("Error: VIDIOC_S_FMT");  
  26.         goto done;  
  27.     }  
  28.   
  29.     /* VIDIOC_S_PARM */  
  30.     memset(&parm, 0, sizeof(parm));  
  31.     parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  32.     parm.parm.capture.timeperframe.numerator = 2;  
  33.     parm.parm.capture.timeperframe.denominator = 15;  
  34.     if (ioctl(fd, VIDIOC_S_PARM, &parm) < 0)  
  35.     {  
  36.         LOGE("Error: VIDIOC_S_PARM");  
  37.         goto done;  
  38.     }  
  39.   
  40.     /* VIDIOC_REQBUFS */  
  41.     memset(&reqbuf, 0, sizeof(reqbuf));  
  42.     reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  43.     reqbuf.memory = V4L2_MEMORY_MMAP;  
  44.     reqbuf.count = 1;  
  45.     if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0)  
  46.     {  
  47.         LOGE ("Error: VIDIOC_REQBUFS");  
  48.         goto done;  
  49.     }  
  50.   
  51.     memset(&v4l2_buf_picture, 0, sizeof(v4l2_buf_picture));  
  52.     v4l2_buf_picture.index = 0;  
  53.     v4l2_buf_picture.type = reqbuf.type;  
  54.     if (ioctl(fd, VIDIOC_QUERYBUF, &v4l2_buf_picture) < 0)  
  55.     {  
  56.         LOGE("Error: VIDIOC_QUERYBUF");  
  57.         goto done;  
  58.     }  
  59.   
  60.     /* use MemoryHeapBase to do mmap */  
  61.     rawPictureHeap = new MemoryHeapBase(fd,  
  62.             v4l2_buf_picture.length, 0, v4l2_buf_picture.m.offset);  
  63.     if (rawPictureHeap == NULL)  
  64.     {  
  65.         LOGE("Error: Cannot create rawPictureHeap");  
  66.         goto done;  
  67.     }  
  68.   
  69.     /* VIDIOC_QBUF */  
  70.     if (ioctl(fd, VIDIOC_QBUF, &v4l2_buf_picture) < 0)  
  71.     {  
  72.         LOGE("Error: VIDIOC_QBUF");  
  73.     }  
  74.     StartStreaming();  
  75.   
  76.     for(i = 0; i < PICTURE_FRAME_GRAB_COUNT; i++){  
  77.         /* get one frame from camera */  
  78.         if (ioctl(fd, VIDIOC_DQBUF, &v4l2_buf_picture) < 0){  
  79.             LOGE("Error: VIDIOC_DQBUF");  
  80.             goto done;  
  81.         }  
  82.         if((ioctl(fd, VIDIOC_QBUF, &v4l2_buf_picture)) < 0){  
  83.             LOGE("Error: VIDIOC_QBUF = %d:%d", ret, errno);  
  84.         }  
  85.         usleep(50*1000);  
  86.     }  
  87.       
  88.     output = fopen("/data/tmp.jpg""wb");  
  89.   
  90.     if (output == NULL) {  
  91.         LOGE("GrabJpegFrame: Ouput file == NULL");  
  92.         return NULL;  
  93.     }  
  94.   
  95.     fileSize = saveYUYVtoJPEG((unsigned char *)rawPictureHeap->getBase(), pic_width, pic_height, output, 85);  
  96.   
  97.     fclose(output);  
  98.   
  99.     input = fopen("/data/tmp.jpg""rb");  
  100.   
  101.     if (input == NULL)  
  102.         LOGE("GrabJpegFrame: Input file == NULL");  
  103.     else {  
  104.         mjpegPictureHeap = new MemoryHeapBase(fileSize);  
  105.         jpegMemBase = new MemoryBase(mjpegPictureHeap, 0, fileSize);  
  106.   
  107.         fread((uint8_t *)mjpegPictureHeap->base(), 1, fileSize, input);  
  108.         fclose(input);  
  109.   
  110.         rawPictureHeap.clear();  
  111.         StopStreaming();  
  112.         return jpegMemBase;  
  113.     }  
  114.   
  115. done:  
  116.     rawPictureHeap.clear();  
  117.     StopStreaming();  
  118.     return NULL;  
  119. }  
  120.   
  121. int V4L2Camera::saveYUYVtoJPEG (unsigned char *inputBuffer, int width, int height, FILE *file, int quality)  
  122. {  
  123.     struct jpeg_compress_struct cinfo;  
  124.     struct jpeg_error_mgr jerr;  
  125.     JSAMPROW row_pointer[1];  
  126.     unsigned char *line_buffer, *yuyv;  
  127.     int z;  
  128.     int fileSize;  
  129.   
  130.     line_buffer = (unsigned char *) calloc (width * 3, 1);  
  131.     yuyv = inputBuffer;  
  132.   
  133.     cinfo.err = jpeg_std_error (&jerr);  
  134.     jpeg_create_compress (&cinfo);  
  135.     jpeg_stdio_dest (&cinfo, file);  
  136.   
  137.     LOGI("JPEG PICTURE WIDTH AND HEIGHT: %dx%d", width, height);  
  138.   
  139.     cinfo.image_width = width;  
  140.     cinfo.image_height = height;  
  141.     cinfo.input_components = 3;  
  142.     cinfo.in_color_space = JCS_RGB;  
  143.   
  144.     jpeg_set_defaults (&cinfo);  
  145.     jpeg_set_quality (&cinfo, quality, TRUE);  
  146.   
  147.     jpeg_start_compress (&cinfo, TRUE);  
  148.   
  149.     z = 0;  
  150.     while (cinfo.next_scanline < cinfo.image_height) {  
  151.         int x;  
  152.         unsigned char *ptr = line_buffer;  
  153.   
  154.         for (x = 0; x < width; x++) {  
  155.             int r, g, b;  
  156.             int y, u, v;  
  157.   
  158.             if (!z)  
  159.                 y = yuyv[0] << 8;  
  160.             else  
  161.                 y = yuyv[2] << 8;  
  162.   
  163.             u = yuyv[1] - 128;  
  164.             v = yuyv[3] - 128;  
  165.   
  166.             r = (y + (359 * v)) >> 8;  
  167.             g = (y - (88 * u) - (183 * v)) >> 8;  
  168.             b = (y + (454 * u)) >> 8;  
  169.   
  170.             *(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);  
  171.             *(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);  
  172.             *(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);  
  173.   
  174.             if (z++) {  
  175.                 z = 0;  
  176.                 yuyv += 4;  
  177.             }  
  178.         }  
  179.   
  180.         row_pointer[0] = line_buffer;  
  181.         jpeg_write_scanlines (&cinfo, row_pointer, 1);  
  182.     }  
  183.   
  184.     jpeg_finish_compress (&cinfo);  
  185.     fileSize = ftell(file);  
  186.     jpeg_destroy_compress (&cinfo);  
  187.   
  188.     free (line_buffer);  
  189.   
  190.     return fileSize;  
  191. }  
sp<IMemory> V4L2Camera::GrabJpegFrame (int pic_width, int pic_height)
{
    FILE *output;
    FILE *input;
    int fileSize;
    int ret, i;

    int w, h;
    struct v4l2_buffer v4l2_buf_picture;
    struct v4l2_format format;
    struct v4l2_streamparm parm;
    struct v4l2_requestbuffers reqbuf;
    sp<MemoryHeapBase> rawPictureHeap;
    sp<MemoryHeapBase> mjpegPictureHeap;
    sp<MemoryBase> jpegMemBase;

    /* VIDIOC_S_FMT */
    memset(&format, 0, sizeof(format));
    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    format.fmt.pix.width = pic_width;
    format.fmt.pix.height = pic_height;
    format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
    if (ioctl(fd, VIDIOC_S_FMT, &format) < 0)
    {
        LOGE("Error: VIDIOC_S_FMT");
        goto done;
    }

    /* VIDIOC_S_PARM */
    memset(&parm, 0, sizeof(parm));
    parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    parm.parm.capture.timeperframe.numerator = 2;
    parm.parm.capture.timeperframe.denominator = 15;
    if (ioctl(fd, VIDIOC_S_PARM, &parm) < 0)
    {
        LOGE("Error: VIDIOC_S_PARM");
        goto done;
    }

    /* VIDIOC_REQBUFS */
    memset(&reqbuf, 0, sizeof(reqbuf));
    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf.memory = V4L2_MEMORY_MMAP;
    reqbuf.count = 1;
    if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0)
    {
        LOGE ("Error: VIDIOC_REQBUFS");
        goto done;
    }

    memset(&v4l2_buf_picture, 0, sizeof(v4l2_buf_picture));
    v4l2_buf_picture.index = 0;
    v4l2_buf_picture.type = reqbuf.type;
    if (ioctl(fd, VIDIOC_QUERYBUF, &v4l2_buf_picture) < 0)
    {
        LOGE("Error: VIDIOC_QUERYBUF");
        goto done;
    }

    /* use MemoryHeapBase to do mmap */
    rawPictureHeap = new MemoryHeapBase(fd,
            v4l2_buf_picture.length, 0, v4l2_buf_picture.m.offset);
    if (rawPictureHeap == NULL)
    {
        LOGE("Error: Cannot create rawPictureHeap");
        goto done;
    }

    /* VIDIOC_QBUF */
    if (ioctl(fd, VIDIOC_QBUF, &v4l2_buf_picture) < 0)
    {
        LOGE("Error: VIDIOC_QBUF");
    }
    StartStreaming();

    for(i = 0; i < PICTURE_FRAME_GRAB_COUNT; i++){
        /* get one frame from camera */
        if (ioctl(fd, VIDIOC_DQBUF, &v4l2_buf_picture) < 0){
            LOGE("Error: VIDIOC_DQBUF");
            goto done;
        }
        if((ioctl(fd, VIDIOC_QBUF, &v4l2_buf_picture)) < 0){
            LOGE("Error: VIDIOC_QBUF = %d:%d", ret, errno);
        }
        usleep(50*1000);
    }
    
    output = fopen("/data/tmp.jpg", "wb");

    if (output == NULL) {
        LOGE("GrabJpegFrame: Ouput file == NULL");
        return NULL;
    }

    fileSize = saveYUYVtoJPEG((unsigned char *)rawPictureHeap->getBase(), pic_width, pic_height, output, 85);

    fclose(output);

    input = fopen("/data/tmp.jpg", "rb");

    if (input == NULL)
        LOGE("GrabJpegFrame: Input file == NULL");
    else {
        mjpegPictureHeap = new MemoryHeapBase(fileSize);
        jpegMemBase = new MemoryBase(mjpegPictureHeap, 0, fileSize);

        fread((uint8_t *)mjpegPictureHeap->base(), 1, fileSize, input);
        fclose(input);

        rawPictureHeap.clear();
        StopStreaming();
        return jpegMemBase;
    }

done:
    rawPictureHeap.clear();
    StopStreaming();
    return NULL;
}

int V4L2Camera::saveYUYVtoJPEG (unsigned char *inputBuffer, int width, int height, FILE *file, int quality)
{
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    JSAMPROW row_pointer[1];
    unsigned char *line_buffer, *yuyv;
    int z;
    int fileSize;

    line_buffer = (unsigned char *) calloc (width * 3, 1);
    yuyv = inputBuffer;

    cinfo.err = jpeg_std_error (&jerr);
    jpeg_create_compress (&cinfo);
    jpeg_stdio_dest (&cinfo, file);

    LOGI("JPEG PICTURE WIDTH AND HEIGHT: %dx%d", width, height);

    cinfo.image_width = width;
    cinfo.image_height = height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;

    jpeg_set_defaults (&cinfo);
    jpeg_set_quality (&cinfo, quality, TRUE);

    jpeg_start_compress (&cinfo, TRUE);

    z = 0;
    while (cinfo.next_scanline < cinfo.image_height) {
        int x;
        unsigned char *ptr = line_buffer;

        for (x = 0; x < width; x++) {
            int r, g, b;
            int y, u, v;

            if (!z)
                y = yuyv[0] << 8;
            else
                y = yuyv[2] << 8;

            u = yuyv[1] - 128;
            v = yuyv[3] - 128;

            r = (y + (359 * v)) >> 8;
            g = (y - (88 * u) - (183 * v)) >> 8;
            b = (y + (454 * u)) >> 8;

            *(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);
            *(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);
            *(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);

            if (z++) {
                z = 0;
                yuyv += 4;
            }
        }

        row_pointer[0] = line_buffer;
        jpeg_write_scanlines (&cinfo, row_pointer, 1);
    }

    jpeg_finish_compress (&cinfo);
    fileSize = ftell(file);
    jpeg_destroy_compress (&cinfo);

    free (line_buffer);

    return fileSize;
}
下面這個函數,可以查詢攝像頭模塊支持哪些照片的尺寸:
  1. String8 V4L2Camera::GetSupportPictureSize(int fd, int pixelformat, int &w, int &h)  
  2. {  
  3.     LOGD("%s", __func__);  
  4.     String8 size_list;  
  5.     struct v4l2_frmsizeenum framesize_enum;  
  6.     memset(&framesize_enum, 0, sizeof(framesize_enum));  
  7.     framesize_enum.index = 0;  
  8.     framesize_enum.pixel_format = pixelformat;  
  9.     int ret = ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &framesize_enum);  
  10.     if (ret < 0) {  
  11.         LOGE("Error: VIDIOC_ENUM_FRAMESIZES - %s", strerror(errno));  
  12.         return size_list;  
  13.     }  
  14.     switch(framesize_enum.type)  
  15.     {  
  16.         case V4L2_FRMSIZE_TYPE_DISCRETE:  
  17.             do {  
  18.             if (framesize_enum.index) {  
  19.                 w = framesize_enum.discrete.width;  
  20.                 h = framesize_enum.discrete.height;  
  21.             }  
  22.             size_list.appendFormat(  
  23.                     framesize_enum.index ? ",%dx%d" : "%dx%d",  
  24.                     framesize_enum.discrete.width,  
  25.                     framesize_enum.discrete.height);  
  26.             framesize_enum.index++;  
  27.             ret = ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &framesize_enum);  
  28.         } while (ret >= 0);  
  29.         LOGD("Supported sizes string: %s", size_list.string());  
  30.         break;  
  31.         case V4L2_FRMSIZE_TYPE_STEPWISE:  
  32.         case V4L2_FRMSIZE_TYPE_CONTINUOUS:  
  33.             LOGD("STEPWISE/CONTINUOUS ignored: %dx%d-%dx%d/%dx%d",  
  34.                 framesize_enum.stepwise.min_width,  
  35.                 framesize_enum.stepwise.min_height,  
  36.                 framesize_enum.stepwise.max_width,  
  37.                 framesize_enum.stepwise.max_height,  
  38.                 framesize_enum.stepwise.step_width,  
  39.                 framesize_enum.stepwise.step_height);  
  40.             break;  
  41.         default:  
  42.            LOGE("Unknown format type: %d!!!", framesize_enum.type);  
  43.     }  
  44.     return size_list;  

camera recording流程

分類: Camera 140人閱讀 評論(0) 收藏 舉報

開始app調用到cameraservices

  1. // start recording mode   
  2.   
  3. status_t CameraService::Client::startRecording() {  
  4.     LOG1("startRecording (pid %d)", getCallingPid());  
  5.     return startCameraMode(CAMERA_RECORDING_MODE);  
  6. }  
  7.   
  8. // start preview or recording   
  9.   
  10. status_t CameraService::Client::startCameraMode(camera_mode mode) {  
  11.     LOG1("startCameraMode(%d)", mode);  
  12.     Mutex::Autolock lock(mLock);  
  13.     status_t result = checkPidAndHardware();  
  14.     if (result != NO_ERROR) return result;  
  15.   
  16.     switch(mode) {  
  17.         case CAMERA_PREVIEW_MODE:  
  18.             if (mSurface == 0) {  
  19.                 LOG1("mSurface is not set yet.");  
  20.                 // still able to start preview in this case.   
  21.   
  22.             }  
  23.             return startPreviewMode();  
  24.         case CAMERA_RECORDING_MODE:  
  25.             if (mSurface == 0) {  
  26.                 LOGE("mSurface must be set before startRecordingMode.");  
  27.                 return INVALID_OPERATION;  
  28.             }  
  29.             return startRecordingMode();  
  30.         default:  
  31.             return UNKNOWN_ERROR;  
  32.     }  
  33. }  
// start recording mode

status_t CameraService::Client::startRecording() {
    LOG1("startRecording (pid %d)", getCallingPid());
    return startCameraMode(CAMERA_RECORDING_MODE);
}

// start preview or recording

status_t CameraService::Client::startCameraMode(camera_mode mode) {
    LOG1("startCameraMode(%d)", mode);
    Mutex::Autolock lock(mLock);
    status_t result = checkPidAndHardware();
    if (result != NO_ERROR) return result;

    switch(mode) {
        case CAMERA_PREVIEW_MODE:
            if (mSurface == 0) {
                LOG1("mSurface is not set yet.");
                // still able to start preview in this case.

            }
            return startPreviewMode();
        case CAMERA_RECORDING_MODE:
            if (mSurface == 0) {
                LOGE("mSurface must be set before startRecordingMode.");
                return INVALID_OPERATION;
            }
            return startRecordingMode();
        default:
            return UNKNOWN_ERROR;
    }
}

  1. status_t CameraService::Client::startRecordingMode() {  
  2.     LOG1("startRecordingMode");  
  3.     status_t result = NO_ERROR;  
  4.   
  5.     // if recording has been enabled, nothing needs to be done   
  6.   
  7.     if (mHardware->recordingEnabled()) {  
  8.         return NO_ERROR;  
  9.     }  
  10.   
  11.     // if preview has not been started, start preview first   
  12.   
  13.     if (!mHardware->previewEnabled()) {  
  14.         result = startPreviewMode();  
  15.         if (result != NO_ERROR) {  
  16.             return result;  
  17.         }  
  18.     }  
  19.   
  20.     // start recording mode   
  21.   
  22.     enableMsgType(CAMERA_MSG_VIDEO_FRAME);  
  23.     mCameraService->playSound(SOUND_RECORDING);  
  24.     result = mHardware->startRecording();  //調用hal recording.   
  25.     if (result != NO_ERROR) {  
  26.         LOGE("mHardware->startRecording() failed with status %d", result);  
  27.     }  
  28.     return result;  
  29. }  
status_t CameraService::Client::startRecordingMode() {
    LOG1("startRecordingMode");
    status_t result = NO_ERROR;

    // if recording has been enabled, nothing needs to be done

    if (mHardware->recordingEnabled()) {
        return NO_ERROR;
    }

    // if preview has not been started, start preview first

    if (!mHardware->previewEnabled()) {
        result = startPreviewMode();
        if (result != NO_ERROR) {
            return result;
        }
    }

    // start recording mode

    enableMsgType(CAMERA_MSG_VIDEO_FRAME);
    mCameraService->playSound(SOUND_RECORDING);
    result = mHardware->startRecording();  //調用hal recording.
    if (result != NO_ERROR) {
        LOGE("mHardware->startRecording() failed with status %d", result);
    }
    return result;
}
調用HAL 層的 previewthread 線程:
  1. if (mRecordRunning == true && mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {  
  2. 263 yuyv422_to_yuv420sp((unsigned char *)rawFramePointer,  
  3. 264 (unsigned char *)mRecordingHeap->getBase(),  
  4. 265 preview_width, preview_height);  
  5. 266 LOGE(" ------- mRecordRunning --------");  
  6. 267 mDataCbTimestamp(systemTime(SYSTEM_TIME_MONOTONIC), CAMERA_MSG_VIDEO_FRAME, mRecordingBuffer, mCallbackCookie);  
  7. 268 }  
if (mRecordRunning == true && mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
263 yuyv422_to_yuv420sp((unsigned char *)rawFramePointer,
264 (unsigned char *)mRecordingHeap->getBase(),
265 preview_width, preview_height);
266 LOGE(" ------- mRecordRunning --------");
267 mDataCbTimestamp(systemTime(SYSTEM_TIME_MONOTONIC), CAMERA_MSG_VIDEO_FRAME, mRecordingBuffer, mCallbackCookie);
268 }
使用回調函數: 回調到cameraservices .

  1. void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,  
  2.         int32_t msgType, const sp<IMemory>& dataPtr, void* user) {  
  3.     LOG2("dataCallbackTimestamp(%d)", msgType);  
  4.   
  5.     sp<Client> client = getClientFromCookie(user);  
  6.     if (client == 0) return;  
  7.     if (!client->lockIfMessageWanted(msgType)) return;  
  8.   
  9.     if (dataPtr == 0) {  
  10.         LOGE("Null data returned in data with timestamp callback");  
  11.         client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);  
  12.         return;  
  13.     }  
  14.   
  15.     client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);  
  16. }  
void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
        int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
    LOG2("dataCallbackTimestamp(%d)", msgType);

    sp<Client> client = getClientFromCookie(user);
    if (client == 0) return;
    if (!client->lockIfMessageWanted(msgType)) return;

    if (dataPtr == 0) {
        LOGE("Null data returned in data with timestamp callback");
        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
        return;
    }

    client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
}
數據傳給client->handleGenericDataTimestamp(timestamp, msgType, dataPtr)
  1. void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,  
  2.     int32_t msgType, const sp<IMemory>& dataPtr) {  
  3.     sp<ICameraClient> c = mCameraClient;  
  4.     mLock.unlock();  
  5.     if (c != 0) {  
  6.         c->dataCallbackTimestamp(timestamp, msgType, dataPtr);  
  7.     }  
  8. }  
void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,
    int32_t msgType, const sp<IMemory>& dataPtr) {
    sp<ICameraClient> c = mCameraClient;
    mLock.unlock();
    if (c != 0) {
        c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
    }
}
傳給 frameworks/base/libs/camera/Camera.cpp
  1. // callback from camera service when timestamped frame is ready   
  2.   
  3. void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)  
  4. {  
  5.     sp<CameraListener> listener;  
  6.     {  
  7.         Mutex::Autolock _l(mLock);  
  8.         listener = mListener;  
  9.     }  
  10.     if (listener != NULL) {  
  11.         listener->postDataTimestamp(timestamp, msgType, dataPtr);  
  12.     }  
  13. }  
// callback from camera service when timestamped frame is ready

void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
{
    sp<CameraListener> listener;
    {
        Mutex::Autolock _l(mLock);
        listener = mListener;
    }
    if (listener != NULL) {
        listener->postDataTimestamp(timestamp, msgType, dataPtr);
    }
}
調用到 frameworks/base/media/libstagefright/CameraSource.cpp
frameworks/base/libs/camera/ICameraClient.cpp

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章