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_TAG "QCameraHWI_Preview" 20 #include <utils/Log.h> 21 #include <utils/threads.h> 22 #include <fcntl.h> 23 #include <sys/mman.h> 24 #include "QCameraHAL.h" 25 #include "QCameraHWI.h" 26 #include <genlock.h> 27 #include <gralloc_priv.h> 28 29 #define UNLIKELY(exp) __builtin_expect(!!(exp), 0) 30 31 /* QCameraHWI_Preview class implementation goes here*/ 32 /* following code implement the preview mode's image capture & display logic of this class*/ 33 34 namespace android { 35 36 status_t QCameraStream_preview::setPreviewWindow(const camera2_stream_ops_t* window) 37 { 38 status_t retVal = NO_ERROR; 39 ALOGE(" %s: E ", __FUNCTION__); 40 if( window == NULL) { 41 ALOGW(" Setting NULL preview window "); 42 /* TODO: Current preview window will be invalidated. 43 * Release all the buffers back */ 44 // relinquishBuffers(); 45 } 46 Mutex::Autolock lock(mLock); 47 mPreviewWindow = window; 48 ALOGV(" %s : X ", __FUNCTION__ ); 49 return retVal; 50 } 51 52 int QCameraStream_preview::registerStreamBuffers(int num_buffers, 53 buffer_handle_t *buffers) 54 { 55 int err; 56 57 mNumBuffers = num_buffers; 58 mPreviewMemory.buffer_count = num_buffers; 59 for (int i = 0; i < num_buffers; i++) { 60 mPreviewMemory.buffer_handle[i] = buffers[i]; 61 mPreviewMemory.private_buffer_handle[i] = (struct private_handle_t *)buffers[i]; 62 ALOGD("%s:Buffer Size:%d",__func__, mPreviewMemory.private_buffer_handle[i]->size); 63 } 64 mDisplayBuf = new mm_camera_buf_def_t[num_buffers]; 65 if (!mDisplayBuf) { 66 ALOGE("Unable to allocate mDisplayBuf"); 67 return NO_MEMORY; 68 } 69 70 return OK; 71 } 72 73 status_t QCameraStream_preview::initBuffers() 74 { 75 status_t ret = NO_ERROR; 76 int width = mWidth; /* width of channel */ 77 int height = mHeight; /* height of channel */ 78 uint32_t frame_len = mFrameOffsetInfo.frame_len; /* frame planner length */ 79 int buffer_num = mNumBuffers; /* number of buffers for display */ 80 const char *pmem_region; 81 uint8_t num_planes = mFrameOffsetInfo.num_planes; 82 uint32_t planes[VIDEO_MAX_PLANES]; 83 void *vaddr = NULL; 84 buffer_handle_t *buffer_handle; 85 86 ALOGE("%s:BEGIN",__func__); 87 memset(mNotifyBuffer, 0, sizeof(mNotifyBuffer)); 88 89 this->myMode=myMode; /*Need to assign this in constructor after translating from mask*/ 90 num_planes = mFrameOffsetInfo.num_planes; 91 for(int i=0; i < num_planes; i++) 92 planes[i] = mFrameOffsetInfo.mp[i].len; 93 94 95 mPreviewMemoryLock.lock(); 96 memset(mDisplayBuf, 0, sizeof(mm_camera_buf_def_t) * mNumBuffers); 97 98 /*allocate memory for the buffers*/ 99 for(int i = 0; i < mNumBuffers; i++){ 100 mDisplayBuf[i].num_planes = num_planes; 101 mDisplayBuf[i].buf_idx = i; 102 103 /* Plane 0 needs to be set seperately. Set other planes 104 * in a loop. */ 105 mDisplayBuf[i].planes[0].length = planes[0]; 106 mDisplayBuf[i].planes[0].m.userptr = mPreviewMemory.private_buffer_handle[i]->fd; 107 mDisplayBuf[i].planes[0].data_offset = mFrameOffsetInfo.mp[0].offset; 108 mDisplayBuf[i].planes[0].reserved[0] =0; 109 for (int j = 1; j < num_planes; j++) { 110 mDisplayBuf[i].planes[j].length = planes[j]; 111 mDisplayBuf[i].planes[j].m.userptr = mPreviewMemory.private_buffer_handle[i]->fd; 112 mDisplayBuf[i].planes[j].data_offset = mFrameOffsetInfo.mp[j].offset; 113 mDisplayBuf[i].planes[j].reserved[0] = 114 mDisplayBuf[i].planes[j-1].reserved[0] + 115 mDisplayBuf[i].planes[j-1].length; 116 } 117 118 for (int j = 0; j < num_planes; j++) 119 ALOGE("Planes: %d length: %d userptr: %lu offset: %d\n", j, 120 mDisplayBuf[i].planes[j].length, 121 mDisplayBuf[i].planes[j].m.userptr, 122 mDisplayBuf[i].planes[j].reserved[0]); 123 124 mDisplayBuf[i].stream_id = mMmStreamId; 125 mDisplayBuf[i].fd = mPreviewMemory.private_buffer_handle[i]->fd; 126 ALOGE("DEBUG2:Display buf[%d] fd:%d",i,mDisplayBuf[i].fd); 127 mDisplayBuf[i].frame_len = mFrameOffsetInfo.frame_len; 128 }/*end of for loop*/ 129 130 /* Dequeue N frames from native window and queue into interface. Only dequeue our requested buffers */ 131 for (int i = 0; i < mNumBuffers; i++) 132 mPreviewMemory.local_flag[i] = BUFFER_NOT_REGGED; 133 for (int i = 0; i < OPAQUE_BUFFER_COUNT; i++) { 134 ALOGE("mPreview Window %p",mPreviewWindow); 135 int err = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer_handle); 136 if (err == NO_ERROR && buffer_handle) { 137 int j; 138 for (j = 0; j < mPreviewMemory.buffer_count; j++) { 139 if (mPreviewMemory.buffer_handle[j] == *buffer_handle) { 140 mPreviewMemory.local_flag[j] = BUFFER_OWNED; 141 ALOGE("%s: [%d]: local_flag = 1", __func__, j); 142 break; 143 } 144 } 145 if (j == mPreviewMemory.buffer_count) { 146 ALOGE("Cannot find matching handle in the table."); 147 return INVALID_OPERATION; 148 } 149 } else { 150 ALOGE("dequeue_buffer failed."); 151 return INVALID_OPERATION; 152 } 153 } 154 155 /* register the streaming buffers for the channel*/ 156 mPreviewMemoryLock.unlock(); 157 ALOGE("%s:END",__func__); 158 return NO_ERROR; 159 160 error: 161 mPreviewMemoryLock.unlock(); 162 163 ALOGV("%s: X", __func__); 164 return ret; 165 } 166 167 void QCameraStream_preview::deinitBuffers() 168 { 169 mPreviewMemoryLock.lock(); 170 for (int i = 0; i < mNumBuffers; i++) { 171 if (mPreviewMemory.local_flag[i] == BUFFER_OWNED) { 172 mPreviewWindow->cancel_buffer(mPreviewWindow, 173 &mPreviewMemory.buffer_handle[i]); 174 mPreviewMemory.local_flag[i] = BUFFER_NOT_OWNED; 175 } 176 } 177 mPreviewMemoryLock.unlock(); 178 } 179 180 void QCameraStream_preview::dumpFrameToFile(mm_camera_buf_def_t *newFrame) 181 { 182 int32_t enabled = 0; 183 int frm_num; 184 uint32_t skip_mode; 185 char value[PROPERTY_VALUE_MAX]; 186 char buf[32]; 187 int w, h; 188 static int count = 0; 189 int file_fd; 190 int rc = 0; 191 int len; 192 unsigned long addr; 193 unsigned long * tmp = (unsigned long *)newFrame->buffer; 194 addr = *tmp; 195 196 len = newFrame->frame_len; 197 count++; 198 if(count < 100) { 199 snprintf(buf, sizeof(buf), "/data/mzhu%d.yuv", count); 200 file_fd = open(buf, O_RDWR | O_CREAT, 0777); 201 202 rc = write(file_fd, (const void *)addr, len); 203 ALOGE("%s: file='%s', vaddr_old=0x%x, addr_map = 0x%p, len = %d, rc = %d", 204 __func__, buf, (uint32_t)newFrame->buffer, (void *)addr, len, rc); 205 close(file_fd); 206 ALOGE("%s: dump %s, rc = %d, len = %d", __func__, buf, rc, len); 207 } 208 } 209 210 int QCameraStream_preview::prepareStream() 211 { 212 mm_camera_img_mode img_mode; 213 cam_format_t format; 214 struct private_handle_t *private_handle = mPreviewMemory.private_buffer_handle[0]; 215 216 ALOGE("%s: private_handle->format = %d, flags = %d", __func__, 217 private_handle->format, private_handle->flags); 218 if (private_handle->flags & private_handle_t::PRIV_FLAGS_VIDEO_ENCODER) 219 img_mode = MM_CAMERA_VIDEO; 220 else if (private_handle->flags & private_handle_t::PRIV_FLAGS_CAMERA_WRITE) 221 img_mode = MM_CAMERA_PREVIEW; 222 else { 223 ALOGE("%s: Invalid flags %d\n", __func__, private_handle->flags); 224 return BAD_VALUE; 225 } 226 227 switch (private_handle->format) { 228 case HAL_PIXEL_FORMAT_YCbCr_420_SP: 229 format = CAMERA_YUV_420_NV12; 230 break; 231 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 232 format = CAMERA_YUV_420_NV21; 233 break; 234 default: 235 ALOGE("%s: Invalid format!!!", __func__); 236 return BAD_VALUE; 237 } 238 if(NO_ERROR!=initStream(img_mode, format)) { 239 ALOGE("Init stream failed"); 240 return BAD_VALUE; 241 } 242 return OK; 243 } 244 245 status_t QCameraStream_preview::processPreviewFrame ( 246 mm_camera_super_buf_t *frame) 247 { 248 ALOGV("%s",__func__); 249 int err = 0; 250 int msgType = 0; 251 int i; 252 camera_frame_metadata_t *metadata = NULL; 253 254 Mutex::Autolock lock(mLock); 255 if(!mActive) { 256 ALOGE("Preview Stopped. Returning callback"); 257 return NO_ERROR; 258 } 259 260 if(mHalCamCtrl==NULL) { 261 ALOGE("%s: X: HAL control object not set",__func__); 262 /*Call buf done*/ 263 return BAD_VALUE; 264 } 265 nsecs_t timeStamp = seconds_to_nanoseconds(frame->bufs[0]->ts.tv_sec) ; 266 timeStamp += frame->bufs[0]->ts.tv_nsec; 267 268 if(mFirstFrameRcvd == false) { 269 //mm_camera_util_profile("HAL: First preview frame received"); 270 mFirstFrameRcvd = true; 271 } 272 273 // dumpFrameToFile(frame->bufs[0]); 274 275 mPreviewMemoryLock.lock(); 276 mNotifyBuffer[frame->bufs[0]->buf_idx] = *frame; 277 ALOGE("processPreviewFrame: timeStamp = %lld", (int64_t)timeStamp); 278 err = mPreviewWindow->enqueue_buffer(mPreviewWindow, (int64_t)timeStamp, 279 &mPreviewMemory.buffer_handle[frame->bufs[0]->buf_idx]); 280 if(err != 0) { 281 ALOGE("%s: enqueue_buffer failed, err = %d", __func__, err); 282 } 283 mPreviewMemory.local_flag[frame->bufs[0]->buf_idx] = BUFFER_NOT_OWNED; 284 285 buffer_handle_t *buffer_handle = NULL; 286 err = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer_handle); 287 if (err == NO_ERROR && buffer_handle != NULL) { 288 int rc = MM_CAMERA_OK; 289 ALOGD("%s: dequed buf hdl =%p", __func__, *buffer_handle); 290 for(i = 0; i < mPreviewMemory.buffer_count; i++) { 291 if(mPreviewMemory.buffer_handle[i] == *buffer_handle) { 292 ALOGE("<DEBUG2>:Found buffer in idx:%d",i); 293 break; 294 } 295 } 296 if (mPreviewMemory.local_flag[i] == BUFFER_NOT_REGGED) { 297 mm_camera_buf_def_t buf = mDisplayBuf[i]; 298 mPreviewMemory.local_flag[i] = BUFFER_OWNED; 299 rc = p_mm_ops->ops->qbuf(mCameraHandle, mChannelId, &buf); 300 } else { 301 mPreviewMemory.local_flag[i] = BUFFER_OWNED; 302 rc = p_mm_ops->ops->qbuf(mCameraHandle, mChannelId, mNotifyBuffer[i].bufs[0]); 303 } 304 305 if(rc != MM_CAMERA_OK) { 306 /* how to handle the error of qbuf? */ 307 ALOGE("BUF DONE FAILED"); 308 } 309 } 310 /* Save the last displayed frame. We'll be using it to fill the gap between 311 when preview stops and postview start during snapshot.*/ 312 mLastQueuedFrame = &(mDisplayBuf[frame->bufs[0]->buf_idx]); 313 mPreviewMemoryLock.unlock(); 314 315 return NO_ERROR; 316 } 317 318 // --------------------------------------------------------------------------- 319 // QCameraStream_preview 320 // --------------------------------------------------------------------------- 321 322 QCameraStream_preview::QCameraStream_preview(uint32_t CameraHandle, 323 uint32_t ChannelId, 324 uint32_t Width, 325 uint32_t Height, 326 int requestedFormat, 327 mm_camera_vtbl_t *mm_ops, 328 camera_mode_t mode) : 329 QCameraStream(CameraHandle, 330 ChannelId, 331 Width, 332 Height, 333 mm_ops, 334 mode), 335 mLastQueuedFrame(NULL), 336 mDisplayBuf(NULL), 337 mNumFDRcvd(0) 338 { 339 mHalCamCtrl = NULL; 340 ALOGE("%s: E", __func__); 341 342 mStreamId = allocateStreamId(); 343 344 switch (requestedFormat) { 345 case CAMERA2_HAL_PIXEL_FORMAT_OPAQUE: 346 mMaxBuffers = 5; 347 break; 348 case HAL_PIXEL_FORMAT_BLOB: 349 mMaxBuffers = 1; 350 break; 351 default: 352 ALOGE("Unsupported requested format %d", requestedFormat); 353 mMaxBuffers = 1; 354 break; 355 } 356 /*TODO: There has to be a better way to do this*/ 357 ALOGE("%s: X", __func__); 358 } 359 // --------------------------------------------------------------------------- 360 // QCameraStream_preview 361 // --------------------------------------------------------------------------- 362 363 QCameraStream_preview::~QCameraStream_preview() { 364 ALOGV("%s: E", __func__); 365 if(mActive) { 366 streamOff(0); 367 } 368 if(mInit) { 369 deinitStream(); 370 } 371 mInit = false; 372 mActive = false; 373 if (mDisplayBuf) { 374 delete[] mDisplayBuf; 375 mDisplayBuf = NULL; 376 } 377 deallocateStreamId(mStreamId); 378 ALOGV("%s: X", __func__); 379 380 } 381 // --------------------------------------------------------------------------- 382 // QCameraStream_preview 383 // --------------------------------------------------------------------------- 384 385 status_t QCameraStream_preview::init() 386 { 387 status_t ret = NO_ERROR; 388 ALOGV("%s: E", __func__); 389 390 #if 0 391 if (!(myMode & CAMERA_ZSL_MODE)) { 392 ALOGE("Setting OP MODE to MM_CAMERA_OP_MODE_VIDEO"); 393 mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_VIDEO; 394 ret = p_mm_ops->ops->set_parm (mCameraHandle, MM_CAMERA_PARM_OP_MODE, 395 &op_mode); 396 ALOGE("OP Mode Set"); 397 398 if(MM_CAMERA_OK != ret) { 399 ALOGE("%s: X :set mode MM_CAMERA_OP_MODE_VIDEO err=%d\n", __func__, ret); 400 return BAD_VALUE; 401 } 402 }else { 403 ALOGE("Setting OP MODE to MM_CAMERA_OP_MODE_ZSL"); 404 mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_ZSL; 405 ret =p_mm_ops->ops->set_parm (mCameraHandle, MM_CAMERA_PARM_OP_MODE, 406 &op_mode); 407 if(MM_CAMERA_OK != ret) { 408 ALOGE("%s: X :set mode MM_CAMERA_OP_MODE_ZSL err=%d\n", __func__, ret); 409 return BAD_VALUE; 410 } 411 } 412 413 setFormat(); 414 ret = QCameraStream::initStream(); 415 if (NO_ERROR!=ret) { 416 ALOGE("%s E: can't init native cammera preview ch\n",__func__); 417 return ret; 418 } 419 420 mInit = true; 421 #endif 422 return ret; 423 } 424 // --------------------------------------------------------------------------- 425 // QCameraStream_preview 426 // --------------------------------------------------------------------------- 427 428 status_t QCameraStream_preview::start() 429 { 430 ALOGV("%s: E", __func__); 431 status_t ret = NO_ERROR; 432 433 Mutex::Autolock lock(mLock); 434 435 /* call start() in parent class to start the monitor thread*/ 436 //QCameraStream::start (); 437 438 #if 0 439 ret = cam_config_prepare_buf(mCameraId, &mDisplayBuf); 440 ALOGE("Debug : %s : cam_config_prepare_buf",__func__); 441 if(ret != MM_CAMERA_OK) { 442 ALOGV("%s:reg preview buf err=%d\n", __func__, ret); 443 ret = BAD_VALUE; 444 goto error; 445 }else { 446 ret = NO_ERROR; 447 } 448 #endif 449 /* For preview, the OP_MODE we set is dependent upon whether we are 450 starting camera or camcorder. For snapshot, anyway we disable preview. 451 However, for ZSL we need to set OP_MODE to OP_MODE_ZSL and not 452 OP_MODE_VIDEO. We'll set that for now in CamCtrl. So in case of 453 ZSL we skip setting Mode here */ 454 455 456 /* call mm_camera action start(...) */ 457 ALOGE("Starting Preview/Video Stream. "); 458 mFirstFrameRcvd = false; 459 460 ALOGE("Starting Preview/Video Stream. "); 461 ret = streamOn(); 462 if (MM_CAMERA_OK != ret) { 463 ALOGE ("%s: preview streaming start err=%d\n", __func__, ret); 464 ret = BAD_VALUE; 465 goto end; 466 } 467 468 ALOGE("Debug : %s : Preview streaming Started",__func__); 469 ret = NO_ERROR; 470 471 mActive = true; 472 goto end; 473 474 end: 475 ALOGE("%s: X", __func__); 476 return ret; 477 } 478 479 480 // --------------------------------------------------------------------------- 481 // QCameraStream_preview 482 // --------------------------------------------------------------------------- 483 void QCameraStream_preview::stop() { 484 ALOGE("%s: E", __func__); 485 int ret=MM_CAMERA_OK; 486 487 if(!mActive) { 488 return; 489 } 490 Mutex::Autolock lock(mLock); 491 mActive = false; 492 /* unregister the notify fn from the mmmm_camera_t object*/ 493 494 ALOGI("%s: Stop the thread \n", __func__); 495 /* call stop() in parent class to stop the monitor thread*/ 496 //stream_info = mHalCamCtrl->getChannelInterface(); 497 498 ret = streamOff(0); 499 if(MM_CAMERA_OK != ret) { 500 ALOGE ("%s: camera preview stop err=%d\n", __func__, ret); 501 } 502 #if 0 503 ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_PREVIEW); 504 if(ret != MM_CAMERA_OK) { 505 ALOGE("%s:Unreg preview buf err=%d\n", __func__, ret); 506 //ret = BAD_VALUE; 507 } 508 #endif 509 /* In case of a clean stop, we need to clean all buffers*/ 510 ALOGE("Debug : %s : Buffer Unprepared",__func__); 511 /*free camera_memory handles and return buffer back to surface*/ 512 ret= QCameraStream::deinitStream(); 513 ALOGE(": %s : De init Channel",__func__); 514 if(ret != MM_CAMERA_OK) { 515 ALOGE("%s:Deinit preview channel failed=%d\n", __func__, ret); 516 //ret = BAD_VALUE; 517 } 518 ALOGE("%s: X", __func__); 519 520 } 521 // --------------------------------------------------------------------------- 522 // QCameraStream_preview 523 // --------------------------------------------------------------------------- 524 void QCameraStream_preview::release() { 525 526 ALOGE("%s : BEGIN",__func__); 527 int ret=MM_CAMERA_OK,i; 528 529 if(!mInit) 530 { 531 ALOGE("%s : Stream not Initalized",__func__); 532 return; 533 } 534 535 if(mActive) { 536 this->streamOff(0); 537 } 538 539 540 if(mInit) { 541 deinitStream(); 542 } 543 mInit = false; 544 ALOGE("%s: END", __func__); 545 546 } 547 548 QCameraStream* 549 QCameraStream_preview::createInstance(uint32_t CameraHandle, 550 uint32_t ChannelId, 551 uint32_t Width, 552 uint32_t Height, 553 int requestedFormat, 554 mm_camera_vtbl_t *mm_ops, 555 camera_mode_t mode) 556 { 557 QCameraStream* pme = new QCameraStream_preview(CameraHandle, 558 ChannelId, 559 Width, 560 Height, 561 requestedFormat, 562 mm_ops, 563 mode); 564 return pme; 565 } 566 // --------------------------------------------------------------------------- 567 // QCameraStream_preview 568 // --------------------------------------------------------------------------- 569 570 void QCameraStream_preview::deleteInstance(QCameraStream *p) 571 { 572 if (p){ 573 ALOGV("%s: BEGIN", __func__); 574 p->release(); 575 delete p; 576 p = NULL; 577 ALOGV("%s: END", __func__); 578 } 579 } 580 581 582 /* Temp helper function */ 583 void *QCameraStream_preview::getLastQueuedFrame(void) 584 { 585 return mLastQueuedFrame; 586 } 587 588 // --------------------------------------------------------------------------- 589 // No code beyone this line 590 // --------------------------------------------------------------------------- 591 }; // namespace android 592