Home | History | Annotate | Download | only in src
      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