ITKeyword,专注技术干货聚合推荐

注册 | 登录

Android S5PV210 cameraHAL 录像功能分析

mirkerson 分享于

推荐:S5PV210 Android cameraHAL 录像功能分析

Camera系统进行视频录制的过程,涉及到camera driver,camera HAL,camera Service,camera Java 几层 camera 录像功能一般是和preview功能同时进行的,samsung

2019阿里云全部产品优惠券(新购或升级都可以使用,强烈推荐)
领取地址https://promotion.aliyun.com/ntms/yunparter/invite.html


分类:  Samsung S5PV210 2012-07-27 18:01  325人阅读  评论(0)  收藏  举报

Camera系统进行视频录制的过程,涉及到camera driver,camera HAL,camera Service,camera Java 几层

camera 录像功能一般是和preview功能同时进行的,samsung HAL的录像线程是借助preview线程来实现的,在这个线程中FIMC0获取preview使用的原始数据,同时FIMC2获取录像需要的原始数据,这里之所以使用两个FIMC获取数据,我想是因为preview和录像需要的原始数据是有差异的,而S5PV210恰好又支持两个fimc控制器同时输出一个sensor的BT656信号。


libcamera/SecCameraHWInterface.cpp

[cpp]  view plain copy
  1. 802 status_t CameraHardwareSec::startRecording()  
  2. 803 {  
  3. 804     LOGV("%s :", __func__);  
  4. 805   
  5. 806     if (mRecordRunning == false) {  
  6. 807         if (mSecCamera->startRecord() < 0) {  
  7. 808             LOGE("ERR(%s):Fail on mSecCamera->startRecord()", __func__);  
  8. 809             // sw5771.park : temporary fix  
  9. 810             //               with HDMI, fimc2 is conflict...  
  10. 811 #ifdef BOARD_USES_HDMI  
  11. 812 #else  
  12. 813             return UNKNOWN_ERROR;  
  13. 814 #endif  
  14. 815         }  
  15. 816         mRecordRunning = true;  
  16. 817     }  
  17. 818     return NO_ERROR;  
  18. 819 }  

807 mSecCamera->startRecord 设置并启动recording对应的fimc控制器

816 设置启动标志,previewThread线程中会通过mRecordRunning判断是否需要录像处理


libcamera/SecCamera.cpp:SecCamera::startRecord()

[cpp]  view plain copy
  1. 1084 int SecCamera::startRecord(void)  
  2. 1085 {  
  3. 1086     int ret, i;  
  4. 1087   
  5. 1088     LOGV("%s :", __func__);  
  6. 1089   
  7. 1090     // aleady started  
  8. 1091     if (m_flag_record_start > 0) {  
  9. 1092         LOGE("ERR(%s):Recording was already started\n", __func__);  
  10. 1093         return 0;  
  11. 1094     }  
  12. 1095   
  13. 1096     if (m_cam_fd2 <= 0) {  
  14. 1097         LOGE("ERR(%s):Camera was closed\n", __func__);  
  15. 1098         return -1;  
  16. 1099     }  
  17. 1100   
  18. 1101     /* enum_fmt, s_fmt sample */  
  19. 1102     ret = fimc_v4l2_enum_fmt(m_cam_fd2, V4L2_PIX_FMT_NV12T);  
  20. 1103     CHECK(ret);  
  21. 1104   
  22. 1105     LOGI("%s: m_recording_width = %d, m_recording_height = %d\n",  
  23. 1106          __func__, m_recording_width, m_recording_height);  
  24. 1107   
  25. 1108     ret = fimc_v4l2_s_fmt(m_cam_fd2, m_recording_width, m_recording_height,  
  26. 1109                           V4L2_PIX_FMT_NV12T, 0);  
  27. 1110     CHECK(ret);  
  28. 1111   
  29. 1112     ret = fimc_v4l2_reqbufs(m_cam_fd2, V4L2_BUF_TYPE_VIDEO_CAPTURE, MAX_BUFFERS);  
  30. 1113     CHECK(ret);  
  31. 1114   
  32. 1115     ret = this->m_setCameraAngle(m_cam_fd2);  
  33. 1116     CHECK(ret);  
  34. 1117   
  35. 1118     /* start with all buffers in queue */  
  36. 1119     for (i = 0; i < MAX_BUFFERS; i++) {  
  37. 1120         ret = fimc_v4l2_qbuf(m_cam_fd2, i);  
  38. 1121         CHECK(ret);  
  39. 1122     }  
  40. 1123   
  41. 1124     ret = fimc_v4l2_streamon(m_cam_fd2);  
  42. 1125     CHECK(ret);  
  43. 1126   
  44. 1127     // Get and throw away the first frame since it is often garbled.  
  45. 1128     memset(&m_events_c2, 0, sizeof(m_events_c2));  
  46. 1129     m_events_c2.fd = m_cam_fd2;  
  47. 1130     m_events_c2.events = POLLIN | POLLERR;  
  48. 1131     ret = fimc_poll(&m_events_c2);  
  49. 1132     CHECK(ret);  
  50. 1133   
  51. 1134     m_flag_record_start = 1;  
  52. 1135   
  53. 1136     LOGE("(%s): end\n", __func__);  
  54. 1137     return 0;  
  55. 1138 }  

1102 检查设备是否支持NV12T格式,这里使用的是m_cam_fd2,对应着FIMC2控制器

接下来的流程类似于普通拍照时camera设备的初始化流程

1108 ~ 1109 设置录像的宽度,高度和格式

1112 申请拍照用的queue buffer

1118 ~ 1112 把这些buffer加入等待队列

1124 启动FIMC2的capture stream on 模式,FIMC2开始抓取数据,FIMC2每获取一帧数据都会唤醒调用fimc_poll阻塞的进程

1128 ~ 1132 等待第一帧的到来,并且忽略掉,因为第一帧的数据经常错乱


[cpp]  view plain copy
  1. 821 void CameraHardwareSec::stopRecording()  
  2. 822 {  
  3. 823     LOGV("%s :", __func__);  
  4. 824   
  5. 825     if (mRecordRunning == true) {  
  6. 826         if (mSecCamera->stopRecord() < 0) {  
  7. 827             LOGE("ERR(%s):Fail on mSecCamera->stopRecord()", __func__);  
  8. 828             return;  
  9. 829         }  
  10. 830         mRecordRunning = false;  
  11. 831     }  
  12. 832 }  

826 停止FIMC2设备的capture stream

830 mRecordRunning = false,会停止previewThread中针对record的处理


[cpp]  view plain copy
  1. 841 void CameraHardwareSec::releaseRecordingFrame(const sp<IMemory>& mem)  
  2. 842 {  
  3. 843     ssize_t offset;  
  4. 844     sp<IMemoryHeap> heap = mem->getMemory(&offset, NULL);  
  5. 845     struct ADDRS *addrs = (struct ADDRS *)((uint8_t *)heap->base() + offset);  
  6. 846  
  7. 847     mSecCamera->releaseRecordFrame(addrs->buf_idx);  
  8. 848 }  

buffer数据要传送给上层处理,在上层处理完之前,驱动层和HAL不能修改这个buffer,直到上层应用调用releaseRecordingFrame接口释放buffer

847 mSecCamera->releaseRecordFrame会把addrs->buf_idx对应的buffer加到队列中

[cpp]  view plain copy
  1.  542 int CameraHardwareSec::previewThread()  
  2.  543 {  
  3.  544     int index;  
  4.  545     nsecs_t timestamp;  
  5.  546     unsigned int phyYAddr;  
  6.  547     unsigned int phyCAddr;  
  7.  548     struct ADDRS *addrs;  
  8.  549   
  9.  550     index = mSecCamera->getPreview();  
  10.  551     if (index < 0) {  
  11.  552         LOGE("ERR(%s):Fail on SecCamera->getPreview()", __func__);  
  12.  553         return UNKNOWN_ERROR;  
  13.  554     }  
  14.  555     mSkipFrameLock.lock();  
  15.  556     if (mSkipFrame > 0) {  
  16.  557         mSkipFrame--;  
  17.  558         mSkipFrameLock.unlock();  
  18.  559         return NO_ERROR;  
  19.  560     }  
  20.  561     mSkipFrameLock.unlock();  
  21.  562     gInterlace++;  
  22.  563     //if (gInterlace % 8) {  
  23.  564     //  return NO_ERROR;  
  24.  565     //}  
  25.  566   
  26.  567     timestamp = systemTime(SYSTEM_TIME_MONOTONIC);  
  27.  568   
  28.  569     phyYAddr = mSecCamera->getPhyAddrY(index);  
  29.  570     phyCAddr = mSecCamera->getPhyAddrC(index);  
  30.  571   
  31.  572     if (phyYAddr == 0xffffffff || phyCAddr == 0xffffffff) {  
  32.  573         LOGE("ERR(%s):Fail on SecCamera getPhyAddr Y addr = %0x C addr = %0x", __func__, phyYAddr, phyCAddr);  
  33.  574         return UNKNOWN_ERROR;  
  34.  575      }  
  35.  576  
  36.  577     int width, height, frame_size, offset;  
  37.  578   
  38.  579     mSecCamera->getPreviewSize(&width, &height, &frame_size);  
  39.  580   
  40.  581     offset = (frame_size + mSizeOfADDRS) * index;  
  41.  582     sp<MemoryBase> buffer = new MemoryBase(mPreviewHeap, offset, frame_size);  
  42.  583   
  43.  584     memcpy(static_cast<unsigned char *>(mPreviewHeap->base()) + (offset + frame_size    ), &phyYAddr, 4);  
  44.  585     memcpy(static_cast<unsigned char *>(mPreviewHeap->base()) + (offset + frame_size + 4), &phyCAddr, 4);  
  45.  586   
  46.  587 #if defined(BOARD_USES_OVERLAY)  
  47.  588     if (mUseOverlay) {  
  48.  589         int ret;  
  49.  590         overlay_buffer_t overlay_buffer;  
  50.  591   
  51.  592         mOverlayBufferIdx ^= 1;  
  52.  593         memcpy(static_cast<unsigned char*>(mPreviewHeap->base()) + offset + frame_size + sizeof(phyYAddr) + sizeof(phyCA     ddr),  
  53.  594                 &mOverlayBufferIdx, sizeof(mOverlayBufferIdx));  
  54.  595   
  55.  596         ret = mOverlay->queueBuffer((void*)(static_cast<unsigned char *>(mPreviewHeap->base()) + (offset + frame_size)))     ;  
  56.  597   
  57.  598         if (ret == -1 ) {  
  58.  599             LOGE("ERR(%s):overlay queueBuffer fail", __func__);  
  59.  600         } else if (ret != ALL_BUFFERS_FLUSHED) {  
  60.  601             ret = mOverlay->dequeueBuffer(&overlay_buffer);  
  61.  602             if (ret == -1) {  
  62.  603                 LOGE("ERR(%s):overlay dequeueBuffer fail", __func__);  
  63.  604             }  
  64.  605          }  
  65.  606      }  
  66.  607 #endif  
  67.  608       
  68.  609     // Notify the client of a new frame.  
  69.  610     if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {  
  70.  611         mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);  
  71.  612     }     
  72.  613       
  73.  614     if (mRecordRunning == true) {  
  74.  615         // sw5771.park : temporary fix  
  75.  616         //               with HDMI, fimc2 is conflict...  
  76.  617 #ifdef BOARD_USES_HDMI  
  77.  618         int preview_index = index;  
  78.  619           
  79.  620         index = mSecCamera->getRecordFrame();  
  80.  621         if (index < 0) {  
  81.  622             LOGE("ERR(%s):Fail on SecCamera->getRecordFrame()", __func__);  
  82.  623             index = preview_index;  
  83.  624             //return UNKNOWN_ERROR;  
  84.  625         } else {  
  85.  626             phyYAddr = mSecCamera->getRecPhyAddrY(index);  
  86.  627             phyCAddr = mSecCamera->getRecPhyAddrC(index);  
  87.  628         }  
  88.  629 #else  
  89.  630         index = mSecCamera->getRecordFrame();  
  90.  631         if (index < 0) {  
  91.  632             LOGE("ERR(%s):Fail on SecCamera->getRecordFrame()", __func__);  
  92.  633             return UNKNOWN_ERROR;  
  93.  634         }  
  94.  635   
  95.  636         phyYAddr = mSecCamera->getRecPhyAddrY(index);  
  96.  637         phyCAddr = mSecCamera->getRecPhyAddrC(index);  
  97.  638 #endif  
  98.  639   
  99.  640         if (phyYAddr == 0xffffffff || phyCAddr == 0xffffffff) {  
  100.  641             LOGE("ERR(%s):Fail on SecCamera getRectPhyAddr Y addr = %0x C addr = %0x", __func__, phyYAddr, phyCAddr);  
  101.  642             return UNKNOWN_ERROR;  
  102.  643         }  
  103.  644   
  104.  645         addrs = (struct ADDRS *)mRecordHeap->base();  
  105.  646   
  106.  647         sp<MemoryBase> buffer = new MemoryBase(mRecordHeap, mSizeOfADDRS * index, mSizeOfADDRS);  
  107.  648         addrs[index].addr_y = phyYAddr;  
  108.  649         addrs[index].addr_cbcr = phyCAddr;  
  109.  650         addrs[index].buf_idx = index;  
  110.  651   
  111.  652         // Notify the client of a new frame.  
  112.  653         if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {  
  113.  654             mDataCbTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, buffer, mCallbackCookie);  
  114.  655         } else {  
  115.  656             mSecCamera->releaseRecordFrame(index);  
  116.  657         }  
  117.  658     }  
  118.  659   
  119.  660     return NO_ERROR;  
  120.  661 }  

614 ~ 658是和record相关的代码

630 获取record frame,getRecordFrame()会阻塞在FIMC2设备节点的poll函数上,直到有可用数据,返回值index是可用buffer的索引

636 ~ 637 获取buffer对应的物理地址,这里不太明白为什么录像要获取物理地址,也许是传给上层后视频编码过程能够处理物理地址吧

653  上层如果需要处理数据那么就要设置 mMsgEnable为CAMERA_MSG_VIDEO_FRAME,这样HAL层就会通过mDataCbTimestamp上传数据,上层处理完后要负责调用releaseRecordFrame接口释放buffer

656 上层不做处理,那么直接释放buffer(重新入队),不过实在想像不出有什么场景会不做处理


三星S5PV210由于硬件的特殊性,因此可以在preview中启动两个camera capture stream,并且两个FIMC控制器fimc1 fime2从同一个camera sensor获取数据,这两份数据一份用来preview,另外一份用来recording,而其他平台的preview 和recording一般都是共享同一份raw数据。


推荐:S5PV210 Android 创建的video设备

S5PV210会在/dev/下生成几个video相关的设备节点,分别为 /dev/video0, /dev/video1, /dev/video2 /dev/video14, /dev/video21, /dev/video22 video0, video1, v


分享到: 
  • 上一篇:Android S5PV210 camera S_INPUT实现
  • ,

    Camera系统进行视频录制的过程,涉及到camera driver,camera HAL,camera Service,camera Java 几层

    camera 录像功能一般是和preview功能同时进行的,samsung HAL的录像线程是借助preview线程来实现的,在这个线程中FIMC0获取preview使用的原始数据,同时FIMC2获取录像需要的原始数据,这里之所以使用两个FIMC获取数据,我想是因为preview和录像需要的原始数据是有差异的,而S5PV210恰好又支持两个fimc控制器同时输出一个sensor的BT656信号。


    libcamera/SecCameraHWInterface.cpp

    [cpp]  view plain copy
    1. 802 status_t CameraHardwareSec::startRecording()  
    2. 803 {  
    3. 804     LOGV("%s :", __func__);  
    4. 805   
    5. 806     if (mRecordRunning == false) {  
    6. 807         if (mSecCamera->startRecord() < 0) {  
    7. 808             LOGE("ERR(%s):Fail on mSecCamera->startRecord()", __func__);  
    8. 809             // sw5771.park : temporary fix  
    9. 810             //               with HDMI, fimc2 is conflict...  
    10. 811 #ifdef BOARD_USES_HDMI  
    11. 812 #else  
    12. 813             return UNKNOWN_ERROR;  
    13. 814 #endif  
    14. 815         }  
    15. 816         mRecordRunning = true;  
    16. 817     }  
    17. 818     return NO_ERROR;  
    18. 819 }  

    807 mSecCamera->startRecord 设置并启动recording对应的fimc控制器

    816 设置启动标志,previewThread线程中会通过mRecordRunning判断是否需要录像处理


    libcamera/SecCamera.cpp:SecCamera::startRecord()

    [cpp]  view plain copy
    1. 1084 int SecCamera::startRecord(void)  
    2. 1085 {  
    3. 1086     int ret, i;  
    4. 1087   
    5. 1088     LOGV("%s :", __func__);  
    6. 1089   
    7. 1090     // aleady started  
    8. 1091     if (m_flag_record_start > 0) {  
    9. 1092         LOGE("ERR(%s):Recording was already started\n", __func__);  
    10. 1093         return 0;  
    11. 1094     }  
    12. 1095   
    13. 1096     if (m_cam_fd2 <= 0) {  
    14. 1097         LOGE("ERR(%s):Camera was closed\n", __func__);  
    15. 1098         return -1;  
    16. 1099     }  
    17. 1100   
    18. 1101     /* enum_fmt, s_fmt sample */  
    19. 1102     ret = fimc_v4l2_enum_fmt(m_cam_fd2, V4L2_PIX_FMT_NV12T);  
    20. 1103     CHECK(ret);  
    21. 1104   
    22. 1105     LOGI("%s: m_recording_width = %d, m_recording_height = %d\n",  
    23. 1106          __func__, m_recording_width, m_recording_height);  
    24. 1107   
    25. 1108     ret = fimc_v4l2_s_fmt(m_cam_fd2, m_recording_width, m_recording_height,  
    26. 1109                           V4L2_PIX_FMT_NV12T, 0);  
    27. 1110     CHECK(ret);  
    28. 1111   
    29. 1112     ret = fimc_v4l2_reqbufs(m_cam_fd2, V4L2_BUF_TYPE_VIDEO_CAPTURE, MAX_BUFFERS);  
    30. 1113     CHECK(ret);  
    31. 1114   
    32. 1115     ret = this->m_setCameraAngle(m_cam_fd2);  
    33. 1116     CHECK(ret);  
    34. 1117   
    35. 1118     /* start with all buffers in queue */  
    36. 1119     for (i = 0; i < MAX_BUFFERS; i++) {  
    37. 1120         ret = fimc_v4l2_qbuf(m_cam_fd2, i);  
    38. 1121         CHECK(ret);  
    39. 1122     }  
    40. 1123   
    41. 1124     ret = fimc_v4l2_streamon(m_cam_fd2);  
    42. 1125     CHECK(ret);  
    43. 1126   
    44. 1127     // Get and throw away the first frame since it is often garbled.  
    45. 1128     memset(&m_events_c2, 0, sizeof(m_events_c2));  
    46. 1129     m_events_c2.fd = m_cam_fd2;  
    47. 1130     m_events_c2.events = POLLIN | POLLERR;  
    48. 1131     ret = fimc_poll(&m_events_c2);  
    49. 1132     CHECK(ret);  
    50. 1133   
    51. 1134     m_flag_record_start = 1;  
    52. 1135   
    53. 1136     LOGE("(%s): end\n", __func__);  
    54. 1137     return 0;  
    55. 1138 }  

    1102 检查设备是否支持NV12T格式,这里使用的是m_cam_fd2,对应着FIMC2控制器

    接下来的流程类似于普通拍照时camera设备的初始化流程

    1108 ~ 1109 设置录像的宽度,高度和格式

    1112 申请拍照用的queue buffer

    1118 ~ 1112 把这些buffer加入等待队列

    1124 启动FIMC2的capture stream on 模式,FIMC2开始抓取数据,FIMC2每获取一帧数据都会唤醒调用fimc_poll阻塞的进程

    1128 ~ 1132 等待第一帧的到来,并且忽略掉,因为第一帧的数据经常错乱


    [cpp]  view plain copy
    1. 821 void CameraHardwareSec::stopRecording()  
    2. 822 {  
    3. 823     LOGV("%s :", __func__);  
    4. 824   
    5. 825     if (mRecordRunning == true) {  
    6. 826         if (mSecCamera->stopRecord() < 0) {  
    7. 827             LOGE("ERR(%s):Fail on mSecCamera->stopRecord()", __func__);  
    8. 828             return;  
    9. 829         }  
    10. 830         mRecordRunning = false;  
    11. 831     }  
    12. 832 }  

    826 停止FIMC2设备的capture stream

    830 mRecordRunning = false,会停止previewThread中针对record的处理


    [cpp]  view plain copy
    1. 841 void CameraHardwareSec::releaseRecordingFrame(const sp<IMemory>& mem)  
    2. 842 {  
    3. 843     ssize_t offset;  
    4. 844     sp<IMemoryHeap> heap = mem->getMemory(&offset, NULL);  
    5. 845     struct ADDRS *addrs = (struct ADDRS *)((uint8_t *)heap->base() + offset);  
    6. 846  
    7. 847     mSecCamera->releaseRecordFrame(addrs->buf_idx);  
    8. 848 }  

    buffer数据要传送给上层处理,在上层处理完之前,驱动层和HAL不能修改这个buffer,直到上层应用调用releaseRecordingFrame接口释放buffer

    847 mSecCamera->releaseRecordFrame会把addrs->buf_idx对应的buffer加到队列中

    [cpp]  view plain copy
    1.  542 int CameraHardwareSec::previewThread()  
    2.  543 {  
    3.  544     int index;  
    4.  545     nsecs_t timestamp;  
    5.  546     unsigned int phyYAddr;  
    6.  547     unsigned int phyCAddr;  
    7.  548     struct ADDRS *addrs;  
    8.  549   
    9.  550     index = mSecCamera->getPreview();  
    10.  551     if (index < 0) {  
    11.  552         LOGE("ERR(%s):Fail on SecCamera->getPreview()", __func__);  
    12.  553         return UNKNOWN_ERROR;  
    13.  554     }  
    14.  555     mSkipFrameLock.lock();  
    15.  556     if (mSkipFrame > 0) {  
    16.  557         mSkipFrame--;  
    17.  558         mSkipFrameLock.unlock();  
    18.  559         return NO_ERROR;  
    19.  560     }  
    20.  561     mSkipFrameLock.unlock();  
    21.  562     gInterlace++;  
    22.  563     //if (gInterlace % 8) {  
    23.  564     //  return NO_ERROR;  
    24.  565     //}  
    25.  566   
    26.  567     timestamp = systemTime(SYSTEM_TIME_MONOTONIC);  
    27.  568   
    28.  569     phyYAddr = mSecCamera->getPhyAddrY(index);  
    29.  570     phyCAddr = mSecCamera->getPhyAddrC(index);  
    30.  571   
    31.  572     if (phyYAddr == 0xffffffff || phyCAddr == 0xffffffff) {  
    32.  573         LOGE("ERR(%s):Fail on SecCamera getPhyAddr Y addr = %0x C addr = %0x", __func__, phyYAddr, phyCAddr);  
    33.  574         return UNKNOWN_ERROR;  
    34.  575      }  
    35.  576  
    36.  577     int width, height, frame_size, offset;  
    37.  578   
    38.  579     mSecCamera->getPreviewSize(&width, &height, &frame_size);  
    39.  580   
    40.  581     offset = (frame_size + mSizeOfADDRS) * index;  
    41.  582     sp<MemoryBase> buffer = new MemoryBase(mPreviewHeap, offset, frame_size);  
    42.  583   
    43.  584     memcpy(static_cast<unsigned char *>(mPreviewHeap->base()) + (offset + frame_size    ), &phyYAddr, 4);  
    44.  585     memcpy(static_cast<unsigned char *>(mPreviewHeap->base()) + (offset + frame_size + 4), &phyCAddr, 4);  
    45.  586   
    46.  587 #if defined(BOARD_USES_OVERLAY)  
    47.  588     if (mUseOverlay) {  
    48.  589         int ret;  
    49.  590         overlay_buffer_t overlay_buffer;  
    50.  591   
    51.  592         mOverlayBufferIdx ^= 1;  
    52.  593         memcpy(static_cast<unsigned char*>(mPreviewHeap->base()) + offset + frame_size + sizeof(phyYAddr) + sizeof(phyCA     ddr),  
    53.  594                 &mOverlayBufferIdx, sizeof(mOverlayBufferIdx));  
    54.  595   
    55.  596         ret = mOverlay->queueBuffer((void*)(static_cast<unsigned char *>(mPreviewHeap->base()) + (offset + frame_size)))     ;  
    56.  597   
    57.  598         if (ret == -1 ) {  
    58.  599             LOGE("ERR(%s):overlay queueBuffer fail", __func__);  
    59.  600         } else if (ret != ALL_BUFFERS_FLUSHED) {  
    60.  601             ret = mOverlay->dequeueBuffer(&overlay_buffer);  
    61.  602             if (ret == -1) {  
    62.  603                 LOGE("ERR(%s):overlay dequeueBuffer fail", __func__);  
    63.  604             }  
    64.  605          }  
    65.  606      }  
    66.  607 #endif  
    67.  608       
    68.  609     // Notify the client of a new frame.  
    69.  610     if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {  
    70.  611         mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);  
    71.  612     }     
    72.  613       
    73.  614     if (mRecordRunning == true) {  
    74.  615         // sw5771.park : temporary fix  
    75.  616         //               with HDMI, fimc2 is conflict...  
    76.  617 #ifdef BOARD_USES_HDMI  
    77.  618         int preview_index = index;  
    78.  619           
    79.  620         index = mSecCamera->getRecordFrame();  
    80.  621         if (index < 0) {  
    81.  622             LOGE("ERR(%s):Fail on SecCamera->getRecordFrame()", __func__);  
    82.  623             index = preview_index;  
    83.  624             //return UNKNOWN_ERROR;  
    84.  625         } else {  
    85.  626             phyYAddr = mSecCamera->getRecPhyAddrY(index);  
    86.  627             phyCAddr = mSecCamera->getRecPhyAddrC(index);  
    87.  628         }  
    88.  629 #else  
    89.  630         index = mSecCamera->getRecordFrame();  
    90.  631         if (index < 0) {  
    91.  632             LOGE("ERR(%s):Fail on SecCamera->getRecordFrame()", __func__);  
    92.  633             return UNKNOWN_ERROR;  
    93.  634         }  
    94.  635   
    95.  636         phyYAddr = mSecCamera->getRecPhyAddrY(index);  
    96.  637         phyCAddr = mSecCamera->getRecPhyAddrC(index);  
    97.  638 #endif  
    98.  639   
    99.  640         if (phyYAddr == 0xffffffff || phyCAddr == 0xffffffff) {  
    100.  641             LOGE("ERR(%s):Fail on SecCamera getRectPhyAddr Y addr = %0x C addr = %0x", __func__, phyYAddr, phyCAddr);  
    101.  642             return UNKNOWN_ERROR;  
    102.  643         }  
    103.  644   
    104.  645         addrs = (struct ADDRS *)mRecordHeap->base();  
    105.  646   
    106.  647         sp<MemoryBase> buffer = new MemoryBase(mRecordHeap, mSizeOfADDRS * index, mSizeOfADDRS);  
    107.  648         addrs[index].addr_y = phyYAddr;  
    108.  649         addrs[index].addr_cbcr = phyCAddr;  
    109.  650         addrs[index].buf_idx = index;  
    110.  651   
    111.  652         // Notify the client of a new frame.  
    112.  653         if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {  
    113.  654             mDataCbTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, buffer, mCallbackCookie);  
    114.  655         } else {  
    115.  656             mSecCamera->releaseRecordFrame(index);  
    116.  657         }  
    117.  658     }  
    118.  659   
    119.  660     return NO_ERROR;  
    120.  661 }  

    614 ~ 658是和record相关的代码

    630 获取record frame,getRecordFrame()会阻塞在FIMC2设备节点的poll函数上,直到有可用数据,返回值index是可用buffer的索引

    636 ~ 637 获取buffer对应的物理地址,这里不太明白为什么录像要获取物理地址,也许是传给上层后视频编码过程能够处理物理地址吧

    653  上层如果需要处理数据那么就要设置 mMsgEnable为CAMERA_MSG_VIDEO_FRAME,这样HAL层就会通过mDataCbTimestamp上传数据,上层处理完后要负责调用releaseRecordFrame接口释放buffer

    656 上层不做处理,那么直接释放buffer(重新入队),不过实在想像不出有什么场景会不做处理


    三星S5PV210由于硬件的特殊性,因此可以在preview中启动两个camera capture stream,并且两个FIMC控制器fimc1 fime2从同一个camera sensor获取数据,这两份数据一份用来preview,另外一份用来recording,而其他平台的preview 和recording一般都是共享同一份raw数据。



    推荐:Android S5PV210 camera驱动测试程序

    分类:  Android  Samsung S5PV210 2012-07-04 13:47  480人阅读  评论(13)  收藏  举报 最近在调试S5PV210上的camera驱动,因为对Android的samsung camera hal

    分类:  Samsung S5PV210 2012-07-27 18:01  325人阅读  评论(0)  收藏  举报 Camera系统进行视频录制的过程,涉及到camera driver,camera HAL,camera Service,camera Java 几层 camera 录像

    相关阅读排行


    用户评论

    游客

    相关内容推荐

    最新文章

    ×

    ×

    请激活账号

    为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

    您的注册邮箱: 修改

    重新发送激活邮件 进入我的邮箱

    如果您没有收到激活邮件,请注意检查垃圾箱。