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 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 35namespace android { 36 37extern void stream_cb_routine(mm_camera_super_buf_t *bufs, 38 void *userdata); 39extern void superbuf_cb_routine(mm_camera_super_buf_t *bufs, 40 void *userdata); 41 42 43/*Command Thread startup function*/ 44 45void *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 57int 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 89end: 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 116void 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*/ 186int32_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 202int32_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 213int 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 249int 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 262QCameraHardwareInterface:: 263QCameraHardwareInterface(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 295QCameraHardwareInterface::~QCameraHardwareInterface() 296{ 297 mCameraHandle->ops->camera_close(mCameraHandle->camera_handle); 298} 299 300void QCameraHardwareInterface::release() 301{ 302} 303 304bool QCameraHardwareInterface::isCameraReady() 305{ 306 return true; 307} 308 309int 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 318int 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 339int 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 346int QCameraHardwareInterface::get_in_progress_count() 347{ 348 return mPendingRequests; 349} 350 351int 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 386int 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 431int 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 453int 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 462int 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 474int QCameraHardwareInterface::release_reprocess_stream(uint32_t stream_id) 475{ 476 return INVALID_OPERATION; 477} 478 479int QCameraHardwareInterface::get_metadata_vendor_tag_ops(vendor_tag_query_ops_t **ops) 480{ 481 *ops = NULL; 482 return OK; 483} 484 485int 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