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