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