comparison libvo/vo_yuv4mpeg.c @ 31254:e888e262e3f0

Remove colorspace conversion code from -vo yuv4mpeg, -vf scale should be able to handle this just as well (or better) including interlaced. If not, this needs to be fixed there instead of duplicating code.
author reimar
date Sat, 05 Jun 2010 06:45:01 +0000
parents 05f2b2395578
children fbe5c829c69b
comparison
equal deleted inserted replaced
31253:b470391059f3 31254:e888e262e3f0
53 #include "help_mp.h" 53 #include "help_mp.h"
54 54
55 #include "sub.h" 55 #include "sub.h"
56 56
57 #include "fastmemcpy.h" 57 #include "fastmemcpy.h"
58 #include "libswscale/swscale.h"
59 #ifdef CONFIG_LIBSWSCALE_A
60 #include "libswscale/rgb2rgb.h"
61 #endif
62 #include "libmpcodecs/vf_scale.h"
63 #include "libavutil/rational.h" 58 #include "libavutil/rational.h"
64 59
65 static const vo_info_t info = 60 static const vo_info_t info =
66 { 61 {
67 "yuv4mpeg output for mjpegtools", 62 "yuv4mpeg output for mjpegtools",
78 73
79 static uint8_t *image = NULL; 74 static uint8_t *image = NULL;
80 static uint8_t *image_y = NULL; 75 static uint8_t *image_y = NULL;
81 static uint8_t *image_u = NULL; 76 static uint8_t *image_u = NULL;
82 static uint8_t *image_v = NULL; 77 static uint8_t *image_v = NULL;
83
84 static uint8_t *rgb_buffer = NULL;
85 static uint8_t *rgb_line_buffer = NULL;
86 78
87 static char *yuv_filename = NULL; 79 static char *yuv_filename = NULL;
88 80
89 static int using_format = 0; 81 static int using_format = 0;
90 static FILE *yuv_out; 82 static FILE *yuv_out;
126 { 118 {
127 mp_msg(MSGT_VO,MSGL_FATAL, 119 mp_msg(MSGT_VO,MSGL_FATAL,
128 MSGTR_VO_YUV4MPEG_InterlacedHeightDivisibleBy4); 120 MSGTR_VO_YUV4MPEG_InterlacedHeightDivisibleBy4);
129 return -1; 121 return -1;
130 } 122 }
131
132 rgb_line_buffer = malloc(image_width * 3);
133 if (!rgb_line_buffer)
134 {
135 mp_msg(MSGT_VO,MSGL_FATAL,
136 MSGTR_VO_YUV4MPEG_InterlacedLineBufAllocFail);
137 return -1;
138 }
139
140 if (using_format == IMGFMT_YV12)
141 mp_msg(MSGT_VO,MSGL_WARN,
142 MSGTR_VO_YUV4MPEG_InterlacedInputNotRGB);
143 } 123 }
144 124
145 if (width % 2) 125 if (width % 2)
146 { 126 {
147 mp_msg(MSGT_VO,MSGL_FATAL, 127 mp_msg(MSGT_VO,MSGL_FATAL,
148 MSGTR_VO_YUV4MPEG_WidthDivisibleBy2); 128 MSGTR_VO_YUV4MPEG_WidthDivisibleBy2);
149 return -1; 129 return -1;
150 } 130 }
151
152 #ifdef CONFIG_LIBSWSCALE_A
153 if(using_format != IMGFMT_YV12)
154 {
155 sws_rgb2rgb_init(get_sws_cpuflags());
156 rgb_buffer = malloc(image_width * image_height * 3);
157 if (!rgb_buffer)
158 {
159 mp_msg(MSGT_VO,MSGL_FATAL,
160 MSGTR_VO_YUV4MPEG_NoMemRGBFrameBuf);
161 return -1;
162 }
163 }
164 #endif
165 131
166 write_bytes = image_width * image_height * 3 / 2; 132 write_bytes = image_width * image_height * 3 / 2;
167 image = malloc(write_bytes); 133 image = malloc(write_bytes);
168 134
169 yuv_out = fopen(yuv_filename, "wb"); 135 yuv_out = fopen(yuv_filename, "wb");
185 151
186 fflush(yuv_out); 152 fflush(yuv_out);
187 return 0; 153 return 0;
188 } 154 }
189 155
190 /* Only use when h divisable by 2! */
191 static void swap_fields(uint8_t *ptr, const int h, const int stride)
192 {
193 int i;
194
195 for (i=0; i<h; i +=2)
196 {
197 fast_memcpy(rgb_line_buffer , ptr + stride * i , stride);
198 fast_memcpy(ptr + stride * i , ptr + stride * (i+1), stride);
199 fast_memcpy(ptr + stride * (i+1), rgb_line_buffer , stride);
200 }
201 }
202
203 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, 156 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
204 unsigned char *srca, int stride) { 157 unsigned char *srca, int stride) {
205 switch (using_format)
206 {
207 case IMGFMT_YV12:
208 vo_draw_alpha_yv12(w, h, src, srca, stride, 158 vo_draw_alpha_yv12(w, h, src, srca, stride,
209 image + y0 * image_width + x0, image_width); 159 image + y0 * image_width + x0, image_width);
210 break;
211
212 case IMGFMT_BGR|24:
213 case IMGFMT_RGB|24:
214 if (config_interlace != Y4M_ILACE_BOTTOM_FIRST)
215 vo_draw_alpha_rgb24(w, h, src, srca, stride,
216 rgb_buffer + (y0 * image_width + x0) * 3, image_width * 3);
217 else
218 {
219 swap_fields (rgb_buffer, image_height, image_width * 3);
220
221 vo_draw_alpha_rgb24(w, h, src, srca, stride,
222 rgb_buffer + (y0 * image_width + x0) * 3, image_width * 3);
223
224 swap_fields (rgb_buffer, image_height, image_width * 3);
225 }
226 break;
227 }
228 } 160 }
229 161
230 static void draw_osd(void) 162 static void draw_osd(void)
231 { 163 {
232 vo_draw_text(image_width, image_height, draw_alpha); 164 vo_draw_text(image_width, image_height, draw_alpha);
233 } 165 }
234
235 #ifdef CONFIG_LIBSWSCALE_A
236 static void deinterleave_fields(uint8_t *ptr, const int stride,
237 const int img_height)
238 {
239 unsigned int i, j, k_start = 1, modv = img_height - 1;
240 unsigned char *line_state = malloc(modv);
241
242 for (i=0; i<modv; i++)
243 line_state[i] = 0;
244
245 line_state[0] = 1;
246
247 while(k_start < modv)
248 {
249 i = j = k_start;
250 fast_memcpy(rgb_line_buffer, ptr + stride * i, stride);
251
252 while (!line_state[j])
253 {
254 line_state[j] = 1;
255 i = j;
256 j = j * 2 % modv;
257 fast_memcpy(ptr + stride * i, ptr + stride * j, stride);
258 }
259 fast_memcpy(ptr + stride * i, rgb_line_buffer, stride);
260
261 while(k_start < modv && line_state[k_start])
262 k_start++;
263 }
264 free(line_state);
265 }
266 #endif
267 166
268 static void vo_y4m_write(const void *ptr, const size_t num_bytes) 167 static void vo_y4m_write(const void *ptr, const size_t num_bytes)
269 { 168 {
270 if (fwrite(ptr, 1, num_bytes, yuv_out) != num_bytes) 169 if (fwrite(ptr, 1, num_bytes, yuv_out) != num_bytes)
271 mp_msg(MSGT_VO,MSGL_ERR, 170 mp_msg(MSGT_VO,MSGL_ERR,
272 MSGTR_VO_YUV4MPEG_OutFileWriteError); 171 MSGTR_VO_YUV4MPEG_OutFileWriteError);
273 } 172 }
274 173
275 static int write_last_frame(void) 174 static int write_last_frame(void)
276 { 175 {
277
278 uint8_t *upper_y, *upper_u, *upper_v, *rgb_buffer_lower;
279 int rgb_stride, uv_stride, field_height;
280 unsigned int i, low_ofs;
281
282 fprintf(yuv_out, "FRAME\n"); 176 fprintf(yuv_out, "FRAME\n");
283 177
284 if (using_format != IMGFMT_YV12)
285 {
286 rgb_stride = image_width * 3;
287 uv_stride = image_width / 2;
288
289 if (Y4M_IS_INTERLACED)
290 {
291 field_height = image_height / 2;
292
293 upper_y = image;
294 upper_u = upper_y + image_width * field_height;
295 upper_v = upper_u + image_width * field_height / 4;
296 low_ofs = image_width * field_height * 3 / 2;
297 rgb_buffer_lower = rgb_buffer + rgb_stride * field_height;
298
299 /* Write Y plane */
300 for(i = 0; i < field_height; i++)
301 {
302 vo_y4m_write(upper_y + image_width * i, image_width);
303 vo_y4m_write(upper_y + image_width * i + low_ofs, image_width);
304 }
305
306 /* Write U and V plane */
307 for(i = 0; i < field_height / 2; i++)
308 {
309 vo_y4m_write(upper_u + uv_stride * i, uv_stride);
310 vo_y4m_write(upper_u + uv_stride * i + low_ofs, uv_stride);
311 }
312 for(i = 0; i < field_height / 2; i++)
313 {
314 vo_y4m_write(upper_v + uv_stride * i, uv_stride);
315 vo_y4m_write(upper_v + uv_stride * i + low_ofs, uv_stride);
316 }
317 return VO_TRUE; /* Image written; We have to stop here */
318 }
319 }
320 /* Write progressive frame */
321 vo_y4m_write(image, write_bytes); 178 vo_y4m_write(image, write_bytes);
322 return VO_TRUE; 179 return VO_TRUE;
323 } 180 }
324 181
325 static void flip_page (void) 182 static void flip_page (void)
326 { 183 {
327 fprintf(yuv_out, "FRAME\n"); 184 fprintf(yuv_out, "FRAME\n");
328 185
329 #ifdef CONFIG_LIBSWSCALE_A
330 if (using_format != IMGFMT_YV12)
331 {
332 uint8_t *upper_y, *upper_u, *upper_v, *rgb_buffer_lower;
333 int rgb_stride, uv_stride, field_height;
334 unsigned int i, low_ofs;
335
336 rgb_stride = image_width * 3;
337 uv_stride = image_width / 2;
338
339 if (Y4M_IS_INTERLACED)
340 {
341 field_height = image_height / 2;
342
343 upper_y = image;
344 upper_u = upper_y + image_width * field_height;
345 upper_v = upper_u + image_width * field_height / 4;
346 low_ofs = image_width * field_height * 3 / 2;
347 rgb_buffer_lower = rgb_buffer + rgb_stride * field_height;
348
349 deinterleave_fields(rgb_buffer, rgb_stride, image_height);
350
351 rgb24toyv12(rgb_buffer, upper_y, upper_u, upper_v,
352 image_width, field_height,
353 image_width, uv_stride, rgb_stride);
354 rgb24toyv12(rgb_buffer_lower, upper_y + low_ofs,
355 upper_u + low_ofs, upper_v + low_ofs,
356 image_width, field_height,
357 image_width, uv_stride, rgb_stride);
358
359 /* Write Y plane */
360 for(i = 0; i < field_height; i++)
361 {
362 vo_y4m_write(upper_y + image_width * i, image_width);
363 vo_y4m_write(upper_y + image_width * i + low_ofs, image_width);
364 }
365
366 /* Write U and V plane */
367 for(i = 0; i < field_height / 2; i++)
368 {
369 vo_y4m_write(upper_u + uv_stride * i, uv_stride);
370 vo_y4m_write(upper_u + uv_stride * i + low_ofs, uv_stride);
371 }
372 for(i = 0; i < field_height / 2; i++)
373 {
374 vo_y4m_write(upper_v + uv_stride * i, uv_stride);
375 vo_y4m_write(upper_v + uv_stride * i + low_ofs, uv_stride);
376 }
377 return; /* Image written; We have to stop here */
378 }
379
380 rgb24toyv12(rgb_buffer, image_y, image_u, image_v,
381 image_width, image_height,
382 image_width, uv_stride, rgb_stride);
383 }
384 #endif
385
386 /* Write progressive frame */
387 vo_y4m_write(image, write_bytes); 186 vo_y4m_write(image, write_bytes);
388 } 187 }
389 188
390 static int draw_slice(uint8_t *srcimg[], int stride[], int w,int h,int x,int y) 189 static int draw_slice(uint8_t *srcimg[], int stride[], int w,int h,int x,int y)
391 { 190 {
392 int i; 191 int i;
393 uint8_t *dst, *src = srcimg[0]; 192 uint8_t *dst, *src = srcimg[0];
394
395 switch (using_format)
396 {
397 case IMGFMT_YV12:
398 193
399 // copy Y: 194 // copy Y:
400 dst = image_y + image_width * y + x; 195 dst = image_y + image_width * y + x;
401 for (i = 0; i < h; i++) 196 for (i = 0; i < h; i++)
402 { 197 {
419 src2 += stride[2]; 214 src2 += stride[2];
420 dstu += imgstride; 215 dstu += imgstride;
421 dstv += imgstride; 216 dstv += imgstride;
422 } 217 }
423 } 218 }
424 break;
425
426 case IMGFMT_BGR24:
427 case IMGFMT_RGB24:
428 dst = rgb_buffer + (image_width * y + x) * 3;
429 for (i = 0; i < h; i++)
430 {
431 fast_memcpy(dst, src, w * 3);
432 src += stride[0];
433 dst += image_width * 3;
434 }
435 break;
436 }
437 return 0; 219 return 0;
438 } 220 }
439 221
440 static int draw_frame(uint8_t * src[]) 222 static int draw_frame(uint8_t * src[])
441 { 223 {
442 switch(using_format)
443 {
444 case IMGFMT_YV12:
445 // gets done in draw_slice 224 // gets done in draw_slice
446 break;
447
448 case IMGFMT_BGR24:
449 case IMGFMT_RGB24:
450 fast_memcpy(rgb_buffer, src[0], image_width * image_height * 3);
451 break;
452 }
453 return 0; 225 return 0;
454 } 226 }
455 227
456 static int query_format(uint32_t format) 228 static int query_format(uint32_t format)
457 { 229 {
458 230 if (format == IMGFMT_YV12)
459 if (Y4M_IS_INTERLACED) 231 return VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW|VFCAP_OSD|VFCAP_ACCEPT_STRIDE;
460 {
461 /* When processing interlaced material we want to get the raw RGB
462 * data and do the YV12 conversion ourselves to have the chrominance
463 * information sampled correct. */
464
465 switch(format)
466 {
467 case IMGFMT_YV12:
468 return VFCAP_CSP_SUPPORTED|VFCAP_OSD|VFCAP_ACCEPT_STRIDE;
469 #ifdef CONFIG_LIBSWSCALE_A
470 case IMGFMT_BGR|24:
471 case IMGFMT_RGB|24:
472 return VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW|VFCAP_OSD|VFCAP_ACCEPT_STRIDE;
473 #endif
474 }
475 }
476 else
477 {
478
479 switch(format)
480 {
481 case IMGFMT_YV12:
482 return VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW|VFCAP_OSD|VFCAP_ACCEPT_STRIDE;
483 #ifdef CONFIG_LIBSWSCALE_A
484 case IMGFMT_BGR|24:
485 case IMGFMT_RGB|24:
486 return VFCAP_CSP_SUPPORTED|VFCAP_OSD|VFCAP_ACCEPT_STRIDE;
487 #endif
488 }
489 }
490 return 0; 232 return 0;
491 } 233 }
492 234
493 // WARNING: config(...) also uses this 235 // WARNING: config(...) also uses this
494 static void uninit(void) 236 static void uninit(void)
498 image = NULL; 240 image = NULL;
499 241
500 if(yuv_out) 242 if(yuv_out)
501 fclose(yuv_out); 243 fclose(yuv_out);
502 yuv_out = NULL; 244 yuv_out = NULL;
503
504 if(rgb_buffer)
505 free(rgb_buffer);
506 rgb_buffer = NULL;
507
508 if(rgb_line_buffer)
509 free(rgb_line_buffer);
510 rgb_line_buffer = NULL;
511 245
512 if (yuv_filename) 246 if (yuv_filename)
513 free(yuv_filename); 247 free(yuv_filename);
514 yuv_filename = NULL; 248 yuv_filename = NULL;
515 image_width = 0; 249 image_width = 0;