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 33 StreamQueue::StreamQueue(){ 34 mInitialized = false; 35 } 36 37 StreamQueue::~StreamQueue(){ 38 flush(); 39 } 40 41 void StreamQueue::init(){ 42 Mutex::Autolock l(&mQueueLock); 43 mInitialized = true; 44 mQueueWait.signal(); 45 } 46 47 void StreamQueue::deinit(){ 48 Mutex::Autolock l(&mQueueLock); 49 mInitialized = false; 50 mQueueWait.signal(); 51 } 52 53 bool StreamQueue::isInitialized(){ 54 Mutex::Autolock l(&mQueueLock); 55 return mInitialized; 56 } 57 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 69 bool StreamQueue::isEmpty(){ 70 return (mInitialized && mContainer.isEmpty()); 71 } 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 91 void StreamQueue::flush(){ 92 Mutex::Autolock l(&mQueueLock); 93 mContainer.clear(); 94 } 95 96 97 // --------------------------------------------------------------------------- 98 // QCameraStream 99 // --------------------------------------------------------------------------- 100 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 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 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 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 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 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*/ 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 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 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 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 350 QCameraStream::QCameraStream (){ 351 mInit = false; 352 mActive = false; 353 /* memset*/ 354 memset(&mCrop, 0, sizeof(mm_camera_rect_t)); 355 } 356 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 382 QCameraStream::~QCameraStream () {;} 383 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 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 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 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 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 443 status_t QCameraStream::init() { 444 return NO_ERROR; 445 } 446 447 status_t QCameraStream::start() { 448 return NO_ERROR; 449 } 450 451 void QCameraStream::stop() { 452 return; 453 } 454 455 void QCameraStream::release() { 456 return; 457 } 458 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