Home | History | Annotate | Download | only in src
      1 /*
      2 ** Copyright (c) 2011-2012 The Linux Foundation. All rights reserved.
      3 **
      4 ** Not a Contribution, Apache license notifications and license are retained
      5 ** for attribution purposes only.
      6 **
      7 ** Licensed under the Apache License, Version 2.0 (the "License");
      8 ** you may not use this file except in compliance with the License.
      9 ** You may obtain a copy of the License at
     10 **
     11 **     http://www.apache.org/licenses/LICENSE-2.0
     12 **
     13 ** Unless required by applicable law or agreed to in writing, software
     14 ** distributed under the License is distributed on an "AS IS" BASIS,
     15 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16 ** See the License for the specific language governing permissions and
     17 ** limitations under the License.
     18 */
     19 
     20 /*#error uncomment this for compiler test!*/
     21 
     22 //#define ALOG_NDEBUG 0
     23 #define ALOG_NIDEBUG 0
     24 #define LOG_TAG "QCameraHWI_Record"
     25 #include <utils/Log.h>
     26 #include <utils/threads.h>
     27 #include <cutils/properties.h>
     28 #include <fcntl.h>
     29 #include <sys/mman.h>
     30 
     31 #include "QCameraStream.h"
     32 
     33 
     34 #define LIKELY(exp)   __builtin_expect(!!(exp), 1)
     35 #define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
     36 
     37 /* QCameraStream_record class implementation goes here*/
     38 /* following code implement the video streaming capture & encoding logic of this class*/
     39 // ---------------------------------------------------------------------------
     40 // QCameraStream_record createInstance()
     41 // ---------------------------------------------------------------------------
     42 namespace android {
     43 
     44 
     45 // ---------------------------------------------------------------------------
     46 // QCameraStream_record Constructor
     47 // ---------------------------------------------------------------------------
     48 QCameraStream_record::QCameraStream_record(uint32_t CameraHandle,
     49                                            uint32_t ChannelId,
     50                                            uint32_t Width,
     51                                            uint32_t Height,
     52                                            uint32_t Format,
     53                                            uint8_t NumBuffers,
     54                                            mm_camera_vtbl_t *mm_ops,
     55                                            mm_camera_img_mode imgmode,
     56                                            camera_mode_t mode,
     57                                            QCameraHardwareInterface* camCtrl)
     58 //  : QCameraStream(cameraId,mode),
     59   :QCameraStream(CameraHandle,
     60                  ChannelId,
     61                  Width,
     62                  Height,
     63                  Format,
     64                  NumBuffers,
     65                  mm_ops,
     66                  imgmode,
     67                  mode,
     68                  camCtrl),
     69                  mDebugFps(false)
     70 {
     71   char value[PROPERTY_VALUE_MAX];
     72   ALOGV("%s: BEGIN", __func__);
     73 
     74   property_get("persist.debug.sf.showfps", value, "0");
     75   mDebugFps = atoi(value);
     76 
     77   ALOGV("%s: END", __func__);
     78 }
     79 
     80 // ---------------------------------------------------------------------------
     81 // QCameraStream_record Destructor
     82 // ---------------------------------------------------------------------------
     83 QCameraStream_record::~QCameraStream_record() {
     84     ALOGV("%s: BEGIN", __func__);
     85     release();
     86     ALOGV("%s: END", __func__);
     87 }
     88 
     89 int QCameraStream_record::putBuf(uint8_t num_bufs, mm_camera_buf_def_t *bufs)
     90 {
     91     for(int cnt = 0; cnt < mHalCamCtrl->mRecordingMemory.buffer_count; cnt++) {
     92         if (mHalCamCtrl->mStoreMetaDataInFrame) {
     93             struct encoder_media_buffer_type * packet =
     94                 (struct encoder_media_buffer_type  *)mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data;
     95             native_handle_delete(const_cast<native_handle_t *>(packet->meta_handle));
     96             mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->release(
     97                mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]);
     98         }
     99         mHalCamCtrl->mRecordingMemory.camera_memory[cnt]->release(
    100            mHalCamCtrl->mRecordingMemory.camera_memory[cnt]);
    101 
    102 #ifdef USE_ION
    103         mHalCamCtrl->deallocate_ion_memory(&mHalCamCtrl->mRecordingMemory.mem_info[cnt]);
    104 #endif
    105     }
    106     memset(&mHalCamCtrl->mRecordingMemory, 0, sizeof(mHalCamCtrl->mRecordingMemory));
    107     return NO_ERROR;
    108 }
    109 
    110 // ---------------------------------------------------------------------------
    111 // QCameraStream_record
    112 // ---------------------------------------------------------------------------
    113 void QCameraStream_record::release()
    114 {
    115     ALOGV("%s: BEGIN", __func__);
    116     streamOff(0);
    117     deinitStream();
    118     ALOGV("%s: END", __func__);
    119 }
    120 
    121 status_t QCameraStream_record::processRecordFrame(mm_camera_super_buf_t *frame)
    122 {
    123     ALOGV("%s : BEGIN",__func__);
    124     int video_buf_idx = frame->bufs[0]->buf_idx;
    125 
    126     if(!mActive) {
    127       ALOGE("Recording Stopped. Returning callback");
    128       return NO_ERROR;
    129     }
    130 
    131     if (UNLIKELY(mDebugFps)) {
    132         debugShowVideoFPS();
    133     }
    134     ALOGE("DEBUG4:%d",frame->bufs[0]->stream_id);
    135     ALOGE("<DEBUG4>: Timestamp: %ld %ld",frame->bufs[0]->ts.tv_sec,frame->bufs[0]->ts.tv_nsec);
    136     mHalCamCtrl->dumpFrameToFile(frame->bufs[0], HAL_DUMP_FRM_VIDEO);
    137     camera_data_timestamp_callback rcb = mHalCamCtrl->mDataCbTimestamp;
    138     void *rdata = mHalCamCtrl->mCallbackCookie;
    139 	  nsecs_t timeStamp = nsecs_t(frame->bufs[0]->ts.tv_sec)*1000000000LL + \
    140                       frame->bufs[0]->ts.tv_nsec;
    141 
    142     ALOGE("Send Video frame to services/encoder TimeStamp : %lld",timeStamp);
    143     mRecordedFrames[video_buf_idx] = *frame;
    144 
    145     mHalCamCtrl->cache_ops(&mHalCamCtrl->mRecordingMemory.mem_info[video_buf_idx],
    146                            (void *)mHalCamCtrl->mRecordingMemory.camera_memory[video_buf_idx]->data,
    147                            ION_IOC_CLEAN_CACHES);
    148 
    149     if (mHalCamCtrl->mStoreMetaDataInFrame) {
    150         if((rcb != NULL) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
    151             ALOGE("Calling video callback:%d", video_buf_idx);
    152             rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME,
    153                 mHalCamCtrl->mRecordingMemory.metadata_memory[video_buf_idx],
    154                 0, mHalCamCtrl->mCallbackCookie);
    155         }
    156     } else {
    157         if((rcb != NULL) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
    158             ALOGE("Calling video callback2");
    159             rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME,
    160                 mHalCamCtrl->mRecordingMemory.camera_memory[video_buf_idx],
    161                 0, mHalCamCtrl->mCallbackCookie);
    162         }
    163     }
    164 
    165     ALOGV("%s : END",__func__);
    166     return NO_ERROR;
    167 }
    168 
    169 //Record Related Functions
    170 status_t QCameraStream_record::initStream(uint8_t no_cb_needed, uint8_t stream_on)
    171 {
    172     status_t ret = NO_ERROR;
    173 
    174     ALOGI(" %s : E ", __FUNCTION__);
    175     mNumBuffers = VIDEO_BUFFER_COUNT;
    176     if(mHalCamCtrl->isLowPowerCamcorder()) {
    177         ALOGE("%s: lower power camcorder selected", __func__);
    178         mNumBuffers = VIDEO_BUFFER_COUNT_LOW_POWER_CAMCORDER;
    179     }
    180     ret = QCameraStream::initStream(no_cb_needed, stream_on);
    181 end:
    182     ALOGI(" %s : X ", __FUNCTION__);
    183     return ret;
    184 }
    185 
    186 status_t QCameraStream_record::getBuf(mm_camera_frame_len_offset *frame_offset_info,
    187                                       uint8_t num_bufs,
    188                                       uint8_t *initial_reg_flag,
    189                                       mm_camera_buf_def_t  *bufs)
    190 {
    191     ALOGE("%s : BEGIN",__func__);
    192 
    193     if (num_bufs > mNumBuffers) {
    194         mNumBuffers = num_bufs;
    195     }
    196     if ((mNumBuffers == 0) || (mNumBuffers > MM_CAMERA_MAX_NUM_FRAMES)) {
    197         ALOGE("%s: Invalid number of buffers (=%d) requested!",
    198              __func__, mNumBuffers);
    199         return BAD_VALUE;
    200     }
    201 
    202     memset(mRecordBuf, 0, sizeof(mRecordBuf));
    203     memcpy(&mFrameOffsetInfo, frame_offset_info, sizeof(mFrameOffsetInfo));
    204     if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mRecordingMemory,
    205                                  mNumBuffers,
    206                                  mFrameOffsetInfo.frame_len,
    207                                  MSM_PMEM_VIDEO,
    208                                  &mFrameOffsetInfo,
    209                                  mRecordBuf) < 0) {
    210         ALOGE("%s: Error getting heap mem for recording", __func__);
    211         return NO_MEMORY;
    212     }
    213 
    214     if (mHalCamCtrl->mStoreMetaDataInFrame) {
    215         for (int cnt = 0; cnt < mNumBuffers; cnt++) {
    216             mHalCamCtrl->mRecordingMemory.metadata_memory[cnt] =
    217                 mHalCamCtrl->mGetMemory(-1,
    218                                         sizeof(struct encoder_media_buffer_type),
    219                                         1,
    220                                         (void *)this);
    221             struct encoder_media_buffer_type * packet =
    222                 (struct encoder_media_buffer_type *)mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data;
    223             packet->meta_handle = native_handle_create(1, 2); //1 fd, 1 offset and 1 size
    224             packet->buffer_type = kMetadataBufferTypeCameraSource;
    225             native_handle_t * nh = const_cast<native_handle_t *>(packet->meta_handle);
    226             nh->data[0] = mHalCamCtrl->mRecordingMemory.mem_info[cnt].fd;
    227             nh->data[1] = 0;
    228             nh->data[2] = mHalCamCtrl->mRecordingMemory.mem_info[cnt].size;
    229         }
    230     }
    231 
    232     for(int i = 0; i < num_bufs; i++) {
    233         bufs[i] = mRecordBuf[i];
    234         initial_reg_flag[i] = true;
    235     }
    236 
    237     ALOGE("%s : END",__func__);
    238     return NO_ERROR;
    239 }
    240 
    241 void QCameraStream_record::releaseRecordingFrame(const void *opaque)
    242 {
    243     ALOGV("%s : BEGIN, opaque = 0x%p",__func__, opaque);
    244     if(!mActive)
    245     {
    246         ALOGE("%s : Recording already stopped!!! Leak???",__func__);
    247         return;
    248     }
    249     for(int cnt = 0; cnt < mHalCamCtrl->mRecordingMemory.buffer_count; cnt++) {
    250       if (mHalCamCtrl->mStoreMetaDataInFrame) {
    251         if(mHalCamCtrl->mRecordingMemory.metadata_memory[cnt] &&
    252                 mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data == opaque) {
    253             /* found the match */
    254             ALOGE("Releasing video frames:%d",cnt);
    255             if(MM_CAMERA_OK != p_mm_ops->ops->qbuf(mCameraHandle, mChannelId, mRecordedFrames[cnt].bufs[0]))
    256                 ALOGE("%s : Buf Done Failed",__func__);
    257             mHalCamCtrl->cache_ops(&mHalCamCtrl->mRecordingMemory.mem_info[cnt],
    258                                    (void *)mRecordedFrames[cnt].bufs[0]->buffer,
    259                                    ION_IOC_INV_CACHES);
    260             ALOGV("%s : END",__func__);
    261             return;
    262         }
    263       } else {
    264         if(mHalCamCtrl->mRecordingMemory.camera_memory[cnt] &&
    265                 mHalCamCtrl->mRecordingMemory.camera_memory[cnt]->data == opaque) {
    266             /* found the match */
    267             ALOGE("Releasing video frames2");
    268             if(MM_CAMERA_OK != p_mm_ops->ops->qbuf(mCameraHandle, mChannelId, mRecordedFrames[cnt].bufs[0]))
    269                 ALOGE("%s : Buf Done Failed",__func__);
    270             mHalCamCtrl->cache_ops(&mHalCamCtrl->mRecordingMemory.mem_info[cnt],
    271                                    (void *)mRecordedFrames[cnt].bufs[0]->buffer,
    272                                    ION_IOC_INV_CACHES);
    273             ALOGV("%s : END",__func__);
    274             return;
    275         }
    276       }
    277     }
    278 	ALOGE("%s: cannot find the matched frame with opaue = 0x%p", __func__, opaque);
    279 }
    280 
    281 void QCameraStream_record::debugShowVideoFPS() const
    282 {
    283   static int mFrameCount;
    284   static int mLastFrameCount = 0;
    285   static nsecs_t mLastFpsTime = 0;
    286   static float mFps = 0;
    287   mFrameCount++;
    288   nsecs_t now = systemTime();
    289   nsecs_t diff = now - mLastFpsTime;
    290   if (diff > ms2ns(250)) {
    291     mFps =  ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
    292     ALOGI("Video Frames Per Second: %.4f", mFps);
    293     mLastFpsTime = now;
    294     mLastFrameCount = mFrameCount;
    295   }
    296 }
    297 
    298 }//namespace android
    299 
    300