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 LOG_NIDEBUG 0 20 //#define LOG_NDEBUG 0 21 22 #define LOG_TAG "QCameraHWI" 23 #include <utils/Log.h> 24 #include <utils/threads.h> 25 #include <cutils/properties.h> 26 #include <fcntl.h> 27 #include <sys/mman.h> 28 29 #include "QCameraHAL.h" 30 #include "QCameraHWI.h" 31 32 /* QCameraHardwareInterface class implementation goes here*/ 33 /* following code implement the contol logic of this class*/ 34 35 namespace android { 36 37 extern void stream_cb_routine(mm_camera_super_buf_t *bufs, 38 void *userdata); 39 extern void superbuf_cb_routine(mm_camera_super_buf_t *bufs, 40 void *userdata); 41 42 43 /*Command Thread startup function*/ 44 45 void *command_thread(void *obj) 46 { 47 QCameraHardwareInterface *pme = (QCameraHardwareInterface *)obj; 48 ALOGD("%s: E", __func__); 49 if (pme != NULL) { 50 pme->runCommandThread(obj); 51 } 52 else ALOGW("not starting command thread: the object went away!"); 53 ALOGD("%s: X", __func__); 54 return NULL; 55 } 56 57 int QCameraHardwareInterface::tryRestartStreams( 58 camera_metadata_entry_t& streams) 59 { 60 int rc = 0; 61 bool needRestart = false; 62 bool needRecordingHint = false; 63 64 for (uint32_t i = 0; i < streams.count; i++) { 65 int streamId = streams.data.u8[i]; 66 QCameraStream *stream = QCameraStream::getStreamAtId(streamId); 67 if (!stream->mInit) { 68 needRestart = true; 69 if (stream->mFormat == CAMERA_YUV_420_NV12) 70 needRecordingHint = true; 71 } 72 } 73 74 if (!needRestart) 75 goto end; 76 77 QCameraStream::streamOffAll(); 78 79 if (needRecordingHint) { 80 uint32_t recordingHint = 1; 81 rc = mCameraHandle->ops->set_parm(mCameraHandle->camera_handle, 82 MM_CAMERA_PARM_RECORDING_HINT, &recordingHint); 83 if (rc < 0) { 84 ALOGE("set_parm MM_CAMERA_PARM_RECORDING_HINT returns %d", rc); 85 return rc; 86 } 87 } 88 89 end: 90 for (uint32_t i = 0; i < streams.count; i++) { 91 int streamId = streams.data.u8[i]; 92 QCameraStream *stream = QCameraStream::getStreamAtId(streamId); 93 if (!stream->mInit) { 94 rc = stream->prepareStream(); 95 if (rc < 0) { 96 ALOGE("prepareStream for stream %d failed %d", streamId, rc); 97 return rc; 98 } 99 } 100 } 101 for (uint32_t i = 0; i < streams.count; i++) { 102 int streamId = streams.data.u8[i]; 103 QCameraStream *stream = QCameraStream::getStreamAtId(streamId); 104 105 if (!stream->mActive) { 106 rc = stream->streamOn(); 107 if (rc < 0) { 108 ALOGE("streamOn for stream %d failed %d", streamId, rc); 109 return rc; 110 } 111 } 112 } 113 return rc; 114 } 115 116 void QCameraHardwareInterface::runCommandThread(void *data) 117 { 118 119 /** 120 * This function implements the main service routine for the incoming 121 * frame requests, this thread routine is started everytime we get a 122 * notify_request_queue_not_empty trigger, this thread makes the 123 * assumption that once it receives a NULL on a dequest_request call 124 * there will be a fresh notify_request_queue_not_empty call that is 125 * invoked thereby launching a new instance of this thread. Therefore, 126 * once we get a NULL on a dequeue request we simply let this thread die 127 */ 128 int res; 129 camera_metadata_t *request=NULL; 130 mPendingRequests=0; 131 132 while(mRequestQueueSrc) { 133 ALOGV("%s:Dequeue request using mRequestQueueSrc:%p",__func__,mRequestQueueSrc); 134 mRequestQueueSrc->dequeue_request(mRequestQueueSrc,&request); 135 if(request==NULL) { 136 ALOGE("%s:No more requests available from src command \ 137 thread dying",__func__); 138 return; 139 } 140 mPendingRequests++; 141 142 /* Set the metadata values */ 143 144 /* Wait for the SOF for the new metadata values to be applied */ 145 146 /* Check the streams that need to be active in the stream request */ 147 sort_camera_metadata(request); 148 149 camera_metadata_entry_t streams; 150 res = find_camera_metadata_entry(request, 151 ANDROID_REQUEST_OUTPUT_STREAMS, 152 &streams); 153 if (res != NO_ERROR) { 154 ALOGE("%s: error reading output stream tag", __FUNCTION__); 155 return; 156 } 157 158 res = tryRestartStreams(streams); 159 if (res != NO_ERROR) { 160 ALOGE("error tryRestartStreams %d", res); 161 return; 162 } 163 164 /* 3rd pass: Turn on all streams requested */ 165 for (uint32_t i = 0; i < streams.count; i++) { 166 int streamId = streams.data.u8[i]; 167 QCameraStream *stream = QCameraStream::getStreamAtId(streamId); 168 169 /* Increment the frame pending count in each stream class */ 170 171 /* Assuming we will have the stream obj in had at this point may be 172 * may be multiple objs in which case we loop through array of streams */ 173 stream->onNewRequest(); 174 } 175 ALOGV("%s:Freeing request using mRequestQueueSrc:%p",__func__,mRequestQueueSrc); 176 /* Free the request buffer */ 177 mRequestQueueSrc->free_request(mRequestQueueSrc,request); 178 mPendingRequests--; 179 ALOGV("%s:Completed request",__func__); 180 } 181 182 QCameraStream::streamOffAll(); 183 } 184 185 /*Mem Hooks*/ 186 int32_t get_buffer_hook(uint32_t camera_handle, 187 uint32_t ch_id, uint32_t stream_id, 188 void *user_data, 189 mm_camera_frame_len_offset *frame_offset_info, 190 uint8_t num_bufs, 191 uint8_t *initial_reg_flag, 192 mm_camera_buf_def_t *bufs) 193 { 194 QCameraHardwareInterface *pme=(QCameraHardwareInterface *)user_data; 195 return pme->getBuf(camera_handle, ch_id, stream_id, 196 user_data, frame_offset_info, 197 num_bufs,initial_reg_flag, 198 bufs); 199 200 } 201 202 int32_t put_buffer_hook(uint32_t camera_handle, 203 uint32_t ch_id, uint32_t stream_id, 204 void *user_data, uint8_t num_bufs, 205 mm_camera_buf_def_t *bufs) 206 { 207 QCameraHardwareInterface *pme=(QCameraHardwareInterface *)user_data; 208 return pme->putBuf(camera_handle, ch_id, stream_id, 209 user_data, num_bufs, bufs); 210 211 } 212 213 int QCameraHardwareInterface::getBuf(uint32_t camera_handle, 214 uint32_t ch_id, uint32_t mm_stream_id, 215 void *user_data, 216 mm_camera_frame_len_offset *frame_offset_info, 217 uint8_t num_bufs, 218 uint8_t *initial_reg_flag, 219 mm_camera_buf_def_t *bufs) 220 { 221 status_t ret=NO_ERROR; 222 ALOGE("%s: E, stream_id = %d\n", __func__, mm_stream_id); 223 QCameraStream_preview *stream = (QCameraStream_preview *) 224 QCameraStream::getStreamAtMmId(mm_stream_id); 225 226 ALOGE("%s: len:%d, y_off:%d, cbcr:%d num buffers: %d planes:%d streamid:%d", 227 __func__, 228 frame_offset_info->frame_len, 229 frame_offset_info->mp[0].len, 230 frame_offset_info->mp[1].len, 231 num_bufs,frame_offset_info->num_planes, 232 mm_stream_id); 233 /*************Preiew Stream*****************/ 234 ALOGE("Interface requesting Preview Buffers"); 235 stream->mFrameOffsetInfo=*frame_offset_info; 236 if(NO_ERROR!=stream->initBuffers()){ 237 return BAD_VALUE; 238 } 239 ALOGE("Debug : %s : initDisplayBuffers",__func__); 240 for(int i=0;i<num_bufs;i++) { 241 bufs[i] = stream->mDisplayBuf[i]; 242 initial_reg_flag[i] = 243 (stream->mPreviewMemory.local_flag[i] == BUFFER_OWNED); 244 ALOGE("initial_reg_flag[%d]:%d",i,initial_reg_flag[i]); 245 } 246 return 0; 247 } 248 249 int QCameraHardwareInterface::putBuf(uint32_t camera_handle, 250 uint32_t ch_id, uint32_t mm_stream_id, 251 void *user_data, uint8_t num_bufs, 252 mm_camera_buf_def_t *bufs) 253 { 254 ALOGE("%s:E, stream_id = %d",__func__, mm_stream_id); 255 QCameraStream_preview *stream = (QCameraStream_preview *) 256 QCameraStream::getStreamAtMmId(mm_stream_id); 257 stream->deinitBuffers(); 258 return 0; 259 } 260 261 262 QCameraHardwareInterface:: 263 QCameraHardwareInterface(int cameraId, int mode) 264 : mCameraId(cameraId) 265 { 266 267 cam_ctrl_dimension_t mDimension; 268 269 /* Open camera stack! */ 270 memset(&mMemHooks, 0, sizeof(mm_camear_mem_vtbl_t)); 271 mMemHooks.user_data=this; 272 mMemHooks.get_buf=get_buffer_hook; 273 mMemHooks.put_buf=put_buffer_hook; 274 275 mCameraHandle=camera_open(mCameraId, &mMemHooks); 276 ALOGV("Cam open returned %p",mCameraHandle); 277 if(mCameraHandle == NULL) { 278 ALOGE("startCamera: cam_ops_open failed: id = %d", mCameraId); 279 return; 280 } 281 mCameraHandle->ops->sync(mCameraHandle->camera_handle); 282 283 mChannelId=mCameraHandle->ops->ch_acquire(mCameraHandle->camera_handle); 284 if(mChannelId<=0) 285 { 286 ALOGE("%s:Channel aquire failed",__func__); 287 mCameraHandle->ops->camera_close(mCameraHandle->camera_handle); 288 return; 289 } 290 291 /* Initialize # of frame requests the HAL is handling to zero*/ 292 mPendingRequests=0; 293 } 294 295 QCameraHardwareInterface::~QCameraHardwareInterface() 296 { 297 mCameraHandle->ops->camera_close(mCameraHandle->camera_handle); 298 } 299 300 void QCameraHardwareInterface::release() 301 { 302 } 303 304 bool QCameraHardwareInterface::isCameraReady() 305 { 306 return true; 307 } 308 309 int QCameraHardwareInterface::set_request_queue_src_ops( 310 const camera2_request_queue_src_ops_t *request_src_ops) 311 { 312 ALOGE("%s:E mRequestQueueSrc:%p",__func__,request_src_ops); 313 mRequestQueueSrc = request_src_ops; 314 ALOGE("%s:X",__func__); 315 return 0; 316 } 317 318 int QCameraHardwareInterface::notify_request_queue_not_empty() 319 { 320 321 pthread_attr_t attr; 322 if(pthread_attr_init(&attr)!=0) { 323 ALOGE("%s:pthread_attr_init failed",__func__); 324 return BAD_VALUE; 325 } 326 if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)!=0){ 327 ALOGE("%s:pthread_attr_setdetachstate failed",__func__); 328 return BAD_VALUE; 329 } 330 if(pthread_create(&mCommandThread,&attr, 331 command_thread, (void *)this)!=0) { 332 ALOGE("%s:pthread_create failed to launch command_thread",__func__); 333 return BAD_VALUE; 334 } 335 336 return NO_ERROR; 337 } 338 339 int QCameraHardwareInterface::set_frame_queue_dst_ops( 340 const camera2_frame_queue_dst_ops_t *frame_dst_ops) 341 { 342 mFrameQueueDst = frame_dst_ops; 343 return OK; 344 } 345 346 int QCameraHardwareInterface::get_in_progress_count() 347 { 348 return mPendingRequests; 349 } 350 351 int QCameraHardwareInterface::construct_default_request( 352 int request_template, camera_metadata_t **request) 353 { 354 status_t ret; 355 ALOGD("%s:E:request_template:%d ",__func__,request_template); 356 357 if (request == NULL) 358 return BAD_VALUE; 359 if (request_template < 0 || request_template >= CAMERA2_TEMPLATE_COUNT) 360 return BAD_VALUE; 361 362 ret = constructDefaultRequest(request_template, request, true); 363 if (ret != OK) { 364 ALOGE("%s: Unable to allocate default request: %s (%d)", 365 __FUNCTION__, strerror(-ret), ret); 366 return ret; 367 } 368 ret = constructDefaultRequest(request_template, request, false); 369 if (ret != OK) { 370 ALOGE("%s: Unable to fill in default request: %s (%d)", 371 __FUNCTION__, strerror(-ret), ret); 372 return ret; 373 } 374 375 ALOGE("Setting OP MODE to MM_CAMERA_OP_MODE_VIDEO"); 376 mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_VIDEO; 377 ret = mCameraHandle->ops->set_parm( 378 mCameraHandle->camera_handle, 379 MM_CAMERA_PARM_OP_MODE, 380 &op_mode); 381 ALOGE("OP Mode Set"); 382 383 return ret; 384 } 385 386 int QCameraHardwareInterface::allocate_stream( 387 uint32_t width, 388 uint32_t height, int format, 389 const camera2_stream_ops_t *stream_ops, 390 uint32_t *stream_id, 391 uint32_t *format_actual, 392 uint32_t *usage, 393 uint32_t *max_buffers) 394 { 395 int ret = OK; 396 QCameraStream *stream = NULL; 397 camera_mode_t myMode = (camera_mode_t)(CAMERA_MODE_2D|CAMERA_NONZSL_MODE); 398 ALOGE("%s : BEGIN",__func__); 399 400 ALOGE("Mymode Preview = %d",myMode); 401 stream = QCameraStream_preview::createInstance( 402 mCameraHandle->camera_handle, 403 mChannelId, 404 width, 405 height, 406 format, 407 mCameraHandle, 408 myMode); 409 ALOGE("%s: createInstance done", __func__); 410 if (!stream) { 411 ALOGE("%s: error - can't creat preview stream!", __func__); 412 return BAD_VALUE; 413 } 414 415 stream->setPreviewWindow(stream_ops); 416 *stream_id = stream->getStreamId(); 417 *max_buffers= stream->getMaxBuffers(); 418 ALOGE("%s: stream_id = %d\n", __func__, *stream_id); 419 *usage = GRALLOC_USAGE_HW_CAMERA_WRITE | CAMERA_GRALLOC_HEAP_ID 420 | CAMERA_GRALLOC_FALLBACK_HEAP_ID; 421 /* Set to an arbitrary format SUPPORTED by gralloc */ 422 //*format_actual = HAL_PIXEL_FORMAT_YCbCr_422_SP; 423 *format_actual = HAL_PIXEL_FORMAT_YCrCb_420_SP; 424 /*TODO: For hardware encoder, add CAMERA_GRALLOC_CACHING_ID */ 425 stream->setHALCameraControl(this); 426 427 ALOGV("%s : END",__func__); 428 return ret; 429 } 430 431 int QCameraHardwareInterface::register_stream_buffers( 432 uint32_t stream_id, int num_buffers, 433 buffer_handle_t *buffers) 434 { 435 struct private_handle_t *private_handle = 436 (struct private_handle_t *)buffers[0]; 437 QCameraStream_preview *stream = (QCameraStream_preview *) 438 QCameraStream::getStreamAtId(stream_id); 439 440 if(!stream) { 441 ALOGE("%s: Request for unknown stream",__func__); 442 return BAD_VALUE; 443 } 444 445 if(NO_ERROR!=stream->registerStreamBuffers(num_buffers, buffers)) { 446 ALOGE("%s:registerStreamBuffers failed",__func__); 447 return BAD_VALUE; 448 } 449 450 return NO_ERROR; 451 } 452 453 int QCameraHardwareInterface::release_stream(uint32_t stream_id) 454 { 455 QCameraStream *stream = QCameraStream::getStreamAtId(stream_id); 456 457 QCameraStream_preview::deleteInstance(stream); 458 459 return OK; 460 } 461 462 int QCameraHardwareInterface::allocate_reprocess_stream( 463 uint32_t width, 464 uint32_t height, 465 uint32_t format, 466 const camera2_stream_in_ops_t *reprocess_stream_ops, 467 uint32_t *stream_id, 468 uint32_t *consumer_usage, 469 uint32_t *max_buffers) 470 { 471 return INVALID_OPERATION; 472 } 473 474 int QCameraHardwareInterface::release_reprocess_stream(uint32_t stream_id) 475 { 476 return INVALID_OPERATION; 477 } 478 479 int QCameraHardwareInterface::get_metadata_vendor_tag_ops(vendor_tag_query_ops_t **ops) 480 { 481 *ops = NULL; 482 return OK; 483 } 484 485 int QCameraHardwareInterface::set_notify_callback(camera2_notify_callback notify_cb, 486 void *user) 487 { 488 mNotifyCb = notify_cb; 489 mNotifyUserPtr = user; 490 return OK; 491 } 492 }; // namespace android 493