• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 
use_overlay_fb_display_driver(void)92 void use_overlay_fb_display_driver(void)
93 {
94   use_overlay = 1;
95 }
96 
overlay_set_params(struct mdp_blit_req * e)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 
overlay_set_frame(struct msm_frame * frame)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  *==========================================================================*/
test_app_camframe_callback(struct msm_frame * frame)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 
notify_camframe_fb_thread()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 
camframe_fb_thread(void * data)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 
launch_camframe_fb_thread(void)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 
release_camframe_fb_thread(void)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 
camframe_fb_thread_ready_signal(void)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
draw_rect(char * buf,int buf_w,int x,int y,int dx,int dy)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 
draw_rectangles(struct msm_frame * newFrame)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  *==========================================================================*/
v4l2_render(int frame_fd,struct v4l2_buffer * vb,struct v4l2_crop * crop)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 
mm_app_dl_render(int frame_fd,struct crop_info * cropinfo)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