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_NDEBUG 0
20 #define ALOG_NIDEBUG 0
21 #define LOG_TAG __FILE__
22 #include <utils/Log.h>
23 #include <utils/threads.h>
24 
25 #include "QCameraHWI.h"
26 #include "QCameraStream.h"
27 
28 /* QCameraStream class implementation goes here*/
29 /* following code implement the control logic of this class*/
30 
31 namespace android {
32 
StreamQueue()33 StreamQueue::StreamQueue(){
34     mInitialized = false;
35 }
36 
~StreamQueue()37 StreamQueue::~StreamQueue(){
38     flush();
39 }
40 
init()41 void StreamQueue::init(){
42     Mutex::Autolock l(&mQueueLock);
43     mInitialized = true;
44     mQueueWait.signal();
45 }
46 
deinit()47 void StreamQueue::deinit(){
48     Mutex::Autolock l(&mQueueLock);
49     mInitialized = false;
50     mQueueWait.signal();
51 }
52 
isInitialized()53 bool StreamQueue::isInitialized(){
54    Mutex::Autolock l(&mQueueLock);
55    return mInitialized;
56 }
57 
enqueue(void * element)58 bool StreamQueue::enqueue(
59                  void * element){
60     Mutex::Autolock l(&mQueueLock);
61     if(mInitialized == false)
62         return false;
63 
64     mContainer.add(element);
65     mQueueWait.signal();
66     return true;
67 }
68 
isEmpty()69 bool StreamQueue::isEmpty(){
70     return (mInitialized && mContainer.isEmpty());
71 }
dequeue()72 void* StreamQueue::dequeue(){
73 
74     void *frame;
75     mQueueLock.lock();
76     while(mInitialized && mContainer.isEmpty()){
77         mQueueWait.wait(mQueueLock);
78     }
79 
80     if(!mInitialized){
81         mQueueLock.unlock();
82         return NULL;
83     }
84 
85     frame = mContainer.itemAt(0);
86     mContainer.removeAt(0);
87     mQueueLock.unlock();
88     return frame;
89 }
90 
flush()91 void StreamQueue::flush(){
92     Mutex::Autolock l(&mQueueLock);
93     mContainer.clear();
94 }
95 
96 
97 // ---------------------------------------------------------------------------
98 // QCameraStream
99 // ---------------------------------------------------------------------------
100 
superbuf_cb_routine(mm_camera_super_buf_t * bufs,void * userdata)101 void superbuf_cb_routine(mm_camera_super_buf_t *bufs,
102                        void *userdata)
103 {
104     QCameraHardwareInterface *p_obj=(QCameraHardwareInterface*) userdata;
105     ALOGE("%s: E",__func__);
106 
107     //Implement call to JPEG routine in Snapshot here
108      if(bufs->bufs[0]->stream_id == p_obj->mStreamSnapMain->mMmStreamId){
109          ALOGE("%s : jpeg callback for MM_CAMERA_SNAPSHOT_MAIN", __func__);
110          p_obj->mStreamSnapMain->receiveRawPicture(bufs);
111      }
112 
113 
114     for(int i=0;i<bufs->num_bufs;i++) {
115 
116         p_obj->mCameraHandle->ops->qbuf(p_obj->mCameraHandle->camera_handle,
117                                        p_obj->mChannelId,
118                                        bufs->bufs[i]);
119 
120     }
121 
122 
123 }
124 
stream_cb_routine(mm_camera_super_buf_t * bufs,void * userdata)125 void stream_cb_routine(mm_camera_super_buf_t *bufs,
126                        void *userdata)
127 {
128     ALOGE("%s E ", __func__);
129     QCameraStream *p_obj=(QCameraStream*) userdata;
130     ALOGE("DEBUG4:ExtMode:%d,streamid:%d",p_obj->mExtImgMode,bufs->bufs[0]->stream_id);
131     switch(p_obj->mExtImgMode) {
132     case MM_CAMERA_PREVIEW:
133         ALOGE("%s : callback for MM_CAMERA_PREVIEW", __func__);
134         ((QCameraStream_preview *)p_obj)->dataCallback(bufs);
135         break;
136     case MM_CAMERA_VIDEO:
137         ALOGE("%s : callback for MM_CAMERA_VIDEO", __func__);
138         ((QCameraStream_preview *)p_obj)->dataCallback(bufs);
139         break;
140     case MM_CAMERA_SNAPSHOT_MAIN:
141 #if 0
142                 if(p_obj->mHalCamCtrl->getHDRMode()) {
143                     ALOGE("%s: Skipping Q Buf for HDR mode",__func__);
144                     break;
145                 }
146 #endif
147 
148                 ALOGE("%s : callback for MM_CAMERA_SNAPSHOT_MAIN", __func__);
149                 p_obj->p_mm_ops->ops->qbuf(p_obj->mCameraHandle,
150                                            p_obj->mChannelId,
151                                            bufs->bufs[0]);
152                 break;
153          case MM_CAMERA_SNAPSHOT_THUMBNAIL:
154                 break;
155          default:
156                 break;
157 
158     }
159     ALOGE("%s X ", __func__);
160 }
161 
162 QCameraStream *QCameraStream::mStreamTable[STREAM_TABLE_SIZE];
163 
dataCallback(mm_camera_super_buf_t * bufs)164 void QCameraStream::dataCallback(mm_camera_super_buf_t *bufs)
165 {
166     if(mPendingCount!=0) {
167         ALOGD("Got frame request");
168         pthread_mutex_lock(&mFrameDeliveredMutex);
169         mPendingCount--;
170         ALOGD("Completed frame request");
171         pthread_cond_signal(&mFrameDeliveredCond);
172         pthread_mutex_unlock(&mFrameDeliveredMutex);
173         processPreviewFrame(bufs);
174     } else {
175         p_mm_ops->ops->qbuf(mCameraHandle,
176                 mChannelId, bufs->bufs[0]);
177     }
178 }
179 
onNewRequest()180 void QCameraStream::onNewRequest()
181 {
182     ALOGI("%s:E",__func__);
183     pthread_mutex_lock(&mFrameDeliveredMutex);
184     ALOGI("Sending Frame request");
185     mPendingCount++;
186     pthread_cond_wait(&mFrameDeliveredCond,&mFrameDeliveredMutex);
187     ALOGV("Got frame");
188     pthread_mutex_unlock(&mFrameDeliveredMutex);
189     ALOGV("%s:X",__func__);
190 }
191 
streamOn()192 int32_t QCameraStream::streamOn()
193 {
194    status_t rc=NO_ERROR;
195    mm_camera_stream_config_t stream_config;
196    ALOGE("%s:streamid:%d",__func__,mMmStreamId);
197    Mutex::Autolock lock(mLock);
198    if(mActive){
199        ALOGE("%s: Stream:%d is already active",
200             __func__,mMmStreamId);
201        return rc;
202    }
203 
204    if (mInit == true) {
205        /* this is the restart case */
206        memset(&stream_config, 0, sizeof(mm_camera_stream_config_t));
207        stream_config.fmt.fmt=(cam_format_t)mFormat;
208        stream_config.fmt.meta_header=MM_CAMEAR_META_DATA_TYPE_DEF;
209        stream_config.fmt.width=mWidth;
210        stream_config.fmt.height=mHeight;
211        stream_config.fmt.rotation = 0;
212        ALOGE("<DEBUG>::%s: Width :%d Height:%d Format:%d",__func__,mWidth,mHeight,mFormat);
213        stream_config.num_of_bufs=mNumBuffers;
214        stream_config.need_stream_on=true;
215        rc=p_mm_ops->ops->config_stream(mCameraHandle,
216                                  mChannelId,
217                                  mMmStreamId,
218                                  &stream_config);
219        ALOGE("%s: config_stream, rc = %d", __func__, rc);
220    }
221 
222    rc = p_mm_ops->ops->start_streams(mCameraHandle,
223                               mChannelId,
224                               1,
225                               &mMmStreamId);
226    if(rc==NO_ERROR)
227        mActive = true;
228    return rc;
229 }
230 
streamOff(bool isAsyncCmd)231 int32_t QCameraStream::streamOff(bool isAsyncCmd)
232 {
233     status_t rc=NO_ERROR;
234     Mutex::Autolock lock(mLock);
235     if(!mActive) {
236         ALOGE("%s: Stream:%d is not active",
237               __func__,mMmStreamId);
238         return rc;
239     }
240 
241     rc = p_mm_ops->ops->stop_streams(mCameraHandle,
242                               mChannelId,
243                               1,
244                               &mMmStreamId);
245 
246     mActive=false;
247     return rc;
248 
249 }
250 
251 /* initialize a streaming channel*/
initStream(mm_camera_img_mode imgmode,cam_format_t format)252 status_t QCameraStream::initStream(mm_camera_img_mode imgmode,
253     cam_format_t format)
254 {
255     int rc = MM_CAMERA_OK;
256     status_t ret = NO_ERROR;
257     mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_VIDEO;
258     cam_ctrl_dimension_t dim;
259     int i;
260     mm_camera_stream_config_t stream_config;
261 
262     ALOGE("QCameraStream::initStream : E");
263 
264     mFormat = format;
265     /*TODO: Convert between TEMPLATE to img_mode */
266     mExtImgMode = imgmode;
267     /***********Allocate Stream**************/
268 
269     rc=p_mm_ops->ops->add_stream(mCameraHandle,
270                         mChannelId,
271                         stream_cb_routine,
272                         (void *)this,
273                         mExtImgMode,
274                         0/*sensor_idx*/);
275 
276     if (rc < 0)
277        goto error1;
278 
279     mMmStreamId=rc;
280     ALOGE("%s: mMmStreamId = %d\n", __func__, mMmStreamId);
281 
282     memset(&stream_config, 0, sizeof(mm_camera_stream_config_t));
283     stream_config.fmt.fmt=format;
284     stream_config.fmt.meta_header=MM_CAMEAR_META_DATA_TYPE_DEF;
285     stream_config.fmt.width=mWidth;
286     stream_config.fmt.height=mHeight;
287     ALOGE("<DEBUG>::%s: Width :%d Height:%d Format:%d",__func__,mWidth,mHeight,format);
288     stream_config.num_of_bufs=mNumBuffers;
289     stream_config.need_stream_on=true;
290     rc=p_mm_ops->ops->config_stream(mCameraHandle,
291                               mChannelId,
292                               mMmStreamId,
293                               &stream_config);
294     if(MM_CAMERA_OK != rc)
295         goto error2;
296 
297     goto end;
298 
299 
300 error2:
301     ALOGE("%s: Error configuring stream",__func__);
302     p_mm_ops->ops->del_stream(mCameraHandle,mChannelId,
303                               mMmStreamId);
304 
305 error1:
306     return BAD_VALUE;
307 end:
308     ALOGE("Setting mInit to true");
309     mInit=true;
310     return NO_ERROR;
311 
312 }
313 
deinitStream()314 status_t QCameraStream::deinitStream()
315 {
316 
317     int rc = MM_CAMERA_OK;
318 
319     ALOGI("%s: E, Stream = %d\n", __func__, mMmStreamId);
320 
321     rc= p_mm_ops->ops->del_stream(mCameraHandle,mChannelId,
322                               mMmStreamId);
323 
324     ALOGI("%s: X, Stream = %d\n", __func__, mMmStreamId);
325     mInit=false;
326     return NO_ERROR;
327 }
328 
setMode(int enable)329 status_t QCameraStream::setMode(int enable) {
330   ALOGE("%s :myMode %x ", __func__, myMode);
331   if (enable) {
332       myMode = (camera_mode_t)(myMode | CAMERA_ZSL_MODE);
333   } else {
334       myMode = (camera_mode_t)(myMode & ~CAMERA_ZSL_MODE);
335   }
336   return NO_ERROR;
337 }
338 
setFormat()339 status_t QCameraStream::setFormat()
340 {
341     ALOGE("%s: E",__func__);
342 
343     char mDeviceName[PROPERTY_VALUE_MAX];
344     property_get("ro.product.device",mDeviceName," ");
345 
346     ALOGE("%s: X",__func__);
347     return NO_ERROR;
348 }
349 
QCameraStream()350 QCameraStream::QCameraStream (){
351     mInit = false;
352     mActive = false;
353     /* memset*/
354     memset(&mCrop, 0, sizeof(mm_camera_rect_t));
355 }
356 
QCameraStream(uint32_t CameraHandle,uint32_t ChannelId,uint32_t Width,uint32_t Height,mm_camera_vtbl_t * mm_ops,camera_mode_t mode)357 QCameraStream::QCameraStream(uint32_t CameraHandle,
358                        uint32_t ChannelId,
359                         uint32_t Width,
360                         uint32_t Height,
361                         mm_camera_vtbl_t *mm_ops,
362                         camera_mode_t mode)
363               :myMode(mode)
364 {
365     mInit = false;
366     mActive = false;
367 
368     mCameraHandle=CameraHandle;
369     mChannelId=ChannelId;
370     mWidth=Width;
371     mHeight=Height;
372     p_mm_ops=mm_ops;
373 
374     /* memset*/
375     memset(&mCrop, 0, sizeof(mm_camera_rect_t));
376 
377     mPendingCount=0;
378     pthread_mutex_init(&mFrameDeliveredMutex, NULL);
379     pthread_cond_init(&mFrameDeliveredCond, NULL);
380 }
381 
~QCameraStream()382 QCameraStream::~QCameraStream () {;}
383 
allocateStreamId()384 int QCameraStream::allocateStreamId() {
385     int i = 0;
386     for (i = 0; i < STREAM_TABLE_SIZE; i++)
387         if (mStreamTable[i] == NULL) {
388             mStreamTable[i] = this;
389             break;
390         }
391     if (i == STREAM_TABLE_SIZE)
392         return INVALID_OPERATION;
393     ALOGE("%s: mStreamTable[%d] = %p\n", __func__, i, mStreamTable[i]);
394     return i;
395 }
396 
deallocateStreamId(int id)397 int QCameraStream::deallocateStreamId(int id) {
398     if (id < 0 || id >= STREAM_TABLE_SIZE)
399         return BAD_VALUE;
400     mStreamTable[id] = NULL;
401     return OK;
402 }
403 
getStreamAtId(int id)404 QCameraStream *QCameraStream::getStreamAtId(int id) {
405     if (id < 0 || id >= STREAM_TABLE_SIZE)
406         return NULL;
407     else
408         return mStreamTable[id];
409 }
410 
getStreamAtMmId(uint32_t mm_id)411 QCameraStream *QCameraStream::getStreamAtMmId(uint32_t mm_id) {
412     /*TODO: More efficient to do direct lookup. But it requires
413      *mm-camera-interface to expose a macro for handle-index mapping*/
414     for (int i = 0; i < STREAM_TABLE_SIZE; i++) {
415         ALOGE("%s: %d: ", __func__, i);
416         if (mStreamTable[i])
417             ALOGE("%s: mMmStreamId = %d", __func__, mStreamTable[i]->mMmStreamId);
418         if (mStreamTable[i] && (mStreamTable[i]->mMmStreamId == mm_id))
419             return mStreamTable[i];
420     }
421     ALOGE("%s: Cannot find stream with interface id %d", __func__, mm_id);
422     return NULL;
423 }
424 
streamOffAll()425 void QCameraStream::streamOffAll()
426 {
427     for (int i = 0; i < STREAM_TABLE_SIZE; i++) {
428         if (mStreamTable[i]) {
429             if (mStreamTable[i]->mActive) {
430                 ALOGI("%s: stream off stream[%d]", __func__, i);
431                 mStreamTable[i]->streamOff(0);
432                 ALOGI("%s: stream off stream[%d] done", __func__, i);
433             }
434             if (mStreamTable[i]->mInit) {
435                 ALOGI("%s: deinit stream[%d]", __func__, i);
436                 mStreamTable[i]->deinitStream();
437                 ALOGI("%s: deinit stream[%d] done", __func__, i);
438             }
439         }
440     }
441 }
442 
init()443 status_t QCameraStream::init() {
444     return NO_ERROR;
445 }
446 
start()447 status_t QCameraStream::start() {
448     return NO_ERROR;
449 }
450 
stop()451 void QCameraStream::stop() {
452     return;
453 }
454 
release()455 void QCameraStream::release() {
456     return;
457 }
458 
setHALCameraControl(QCameraHardwareInterface * ctrl)459 void QCameraStream::setHALCameraControl(QCameraHardwareInterface* ctrl) {
460 
461     /* provide a frame data user,
462     for the  queue monitor thread to call the busy queue is not empty*/
463     mHalCamCtrl = ctrl;
464 }
465 
466 }; // namespace android
467