1 /* 2 Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are 6 met: 7 * Redistributions of source code must retain the above copyright 8 notice, this list of conditions and the following disclaimer. 9 * Redistributions in binary form must reproduce the above 10 copyright notice, this list of conditions and the following 11 disclaimer in the documentation and/or other materials provided 12 with the distribution. 13 * Neither the name of The Linux Foundation nor the names of its 14 contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <fcntl.h> 31 #include <stdio.h> 32 #include <unistd.h> 33 #include <stdlib.h> 34 #include <pthread.h> 35 #include <sys/ioctl.h> 36 struct file; 37 struct inode; 38 #include <linux/android_pmem.h> 39 #include <sys/mman.h> 40 #include <errno.h> 41 #include <sys/time.h> 42 #include <string.h> 43 44 #include <inttypes.h> 45 #include <linux/msm_mdp.h> 46 #include <linux/fb.h> 47 #include "camera.h" 48 #include "mm_camera_dbg.h" 49 50 #ifdef DRAW_RECTANGLES 51 extern roi_info_t camframe_roi; 52 53 #undef CAM_FRM_DRAW_RECT 54 #define CAM_FRM_DRAW_RECT 55 #endif 56 57 #ifdef CAM_FRM_DRAW_FD_RECT 58 #undef CAM_FRM_DRAW_RECT 59 #define CAM_FRM_DRAW_RECT 60 #endif 61 62 struct fb_var_screeninfo vinfo; 63 struct fb_fix_screeninfo finfo; 64 int fb_fd = 0; 65 union { 66 char dummy[sizeof(struct mdp_blit_req_list) + 67 sizeof(struct mdp_blit_req) * 1]; 68 struct mdp_blit_req_list list; 69 } yuv; 70 71 static pthread_t cam_frame_fb_thread_id; 72 static int camframe_fb_exit; 73 74 static int is_camframe_fb_thread_ready; 75 USER_INPUT_DISPLAY_T input_display; 76 77 unsigned use_overlay = 0; 78 struct msmfb_overlay_data ov_front, ov_back, *ovp_front, *ovp_back; 79 struct mdp_overlay overlay, *overlayp; 80 int vid_buf_front_id, vid_buf_back_id; 81 static unsigned char please_initialize = 1; 82 int num_of_ready_frames = 0; 83 84 static pthread_cond_t sub_thread_ready_cond = PTHREAD_COND_INITIALIZER; 85 static pthread_mutex_t sub_thread_ready_mutex = PTHREAD_MUTEX_INITIALIZER; 86 pthread_cond_t camframe_fb_cond = PTHREAD_COND_INITIALIZER; 87 pthread_mutex_t camframe_fb_mutex = PTHREAD_MUTEX_INITIALIZER; 88 static void notify_camframe_fb_thread(); 89 90 void use_overlay_fb_display_driver(void) 91 { 92 use_overlay = 1; 93 } 94 95 void overlay_set_params(struct mdp_blit_req *e) 96 { 97 int result; 98 99 if (please_initialize) { 100 overlayp = &overlay; 101 ovp_front = &ov_front; 102 ovp_back = &ov_back; 103 104 overlayp->id = MSMFB_NEW_REQUEST; 105 } 106 107 overlayp->src.width = e->src.width; 108 overlayp->src.height = e->src.height; 109 overlayp->src.format = e->src.format; 110 111 overlayp->src_rect.x = e->src_rect.x; 112 overlayp->src_rect.y = e->src_rect.y; 113 overlayp->src_rect.w = e->src_rect.w; 114 overlayp->src_rect.h = e->src_rect.h; 115 116 overlayp->dst_rect.x = e->dst_rect.x; 117 overlayp->dst_rect.y = e->dst_rect.y; 118 /* ROTATOR is enabled in overlay library, swap dimensions 119 here to take care of that */ 120 overlayp->dst_rect.w = e->dst_rect.h; 121 overlayp->dst_rect.h = e->dst_rect.w; 122 123 if (overlayp->dst_rect.w > 480) 124 overlayp->dst_rect.w = 480; 125 if (overlayp->dst_rect.h > 800) 126 overlayp->dst_rect.h = 800; 127 128 overlayp->z_order = 0; // FB_OVERLAY_VID_0; 129 overlayp->alpha = e->alpha; 130 overlayp->transp_mask = 0; /* 0xF81F */ 131 overlayp->flags = e->flags; 132 overlayp->is_fg = 1; 133 134 if (please_initialize) { 135 CDBG("src.width %d height %d; src_rect.x %d y %d w %d h %d; dst_rect.x %d y %d w %d h %d\n", 136 overlayp->src.width, overlayp->src.height, 137 overlayp->src_rect.x, overlayp->src_rect.y, overlayp->src_rect.w, overlayp->src_rect.h, 138 overlayp->dst_rect.x, overlayp->dst_rect.y, overlayp->dst_rect.w, overlayp->dst_rect.h 139 ); 140 141 result = ioctl(fb_fd, MSMFB_OVERLAY_SET, overlayp); 142 if (result < 0) { 143 CDBG("ERROR: MSMFB_OVERLAY_SET failed!, result =%d\n", result); 144 } 145 } 146 147 if (please_initialize) { 148 vid_buf_front_id = overlayp->id; /* keep return id */ 149 150 ov_front.id = overlayp->id; 151 ov_back.id = overlayp->id; 152 please_initialize = 0; 153 } 154 155 return; 156 } 157 158 void overlay_set_frame(struct msm_frame *frame) 159 { 160 ov_front.data.offset = 0; 161 ov_front.data.memory_id = frame->fd; 162 return; 163 } 164 165 /*=========================================================================== 166 * FUNCTION test_app_camframe_callback 167 * DESCRIPTION display frame 168 *==========================================================================*/ 169 void test_app_camframe_callback(struct msm_frame *frame) 170 { 171 int result = 0; 172 struct mdp_blit_req *e; 173 struct timeval td1, td2; 174 struct timezone tz; 175 176 common_crop_t *crop = (common_crop_t *) (frame->cropinfo); 177 178 /* Initialize yuv structure */ 179 yuv.list.count = 1; 180 181 e = &yuv.list.req[0]; 182 183 e->src.width = input_display.user_input_display_width; 184 e->src.height = input_display.user_input_display_height; 185 e->src.format = MDP_Y_CRCB_H2V2; 186 e->src.offset = 0; 187 e->src.memory_id = frame->fd; 188 189 e->dst.width = vinfo.xres; 190 e->dst.height = vinfo.yres; 191 e->dst.format = MDP_RGB_565; 192 e->dst.offset = 0; 193 e->dst.memory_id = fb_fd; 194 195 e->transp_mask = 0xffffffff; 196 e->flags = 0; 197 e->alpha = 0xff; 198 199 /* Starting doing MDP Cropping */ 200 if (frame->path == OUTPUT_TYPE_P) { 201 202 if (crop->in2_w != 0 || crop->in2_h != 0) { 203 204 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1; 205 206 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1; 207 208 e->src_rect.w = crop->in2_w; 209 e->src_rect.h = crop->in2_h; 210 211 CDBG("e->src_rect.x = %d\n", e->src_rect.x); 212 CDBG("e->src_rect.y = %d\n", e->src_rect.y); 213 CDBG("e->src_rect.w = %d\n", e->src_rect.w); 214 CDBG("e->src_rect.h = %d\n", e->src_rect.h); 215 216 e->dst_rect.x = 0; 217 e->dst_rect.y = 0; 218 e->dst_rect.w = input_display.user_input_display_width; 219 e->dst_rect.h = input_display.user_input_display_height; 220 } else { 221 e->src_rect.x = 0; 222 e->src_rect.y = 0; 223 e->src_rect.w = input_display.user_input_display_width; 224 e->src_rect.h = input_display.user_input_display_height; 225 226 e->dst_rect.x = 0; 227 e->dst_rect.y = 0; 228 e->dst_rect.w = input_display.user_input_display_width; 229 e->dst_rect.h = input_display.user_input_display_height; 230 } 231 if (use_overlay) overlay_set_params(e); 232 } else { 233 234 } 235 236 gettimeofday(&td1, &tz); 237 238 if (use_overlay) overlay_set_frame(frame); 239 else { 240 result = ioctl(fb_fd, MSMFB_BLIT, &yuv.list); 241 if (result < 0) { 242 CDBG("MSM_FBIOBLT failed! line=%d\n", __LINE__); 243 } 244 } 245 246 gettimeofday(&td2, &tz); 247 CDBG("Profiling: MSMFB_BLIT takes %ld microseconds\n", 248 ((td2.tv_sec - td1.tv_sec) * 1000000 + (td2.tv_usec - td1.tv_usec))); 249 250 td1 = td2; 251 notify_camframe_fb_thread(); 252 /* add frame back to the free queue*/ 253 //camframe_add_frame(CAM_PREVIEW_FRAME, frame); 254 } 255 256 void notify_camframe_fb_thread() 257 { 258 pthread_mutex_lock(&camframe_fb_mutex); 259 260 num_of_ready_frames ++; 261 pthread_cond_signal(&camframe_fb_cond); 262 263 pthread_mutex_unlock(&camframe_fb_mutex); 264 } 265 266 void camframe_fb_thread_ready_signal(void); 267 268 void *camframe_fb_thread(void *data) 269 { 270 int result = 0; 271 static struct timeval td1, td2; 272 struct timezone tz; 273 274 #ifdef _ANDROID_ 275 fb_fd = open(ANDROID_FB0, O_RDWR); 276 CDBG("%s:android dl '%s', fd=%d\n", __func__, ANDROID_FB0, fb_fd); 277 #else 278 fb_fd = open(LE_FB0, O_RDWR); 279 CDBG("%s:LE_FB0 dl, '%s', fd=%d\n", __func__, LE_FB0, fb_fd); 280 #endif 281 if (fb_fd < 0) { 282 CDBG_ERROR("cannot open framebuffer %s or %s file node\n", 283 ANDROID_FB0, LE_FB0); 284 goto fail1; 285 } 286 287 if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) { 288 CDBG_ERROR("cannot retrieve vscreenInfo!\n"); 289 goto fail; 290 } 291 292 if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0) { 293 CDBG_ERROR("can't retrieve fscreenInfo!\n"); 294 goto fail; 295 } 296 297 vinfo.activate = FB_ACTIVATE_VBL; 298 299 camframe_fb_thread_ready_signal(); 300 301 pthread_mutex_lock(&camframe_fb_mutex); 302 while (!camframe_fb_exit) { 303 CDBG("cam_frame_fb_thread: num_of_ready_frames: %d\n", num_of_ready_frames); 304 if (num_of_ready_frames <= 0) { 305 pthread_cond_wait(&camframe_fb_cond, &camframe_fb_mutex); 306 } 307 if (num_of_ready_frames > 0) { 308 num_of_ready_frames --; 309 310 gettimeofday(&td1, &tz); 311 if (use_overlay) { 312 result = ioctl(fb_fd, MSMFB_OVERLAY_PLAY, ovp_front); 313 } else { 314 result = ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo); 315 } 316 317 gettimeofday(&td2, &tz); 318 319 CDBG("Profiling: frame timestamp after FBIO display = %ld ms\n", 320 (td2.tv_sec*1000) + (td2.tv_usec/1000)); 321 322 CDBG("cam_frame_fb_thread: elapse time for FBIOPAN_DISPLAY = %ld, return = %d\n", 323 (td2.tv_sec - td1.tv_sec) * 1000000 + td2.tv_usec - td1.tv_usec, result); 324 325 if (result < 0) { 326 CDBG("DISPLAY: Failed\n"); 327 } 328 } 329 } 330 331 pthread_mutex_unlock(&camframe_fb_mutex); 332 333 if (use_overlay) { 334 if (ioctl(fb_fd, MSMFB_OVERLAY_UNSET, &vid_buf_front_id)) { 335 CDBG("\nERROR! MSMFB_OVERLAY_UNSET failed! (Line %d)\n", __LINE__); 336 goto fail; 337 } 338 } 339 340 return NULL; 341 342 fail: 343 close(fb_fd); 344 fail1: 345 camframe_fb_exit = -1; 346 camframe_fb_thread_ready_signal(); 347 return NULL; 348 } 349 350 int launch_camframe_fb_thread(void) 351 { 352 353 camframe_fb_exit = 0; 354 is_camframe_fb_thread_ready = 0; 355 pthread_create(&cam_frame_fb_thread_id, NULL, camframe_fb_thread, NULL); 356 357 /* Waiting for launching sub thread ready signal. */ 358 CDBG("launch_camframe_fb_thread(), call pthread_cond_wait\n"); 359 360 pthread_mutex_lock(&sub_thread_ready_mutex); 361 if (!is_camframe_fb_thread_ready) { 362 pthread_cond_wait(&sub_thread_ready_cond, &sub_thread_ready_mutex); 363 } 364 pthread_mutex_unlock(&sub_thread_ready_mutex); 365 366 CDBG("launch_camframe_fb_thread(), call pthread_cond_wait done\n"); 367 CDBG("%s:fb rc=%d\n", __func__, camframe_fb_exit); 368 return camframe_fb_exit; 369 } 370 371 void release_camframe_fb_thread(void) 372 { 373 camframe_fb_exit = 1; 374 please_initialize = 1; 375 376 /* Notify the camframe fb thread to wake up */ 377 if (cam_frame_fb_thread_id != 0) { 378 pthread_mutex_lock(&camframe_fb_mutex); 379 pthread_cond_signal(&camframe_fb_cond); 380 pthread_mutex_unlock(&camframe_fb_mutex); 381 if (pthread_join(cam_frame_fb_thread_id, NULL) != 0) { 382 CDBG("cam_frame_fb_thread exit failure!\n"); 383 } 384 close(fb_fd); 385 } 386 } 387 388 void camframe_fb_thread_ready_signal(void) 389 { 390 /* Send the signal to control thread to indicate that the cam frame fb 391 * ready. 392 */ 393 CDBG("cam_frame_fb_thread() is ready, call pthread_cond_signal\n"); 394 395 pthread_mutex_lock(&sub_thread_ready_mutex); 396 is_camframe_fb_thread_ready = 1; 397 pthread_cond_signal(&sub_thread_ready_cond); 398 pthread_mutex_unlock(&sub_thread_ready_mutex); 399 400 CDBG("cam_frame_fb_thread() is ready, call pthread_cond_signal done\n"); 401 } 402 403 #ifdef CAM_FRM_DRAW_RECT 404 void draw_rect(char *buf, int buf_w, 405 int x, int y, int dx, int dy) 406 { 407 int i; 408 int left = x; 409 int right = x+dx; 410 int top = y; 411 int bottom = y+dy; 412 413 for (i = left; i < right; i++) { 414 buf[top*buf_w+i] = 0xff; 415 buf[bottom*buf_w+i] = 0xff; 416 } 417 for (i = top; i < bottom; i++) { 418 buf[i*buf_w+left] = 0xff; 419 buf[i*buf_w+right] = 0xff; 420 } 421 } 422 #endif 423 424 void draw_rectangles(struct msm_frame* newFrame) 425 { 426 struct fd_roi_t *p_fd_roi; 427 #ifdef DRAW_RECTANGLES 428 uint8_t i; 429 for (i = 0; i < camframe_roi.num_roi; i++) { 430 CDBG("%s: camframe_roi: i=%d, x=%d, y=%d, dx=%d, dy=%d\n", __func__, 431 i, camframe_roi.roi[i].x, camframe_roi.roi[i].y, 432 camframe_roi.roi[i].dx, camframe_roi.roi[i].dy); 433 draw_rect((char*)newFrame->buffer, 640, 434 camframe_roi.roi[i].x, camframe_roi.roi[i].y, 435 camframe_roi.roi[i].dx, camframe_roi.roi[i].dy); 436 } 437 #endif 438 439 #ifdef CAM_FRM_DRAW_FD_RECT 440 p_fd_roi = (struct fd_roi_t *)newFrame->roi_info.info; 441 if(p_fd_roi && p_fd_roi->rect_num > 0){ 442 int i; 443 for(i =0; i < p_fd_roi->rect_num; i++) 444 { 445 draw_rect((char*)newFrame->buffer, 800, 446 p_fd_roi->faces[i].x, p_fd_roi->faces[i].y, 447 p_fd_roi->faces[i].dx, p_fd_roi->faces[i].dy); 448 } 449 } 450 #endif 451 } 452 453 /*=========================================================================== 454 * FUNCTION - v4l2_render - 455 * 456 * DESCRIPTION: 457 *==========================================================================*/ 458 int v4l2_render(int frame_fd, struct v4l2_buffer *vb, struct v4l2_crop *crop) 459 { 460 struct mdp_blit_req *e; 461 /* Initialize yuv structure */ 462 yuv.list.count = 1; 463 e = &yuv.list.req[0]; 464 465 e->src.width = input_display.user_input_display_width; 466 e->src.height = input_display.user_input_display_height; 467 e->src.format = MDP_Y_CBCR_H2V2; 468 e->src.offset = 0; 469 e->src.memory_id = frame_fd; 470 471 e->dst.width = vinfo.xres; 472 e->dst.height = vinfo.yres; 473 e->dst.format = MDP_RGB_565; 474 e->dst.offset = 0; 475 e->dst.memory_id = fb_fd; 476 477 e->transp_mask = 0xffffffff; 478 e->flags = 0; 479 e->alpha = 0xff; 480 481 if (crop != NULL && (crop->c.width != 0 || crop->c.height != 0)) { 482 e->src_rect.x = crop->c.left; 483 e->src_rect.y = crop->c.top; 484 e->src_rect.w = crop->c.width; 485 e->src_rect.h = crop->c.height; 486 487 e->dst_rect.x = 0; 488 e->dst_rect.y = 0; 489 e->dst_rect.w = input_display.user_input_display_width; 490 e->dst_rect.h = input_display.user_input_display_height; 491 } else { 492 e->dst_rect.x = 0; 493 e->dst_rect.y = 0; 494 e->dst_rect.w = input_display.user_input_display_width; 495 e->dst_rect.h = input_display.user_input_display_height; 496 497 e->src_rect.x = 0; 498 e->src_rect.y = 0; 499 e->src_rect.w = input_display.user_input_display_width; 500 e->src_rect.h = input_display.user_input_display_height; 501 } 502 overlay_set_params(e); 503 ov_front.data.offset = 0; 504 ov_front.data.memory_id = frame_fd; 505 notify_camframe_fb_thread(); 506 507 return TRUE; 508 } 509 510 int mm_app_dl_render(int frame_fd, struct crop_info * cropinfo) 511 { 512 struct mdp_blit_req *e; 513 int croplen = 0; 514 //struct crop_info *cropinfo; 515 common_crop_t *crop; 516 517 //cropinfo = (struct crop_info *)vb->input; 518 if(cropinfo != NULL) { 519 crop = (common_crop_t *)cropinfo->info; 520 } 521 /* Initialize yuv structure */ 522 yuv.list.count = 1; 523 e = &yuv.list.req[0]; 524 525 e->src.width = input_display.user_input_display_width; 526 e->src.height = input_display.user_input_display_height; 527 e->src.format = MDP_Y_CRCB_H2V2; 528 e->src.offset = 0; 529 e->src.memory_id = frame_fd; 530 531 e->dst.width = vinfo.xres; 532 e->dst.height = vinfo.yres; 533 e->dst.format = MDP_RGB_565; 534 e->dst.offset = 0; 535 e->dst.memory_id = fb_fd; 536 537 e->transp_mask = 0xffffffff; 538 e->flags = 0; 539 e->alpha = 0xff; 540 541 if (cropinfo != NULL && (crop->in2_w != 0 || crop->in2_h != 0)) { 542 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1; 543 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1; 544 e->src_rect.w = crop->in2_w; 545 e->src_rect.h = crop->in2_h; 546 547 e->dst_rect.x = 0; 548 e->dst_rect.y = 0; 549 e->dst_rect.w = input_display.user_input_display_width; 550 e->dst_rect.h = input_display.user_input_display_height; 551 } else { 552 e->dst_rect.x = 0; 553 e->dst_rect.y = 0; 554 e->dst_rect.w = input_display.user_input_display_width; 555 e->dst_rect.h = input_display.user_input_display_height; 556 557 e->src_rect.x = 0; 558 e->src_rect.y = 0; 559 e->src_rect.w = input_display.user_input_display_width; 560 e->src_rect.h = input_display.user_input_display_height; 561 } 562 563 overlay_set_params(e); 564 565 ov_front.data.offset = 0; 566 ov_front.data.memory_id = frame_fd; 567 notify_camframe_fb_thread(); 568 569 return TRUE; 570 } 571 572 573