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