blob: f9da650ff883698002147843522b10235e9f59ad [file] [log] [blame]
Iliyan Malchev6d016452013-03-27 16:27:56 -07001/*
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// ---------------------------------------------------------------------------
38namespace android {
39
40
41QCameraStream* 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// ---------------------------------------------------------------------------
53void 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// ---------------------------------------------------------------------------
67QCameraStream_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// ---------------------------------------------------------------------------
85QCameraStream_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// ---------------------------------------------------------------------------
102static 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// ---------------------------------------------------------------------------
119status_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
150status_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
199error:
200 releaseEncodeBuffer();
201 ALOGV("%s: END", __func__);
202 return ret;
203}
204
205void 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// ---------------------------------------------------------------------------
240void 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// ---------------------------------------------------------------------------
292void 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
318status_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
380status_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
520void 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
552void 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
570sp<IMemoryHeap> QCameraStream_record::getHeap() const
571{
572 return mRecordHeap != NULL ? mRecordHeap->mHeap : NULL;
573}
574
575#endif
576status_t QCameraStream_record::takeLiveSnapshot(){
577 return true;
578}
579
580}//namespace android
581