1 /* 2 ** Copyright (c) 2011 The Linux Foundation. All rights reserved. 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17 /*#error uncomment this for compiler test!*/ 18 19 //#define ALOG_NDEBUG 0 20 #define ALOG_NIDEBUG 0 21 #define LOG_TAG "QCameraHWI_Record" 22 #include <utils/Log.h> 23 #include <utils/threads.h> 24 #include <cutils/properties.h> 25 #include <fcntl.h> 26 #include <sys/mman.h> 27 28 #include "QCameraStream.h" 29 30 #define LIKELY(exp) __builtin_expect(!!(exp), 1) 31 #define UNLIKELY(exp) __builtin_expect(!!(exp), 0) 32 33 /* QCameraStream_record class implementation goes here*/ 34 /* following code implement the video streaming capture & encoding logic of this class*/ 35 // --------------------------------------------------------------------------- 36 // QCameraStream_record createInstance() 37 // --------------------------------------------------------------------------- 38 namespace android { 39 40 41 QCameraStream* QCameraStream_record::createInstance(int cameraId, 42 camera_mode_t mode) 43 { 44 ALOGV("%s: BEGIN", __func__); 45 QCameraStream* pme = new QCameraStream_record(cameraId, mode); 46 ALOGV("%s: END", __func__); 47 return pme; 48 } 49 50 // --------------------------------------------------------------------------- 51 // QCameraStream_record deleteInstance() 52 // --------------------------------------------------------------------------- 53 void QCameraStream_record::deleteInstance(QCameraStream *ptr) 54 { 55 ALOGV("%s: BEGIN", __func__); 56 if (ptr){ 57 ptr->release(); 58 delete ptr; 59 ptr = NULL; 60 } 61 ALOGV("%s: END", __func__); 62 } 63 64 // --------------------------------------------------------------------------- 65 // QCameraStream_record Constructor 66 // --------------------------------------------------------------------------- 67 QCameraStream_record::QCameraStream_record(int cameraId, 68 camera_mode_t mode) 69 :QCameraStream(cameraId,mode), 70 mDebugFps(false) 71 { 72 mHalCamCtrl = NULL; 73 char value[PROPERTY_VALUE_MAX]; 74 ALOGV("%s: BEGIN", __func__); 75 76 property_get("persist.debug.sf.showfps", value, "0"); 77 mDebugFps = atoi(value); 78 79 ALOGV("%s: END", __func__); 80 } 81 82 // --------------------------------------------------------------------------- 83 // QCameraStream_record Destructor 84 // --------------------------------------------------------------------------- 85 QCameraStream_record::~QCameraStream_record() { 86 ALOGV("%s: BEGIN", __func__); 87 if(mActive) { 88 stop(); 89 } 90 if(mInit) { 91 release(); 92 } 93 mInit = false; 94 mActive = false; 95 ALOGV("%s: END", __func__); 96 97 } 98 99 // --------------------------------------------------------------------------- 100 // QCameraStream_record Callback from mm_camera 101 // --------------------------------------------------------------------------- 102 static void record_notify_cb(mm_camera_ch_data_buf_t *bufs_new, 103 void *user_data) 104 { 105 QCameraStream_record *pme = (QCameraStream_record *)user_data; 106 mm_camera_ch_data_buf_t *bufs_used = 0; 107 ALOGV("%s: BEGIN", __func__); 108 109 /* 110 * Call Function Process Video Data 111 */ 112 pme->processRecordFrame(bufs_new); 113 ALOGV("%s: END", __func__); 114 } 115 116 // --------------------------------------------------------------------------- 117 // QCameraStream_record 118 // --------------------------------------------------------------------------- 119 status_t QCameraStream_record::init() 120 { 121 status_t ret = NO_ERROR; 122 ALOGV("%s: BEGIN", __func__); 123 124 /* 125 * Acquiring Video Channel 126 */ 127 ret = QCameraStream::initChannel (mCameraId, MM_CAMERA_CH_VIDEO_MASK); 128 if (NO_ERROR!=ret) { 129 ALOGE("%s ERROR: Can't init native cammera preview ch\n",__func__); 130 return ret; 131 } 132 133 /* 134 * Register the Callback with camera 135 */ 136 (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_VIDEO, 137 record_notify_cb, 138 MM_CAMERA_REG_BUF_CB_INFINITE, 139 0, 140 this); 141 142 mInit = true; 143 ALOGV("%s: END", __func__); 144 return ret; 145 } 146 // --------------------------------------------------------------------------- 147 // QCameraStream_record 148 // --------------------------------------------------------------------------- 149 150 status_t QCameraStream_record::start() 151 { 152 status_t ret = NO_ERROR; 153 ALOGV("%s: BEGIN", __func__); 154 155 Mutex::Autolock lock(mStopCallbackLock); 156 if(!mInit) { 157 ALOGE("%s ERROR: Record buffer not registered",__func__); 158 return BAD_VALUE; 159 } 160 161 setFormat(MM_CAMERA_CH_VIDEO_MASK , (cam_format_t)0); 162 //mRecordFreeQueueLock.lock(); 163 //mRecordFreeQueue.clear(); 164 //mRecordFreeQueueLock.unlock(); 165 /* 166 * Allocating Encoder Frame Buffers 167 */ 168 ret = initEncodeBuffers(); 169 if (NO_ERROR!=ret) { 170 ALOGE("%s ERROR: Buffer Allocation Failed\n",__func__); 171 goto error; 172 } 173 174 ret = cam_config_prepare_buf(mCameraId, &mRecordBuf); 175 if(ret != MM_CAMERA_OK) { 176 ALOGE("%s ERROR: Reg Record buf err=%d\n", __func__, ret); 177 ret = BAD_VALUE; 178 goto error; 179 }else{ 180 ret = NO_ERROR; 181 } 182 183 /* 184 * Start Video Streaming 185 */ 186 ret = cam_ops_action(mCameraId, true, MM_CAMERA_OPS_VIDEO, 0); 187 if (MM_CAMERA_OK != ret) { 188 ALOGE ("%s ERROR: Video streaming start err=%d\n", __func__, ret); 189 ret = BAD_VALUE; 190 goto error; 191 }else{ 192 ALOGV("%s : Video streaming Started",__func__); 193 ret = NO_ERROR; 194 } 195 mActive = true; 196 ALOGV("%s: END", __func__); 197 return ret; 198 199 error: 200 releaseEncodeBuffer(); 201 ALOGV("%s: END", __func__); 202 return ret; 203 } 204 205 void QCameraStream_record::releaseEncodeBuffer() { 206 for(int cnt = 0; cnt < mHalCamCtrl->mRecordingMemory.buffer_count; cnt++) { 207 if (NO_ERROR != 208 mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_VIDEO, cnt, 209 mCameraId, CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) 210 ALOGE("%s: Unmapping Video Data Failed", __func__); 211 212 if (mHalCamCtrl->mStoreMetaDataInFrame) { 213 struct encoder_media_buffer_type * packet = 214 (struct encoder_media_buffer_type *) 215 mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data; 216 native_handle_delete(const_cast<native_handle_t *>(packet->meta_handle)); 217 mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->release( 218 mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]); 219 220 } 221 mHalCamCtrl->mRecordingMemory.camera_memory[cnt]->release( 222 mHalCamCtrl->mRecordingMemory.camera_memory[cnt]); 223 close(mHalCamCtrl->mRecordingMemory.fd[cnt]); 224 mHalCamCtrl->mRecordingMemory.fd[cnt] = -1; 225 226 #ifdef USE_ION 227 mHalCamCtrl->deallocate_ion_memory(&mHalCamCtrl->mRecordingMemory, cnt); 228 #endif 229 } 230 memset(&mHalCamCtrl->mRecordingMemory, 0, sizeof(mHalCamCtrl->mRecordingMemory)); 231 //mNumRecordFrames = 0; 232 delete[] recordframes; 233 if (mRecordBuf.video.video.buf.mp) 234 delete[] mRecordBuf.video.video.buf.mp; 235 } 236 237 // --------------------------------------------------------------------------- 238 // QCameraStream_record 239 // --------------------------------------------------------------------------- 240 void QCameraStream_record::stop() 241 { 242 status_t ret = NO_ERROR; 243 ALOGV("%s: BEGIN", __func__); 244 245 if(!mActive) { 246 ALOGE("%s : Record stream not started",__func__); 247 return; 248 } 249 mActive = false; 250 Mutex::Autolock lock(mStopCallbackLock); 251 #if 0 //mzhu, when stop recording, all frame will be dirty. no need to queue frame back to kernel any more 252 mRecordFreeQueueLock.lock(); 253 while(!mRecordFreeQueue.isEmpty()) { 254 ALOGV("%s : Pre-releasing of Encoder buffers!\n", __FUNCTION__); 255 mm_camera_ch_data_buf_t releasedBuf = mRecordFreeQueue.itemAt(0); 256 mRecordFreeQueue.removeAt(0); 257 mRecordFreeQueueLock.unlock(); 258 ALOGV("%s (%d): releasedBuf.idx = %d\n", __FUNCTION__, __LINE__, 259 releasedBuf.video.video.idx); 260 if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId,&releasedBuf)) 261 ALOGE("%s : Buf Done Failed",__func__); 262 } 263 mRecordFreeQueueLock.unlock(); 264 #if 0 265 while (!mRecordFreeQueue.isEmpty()) { 266 ALOGE("%s : Waiting for Encoder to release all buffer!\n", __FUNCTION__); 267 } 268 #endif 269 #endif // mzhu 270 /* unregister the notify fn from the mmmm_camera_t object 271 * call stop() in parent class to stop the monitor thread */ 272 273 ret = cam_ops_action(mCameraId, false, MM_CAMERA_OPS_VIDEO, 0); 274 if (MM_CAMERA_OK != ret) { 275 ALOGE ("%s ERROR: Video streaming Stop err=%d\n", __func__, ret); 276 } 277 278 ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_VIDEO); 279 if(ret != MM_CAMERA_OK){ 280 ALOGE("%s ERROR: Ureg video buf \n", __func__); 281 } 282 283 releaseEncodeBuffer(); 284 285 mActive = false; 286 ALOGV("%s: END", __func__); 287 288 } 289 // --------------------------------------------------------------------------- 290 // QCameraStream_record 291 // --------------------------------------------------------------------------- 292 void QCameraStream_record::release() 293 { 294 status_t ret = NO_ERROR; 295 ALOGV("%s: BEGIN", __func__); 296 297 if(mActive) { 298 stop(); 299 } 300 if(!mInit) { 301 ALOGE("%s : Record stream not initialized",__func__); 302 return; 303 } 304 305 ret= QCameraStream::deinitChannel(mCameraId, MM_CAMERA_CH_VIDEO); 306 if(ret != MM_CAMERA_OK) { 307 ALOGE("%s:Deinit Video channel failed=%d\n", __func__, ret); 308 } 309 (void)cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_VIDEO, 310 NULL, 311 (mm_camera_register_buf_cb_type_t)NULL, 312 NULL, 313 NULL); 314 mInit = false; 315 ALOGV("%s: END", __func__); 316 } 317 318 status_t QCameraStream_record::processRecordFrame(void *data) 319 { 320 ALOGV("%s : BEGIN",__func__); 321 mm_camera_ch_data_buf_t* frame = (mm_camera_ch_data_buf_t*) data; 322 323 Mutex::Autolock lock(mStopCallbackLock); 324 if(!mActive) { 325 ALOGE("Recording Stopped. Returning callback"); 326 return NO_ERROR; 327 } 328 329 if (UNLIKELY(mDebugFps)) { 330 debugShowVideoFPS(); 331 } 332 333 mHalCamCtrl->dumpFrameToFile(frame->video.video.frame, HAL_DUMP_FRM_VIDEO); 334 mHalCamCtrl->mCallbackLock.lock(); 335 camera_data_timestamp_callback rcb = mHalCamCtrl->mDataCbTimestamp; 336 void *rdata = mHalCamCtrl->mCallbackCookie; 337 mHalCamCtrl->mCallbackLock.unlock(); 338 339 nsecs_t timeStamp = nsecs_t(frame->video.video.frame->ts.tv_sec)*1000000000LL + \ 340 frame->video.video.frame->ts.tv_nsec; 341 342 ALOGV("Send Video frame to services/encoder TimeStamp : %lld",timeStamp); 343 mRecordedFrames[frame->video.video.idx] = *frame; 344 345 #ifdef USE_ION 346 struct ion_flush_data cache_inv_data; 347 int ion_fd; 348 ion_fd = frame->video.video.frame->ion_dev_fd; 349 cache_inv_data.vaddr = (void *)frame->video.video.frame->buffer; 350 cache_inv_data.fd = frame->video.video.frame->fd; 351 cache_inv_data.handle = frame->video.video.frame->fd_data.handle; 352 cache_inv_data.length = frame->video.video.frame->ion_alloc.len; 353 354 if (mHalCamCtrl->cache_ops(ion_fd, &cache_inv_data, ION_IOC_CLEAN_CACHES) < 0) 355 ALOGE("%s: Cache clean for Video buffer %p fd = %d failed", __func__, 356 cache_inv_data.vaddr, cache_inv_data.fd); 357 #endif 358 359 if (mHalCamCtrl->mStoreMetaDataInFrame) { 360 mStopCallbackLock.unlock(); 361 if(mActive && (rcb != NULL) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) { 362 rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, 363 mHalCamCtrl->mRecordingMemory.metadata_memory[frame->video.video.idx], 364 0, mHalCamCtrl->mCallbackCookie); 365 } 366 } else { 367 mStopCallbackLock.unlock(); 368 if(mActive && (rcb != NULL) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) { 369 rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, 370 mHalCamCtrl->mRecordingMemory.camera_memory[frame->video.video.idx], 371 0, mHalCamCtrl->mCallbackCookie); 372 } 373 } 374 375 ALOGV("%s : END",__func__); 376 return NO_ERROR; 377 } 378 379 //Record Related Functions 380 status_t QCameraStream_record::initEncodeBuffers() 381 { 382 ALOGV("%s : BEGIN",__func__); 383 status_t ret = NO_ERROR; 384 const char *pmem_region; 385 uint32_t frame_len; 386 uint8_t num_planes; 387 uint32_t planes[VIDEO_MAX_PLANES]; 388 //cam_ctrl_dimension_t dim; 389 int width = 0; /* width of channel */ 390 int height = 0; /* height of channel */ 391 int buf_cnt; 392 pmem_region = "/dev/pmem_adsp"; 393 394 395 memset(&mHalCamCtrl->mRecordingMemory, 0, sizeof(mHalCamCtrl->mRecordingMemory)); 396 memset(&dim, 0, sizeof(cam_ctrl_dimension_t)); 397 ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim); 398 if (MM_CAMERA_OK != ret) { 399 ALOGE("%s: ERROR - can't get camera dimension!", __func__); 400 return BAD_VALUE; 401 } 402 else { 403 width = dim.video_width; 404 height = dim.video_height; 405 } 406 num_planes = 2; 407 planes[0] = dim.video_frame_offset.mp[0].len; 408 planes[1] = dim.video_frame_offset.mp[1].len; 409 frame_len = dim.video_frame_offset.frame_len; 410 411 buf_cnt = VIDEO_BUFFER_COUNT; 412 if(mHalCamCtrl->isLowPowerCamcorder()) { 413 ALOGV("%s: lower power camcorder selected", __func__); 414 buf_cnt = VIDEO_BUFFER_COUNT_LOW_POWER_CAMCORDER; 415 } 416 recordframes = new msm_frame[buf_cnt]; 417 memset(recordframes,0,sizeof(struct msm_frame) * buf_cnt); 418 419 mRecordBuf.video.video.buf.mp = new mm_camera_mp_buf_t[buf_cnt * 420 sizeof(mm_camera_mp_buf_t)]; 421 if (!mRecordBuf.video.video.buf.mp) { 422 ALOGE("%s Error allocating memory for mplanar struct ", __func__); 423 return BAD_VALUE; 424 } 425 memset(mRecordBuf.video.video.buf.mp, 0, 426 buf_cnt * sizeof(mm_camera_mp_buf_t)); 427 428 memset(&mHalCamCtrl->mRecordingMemory, 0, sizeof(mHalCamCtrl->mRecordingMemory)); 429 for (int i=0; i<MM_CAMERA_MAX_NUM_FRAMES;i++) { 430 mHalCamCtrl->mRecordingMemory.main_ion_fd[i] = -1; 431 mHalCamCtrl->mRecordingMemory.fd[i] = -1; 432 } 433 434 mHalCamCtrl->mRecordingMemory.buffer_count = buf_cnt; 435 436 mHalCamCtrl->mRecordingMemory.size = frame_len; 437 mHalCamCtrl->mRecordingMemory.cbcr_offset = planes[0]; 438 439 for (int cnt = 0; cnt < mHalCamCtrl->mRecordingMemory.buffer_count; cnt++) { 440 #ifdef USE_ION 441 if(mHalCamCtrl->allocate_ion_memory(&mHalCamCtrl->mRecordingMemory, cnt, 442 ((0x1 << CAMERA_ION_HEAP_ID) | (0x1 << CAMERA_ION_FALLBACK_HEAP_ID))) < 0) { 443 ALOGE("%s ION alloc failed\n", __func__); 444 return UNKNOWN_ERROR; 445 } 446 #else 447 mHalCamCtrl->mRecordingMemory.fd[cnt] = open("/dev/pmem_adsp", O_RDWR|O_SYNC); 448 if(mHalCamCtrl->mRecordingMemory.fd[cnt] <= 0) { 449 ALOGE("%s: no pmem for frame %d", __func__, cnt); 450 return UNKNOWN_ERROR; 451 } 452 #endif 453 mHalCamCtrl->mRecordingMemory.camera_memory[cnt] = 454 mHalCamCtrl->mGetMemory(mHalCamCtrl->mRecordingMemory.fd[cnt], 455 mHalCamCtrl->mRecordingMemory.size, 1, (void *)this); 456 457 if (mHalCamCtrl->mStoreMetaDataInFrame) { 458 mHalCamCtrl->mRecordingMemory.metadata_memory[cnt] = 459 mHalCamCtrl->mGetMemory(-1, 460 sizeof(struct encoder_media_buffer_type), 1, (void *)this); 461 struct encoder_media_buffer_type * packet = 462 (struct encoder_media_buffer_type *) 463 mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data; 464 packet->meta_handle = native_handle_create(1, 2); //1 fd, 1 offset and 1 size 465 packet->buffer_type = kMetadataBufferTypeCameraSource; 466 native_handle_t * nh = const_cast<native_handle_t *>(packet->meta_handle); 467 nh->data[0] = mHalCamCtrl->mRecordingMemory.fd[cnt]; 468 nh->data[1] = 0; 469 nh->data[2] = mHalCamCtrl->mRecordingMemory.size; 470 } 471 recordframes[cnt].fd = mHalCamCtrl->mRecordingMemory.fd[cnt]; 472 recordframes[cnt].buffer = (uint32_t)mHalCamCtrl->mRecordingMemory.camera_memory[cnt]->data; 473 recordframes[cnt].y_off = 0; 474 recordframes[cnt].cbcr_off = mHalCamCtrl->mRecordingMemory.cbcr_offset; 475 recordframes[cnt].path = OUTPUT_TYPE_V; 476 recordframes[cnt].fd_data = mHalCamCtrl->mRecordingMemory.ion_info_fd[cnt]; 477 recordframes[cnt].ion_alloc = mHalCamCtrl->mRecordingMemory.alloc[cnt]; 478 recordframes[cnt].ion_dev_fd = mHalCamCtrl->mRecordingMemory.main_ion_fd[cnt]; 479 480 if (NO_ERROR != 481 mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_VIDEO, cnt, 482 recordframes[cnt].fd, mHalCamCtrl->mRecordingMemory.size, mCameraId, 483 CAM_SOCK_MSG_TYPE_FD_MAPPING)) 484 ALOGE("%s: sending mapping data Msg Failed", __func__); 485 486 ALOGV("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d\n", 487 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off, 488 recordframes[cnt].cbcr_off); 489 //mNumRecordFrames++; 490 491 mRecordBuf.video.video.buf.mp[cnt].frame = recordframes[cnt]; 492 mRecordBuf.video.video.buf.mp[cnt].frame_offset = 0; 493 mRecordBuf.video.video.buf.mp[cnt].num_planes = num_planes; 494 /* Plane 0 needs to be set seperately. Set other planes 495 * in a loop. */ 496 mRecordBuf.video.video.buf.mp[cnt].planes[0].reserved[0] = 497 mRecordBuf.video.video.buf.mp[cnt].frame_offset; 498 mRecordBuf.video.video.buf.mp[cnt].planes[0].length = planes[0]; 499 mRecordBuf.video.video.buf.mp[cnt].planes[0].m.userptr = 500 recordframes[cnt].fd; 501 for (int j = 1; j < num_planes; j++) { 502 mRecordBuf.video.video.buf.mp[cnt].planes[j].length = planes[j]; 503 mRecordBuf.video.video.buf.mp[cnt].planes[j].m.userptr = 504 recordframes[cnt].fd; 505 mRecordBuf.video.video.buf.mp[cnt].planes[j].reserved[0] = 506 mRecordBuf.video.video.buf.mp[cnt].planes[j-1].reserved[0] + 507 mRecordBuf.video.video.buf.mp[cnt].planes[j-1].length; 508 } 509 } 510 511 //memset(&mRecordBuf, 0, sizeof(mRecordBuf)); 512 mRecordBuf.ch_type = MM_CAMERA_CH_VIDEO; 513 mRecordBuf.video.video.num = mHalCamCtrl->mRecordingMemory.buffer_count;//kRecordBufferCount; 514 //mRecordBuf.video.video.frame_offset = &record_offset[0]; 515 //mRecordBuf.video.video.frame = &recordframes[0]; 516 ALOGV("%s : END",__func__); 517 return NO_ERROR; 518 } 519 520 void QCameraStream_record::releaseRecordingFrame(const void *opaque) 521 { 522 ALOGV("%s : BEGIN, opaque = 0x%p",__func__, opaque); 523 if(!mActive) 524 { 525 ALOGE("%s : Recording already stopped!!! Leak???",__func__); 526 return; 527 } 528 for(int cnt = 0; cnt < mHalCamCtrl->mRecordingMemory.buffer_count; cnt++) { 529 if (mHalCamCtrl->mStoreMetaDataInFrame) { 530 if(mHalCamCtrl->mRecordingMemory.metadata_memory[cnt] && 531 mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data == opaque) { 532 /* found the match */ 533 if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId, &mRecordedFrames[cnt])) 534 ALOGE("%s : Buf Done Failed",__func__); 535 ALOGV("%s : END",__func__); 536 return; 537 } 538 } else { 539 if(mHalCamCtrl->mRecordingMemory.camera_memory[cnt] && 540 mHalCamCtrl->mRecordingMemory.camera_memory[cnt]->data == opaque) { 541 /* found the match */ 542 if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId, &mRecordedFrames[cnt])) 543 ALOGE("%s : Buf Done Failed",__func__); 544 ALOGV("%s : END",__func__); 545 return; 546 } 547 } 548 } 549 ALOGE("%s: cannot find the matched frame with opaue = 0x%p", __func__, opaque); 550 } 551 552 void QCameraStream_record::debugShowVideoFPS() const 553 { 554 static int mFrameCount; 555 static int mLastFrameCount = 0; 556 static nsecs_t mLastFpsTime = 0; 557 static float mFps = 0; 558 mFrameCount++; 559 nsecs_t now = systemTime(); 560 nsecs_t diff = now - mLastFpsTime; 561 if (diff > ms2ns(250)) { 562 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff; 563 ALOGV("Video Frames Per Second: %.4f", mFps); 564 mLastFpsTime = now; 565 mLastFrameCount = mFrameCount; 566 } 567 } 568 569 #if 0 570 sp<IMemoryHeap> QCameraStream_record::getHeap() const 571 { 572 return mRecordHeap != NULL ? mRecordHeap->mHeap : NULL; 573 } 574 575 #endif 576 status_t QCameraStream_record::takeLiveSnapshot(){ 577 return true; 578 } 579 580 }//namespace android 581 582