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 <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
52 extern 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
63 struct fb_var_screeninfo vinfo;
64 struct fb_fix_screeninfo finfo;
65 int fb_fd = 0;
66 union {
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
72 static pthread_t cam_frame_fb_thread_id;
73 static int camframe_fb_exit;
74
75 static int is_camframe_fb_thread_ready;
76 USER_INPUT_DISPLAY_T input_display;
77
78 unsigned use_overlay = 0;
79 struct msmfb_overlay_data ov_front, ov_back, *ovp_front, *ovp_back;
80 struct mdp_overlay overlay, *overlayp;
81 int vid_buf_front_id, vid_buf_back_id;
82 static unsigned char please_initialize = 1;
83 int num_of_ready_frames = 0;
84
85 static pthread_cond_t sub_thread_ready_cond = PTHREAD_COND_INITIALIZER;
86 static pthread_mutex_t sub_thread_ready_mutex = PTHREAD_MUTEX_INITIALIZER;
87 pthread_cond_t camframe_fb_cond = PTHREAD_COND_INITIALIZER;
88 pthread_mutex_t camframe_fb_mutex = PTHREAD_MUTEX_INITIALIZER;
89 static void notify_camframe_fb_thread();
90
use_overlay_fb_display_driver(void)91 void use_overlay_fb_display_driver(void)
92 {
93 use_overlay = 1;
94 }
95
overlay_set_params(struct mdp_blit_req * e)96 void 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
overlay_set_frame(struct msm_frame * frame)159 void 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 *==========================================================================*/
test_app_camframe_callback(struct msm_frame * frame)170 void 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
notify_camframe_fb_thread()257 void 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
267 void camframe_fb_thread_ready_signal(void);
268
camframe_fb_thread(void * data)269 void *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
launch_camframe_fb_thread(void)351 int 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
release_camframe_fb_thread(void)372 void 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
camframe_fb_thread_ready_signal(void)389 void 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
draw_rect(char * buf,int buf_w,int x,int y,int dx,int dy)405 void 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
draw_rectangles(struct msm_frame * newFrame)425 void 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 *==========================================================================*/
v4l2_render(int frame_fd,struct v4l2_buffer * vb,struct v4l2_crop * crop)459 int 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
mm_app_dl_render(int frame_fd,struct crop_info * cropinfo)511 int 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