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
use_overlay_fb_display_driver(void)90 void use_overlay_fb_display_driver(void)
91 {
92 use_overlay = 1;
93 }
94
overlay_set_params(struct mdp_blit_req * e)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
overlay_set_frame(struct msm_frame * frame)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 *==========================================================================*/
test_app_camframe_callback(struct msm_frame * frame)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
notify_camframe_fb_thread()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
camframe_fb_thread(void * data)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
launch_camframe_fb_thread(void)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
release_camframe_fb_thread(void)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
camframe_fb_thread_ready_signal(void)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
draw_rect(char * buf,int buf_w,int x,int y,int dx,int dy)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
draw_rectangles(struct msm_frame * newFrame)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 *==========================================================================*/
v4l2_render(int frame_fd,struct v4l2_buffer * vb,struct v4l2_crop * crop)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
mm_app_dl_render(int frame_fd,struct crop_info * cropinfo)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