diff options
Diffstat (limited to 'apps/plugins/mpegplayer/video_out_rockbox.c')
-rw-r--r-- | apps/plugins/mpegplayer/video_out_rockbox.c | 479 |
1 files changed, 347 insertions, 132 deletions
diff --git a/apps/plugins/mpegplayer/video_out_rockbox.c b/apps/plugins/mpegplayer/video_out_rockbox.c index 9dd8d6a467..d5e927e9f1 100644 --- a/apps/plugins/mpegplayer/video_out_rockbox.c +++ b/apps/plugins/mpegplayer/video_out_rockbox.c | |||
@@ -1,189 +1,404 @@ | |||
1 | /* | 1 | /*************************************************************************** |
2 | * video_out_null.c | 2 | * __________ __ ___. |
3 | * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> | 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
4 | * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> | 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
5 | * | 9 | * |
6 | * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. | 10 | * mpegplayer video output routines |
7 | * See http://libmpeg2.sourceforge.net/ for updates. | ||
8 | * | 11 | * |
9 | * mpeg2dec is free software; you can redistribute it and/or modify | 12 | * All files in this archive are subject to the GNU General Public License. |
10 | * it under the terms of the GNU General Public License as published by | 13 | * See the file COPYING in the source tree root for full license agreement. |
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | 14 | * |
14 | * mpeg2dec is distributed in the hope that it will be useful, | 15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | * KIND, either express or implied. |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | 17 | * |
19 | * You should have received a copy of the GNU General Public License | 18 | ****************************************************************************/ |
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include "mpeg2dec_config.h" | 19 | #include "mpeg2dec_config.h" |
25 | 20 | ||
26 | #include "plugin.h" | 21 | #include "plugin.h" |
27 | #include "gray.h" | 22 | #include "mpegplayer.h" |
23 | |||
24 | struct vo_data | ||
25 | { | ||
26 | int image_width; | ||
27 | int image_height; | ||
28 | int image_chroma_x; | ||
29 | int image_chroma_y; | ||
30 | int display_width; | ||
31 | int display_height; | ||
32 | int output_x; | ||
33 | int output_y; | ||
34 | int output_width; | ||
35 | int output_height; | ||
36 | bool visible; | ||
37 | bool thumb_mode; | ||
38 | void *last; | ||
39 | }; | ||
40 | |||
41 | #ifdef PROC_NEEDS_CACHEALIGN | ||
42 | /* Cache aligned and padded to avoid clobbering other processors' cacheable | ||
43 | * data */ | ||
44 | static uint8_t __vo_data[CACHEALIGN_UP(sizeof(struct vo_data))] | ||
45 | CACHEALIGN_ATTR; | ||
46 | #define vo (*((struct vo_data *)__vo_data)) | ||
47 | #else | ||
48 | static struct vo_data vo; | ||
49 | #endif | ||
50 | |||
51 | /* Draw a black rectangle if no video frame is available */ | ||
52 | static void vo_draw_black(void) | ||
53 | { | ||
54 | int foreground = lcd_(get_foreground)(); | ||
28 | 55 | ||
29 | extern struct plugin_api* rb; | 56 | lcd_(set_foreground)(DRAW_BLACK); |
30 | 57 | ||
31 | #include "mpeg2.h" | 58 | lcd_(fillrect)(vo.output_x, vo.output_y, vo.output_width, |
32 | #include "video_out.h" | 59 | vo.output_height); |
60 | lcd_(update_rect)(vo.output_x, vo.output_y, vo.output_width, | ||
61 | vo.output_height); | ||
33 | 62 | ||
34 | static int image_width; | 63 | lcd_(set_foreground)(foreground); |
35 | static int image_height; | 64 | } |
36 | static int image_chroma_x; | ||
37 | static int image_chroma_y; | ||
38 | static int output_x; | ||
39 | static int output_y; | ||
40 | static int output_width; | ||
41 | static int output_height; | ||
42 | 65 | ||
43 | void vo_draw_frame (uint8_t * const * buf) | 66 | 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) | ||
44 | { | 68 | { |
45 | #ifdef HAVE_LCD_COLOR | 69 | #ifdef HAVE_LCD_COLOR |
46 | rb->lcd_yuv_blit(buf, 0,0,image_width, | 70 | rb->lcd_yuv_blit(buf, src_x, src_y, stride, x, y , width, height); |
47 | output_x,output_y,output_width,output_height); | ||
48 | #else | 71 | #else |
49 | gray_ub_gray_bitmap_part(buf[0],0,0,image_width, | 72 | gray_ub_gray_bitmap_part(buf[0], src_x, src_y, stride, x, y, width, height); |
50 | output_x,output_y,output_width,output_height); | ||
51 | #endif | 73 | #endif |
52 | } | 74 | } |
53 | 75 | ||
76 | void vo_draw_frame(uint8_t * const * buf) | ||
77 | { | ||
78 | if (!vo.visible) | ||
79 | { | ||
80 | /* Frame is hidden - copout */ | ||
81 | DEBUGF("vo hidden\n"); | ||
82 | return; | ||
83 | } | ||
84 | else if (buf == NULL) | ||
85 | { | ||
86 | /* No frame exists - draw black */ | ||
87 | vo_draw_black(); | ||
88 | DEBUGF("vo no frame\n"); | ||
89 | return; | ||
90 | } | ||
91 | |||
92 | yuv_blit(buf, 0, 0, vo.image_width, | ||
93 | vo.output_x, vo.output_y, vo.output_width, | ||
94 | vo.output_height); | ||
95 | } | ||
96 | |||
54 | #if LCD_WIDTH >= LCD_HEIGHT | 97 | #if LCD_WIDTH >= LCD_HEIGHT |
55 | #define SCREEN_WIDTH LCD_WIDTH | 98 | #define SCREEN_WIDTH LCD_WIDTH |
56 | #define SCREEN_HEIGHT LCD_HEIGHT | 99 | #define SCREEN_HEIGHT LCD_HEIGHT |
57 | #else /* Assume the screen is rotates on portraid LCDs */ | 100 | #else /* Assume the screen is rotated on portrait LCDs */ |
58 | #define SCREEN_WIDTH LCD_HEIGHT | 101 | #define SCREEN_WIDTH LCD_HEIGHT |
59 | #define SCREEN_HEIGHT LCD_WIDTH | 102 | #define SCREEN_HEIGHT LCD_WIDTH |
60 | #endif | 103 | #endif |
61 | 104 | ||
62 | uint8_t* tmpbufa = 0; | 105 | static inline void vo_rect_clear_inl(struct vo_rect *rc) |
63 | uint8_t* tmpbufb = 0; | 106 | { |
64 | uint8_t* tmpbufc = 0; | 107 | rc->l = rc->t = rc->r = rc->b = 0; |
65 | uint8_t* tmpbuf[3]; | 108 | } |
66 | 109 | ||
67 | void vo_draw_frame_thumb (uint8_t * const * buf) | 110 | static inline bool vo_rect_empty_inl(const struct vo_rect *rc) |
68 | { | 111 | { |
69 | int r,c; | 112 | return rc == NULL || rc->l >= rc->r || rc->t >= rc->b; |
113 | } | ||
70 | 114 | ||
71 | #if LCD_WIDTH >= LCD_HEIGHT | 115 | static inline bool vo_rects_intersect_inl(const struct vo_rect *rc1, |
72 | for (r=0;r<image_width/2;r++) | 116 | const struct vo_rect *rc2) |
73 | for (c=0;c<image_height/2;c++) | 117 | { |
74 | *(tmpbuf[0]+c*image_width/2+r) = | 118 | return !vo_rect_empty_inl(rc1) && |
75 | *(buf[0]+2*c*image_width+2*r); | 119 | !vo_rect_empty_inl(rc2) && |
76 | 120 | rc1->l < rc2->r && rc1->r > rc2->l && | |
77 | for (r=0;r<image_width/4;r++) | 121 | rc1->t < rc2->b && rc1->b > rc2->t; |
78 | for (c=0;c<image_height/4;c++) | 122 | } |
123 | |||
124 | /* Sets all coordinates of a vo_rect to 0 */ | ||
125 | void vo_rect_clear(struct vo_rect *rc) | ||
126 | { | ||
127 | vo_rect_clear_inl(rc); | ||
128 | } | ||
129 | |||
130 | /* Returns true if left >= right or top >= bottom */ | ||
131 | bool vo_rect_empty(const struct vo_rect *rc) | ||
132 | { | ||
133 | return vo_rect_empty_inl(rc); | ||
134 | } | ||
135 | |||
136 | /* Initializes a vo_rect using upper-left corner and extents */ | ||
137 | void vo_rect_set_ext(struct vo_rect *rc, int x, int y, | ||
138 | int width, int height) | ||
139 | { | ||
140 | rc->l = x; | ||
141 | rc->t = y; | ||
142 | rc->r = x + width; | ||
143 | rc->b = y + height; | ||
144 | } | ||
145 | |||
146 | /* Query if two rectangles intersect */ | ||
147 | bool vo_rects_intersect(const struct vo_rect *rc1, | ||
148 | const struct vo_rect *rc2) | ||
149 | { | ||
150 | return vo_rects_intersect_inl(rc1, rc2); | ||
151 | } | ||
152 | |||
153 | /* Intersect two rectangles, placing the result in rc_dst */ | ||
154 | bool vo_rect_intersect(struct vo_rect *rc_dst, | ||
155 | const struct vo_rect *rc1, | ||
156 | const struct vo_rect *rc2) | ||
157 | { | ||
158 | if (rc_dst != NULL) | ||
79 | { | 159 | { |
80 | *(tmpbuf[1]+c*image_width/4+r) = | 160 | if (vo_rects_intersect_inl(rc1, rc2)) |
81 | *(buf[1]+c*image_width+2*r); | 161 | { |
82 | *(tmpbuf[2]+c*image_width/4+r) = | 162 | rc_dst->l = MAX(rc1->l, rc2->l); |
83 | *(buf[2]+c*image_width+2*r); | 163 | rc_dst->r = MIN(rc1->r, rc2->r); |
164 | rc_dst->t = MAX(rc1->t, rc2->t); | ||
165 | rc_dst->b = MIN(rc1->b, rc2->b); | ||
166 | return true; | ||
167 | } | ||
168 | |||
169 | vo_rect_clear_inl(rc_dst); | ||
84 | } | 170 | } |
171 | |||
172 | return false; | ||
173 | } | ||
174 | |||
175 | /* Shink or stretch each axis - rotate counter-clockwise to retain upright | ||
176 | * orientation on rotated displays (they rotate clockwise) */ | ||
177 | void stretch_image_plane(const uint8_t * src, uint8_t *dst, int stride, | ||
178 | int src_w, int src_h, int dst_w, int dst_h) | ||
179 | { | ||
180 | uint8_t *dst_end = dst + dst_w*dst_h; | ||
181 | |||
182 | #if LCD_WIDTH >= LCD_HEIGHT | ||
183 | int src_w2 = src_w*2; /* 2x dimensions (for rounding before division) */ | ||
184 | int dst_w2 = dst_w*2; | ||
185 | int src_h2 = src_h*2; | ||
186 | int dst_h2 = dst_h*2; | ||
187 | int qw = src_w2 / dst_w2; /* src-dst width ratio quotient */ | ||
188 | int rw = src_w2 - qw*dst_w2; /* src-dst width ratio remainder */ | ||
189 | int qh = src_h2 / dst_h2; /* src-dst height ratio quotient */ | ||
190 | int rh = src_h2 - qh*dst_h2; /* src-dst height ratio remainder */ | ||
191 | int dw = dst_w; /* Width error accumulator */ | ||
192 | int dh = dst_h; /* Height error accumulator */ | ||
85 | #else | 193 | #else |
86 | for (r=0;r<image_width/2;r++) | 194 | int src_w2 = src_w*2; |
87 | for (c=0;c<image_height/2;c++) | 195 | int dst_w2 = dst_h*2; |
88 | *(tmpbuf[0]+(image_width/2-1-r)*image_height/2+c) = | 196 | int src_h2 = src_h*2; |
89 | *(buf[0]+2*c*image_width+2*r); | 197 | int dst_h2 = dst_w*2; |
90 | 198 | int qw = src_h2 / dst_w2; | |
91 | for (r=0;r<image_width/4;r++) | 199 | int rw = src_h2 - qw*dst_w2; |
92 | for (c=0;c<image_height/4;c++) | 200 | int qh = src_w2 / dst_h2; |
201 | int rh = src_w2 - qh*dst_h2; | ||
202 | int dw = dst_h; | ||
203 | int dh = dst_w; | ||
204 | |||
205 | src += src_w - 1; | ||
206 | #endif | ||
207 | |||
208 | while (1) | ||
93 | { | 209 | { |
94 | *(tmpbuf[1]+(image_width/4-1-r)*image_height/4+c) = | 210 | const uint8_t *s = src; |
95 | *(buf[1]+c*image_width+2*r); | 211 | #if LCD_WIDTH >= LCD_HEIGHT |
96 | *(tmpbuf[2]+(image_width/4-1-r)*image_height/4+c) = | 212 | uint8_t * const dst_line_end = dst + dst_w; |
97 | *(buf[2]+c*image_width+2*r); | 213 | #else |
98 | } | 214 | uint8_t * const dst_line_end = dst + dst_h; |
99 | #endif | 215 | #endif |
216 | while (1) | ||
217 | { | ||
218 | *dst++ = *s; | ||
100 | 219 | ||
101 | rb->lcd_clear_display(); | 220 | if (dst >= dst_line_end) |
102 | rb->lcd_update(); | 221 | { |
222 | dw = dst_w; | ||
223 | break; | ||
224 | } | ||
103 | 225 | ||
104 | #ifdef HAVE_LCD_COLOR | ||
105 | #ifdef SIMULATOR | ||
106 | #if LCD_WIDTH >= LCD_HEIGHT | 226 | #if LCD_WIDTH >= LCD_HEIGHT |
107 | rb->lcd_yuv_blit(tmpbuf,0,0,image_width/2, | 227 | s += qw; |
108 | (LCD_WIDTH-1-image_width/2)/2, | ||
109 | LCD_HEIGHT-50-(image_height/2), | ||
110 | output_width/2,output_height/2); | ||
111 | |||
112 | #else | 228 | #else |
113 | rb->lcd_yuv_blit(tmpbuf,0,0,image_height/2, | 229 | s += qw*stride; |
114 | LCD_HEIGHT-50-(image_height/2), | ||
115 | (LCD_WIDTH-1-image_width/2)/2, | ||
116 | output_height/2,output_width/2); | ||
117 | #endif | 230 | #endif |
118 | #else | 231 | dw += rw; |
232 | |||
233 | if (dw >= dst_w2) | ||
234 | { | ||
235 | dw -= dst_w2; | ||
119 | #if LCD_WIDTH >= LCD_HEIGHT | 236 | #if LCD_WIDTH >= LCD_HEIGHT |
120 | rb->lcd_yuv_blit(tmpbuf,0,0,image_width/2, | 237 | s++; |
121 | (LCD_WIDTH-1-image_width/2)/2, | ||
122 | LCD_HEIGHT-50-(image_height/2), | ||
123 | output_width/2,output_height/2); | ||
124 | #else | 238 | #else |
125 | rb->lcd_yuv_blit(tmpbuf,0,0,image_height/2, | 239 | s += stride; |
126 | LCD_HEIGHT-50-(image_height/2), | ||
127 | (LCD_WIDTH-1-image_width/2)/2, | ||
128 | output_height/2,output_width/2); | ||
129 | #endif | ||
130 | #endif | 240 | #endif |
241 | } | ||
242 | } | ||
243 | |||
244 | if (dst >= dst_end) | ||
245 | break; | ||
246 | #if LCD_WIDTH >= LCD_HEIGHT | ||
247 | src += qh*stride; | ||
131 | #else | 248 | #else |
249 | src -= qh; | ||
250 | #endif | ||
251 | dh += rh; | ||
252 | |||
253 | if (dh >= dst_h2) | ||
254 | { | ||
255 | dh -= dst_h2; | ||
132 | #if LCD_WIDTH >= LCD_HEIGHT | 256 | #if LCD_WIDTH >= LCD_HEIGHT |
133 | gray_ub_gray_bitmap_part(tmpbuf[0],0,0,image_width/2, | 257 | src += stride; |
134 | (LCD_WIDTH-1-image_width/2)/2, | ||
135 | LCD_HEIGHT-50-(image_height/2), | ||
136 | output_width/2,output_height/2); | ||
137 | #else | 258 | #else |
138 | gray_ub_gray_bitmap_part(tmpbuf[0],0,0,image_height/2, | 259 | src--; |
139 | LCD_HEIGHT-50-(image_height/2), | 260 | #endif |
140 | (LCD_WIDTH-1-image_width/2)/2, | 261 | } |
141 | output_height/2,output_width/2); | 262 | } |
263 | } | ||
264 | |||
265 | bool vo_draw_frame_thumb(uint8_t * const * buf, const struct vo_rect *rc) | ||
266 | { | ||
267 | void *mem; | ||
268 | size_t bufsize; | ||
269 | uint8_t *yuv[3]; | ||
270 | struct vo_rect thumb_rc; | ||
271 | int thumb_width, thumb_height; | ||
272 | int thumb_uv_width, thumb_uv_height; | ||
273 | |||
274 | if (buf == NULL) | ||
275 | return false; | ||
276 | |||
277 | /* Obtain rectangle as clipped to the screen */ | ||
278 | vo_rect_set_ext(&thumb_rc, 0, 0, LCD_WIDTH, LCD_HEIGHT); | ||
279 | if (!vo_rect_intersect(&thumb_rc, rc, &thumb_rc)) | ||
280 | return true; | ||
281 | |||
282 | DEBUGF("thumb_rc: %d, %d, %d, %d\n", thumb_rc.l, thumb_rc.t, | ||
283 | thumb_rc.r, thumb_rc.b); | ||
284 | |||
285 | thumb_width = rc->r - rc->l; | ||
286 | thumb_height = rc->b - rc->t; | ||
287 | thumb_uv_width = thumb_width / 2; | ||
288 | thumb_uv_height = thumb_height / 2; | ||
289 | |||
290 | DEBUGF("thumb: w: %d h: %d uvw: %d uvh: %d\n", thumb_width, | ||
291 | thumb_height, thumb_uv_width, thumb_uv_height); | ||
292 | |||
293 | /* Use remaining mpeg2 buffer as temp space */ | ||
294 | mem = mpeg2_get_buf(&bufsize); | ||
295 | |||
296 | if (bufsize < (size_t)(thumb_width*thumb_height) | ||
297 | #ifdef HAVE_LCD_COLOR | ||
298 | + 2u*(thumb_uv_width * thumb_uv_height) | ||
142 | #endif | 299 | #endif |
300 | ) | ||
301 | { | ||
302 | DEBUGF("thumb: insufficient buffer\n"); | ||
303 | return false; | ||
304 | } | ||
305 | |||
306 | yuv[0] = mem; | ||
307 | stretch_image_plane(buf[0], yuv[0], vo.image_width, | ||
308 | vo.display_width, vo.display_height, | ||
309 | thumb_width, thumb_height); | ||
310 | |||
311 | #ifdef HAVE_LCD_COLOR | ||
312 | yuv[1] = yuv[0] + thumb_width*thumb_height; | ||
313 | yuv[2] = yuv[1] + thumb_uv_width*thumb_uv_height; | ||
314 | |||
315 | stretch_image_plane(buf[1], yuv[1], vo.image_width / 2, | ||
316 | vo.display_width / 2, vo.display_height / 2, | ||
317 | thumb_uv_width, thumb_uv_height); | ||
318 | |||
319 | stretch_image_plane(buf[2], yuv[2], vo.image_width / 2, | ||
320 | vo.display_width / 2, vo.display_height / 2, | ||
321 | thumb_uv_width, thumb_uv_height); | ||
143 | #endif | 322 | #endif |
323 | |||
324 | #if LCD_WIDTH >= LCD_HEIGHT | ||
325 | yuv_blit(yuv, 0, 0, thumb_width, | ||
326 | thumb_rc.l, thumb_rc.t, | ||
327 | thumb_rc.r - thumb_rc.l, | ||
328 | thumb_rc.b - thumb_rc.t); | ||
329 | #else | ||
330 | yuv_blit(yuv, 0, 0, thumb_height, | ||
331 | thumb_rc.t, thumb_rc.l, | ||
332 | thumb_rc.b - thumb_rc.t, | ||
333 | thumb_rc.r - thumb_rc.l); | ||
334 | #endif /* LCD_WIDTH >= LCD_HEIGHT */ | ||
335 | |||
336 | return true; | ||
144 | } | 337 | } |
145 | 338 | ||
146 | void vo_setup(const mpeg2_sequence_t * sequence) | 339 | void vo_setup(const mpeg2_sequence_t * sequence) |
147 | { | 340 | { |
148 | image_width=sequence->width; | 341 | vo.image_width = sequence->width; |
149 | image_height=sequence->height; | 342 | vo.image_height = sequence->height; |
150 | 343 | vo.display_width = sequence->display_width; | |
151 | tmpbufa = (uint8_t*)mpeg2_malloc(sizeof(uint8_t)*image_width* | 344 | vo.display_height = sequence->display_height; |
152 | image_height/4, -2); | 345 | |
153 | tmpbufb = (uint8_t*)mpeg2_malloc(sizeof(uint8_t)*image_width* | 346 | DEBUGF("vo_setup - w:%d h:%d\n", vo.display_width, vo.display_height); |
154 | image_height/16, -2); | 347 | |
155 | tmpbufc = (uint8_t*)mpeg2_malloc(sizeof(uint8_t)*image_width* | 348 | vo.image_chroma_x = vo.image_width / sequence->chroma_width; |
156 | image_height/16, -2); | 349 | vo.image_chroma_y = vo.image_height / sequence->chroma_height; |
157 | tmpbuf[0] = tmpbufa; | 350 | |
158 | tmpbuf[1] = tmpbufb; | 351 | if (sequence->display_width >= SCREEN_WIDTH) |
159 | tmpbuf[2] = tmpbufc; | 352 | { |
160 | 353 | vo.output_width = SCREEN_WIDTH; | |
161 | image_chroma_x=image_width/sequence->chroma_width; | 354 | vo.output_x = 0; |
162 | image_chroma_y=image_height/sequence->chroma_height; | 355 | } |
163 | 356 | else | |
164 | if (sequence->display_width >= SCREEN_WIDTH) { | 357 | { |
165 | output_width = SCREEN_WIDTH; | 358 | vo.output_width = sequence->display_width; |
166 | output_x = 0; | 359 | vo.output_x = (SCREEN_WIDTH - sequence->display_width) / 2; |
167 | } else { | ||
168 | output_width = sequence->display_width; | ||
169 | output_x = (SCREEN_WIDTH-sequence->display_width)/2; | ||
170 | } | 360 | } |
171 | 361 | ||
172 | if (sequence->display_height >= SCREEN_HEIGHT) { | 362 | if (sequence->display_height >= SCREEN_HEIGHT) |
173 | output_height = SCREEN_HEIGHT; | 363 | { |
174 | output_y = 0; | 364 | vo.output_height = SCREEN_HEIGHT; |
175 | } else { | 365 | vo.output_y = 0; |
176 | output_height = sequence->display_height; | 366 | } |
177 | output_y = (SCREEN_HEIGHT-sequence->display_height)/2; | 367 | else |
368 | { | ||
369 | vo.output_height = sequence->display_height; | ||
370 | vo.output_y = (SCREEN_HEIGHT - sequence->display_height) / 2; | ||
178 | } | 371 | } |
179 | } | 372 | } |
180 | 373 | ||
374 | void vo_dimensions(struct vo_ext *sz) | ||
375 | { | ||
376 | sz->w = vo.display_width; | ||
377 | sz->h = vo.display_height; | ||
378 | } | ||
379 | |||
380 | bool vo_init(void) | ||
381 | { | ||
382 | vo.visible = false; | ||
383 | return true; | ||
384 | } | ||
385 | |||
386 | bool vo_show(bool show) | ||
387 | { | ||
388 | bool vis = vo.visible; | ||
389 | vo.visible = show; | ||
390 | return vis; | ||
391 | } | ||
392 | |||
393 | bool vo_is_visible(void) | ||
394 | { | ||
395 | return vo.visible; | ||
396 | } | ||
397 | |||
181 | void vo_cleanup(void) | 398 | void vo_cleanup(void) |
182 | { | 399 | { |
183 | if (tmpbufc) | 400 | vo.visible = false; |
184 | mpeg2_free(tmpbufc); | 401 | #ifndef HAVE_LCD_COLOR |
185 | if (tmpbufb) | 402 | gray_release(); |
186 | mpeg2_free(tmpbufb); | 403 | #endif |
187 | if (tmpbufa) | ||
188 | mpeg2_free(tmpbufa); | ||
189 | } | 404 | } |