diff options
Diffstat (limited to 'apps/plugins/mpegplayer/video_out_rockbox.c')
-rw-r--r-- | apps/plugins/mpegplayer/video_out_rockbox.c | 171 |
1 files changed, 146 insertions, 25 deletions
diff --git a/apps/plugins/mpegplayer/video_out_rockbox.c b/apps/plugins/mpegplayer/video_out_rockbox.c index ff0d39eba6..6efbaf0a01 100644 --- a/apps/plugins/mpegplayer/video_out_rockbox.c +++ b/apps/plugins/mpegplayer/video_out_rockbox.c | |||
@@ -21,6 +21,9 @@ | |||
21 | #include "plugin.h" | 21 | #include "plugin.h" |
22 | #include "mpegplayer.h" | 22 | #include "mpegplayer.h" |
23 | 23 | ||
24 | #define VO_NON_NULL_RECT 0x1 | ||
25 | #define VO_VISIBLE 0x2 | ||
26 | |||
24 | struct vo_data | 27 | struct vo_data |
25 | { | 28 | { |
26 | int image_width; | 29 | int image_width; |
@@ -34,8 +37,9 @@ struct vo_data | |||
34 | int output_width; | 37 | int output_width; |
35 | int output_height; | 38 | int output_height; |
36 | bool visible; | 39 | bool visible; |
37 | bool thumb_mode; | 40 | unsigned flags; |
38 | void *last; | 41 | struct vo_rect rc_vid; |
42 | struct vo_rect rc_clip; | ||
39 | }; | 43 | }; |
40 | 44 | ||
41 | #ifdef PROC_NEEDS_CACHEALIGN | 45 | #ifdef PROC_NEEDS_CACHEALIGN |
@@ -48,10 +52,40 @@ static uint8_t __vo_data[CACHEALIGN_UP(sizeof(struct vo_data))] | |||
48 | static struct vo_data vo; | 52 | static struct vo_data vo; |
49 | #endif | 53 | #endif |
50 | 54 | ||
55 | #if NUM_CORES > 1 | ||
56 | static struct mutex vo_mtx NOCACHEBSS_ATTR; | ||
57 | #endif | ||
58 | |||
59 | static inline void video_lock_init(void) | ||
60 | { | ||
61 | #if NUM_CORES > 1 | ||
62 | rb->mutex_init(&vo_mtx); | ||
63 | #endif | ||
64 | } | ||
65 | |||
66 | static inline void video_lock(void) | ||
67 | { | ||
68 | #if NUM_CORES > 1 | ||
69 | rb->mutex_lock(&vo_mtx); | ||
70 | #endif | ||
71 | } | ||
72 | |||
73 | static inline void video_unlock(void) | ||
74 | { | ||
75 | #if NUM_CORES > 1 | ||
76 | rb->mutex_unlock(&vo_mtx); | ||
77 | #endif | ||
78 | } | ||
79 | |||
80 | |||
51 | /* Draw a black rectangle if no video frame is available */ | 81 | /* Draw a black rectangle if no video frame is available */ |
52 | static void vo_draw_black(void) | 82 | static void vo_draw_black(void) |
53 | { | 83 | { |
54 | int foreground = lcd_(get_foreground)(); | 84 | int foreground; |
85 | |||
86 | video_lock(); | ||
87 | |||
88 | foreground = lcd_(get_foreground)(); | ||
55 | 89 | ||
56 | lcd_(set_foreground)(DRAW_BLACK); | 90 | lcd_(set_foreground)(DRAW_BLACK); |
57 | 91 | ||
@@ -61,21 +95,27 @@ static void vo_draw_black(void) | |||
61 | vo.output_height); | 95 | vo.output_height); |
62 | 96 | ||
63 | lcd_(set_foreground)(foreground); | 97 | lcd_(set_foreground)(foreground); |
98 | |||
99 | video_unlock(); | ||
64 | } | 100 | } |
65 | 101 | ||
66 | static inline void yuv_blit(uint8_t * const * buf, int src_x, int src_y, | 102 | static inline void yuv_blit(uint8_t * const * buf, int src_x, int src_y, |
67 | int stride, int x, int y, int width, int height) | 103 | int stride, int x, int y, int width, int height) |
68 | { | 104 | { |
105 | video_lock(); | ||
106 | |||
69 | #ifdef HAVE_LCD_COLOR | 107 | #ifdef HAVE_LCD_COLOR |
70 | rb->lcd_yuv_blit(buf, src_x, src_y, stride, x, y , width, height); | 108 | rb->lcd_yuv_blit(buf, src_x, src_y, stride, x, y , width, height); |
71 | #else | 109 | #else |
72 | gray_ub_gray_bitmap_part(buf[0], src_x, src_y, stride, x, y, width, height); | 110 | gray_ub_gray_bitmap_part(buf[0], src_x, src_y, stride, x, y, width, height); |
73 | #endif | 111 | #endif |
112 | |||
113 | video_unlock(); | ||
74 | } | 114 | } |
75 | 115 | ||
76 | void vo_draw_frame(uint8_t * const * buf) | 116 | void vo_draw_frame(uint8_t * const * buf) |
77 | { | 117 | { |
78 | if (!vo.visible) | 118 | if (vo.flags == 0) |
79 | { | 119 | { |
80 | /* Frame is hidden - copout */ | 120 | /* Frame is hidden - copout */ |
81 | DEBUGF("vo hidden\n"); | 121 | DEBUGF("vo hidden\n"); |
@@ -94,14 +134,6 @@ void vo_draw_frame(uint8_t * const * buf) | |||
94 | vo.output_height); | 134 | vo.output_height); |
95 | } | 135 | } |
96 | 136 | ||
97 | #if LCD_WIDTH >= LCD_HEIGHT | ||
98 | #define SCREEN_WIDTH LCD_WIDTH | ||
99 | #define SCREEN_HEIGHT LCD_HEIGHT | ||
100 | #else /* Assume the screen is rotated on portrait LCDs */ | ||
101 | #define SCREEN_WIDTH LCD_HEIGHT | ||
102 | #define SCREEN_HEIGHT LCD_WIDTH | ||
103 | #endif | ||
104 | |||
105 | static inline void vo_rect_clear_inl(struct vo_rect *rc) | 137 | static inline void vo_rect_clear_inl(struct vo_rect *rc) |
106 | { | 138 | { |
107 | rc->l = rc->t = rc->r = rc->b = 0; | 139 | rc->l = rc->t = rc->r = rc->b = 0; |
@@ -172,6 +204,48 @@ bool vo_rect_intersect(struct vo_rect *rc_dst, | |||
172 | return false; | 204 | return false; |
173 | } | 205 | } |
174 | 206 | ||
207 | bool vo_rect_union(struct vo_rect *rc_dst, | ||
208 | const struct vo_rect *rc1, | ||
209 | const struct vo_rect *rc2) | ||
210 | { | ||
211 | if (rc_dst != NULL) | ||
212 | { | ||
213 | if (!vo_rect_empty_inl(rc1)) | ||
214 | { | ||
215 | if (!vo_rect_empty_inl(rc2)) | ||
216 | { | ||
217 | rc_dst->l = MIN(rc1->l, rc2->l); | ||
218 | rc_dst->t = MIN(rc1->t, rc2->t); | ||
219 | rc_dst->r = MAX(rc1->r, rc2->r); | ||
220 | rc_dst->b = MAX(rc1->b, rc2->b); | ||
221 | } | ||
222 | else | ||
223 | { | ||
224 | *rc_dst = *rc1; | ||
225 | } | ||
226 | |||
227 | return true; | ||
228 | } | ||
229 | else if (!vo_rect_empty(rc2)) | ||
230 | { | ||
231 | *rc_dst = *rc2; | ||
232 | return true; | ||
233 | } | ||
234 | |||
235 | vo_rect_clear_inl(rc_dst); | ||
236 | } | ||
237 | |||
238 | return false; | ||
239 | } | ||
240 | |||
241 | void vo_rect_offset(struct vo_rect *rc, int dx, int dy) | ||
242 | { | ||
243 | rc->l += dx; | ||
244 | rc->t += dy; | ||
245 | rc->r += dx; | ||
246 | rc->b += dy; | ||
247 | } | ||
248 | |||
175 | /* Shink or stretch each axis - rotate counter-clockwise to retain upright | 249 | /* Shink or stretch each axis - rotate counter-clockwise to retain upright |
176 | * orientation on rotated displays (they rotate clockwise) */ | 250 | * orientation on rotated displays (they rotate clockwise) */ |
177 | void stretch_image_plane(const uint8_t * src, uint8_t *dst, int stride, | 251 | void stretch_image_plane(const uint8_t * src, uint8_t *dst, int stride, |
@@ -350,25 +424,27 @@ void vo_setup(const mpeg2_sequence_t * sequence) | |||
350 | 424 | ||
351 | if (sequence->display_width >= SCREEN_WIDTH) | 425 | if (sequence->display_width >= SCREEN_WIDTH) |
352 | { | 426 | { |
353 | vo.output_width = SCREEN_WIDTH; | 427 | vo.rc_vid.l = 0; |
354 | vo.output_x = 0; | 428 | vo.rc_vid.r = SCREEN_WIDTH; |
355 | } | 429 | } |
356 | else | 430 | else |
357 | { | 431 | { |
358 | vo.output_width = sequence->display_width; | 432 | vo.rc_vid.l = (SCREEN_WIDTH - sequence->display_width) / 2; |
359 | vo.output_x = (SCREEN_WIDTH - sequence->display_width) / 2; | 433 | vo.rc_vid.r = vo.rc_vid.l + sequence->display_width; |
360 | } | 434 | } |
361 | 435 | ||
362 | if (sequence->display_height >= SCREEN_HEIGHT) | 436 | if (sequence->display_height >= SCREEN_HEIGHT) |
363 | { | 437 | { |
364 | vo.output_height = SCREEN_HEIGHT; | 438 | vo.rc_vid.t = 0; |
365 | vo.output_y = 0; | 439 | vo.rc_vid.b = SCREEN_HEIGHT; |
366 | } | 440 | } |
367 | else | 441 | else |
368 | { | 442 | { |
369 | vo.output_height = sequence->display_height; | 443 | vo.rc_vid.t = (SCREEN_HEIGHT - sequence->display_height) / 2; |
370 | vo.output_y = (SCREEN_HEIGHT - sequence->display_height) / 2; | 444 | vo.rc_vid.b = vo.rc_vid.t + sequence->display_height; |
371 | } | 445 | } |
446 | |||
447 | vo_set_clip_rect(&vo.rc_clip); | ||
372 | } | 448 | } |
373 | 449 | ||
374 | void vo_dimensions(struct vo_ext *sz) | 450 | void vo_dimensions(struct vo_ext *sz) |
@@ -379,23 +455,68 @@ void vo_dimensions(struct vo_ext *sz) | |||
379 | 455 | ||
380 | bool vo_init(void) | 456 | bool vo_init(void) |
381 | { | 457 | { |
382 | vo.visible = false; | 458 | vo.flags = 0; |
459 | vo_rect_set_ext(&vo.rc_clip, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); | ||
460 | video_lock_init(); | ||
383 | return true; | 461 | return true; |
384 | } | 462 | } |
385 | 463 | ||
386 | bool vo_show(bool show) | 464 | bool vo_show(bool show) |
387 | { | 465 | { |
388 | bool vis = vo.visible; | 466 | bool vis = vo.flags & VO_VISIBLE; |
389 | vo.visible = show; | 467 | |
468 | if (show) | ||
469 | vo.flags |= VO_VISIBLE; | ||
470 | else | ||
471 | vo.flags &= ~VO_VISIBLE; | ||
472 | |||
390 | return vis; | 473 | return vis; |
391 | } | 474 | } |
392 | 475 | ||
393 | bool vo_is_visible(void) | 476 | bool vo_is_visible(void) |
394 | { | 477 | { |
395 | return vo.visible; | 478 | return vo.flags & VO_VISIBLE; |
396 | } | 479 | } |
397 | 480 | ||
398 | void vo_cleanup(void) | 481 | void vo_cleanup(void) |
399 | { | 482 | { |
400 | vo.visible = false; | 483 | vo.flags = 0; |
401 | } | 484 | } |
485 | |||
486 | void vo_set_clip_rect(const struct vo_rect *rc) | ||
487 | { | ||
488 | struct vo_rect rc_out; | ||
489 | |||
490 | if (rc == NULL) | ||
491 | vo_rect_set_ext(&vo.rc_clip, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); | ||
492 | else | ||
493 | vo.rc_clip = *rc; | ||
494 | |||
495 | if (!vo_rect_intersect(&rc_out, &vo.rc_vid, &vo.rc_clip)) | ||
496 | vo.flags &= ~VO_NON_NULL_RECT; | ||
497 | else | ||
498 | vo.flags |= VO_NON_NULL_RECT; | ||
499 | |||
500 | vo.output_x = rc_out.l; | ||
501 | vo.output_y = rc_out.t; | ||
502 | vo.output_width = rc_out.r - rc_out.l; | ||
503 | vo.output_height = rc_out.b - rc_out.t; | ||
504 | } | ||
505 | |||
506 | #if NUM_CORES > 1 || !defined (HAVE_LCD_COLOR) | ||
507 | void vo_lock(void) | ||
508 | { | ||
509 | #ifndef HAVE_LCD_COLOR | ||
510 | set_irq_level(HIGHEST_IRQ_LEVEL); | ||
511 | #endif | ||
512 | video_lock(); | ||
513 | } | ||
514 | |||
515 | void vo_unlock(void) | ||
516 | { | ||
517 | video_unlock(); | ||
518 | #ifndef HAVE_LCD_COLOR | ||
519 | set_irq_level(0); | ||
520 | #endif | ||
521 | } | ||
522 | #endif | ||