1/*
2** Copyright (c) 2011-2012 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 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
34namespace android {
35
36status_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
52int 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
73status_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
160error:
161    mPreviewMemoryLock.unlock();
162
163    ALOGV("%s: X", __func__);
164    return ret;
165}
166
167void 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
180void 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
210int 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
245status_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
322QCameraStream_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
363QCameraStream_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
385status_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
428status_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
474end:
475    ALOGE("%s: X", __func__);
476    return ret;
477  }
478
479
480// ---------------------------------------------------------------------------
481// QCameraStream_preview
482// ---------------------------------------------------------------------------
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// ---------------------------------------------------------------------------
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
548QCameraStream*
549QCameraStream_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
570void 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 */
583void *QCameraStream_preview::getLastQueuedFrame(void)
584{
585    return mLastQueuedFrame;
586}
587
588// ---------------------------------------------------------------------------
589// No code beyone this line
590// ---------------------------------------------------------------------------
591}; // namespace android
592