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