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 <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