1 /*
2 ** Copyright (c) 2011-2012 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_TAG "QCameraHWI_Preview"
20 #include <utils/Log.h>
21 #include <utils/threads.h>
22 #include <fcntl.h>
23 #include <sys/mman.h>
24 #include "QCameraHAL.h"
25 #include "QCameraHWI.h"
26 #include <genlock.h>
27 #include <gralloc_priv.h>
28
29 #define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
30
31 /* QCameraHWI_Preview class implementation goes here*/
32 /* following code implement the preview mode's image capture & display logic of this class*/
33
34 namespace android {
35
setPreviewWindow(const camera2_stream_ops_t * window)36 status_t QCameraStream_preview::setPreviewWindow(const camera2_stream_ops_t* window)
37 {
38 status_t retVal = NO_ERROR;
39 ALOGE(" %s: E ", __FUNCTION__);
40 if( window == NULL) {
41 ALOGW(" Setting NULL preview window ");
42 /* TODO: Current preview window will be invalidated.
43 * Release all the buffers back */
44 // relinquishBuffers();
45 }
46 Mutex::Autolock lock(mLock);
47 mPreviewWindow = window;
48 ALOGV(" %s : X ", __FUNCTION__ );
49 return retVal;
50 }
51
registerStreamBuffers(int num_buffers,buffer_handle_t * buffers)52 int QCameraStream_preview::registerStreamBuffers(int num_buffers,
53 buffer_handle_t *buffers)
54 {
55 int err;
56
57 mNumBuffers = num_buffers;
58 mPreviewMemory.buffer_count = num_buffers;
59 for (int i = 0; i < num_buffers; i++) {
60 mPreviewMemory.buffer_handle[i] = buffers[i];
61 mPreviewMemory.private_buffer_handle[i] = (struct private_handle_t *)buffers[i];
62 ALOGD("%s:Buffer Size:%d",__func__, mPreviewMemory.private_buffer_handle[i]->size);
63 }
64 mDisplayBuf = new mm_camera_buf_def_t[num_buffers];
65 if (!mDisplayBuf) {
66 ALOGE("Unable to allocate mDisplayBuf");
67 return NO_MEMORY;
68 }
69
70 return OK;
71 }
72
initBuffers()73 status_t QCameraStream_preview::initBuffers()
74 {
75 status_t ret = NO_ERROR;
76 int width = mWidth; /* width of channel */
77 int height = mHeight; /* height of channel */
78 uint32_t frame_len = mFrameOffsetInfo.frame_len; /* frame planner length */
79 int buffer_num = mNumBuffers; /* number of buffers for display */
80 const char *pmem_region;
81 uint8_t num_planes = mFrameOffsetInfo.num_planes;
82 uint32_t planes[VIDEO_MAX_PLANES];
83 void *vaddr = NULL;
84 buffer_handle_t *buffer_handle;
85
86 ALOGE("%s:BEGIN",__func__);
87 memset(mNotifyBuffer, 0, sizeof(mNotifyBuffer));
88
89 this->myMode=myMode; /*Need to assign this in constructor after translating from mask*/
90 num_planes = mFrameOffsetInfo.num_planes;
91 for(int i=0; i < num_planes; i++)
92 planes[i] = mFrameOffsetInfo.mp[i].len;
93
94
95 mPreviewMemoryLock.lock();
96 memset(mDisplayBuf, 0, sizeof(mm_camera_buf_def_t) * mNumBuffers);
97
98 /*allocate memory for the buffers*/
99 for(int i = 0; i < mNumBuffers; i++){
100 mDisplayBuf[i].num_planes = num_planes;
101 mDisplayBuf[i].buf_idx = i;
102
103 /* Plane 0 needs to be set seperately. Set other planes
104 * in a loop. */
105 mDisplayBuf[i].planes[0].length = planes[0];
106 mDisplayBuf[i].planes[0].m.userptr = mPreviewMemory.private_buffer_handle[i]->fd;
107 mDisplayBuf[i].planes[0].data_offset = mFrameOffsetInfo.mp[0].offset;
108 mDisplayBuf[i].planes[0].reserved[0] =0;
109 for (int j = 1; j < num_planes; j++) {
110 mDisplayBuf[i].planes[j].length = planes[j];
111 mDisplayBuf[i].planes[j].m.userptr = mPreviewMemory.private_buffer_handle[i]->fd;
112 mDisplayBuf[i].planes[j].data_offset = mFrameOffsetInfo.mp[j].offset;
113 mDisplayBuf[i].planes[j].reserved[0] =
114 mDisplayBuf[i].planes[j-1].reserved[0] +
115 mDisplayBuf[i].planes[j-1].length;
116 }
117
118 for (int j = 0; j < num_planes; j++)
119 ALOGE("Planes: %d length: %d userptr: %lu offset: %d\n", j,
120 mDisplayBuf[i].planes[j].length,
121 mDisplayBuf[i].planes[j].m.userptr,
122 mDisplayBuf[i].planes[j].reserved[0]);
123
124 mDisplayBuf[i].stream_id = mMmStreamId;
125 mDisplayBuf[i].fd = mPreviewMemory.private_buffer_handle[i]->fd;
126 ALOGE("DEBUG2:Display buf[%d] fd:%d",i,mDisplayBuf[i].fd);
127 mDisplayBuf[i].frame_len = mFrameOffsetInfo.frame_len;
128 }/*end of for loop*/
129
130 /* Dequeue N frames from native window and queue into interface. Only dequeue our requested buffers */
131 for (int i = 0; i < mNumBuffers; i++)
132 mPreviewMemory.local_flag[i] = BUFFER_NOT_REGGED;
133 for (int i = 0; i < OPAQUE_BUFFER_COUNT; i++) {
134 ALOGE("mPreview Window %p",mPreviewWindow);
135 int err = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer_handle);
136 if (err == NO_ERROR && buffer_handle) {
137 int j;
138 for (j = 0; j < mPreviewMemory.buffer_count; j++) {
139 if (mPreviewMemory.buffer_handle[j] == *buffer_handle) {
140 mPreviewMemory.local_flag[j] = BUFFER_OWNED;
141 ALOGE("%s: [%d]: local_flag = 1", __func__, j);
142 break;
143 }
144 }
145 if (j == mPreviewMemory.buffer_count) {
146 ALOGE("Cannot find matching handle in the table.");
147 return INVALID_OPERATION;
148 }
149 } else {
150 ALOGE("dequeue_buffer failed.");
151 return INVALID_OPERATION;
152 }
153 }
154
155 /* register the streaming buffers for the channel*/
156 mPreviewMemoryLock.unlock();
157 ALOGE("%s:END",__func__);
158 return NO_ERROR;
159
160 error:
161 mPreviewMemoryLock.unlock();
162
163 ALOGV("%s: X", __func__);
164 return ret;
165 }
166
deinitBuffers()167 void QCameraStream_preview::deinitBuffers()
168 {
169 mPreviewMemoryLock.lock();
170 for (int i = 0; i < mNumBuffers; i++) {
171 if (mPreviewMemory.local_flag[i] == BUFFER_OWNED) {
172 mPreviewWindow->cancel_buffer(mPreviewWindow,
173 &mPreviewMemory.buffer_handle[i]);
174 mPreviewMemory.local_flag[i] = BUFFER_NOT_OWNED;
175 }
176 }
177 mPreviewMemoryLock.unlock();
178 }
179
dumpFrameToFile(mm_camera_buf_def_t * newFrame)180 void QCameraStream_preview::dumpFrameToFile(mm_camera_buf_def_t *newFrame)
181 {
182 int32_t enabled = 0;
183 int frm_num;
184 uint32_t skip_mode;
185 char value[PROPERTY_VALUE_MAX];
186 char buf[32];
187 int w, h;
188 static int count = 0;
189 int file_fd;
190 int rc = 0;
191 int len;
192 unsigned long addr;
193 unsigned long * tmp = (unsigned long *)newFrame->buffer;
194 addr = *tmp;
195
196 len = newFrame->frame_len;
197 count++;
198 if(count < 100) {
199 snprintf(buf, sizeof(buf), "/data/mzhu%d.yuv", count);
200 file_fd = open(buf, O_RDWR | O_CREAT, 0777);
201
202 rc = write(file_fd, (const void *)addr, len);
203 ALOGE("%s: file='%s', vaddr_old=0x%x, addr_map = 0x%p, len = %d, rc = %d",
204 __func__, buf, (uint32_t)newFrame->buffer, (void *)addr, len, rc);
205 close(file_fd);
206 ALOGE("%s: dump %s, rc = %d, len = %d", __func__, buf, rc, len);
207 }
208 }
209
prepareStream()210 int QCameraStream_preview::prepareStream()
211 {
212 mm_camera_img_mode img_mode;
213 cam_format_t format;
214 struct private_handle_t *private_handle = mPreviewMemory.private_buffer_handle[0];
215
216 ALOGE("%s: private_handle->format = %d, flags = %d", __func__,
217 private_handle->format, private_handle->flags);
218 if (private_handle->flags & private_handle_t::PRIV_FLAGS_VIDEO_ENCODER)
219 img_mode = MM_CAMERA_VIDEO;
220 else if (private_handle->flags & private_handle_t::PRIV_FLAGS_CAMERA_WRITE)
221 img_mode = MM_CAMERA_PREVIEW;
222 else {
223 ALOGE("%s: Invalid flags %d\n", __func__, private_handle->flags);
224 return BAD_VALUE;
225 }
226
227 switch (private_handle->format) {
228 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
229 format = CAMERA_YUV_420_NV12;
230 break;
231 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
232 format = CAMERA_YUV_420_NV21;
233 break;
234 default:
235 ALOGE("%s: Invalid format!!!", __func__);
236 return BAD_VALUE;
237 }
238 if(NO_ERROR!=initStream(img_mode, format)) {
239 ALOGE("Init stream failed");
240 return BAD_VALUE;
241 }
242 return OK;
243 }
244
processPreviewFrame(mm_camera_super_buf_t * frame)245 status_t QCameraStream_preview::processPreviewFrame (
246 mm_camera_super_buf_t *frame)
247 {
248 ALOGV("%s",__func__);
249 int err = 0;
250 int msgType = 0;
251 int i;
252 camera_frame_metadata_t *metadata = NULL;
253
254 Mutex::Autolock lock(mLock);
255 if(!mActive) {
256 ALOGE("Preview Stopped. Returning callback");
257 return NO_ERROR;
258 }
259
260 if(mHalCamCtrl==NULL) {
261 ALOGE("%s: X: HAL control object not set",__func__);
262 /*Call buf done*/
263 return BAD_VALUE;
264 }
265 nsecs_t timeStamp = seconds_to_nanoseconds(frame->bufs[0]->ts.tv_sec) ;
266 timeStamp += frame->bufs[0]->ts.tv_nsec;
267
268 if(mFirstFrameRcvd == false) {
269 //mm_camera_util_profile("HAL: First preview frame received");
270 mFirstFrameRcvd = true;
271 }
272
273 // dumpFrameToFile(frame->bufs[0]);
274
275 mPreviewMemoryLock.lock();
276 mNotifyBuffer[frame->bufs[0]->buf_idx] = *frame;
277 ALOGE("processPreviewFrame: timeStamp = %lld", (int64_t)timeStamp);
278 err = mPreviewWindow->enqueue_buffer(mPreviewWindow, (int64_t)timeStamp,
279 &mPreviewMemory.buffer_handle[frame->bufs[0]->buf_idx]);
280 if(err != 0) {
281 ALOGE("%s: enqueue_buffer failed, err = %d", __func__, err);
282 }
283 mPreviewMemory.local_flag[frame->bufs[0]->buf_idx] = BUFFER_NOT_OWNED;
284
285 buffer_handle_t *buffer_handle = NULL;
286 err = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer_handle);
287 if (err == NO_ERROR && buffer_handle != NULL) {
288 int rc = MM_CAMERA_OK;
289 ALOGD("%s: dequed buf hdl =%p", __func__, *buffer_handle);
290 for(i = 0; i < mPreviewMemory.buffer_count; i++) {
291 if(mPreviewMemory.buffer_handle[i] == *buffer_handle) {
292 ALOGE("<DEBUG2>:Found buffer in idx:%d",i);
293 break;
294 }
295 }
296 if (mPreviewMemory.local_flag[i] == BUFFER_NOT_REGGED) {
297 mm_camera_buf_def_t buf = mDisplayBuf[i];
298 mPreviewMemory.local_flag[i] = BUFFER_OWNED;
299 rc = p_mm_ops->ops->qbuf(mCameraHandle, mChannelId, &buf);
300 } else {
301 mPreviewMemory.local_flag[i] = BUFFER_OWNED;
302 rc = p_mm_ops->ops->qbuf(mCameraHandle, mChannelId, mNotifyBuffer[i].bufs[0]);
303 }
304
305 if(rc != MM_CAMERA_OK) {
306 /* how to handle the error of qbuf? */
307 ALOGE("BUF DONE FAILED");
308 }
309 }
310 /* Save the last displayed frame. We'll be using it to fill the gap between
311 when preview stops and postview start during snapshot.*/
312 mLastQueuedFrame = &(mDisplayBuf[frame->bufs[0]->buf_idx]);
313 mPreviewMemoryLock.unlock();
314
315 return NO_ERROR;
316 }
317
318 // ---------------------------------------------------------------------------
319 // QCameraStream_preview
320 // ---------------------------------------------------------------------------
321
QCameraStream_preview(uint32_t CameraHandle,uint32_t ChannelId,uint32_t Width,uint32_t Height,int requestedFormat,mm_camera_vtbl_t * mm_ops,camera_mode_t mode)322 QCameraStream_preview::QCameraStream_preview(uint32_t CameraHandle,
323 uint32_t ChannelId,
324 uint32_t Width,
325 uint32_t Height,
326 int requestedFormat,
327 mm_camera_vtbl_t *mm_ops,
328 camera_mode_t mode) :
329 QCameraStream(CameraHandle,
330 ChannelId,
331 Width,
332 Height,
333 mm_ops,
334 mode),
335 mLastQueuedFrame(NULL),
336 mDisplayBuf(NULL),
337 mNumFDRcvd(0)
338 {
339 mHalCamCtrl = NULL;
340 ALOGE("%s: E", __func__);
341
342 mStreamId = allocateStreamId();
343
344 switch (requestedFormat) {
345 case CAMERA2_HAL_PIXEL_FORMAT_OPAQUE:
346 mMaxBuffers = 5;
347 break;
348 case HAL_PIXEL_FORMAT_BLOB:
349 mMaxBuffers = 1;
350 break;
351 default:
352 ALOGE("Unsupported requested format %d", requestedFormat);
353 mMaxBuffers = 1;
354 break;
355 }
356 /*TODO: There has to be a better way to do this*/
357 ALOGE("%s: X", __func__);
358 }
359 // ---------------------------------------------------------------------------
360 // QCameraStream_preview
361 // ---------------------------------------------------------------------------
362
~QCameraStream_preview()363 QCameraStream_preview::~QCameraStream_preview() {
364 ALOGV("%s: E", __func__);
365 if(mActive) {
366 streamOff(0);
367 }
368 if(mInit) {
369 deinitStream();
370 }
371 mInit = false;
372 mActive = false;
373 if (mDisplayBuf) {
374 delete[] mDisplayBuf;
375 mDisplayBuf = NULL;
376 }
377 deallocateStreamId(mStreamId);
378 ALOGV("%s: X", __func__);
379
380 }
381 // ---------------------------------------------------------------------------
382 // QCameraStream_preview
383 // ---------------------------------------------------------------------------
384
init()385 status_t QCameraStream_preview::init()
386 {
387 status_t ret = NO_ERROR;
388 ALOGV("%s: E", __func__);
389
390 #if 0
391 if (!(myMode & CAMERA_ZSL_MODE)) {
392 ALOGE("Setting OP MODE to MM_CAMERA_OP_MODE_VIDEO");
393 mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_VIDEO;
394 ret = p_mm_ops->ops->set_parm (mCameraHandle, MM_CAMERA_PARM_OP_MODE,
395 &op_mode);
396 ALOGE("OP Mode Set");
397
398 if(MM_CAMERA_OK != ret) {
399 ALOGE("%s: X :set mode MM_CAMERA_OP_MODE_VIDEO err=%d\n", __func__, ret);
400 return BAD_VALUE;
401 }
402 }else {
403 ALOGE("Setting OP MODE to MM_CAMERA_OP_MODE_ZSL");
404 mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_ZSL;
405 ret =p_mm_ops->ops->set_parm (mCameraHandle, MM_CAMERA_PARM_OP_MODE,
406 &op_mode);
407 if(MM_CAMERA_OK != ret) {
408 ALOGE("%s: X :set mode MM_CAMERA_OP_MODE_ZSL err=%d\n", __func__, ret);
409 return BAD_VALUE;
410 }
411 }
412
413 setFormat();
414 ret = QCameraStream::initStream();
415 if (NO_ERROR!=ret) {
416 ALOGE("%s E: can't init native cammera preview ch\n",__func__);
417 return ret;
418 }
419
420 mInit = true;
421 #endif
422 return ret;
423 }
424 // ---------------------------------------------------------------------------
425 // QCameraStream_preview
426 // ---------------------------------------------------------------------------
427
start()428 status_t QCameraStream_preview::start()
429 {
430 ALOGV("%s: E", __func__);
431 status_t ret = NO_ERROR;
432
433 Mutex::Autolock lock(mLock);
434
435 /* call start() in parent class to start the monitor thread*/
436 //QCameraStream::start ();
437
438 #if 0
439 ret = cam_config_prepare_buf(mCameraId, &mDisplayBuf);
440 ALOGE("Debug : %s : cam_config_prepare_buf",__func__);
441 if(ret != MM_CAMERA_OK) {
442 ALOGV("%s:reg preview buf err=%d\n", __func__, ret);
443 ret = BAD_VALUE;
444 goto error;
445 }else {
446 ret = NO_ERROR;
447 }
448 #endif
449 /* For preview, the OP_MODE we set is dependent upon whether we are
450 starting camera or camcorder. For snapshot, anyway we disable preview.
451 However, for ZSL we need to set OP_MODE to OP_MODE_ZSL and not
452 OP_MODE_VIDEO. We'll set that for now in CamCtrl. So in case of
453 ZSL we skip setting Mode here */
454
455
456 /* call mm_camera action start(...) */
457 ALOGE("Starting Preview/Video Stream. ");
458 mFirstFrameRcvd = false;
459
460 ALOGE("Starting Preview/Video Stream. ");
461 ret = streamOn();
462 if (MM_CAMERA_OK != ret) {
463 ALOGE ("%s: preview streaming start err=%d\n", __func__, ret);
464 ret = BAD_VALUE;
465 goto end;
466 }
467
468 ALOGE("Debug : %s : Preview streaming Started",__func__);
469 ret = NO_ERROR;
470
471 mActive = true;
472 goto end;
473
474 end:
475 ALOGE("%s: X", __func__);
476 return ret;
477 }
478
479
480 // ---------------------------------------------------------------------------
481 // QCameraStream_preview
482 // ---------------------------------------------------------------------------
stop()483 void QCameraStream_preview::stop() {
484 ALOGE("%s: E", __func__);
485 int ret=MM_CAMERA_OK;
486
487 if(!mActive) {
488 return;
489 }
490 Mutex::Autolock lock(mLock);
491 mActive = false;
492 /* unregister the notify fn from the mmmm_camera_t object*/
493
494 ALOGI("%s: Stop the thread \n", __func__);
495 /* call stop() in parent class to stop the monitor thread*/
496 //stream_info = mHalCamCtrl->getChannelInterface();
497
498 ret = streamOff(0);
499 if(MM_CAMERA_OK != ret) {
500 ALOGE ("%s: camera preview stop err=%d\n", __func__, ret);
501 }
502 #if 0
503 ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_PREVIEW);
504 if(ret != MM_CAMERA_OK) {
505 ALOGE("%s:Unreg preview buf err=%d\n", __func__, ret);
506 //ret = BAD_VALUE;
507 }
508 #endif
509 /* In case of a clean stop, we need to clean all buffers*/
510 ALOGE("Debug : %s : Buffer Unprepared",__func__);
511 /*free camera_memory handles and return buffer back to surface*/
512 ret= QCameraStream::deinitStream();
513 ALOGE(": %s : De init Channel",__func__);
514 if(ret != MM_CAMERA_OK) {
515 ALOGE("%s:Deinit preview channel failed=%d\n", __func__, ret);
516 //ret = BAD_VALUE;
517 }
518 ALOGE("%s: X", __func__);
519
520 }
521 // ---------------------------------------------------------------------------
522 // QCameraStream_preview
523 // ---------------------------------------------------------------------------
release()524 void QCameraStream_preview::release() {
525
526 ALOGE("%s : BEGIN",__func__);
527 int ret=MM_CAMERA_OK,i;
528
529 if(!mInit)
530 {
531 ALOGE("%s : Stream not Initalized",__func__);
532 return;
533 }
534
535 if(mActive) {
536 this->streamOff(0);
537 }
538
539
540 if(mInit) {
541 deinitStream();
542 }
543 mInit = false;
544 ALOGE("%s: END", __func__);
545
546 }
547
548 QCameraStream*
createInstance(uint32_t CameraHandle,uint32_t ChannelId,uint32_t Width,uint32_t Height,int requestedFormat,mm_camera_vtbl_t * mm_ops,camera_mode_t mode)549 QCameraStream_preview::createInstance(uint32_t CameraHandle,
550 uint32_t ChannelId,
551 uint32_t Width,
552 uint32_t Height,
553 int requestedFormat,
554 mm_camera_vtbl_t *mm_ops,
555 camera_mode_t mode)
556 {
557 QCameraStream* pme = new QCameraStream_preview(CameraHandle,
558 ChannelId,
559 Width,
560 Height,
561 requestedFormat,
562 mm_ops,
563 mode);
564 return pme;
565 }
566 // ---------------------------------------------------------------------------
567 // QCameraStream_preview
568 // ---------------------------------------------------------------------------
569
deleteInstance(QCameraStream * p)570 void QCameraStream_preview::deleteInstance(QCameraStream *p)
571 {
572 if (p){
573 ALOGV("%s: BEGIN", __func__);
574 p->release();
575 delete p;
576 p = NULL;
577 ALOGV("%s: END", __func__);
578 }
579 }
580
581
582 /* Temp helper function */
getLastQueuedFrame(void)583 void *QCameraStream_preview::getLastQueuedFrame(void)
584 {
585 return mLastQueuedFrame;
586 }
587
588 // ---------------------------------------------------------------------------
589 // No code beyone this line
590 // ---------------------------------------------------------------------------
591 }; // namespace android
592