diff options
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/mpegplayer/video_out_rockbox.c | 284 |
1 files changed, 169 insertions, 115 deletions
diff --git a/apps/plugins/mpegplayer/video_out_rockbox.c b/apps/plugins/mpegplayer/video_out_rockbox.c index e3f8ba0264..b55ca8c079 100644 --- a/apps/plugins/mpegplayer/video_out_rockbox.c +++ b/apps/plugins/mpegplayer/video_out_rockbox.c | |||
@@ -45,147 +45,197 @@ static int output_height; | |||
45 | 45 | ||
46 | #if defined(SIMULATOR) && defined(HAVE_LCD_COLOR) | 46 | #if defined(SIMULATOR) && defined(HAVE_LCD_COLOR) |
47 | 47 | ||
48 | #define RYFAC (31*257) | 48 | /** |
49 | #define GYFAC (63*257) | 49 | * |R| |1.000000 -0.000001 1.402000| |Y'| |
50 | #define BYFAC (31*257) | 50 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| |
51 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | 51 | * |B| |1.000000 1.772000 0.000000| |Pr| |
52 | #define GVFAC (-11563) /* 63 * 257 * -0.714136 */ | 52 | * Scaled, normalized, rounded and tweaked to yield RGB 565: |
53 | #define GUFAC (-5572) /* 63 * 257 * -0.344136 */ | 53 | * |R| |74 0 101| |Y' - 16| >> 9 |
54 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | 54 | * |G| = |74 -24 -51| |Cb - 128| >> 8 |
55 | * |B| |74 128 0| |Cr - 128| >> 9 | ||
56 | */ | ||
57 | #define YFAC (74) | ||
58 | #define RVFAC (101) | ||
59 | #define GUFAC (-24) | ||
60 | #define GVFAC (-51) | ||
61 | #define BUFAC (128) | ||
55 | 62 | ||
56 | #define ROUNDOFFS (127*257) | 63 | static inline int clamp(int val, int min, int max) |
64 | { | ||
65 | if (val < min) | ||
66 | val = min; | ||
67 | else if (val > max) | ||
68 | val = max; | ||
69 | return val; | ||
70 | } | ||
57 | 71 | ||
58 | /* Draw a partial YUV colour bitmap - taken from the Rockbox JPEG viewer */ | 72 | /* Draw a partial YUV colour bitmap - similiar behavior to lcd_yuv_blit |
73 | in the core */ | ||
59 | static void yuv_bitmap_part(unsigned char * const src[3], | 74 | static void yuv_bitmap_part(unsigned char * const src[3], |
60 | int src_x, int src_y, int stride, | 75 | int src_x, int src_y, int stride, |
61 | int x, int y, int width, int height) | 76 | int x, int y, int width, int height) |
62 | { | 77 | { |
63 | fb_data *dst, *dst_end; | 78 | const unsigned char *ysrc, *usrc, *vsrc; |
79 | fb_data *dst, *row_end; | ||
80 | off_t z; | ||
64 | 81 | ||
65 | /* nothing to draw? */ | 82 | /* width and height must be >= 2 and an even number */ |
66 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 83 | width &= ~1; |
67 | || (x + width <= 0) || (y + height <= 0)) | 84 | height >>= 1; |
68 | return; | ||
69 | 85 | ||
70 | /* clipping */ | 86 | #if LCD_WIDTH >= LCD_HEIGHT |
71 | if (x < 0) | 87 | dst = rb->lcd_framebuffer + LCD_WIDTH * y + x; |
72 | { | 88 | row_end = dst + width; |
73 | width += x; | 89 | #else |
74 | src_x -= x; | 90 | dst = rb->lcd_framebuffer + x * LCD_WIDTH + (LCD_WIDTH - y) - 1; |
75 | x = 0; | 91 | row_end = dst + LCD_WIDTH * width; |
76 | } | 92 | #endif |
77 | if (y < 0) | 93 | |
78 | { | 94 | z = stride * src_y; |
79 | height += y; | 95 | ysrc = src[0] + z + src_x; |
80 | src_y -= y; | 96 | usrc = src[1] + (z >> 2) + (src_x >> 1); |
81 | y = 0; | 97 | vsrc = src[2] + (usrc - src[1]); |
82 | } | 98 | |
83 | if (x + width > LCD_WIDTH) | 99 | /* stride => amount to jump from end of last row to start of next */ |
84 | width = LCD_WIDTH - x; | 100 | stride -= width; |
85 | if (y + height > LCD_HEIGHT) | ||
86 | height = LCD_HEIGHT - y; | ||
87 | 101 | ||
88 | dst = rb->lcd_framebuffer + LCD_WIDTH * y + x; | 102 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ |
89 | dst_end = dst + LCD_WIDTH * height; | ||
90 | 103 | ||
91 | do | 104 | do |
92 | { | 105 | { |
93 | fb_data *dst_row = dst; | 106 | do |
94 | fb_data *row_end = dst_row + width; | ||
95 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | ||
96 | int y, u, v; | ||
97 | int red, green, blue; | ||
98 | unsigned rbits, gbits, bbits; | ||
99 | |||
100 | if (CSUB_Y) /* colour */ | ||
101 | { | 107 | { |
102 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | 108 | int y, cb, cr, rv, guv, bu, r, g, b; |
103 | const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y) | 109 | |
104 | + (src_x/CSUB_X); | 110 | y = YFAC*(*ysrc++ - 16); |
105 | const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y) | 111 | cb = *usrc++ - 128; |
106 | + (src_x/CSUB_X); | 112 | cr = *vsrc++ - 128; |
107 | int xphase = src_x % CSUB_X; | 113 | |
108 | int rc, gc, bc; | 114 | rv = RVFAC*cr; |
109 | 115 | guv = GUFAC*cb + GVFAC*cr; | |
110 | u = *usrc++ - 128; | 116 | bu = BUFAC*cb; |
111 | v = *vsrc++ - 128; | 117 | |
112 | rc = RVFAC * v + ROUNDOFFS; | 118 | r = y + rv; |
113 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | 119 | g = y + guv; |
114 | bc = BUFAC * u + ROUNDOFFS; | 120 | b = y + bu; |
115 | 121 | ||
116 | do | 122 | if ((unsigned)(r | g | b) > 63*256) |
117 | { | 123 | { |
118 | y = *ysrc++; | 124 | r = clamp(r, 0, 63*256); |
119 | red = RYFAC * y + rc; | 125 | g = clamp(g, 0, 63*256); |
120 | green = GYFAC * y + gc; | 126 | b = clamp(b, 0, 63*256); |
121 | blue = BYFAC * y + bc; | 127 | } |
122 | 128 | ||
123 | if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) | 129 | *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); |
124 | { | 130 | |
125 | if (red < 0) | 131 | #if LCD_WIDTH >= LCD_HEIGHT |
126 | red = 0; | 132 | dst++; |
127 | else | 133 | #else |
128 | red = (RYFAC*255+ROUNDOFFS); | 134 | dst += LCD_WIDTH; |
129 | } | ||
130 | if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) | ||
131 | { | ||
132 | if (green < 0) | ||
133 | green = 0; | ||
134 | else | ||
135 | green = (GYFAC*255+ROUNDOFFS); | ||
136 | } | ||
137 | if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) | ||
138 | { | ||
139 | if (blue < 0) | ||
140 | blue = 0; | ||
141 | else | ||
142 | blue = (BYFAC*255+ROUNDOFFS); | ||
143 | } | ||
144 | rbits = ((unsigned)red) >> 16 ; | ||
145 | gbits = ((unsigned)green) >> 16 ; | ||
146 | bbits = ((unsigned)blue) >> 16 ; | ||
147 | #if LCD_PIXELFORMAT == RGB565 | ||
148 | *dst_row++ = (rbits << 11) | (gbits << 5) | bbits; | ||
149 | #elif LCD_PIXELFORMAT == RGB565SWAPPED | ||
150 | *dst_row++ = swap16((rbits << 11) | (gbits << 5) | bbits); | ||
151 | #endif | 135 | #endif |
152 | 136 | ||
153 | if (++xphase >= CSUB_X) | 137 | y = YFAC*(*ysrc++ - 16); |
154 | { | 138 | r = y + rv; |
155 | u = *usrc++ - 128; | 139 | g = y + guv; |
156 | v = *vsrc++ - 128; | 140 | b = y + bu; |
157 | rc = RVFAC * v + ROUNDOFFS; | 141 | |
158 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | 142 | if ((unsigned)(r | g | b) > 63*256) |
159 | bc = BUFAC * u + ROUNDOFFS; | 143 | { |
160 | xphase = 0; | 144 | r = clamp(r, 0, 63*256); |
161 | } | 145 | g = clamp(g, 0, 63*256); |
146 | b = clamp(b, 0, 63*256); | ||
162 | } | 147 | } |
163 | while (dst_row < row_end); | 148 | |
149 | *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); | ||
150 | |||
151 | #if LCD_WIDTH >= LCD_HEIGHT | ||
152 | dst++; | ||
153 | #else | ||
154 | dst += LCD_WIDTH; | ||
155 | #endif | ||
164 | } | 156 | } |
165 | else /* monochrome */ | 157 | while (dst < row_end); |
158 | |||
159 | ysrc += stride; | ||
160 | usrc -= width >> 1; | ||
161 | vsrc -= width >> 1; | ||
162 | |||
163 | #if LCD_WIDTH >= LCD_HEIGHT | ||
164 | row_end += LCD_WIDTH; | ||
165 | dst += LCD_WIDTH - width; | ||
166 | #else | ||
167 | row_end -= 1; | ||
168 | dst -= LCD_WIDTH*width + 1; | ||
169 | #endif | ||
170 | |||
171 | do | ||
166 | { | 172 | { |
167 | do | 173 | int y, cb, cr, rv, guv, bu, r, g, b; |
174 | |||
175 | y = YFAC*(*ysrc++ - 16); | ||
176 | cb = *usrc++ - 128; | ||
177 | cr = *vsrc++ - 128; | ||
178 | |||
179 | rv = RVFAC*cr; | ||
180 | guv = GUFAC*cb + GVFAC*cr; | ||
181 | bu = BUFAC*cb; | ||
182 | |||
183 | r = y + rv; | ||
184 | g = y + guv; | ||
185 | b = y + bu; | ||
186 | |||
187 | if ((unsigned)(r | g | b) > 63*256) | ||
168 | { | 188 | { |
169 | y = *ysrc++; | 189 | r = clamp(r, 0, 63*256); |
170 | red = RYFAC * y + ROUNDOFFS; /* blue == red */ | 190 | g = clamp(g, 0, 63*256); |
171 | green = GYFAC * y + ROUNDOFFS; | 191 | b = clamp(b, 0, 63*256); |
172 | rbits = ((unsigned)red) >> 16; | 192 | } |
173 | gbits = ((unsigned)green) >> 16; | 193 | |
174 | #if LCD_PIXELFORMAT == RGB565 | 194 | *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); |
175 | *dst_row++ = (rbits << 11) | (gbits << 5) | rbits; | 195 | |
176 | #elif LCD_PIXELFORMAT == RGB565SWAPPED | 196 | #if LCD_WIDTH >= LCD_HEIGHT |
177 | *dst_row++ = swap16((rbits << 11) | (gbits << 5) | rbits); | 197 | dst++; |
198 | #else | ||
199 | dst += LCD_WIDTH; | ||
178 | #endif | 200 | #endif |
201 | |||
202 | y = YFAC*(*ysrc++ - 16); | ||
203 | r = y + rv; | ||
204 | g = y + guv; | ||
205 | b = y + bu; | ||
206 | |||
207 | if ((unsigned)(r | g | b) > 63*256) | ||
208 | { | ||
209 | r = clamp(r, 0, 63*256); | ||
210 | g = clamp(g, 0, 63*256); | ||
211 | b = clamp(b, 0, 63*256); | ||
179 | } | 212 | } |
180 | while (dst_row < row_end); | 213 | |
214 | *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); | ||
215 | |||
216 | #if LCD_WIDTH >= LCD_HEIGHT | ||
217 | dst++; | ||
218 | #else | ||
219 | dst += LCD_WIDTH; | ||
220 | #endif | ||
181 | } | 221 | } |
222 | while (dst < row_end); | ||
223 | |||
224 | ysrc += stride; | ||
225 | usrc += stride >> 1; | ||
226 | vsrc += stride >> 1; | ||
182 | 227 | ||
183 | src_y++; | 228 | #if LCD_WIDTH >= LCD_HEIGHT |
184 | dst += LCD_WIDTH; | 229 | row_end += LCD_WIDTH; |
230 | dst += LCD_WIDTH - width; | ||
231 | #else | ||
232 | row_end -= 1; | ||
233 | dst -= LCD_WIDTH*width + 1; | ||
234 | #endif | ||
185 | } | 235 | } |
186 | while (dst < dst_end); | 236 | while (--height > 0); |
187 | } | 237 | } |
188 | #endif | 238 | #endif /* defined(SIMULATOR) && defined(HAVE_LCD_COLOR) */ |
189 | 239 | ||
190 | void vo_draw_frame (uint8_t * const * buf) | 240 | void vo_draw_frame (uint8_t * const * buf) |
191 | { | 241 | { |
@@ -193,8 +243,12 @@ void vo_draw_frame (uint8_t * const * buf) | |||
193 | #ifdef SIMULATOR | 243 | #ifdef SIMULATOR |
194 | yuv_bitmap_part(buf,0,0,image_width, | 244 | yuv_bitmap_part(buf,0,0,image_width, |
195 | output_x,output_y,output_width,output_height); | 245 | output_x,output_y,output_width,output_height); |
246 | #if LCD_WIDTH >= LCD_HEIGHT | ||
196 | rb->lcd_update_rect(output_x,output_y,output_width,output_height); | 247 | rb->lcd_update_rect(output_x,output_y,output_width,output_height); |
197 | #else | 248 | #else |
249 | rb->lcd_update_rect(output_y,output_x,output_height,output_width); | ||
250 | #endif | ||
251 | #else | ||
198 | rb->lcd_yuv_blit(buf, | 252 | rb->lcd_yuv_blit(buf, |
199 | 0,0,image_width, | 253 | 0,0,image_width, |
200 | output_x,output_y,output_width,output_height); | 254 | output_x,output_y,output_width,output_height); |