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