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