Mercurial > libavcodec.hg
comparison imgconvert.c @ 52:1d796bdb2c2a libavcodec
added 422P, 444P support - added deinterlace support - added xxx to RGB24 convertion
author | glantau |
---|---|
date | Sat, 11 Aug 2001 19:03:02 +0000 |
parents | 1d2077091e88 |
children | 5aa6292a1660 |
comparison
equal
deleted
inserted
replaced
51:6ea595d66852 | 52:1d796bdb2c2a |
---|---|
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
18 */ | 18 */ |
19 #include <stdlib.h> | 19 #include <stdlib.h> |
20 #include <stdio.h> | 20 #include <stdio.h> |
21 #include <string.h> | 21 #include <string.h> |
22 | |
22 #include "avcodec.h" | 23 #include "avcodec.h" |
24 #include "dsputil.h" | |
23 | 25 |
24 #ifdef USE_FASTMEMCPY | 26 #ifdef USE_FASTMEMCPY |
25 #include "fastmemcpy.h" | 27 #include "fastmemcpy.h" |
26 #endif | 28 #endif |
27 /* XXX: totally non optimized */ | 29 /* XXX: totally non optimized */ |
180 p += wrap3; | 182 p += wrap3; |
181 lum += wrap; | 183 lum += wrap; |
182 } | 184 } |
183 } | 185 } |
184 | 186 |
185 int img_convert_to_yuv420(UINT8 *img_out, UINT8 *img, | 187 /* XXX: use generic filter ? */ |
188 /* 1x2 -> 1x1 */ | |
189 static void shrink2(UINT8 *dst, int dst_wrap, | |
190 UINT8 *src, int src_wrap, | |
191 int width, int height) | |
192 { | |
193 int w; | |
194 UINT8 *s1, *s2, *d; | |
195 | |
196 for(;height > 0; height--) { | |
197 s1 = src; | |
198 s2 = s1 + src_wrap; | |
199 d = dst; | |
200 for(w = width;w >= 4; w-=4) { | |
201 d[0] = (s1[0] + s2[0]) >> 1; | |
202 d[1] = (s1[1] + s2[1]) >> 1; | |
203 d[2] = (s1[2] + s2[2]) >> 1; | |
204 d[3] = (s1[3] + s2[3]) >> 1; | |
205 s1 += 4; | |
206 s2 += 4; | |
207 d += 4; | |
208 } | |
209 for(;w > 0; w--) { | |
210 d[0] = (s1[0] + s2[0]) >> 1; | |
211 s1++; | |
212 s2++; | |
213 d++; | |
214 } | |
215 src += 2 * src_wrap; | |
216 dst += dst_wrap; | |
217 } | |
218 } | |
219 | |
220 /* 2x2 -> 1x1 */ | |
221 static void shrink22(UINT8 *dst, int dst_wrap, | |
222 UINT8 *src, int src_wrap, | |
223 int width, int height) | |
224 { | |
225 int w; | |
226 UINT8 *s1, *s2, *d; | |
227 | |
228 for(;height > 0; height--) { | |
229 s1 = src; | |
230 s2 = s1 + src_wrap; | |
231 d = dst; | |
232 for(w = width;w >= 4; w-=4) { | |
233 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1; | |
234 d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 1; | |
235 d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 1; | |
236 d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 1; | |
237 s1 += 8; | |
238 s2 += 8; | |
239 d += 4; | |
240 } | |
241 for(;w > 0; w--) { | |
242 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1; | |
243 s1 += 2; | |
244 s2 += 2; | |
245 d++; | |
246 } | |
247 src += 2 * src_wrap; | |
248 dst += dst_wrap; | |
249 } | |
250 } | |
251 | |
252 static void img_copy(UINT8 *dst, int dst_wrap, | |
253 UINT8 *src, int src_wrap, | |
254 int width, int height) | |
255 { | |
256 for(;height > 0; height--) { | |
257 memcpy(dst, src, width); | |
258 dst += dst_wrap; | |
259 src += src_wrap; | |
260 } | |
261 } | |
262 | |
263 #define SCALE_BITS 10 | |
264 | |
265 #define C_Y (76309 >> (16 - SCALE_BITS)) | |
266 #define C_RV (117504 >> (16 - SCALE_BITS)) | |
267 #define C_BU (138453 >> (16 - SCALE_BITS)) | |
268 #define C_GU (13954 >> (16 - SCALE_BITS)) | |
269 #define C_GV (34903 >> (16 - SCALE_BITS)) | |
270 | |
271 #define RGBOUT(r, g, b, y1)\ | |
272 {\ | |
273 y = (y1 - 16) * C_Y;\ | |
274 r = cm[(y + r_add) >> SCALE_BITS];\ | |
275 g = cm[(y + g_add) >> SCALE_BITS];\ | |
276 b = cm[(y + b_add) >> SCALE_BITS];\ | |
277 } | |
278 | |
279 /* XXX: no chroma interpolating is done */ | |
280 static void yuv420p_to_rgb24(AVPicture *dst, AVPicture *src, | |
281 int width, int height) | |
282 { | |
283 UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; | |
284 int w, y, cb, cr, r_add, g_add, b_add, width2; | |
285 UINT8 *cm = cropTbl + MAX_NEG_CROP; | |
286 | |
287 d = dst->data[0]; | |
288 y1_ptr = src->data[0]; | |
289 cb_ptr = src->data[1]; | |
290 cr_ptr = src->data[2]; | |
291 width2 = width >> 1; | |
292 for(;height > 0; height -= 2) { | |
293 d1 = d; | |
294 d2 = d + dst->linesize[0]; | |
295 y2_ptr = y1_ptr + src->linesize[0]; | |
296 for(w = width2; w > 0; w --) { | |
297 cb = cb_ptr[0] - 128; | |
298 cr = cr_ptr[0] - 128; | |
299 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); | |
300 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); | |
301 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); | |
302 | |
303 /* output 4 pixels */ | |
304 RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]); | |
305 RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]); | |
306 RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]); | |
307 RGBOUT(d2[3], d2[4], d2[5], y2_ptr[1]); | |
308 | |
309 d1 += 6; | |
310 d2 += 6; | |
311 y1_ptr += 2; | |
312 y2_ptr += 2; | |
313 cb_ptr++; | |
314 cr_ptr++; | |
315 } | |
316 d += 2 * dst->linesize[0]; | |
317 y1_ptr += 2 * src->linesize[0] - width; | |
318 cb_ptr += src->linesize[1] - width2; | |
319 cr_ptr += src->linesize[2] - width2; | |
320 } | |
321 } | |
322 | |
323 /* XXX: no chroma interpolating is done */ | |
324 static void yuv422p_to_rgb24(AVPicture *dst, AVPicture *src, | |
325 int width, int height) | |
326 { | |
327 UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1; | |
328 int w, y, cb, cr, r_add, g_add, b_add, width2; | |
329 UINT8 *cm = cropTbl + MAX_NEG_CROP; | |
330 | |
331 d = dst->data[0]; | |
332 y1_ptr = src->data[0]; | |
333 cb_ptr = src->data[1]; | |
334 cr_ptr = src->data[2]; | |
335 width2 = width >> 1; | |
336 for(;height > 0; height --) { | |
337 d1 = d; | |
338 for(w = width2; w > 0; w --) { | |
339 cb = cb_ptr[0] - 128; | |
340 cr = cr_ptr[0] - 128; | |
341 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); | |
342 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); | |
343 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); | |
344 | |
345 /* output 2 pixels */ | |
346 RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]); | |
347 RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]); | |
348 | |
349 d1 += 6; | |
350 y1_ptr += 2; | |
351 cb_ptr++; | |
352 cr_ptr++; | |
353 } | |
354 d += dst->linesize[0]; | |
355 y1_ptr += src->linesize[0] - width; | |
356 cb_ptr += src->linesize[1] - width2; | |
357 cr_ptr += src->linesize[2] - width2; | |
358 } | |
359 } | |
360 | |
361 /* XXX: always use linesize. Return -1 if not supported */ | |
362 int img_convert(AVPicture *dst, int dst_pix_fmt, | |
363 AVPicture *src, int pix_fmt, | |
364 int width, int height) | |
365 { | |
366 int i; | |
367 | |
368 if (dst_pix_fmt == pix_fmt) { | |
369 switch(pix_fmt) { | |
370 case PIX_FMT_YUV420P: | |
371 for(i=0;i<3;i++) { | |
372 if (i == 1) { | |
373 width >>= 1; | |
374 height >>= 1; | |
375 } | |
376 img_copy(dst->data[i], dst->linesize[i], | |
377 src->data[i], src->linesize[i], | |
378 width, height); | |
379 } | |
380 break; | |
381 default: | |
382 return -1; | |
383 } | |
384 } else if (dst_pix_fmt == PIX_FMT_YUV420P) { | |
385 | |
386 switch(pix_fmt) { | |
387 case PIX_FMT_YUV420P: | |
388 for(i=0;i<3;i++) { | |
389 img_copy(dst->data[i], dst->linesize[i], | |
390 src->data[i], src->linesize[i], | |
391 width, height); | |
392 } | |
393 break; | |
394 case PIX_FMT_YUV422P: | |
395 img_copy(dst->data[0], dst->linesize[0], | |
396 src->data[0], src->linesize[0], | |
397 width, height); | |
398 width >>= 1; | |
399 height >>= 1; | |
400 for(i=1;i<3;i++) { | |
401 shrink2(dst->data[i], dst->linesize[i], | |
402 src->data[i], src->linesize[i], | |
403 width, height); | |
404 } | |
405 break; | |
406 case PIX_FMT_YUV444P: | |
407 img_copy(dst->data[0], dst->linesize[0], | |
408 src->data[0], src->linesize[0], | |
409 width, height); | |
410 width >>= 1; | |
411 height >>= 1; | |
412 for(i=1;i<3;i++) { | |
413 shrink22(dst->data[i], dst->linesize[i], | |
414 src->data[i], src->linesize[i], | |
415 width, height); | |
416 } | |
417 break; | |
418 case PIX_FMT_YUV422: | |
419 yuv422_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | |
420 src->data[0], width, height); | |
421 break; | |
422 case PIX_FMT_RGB24: | |
423 rgb24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | |
424 src->data[0], width, height); | |
425 break; | |
426 case PIX_FMT_BGR24: | |
427 bgr24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | |
428 src->data[0], width, height); | |
429 break; | |
430 default: | |
431 return -1; | |
432 } | |
433 } else if (dst_pix_fmt == PIX_FMT_RGB24) { | |
434 switch(pix_fmt) { | |
435 case PIX_FMT_YUV420P: | |
436 yuv420p_to_rgb24(dst, src, width, height); | |
437 break; | |
438 case PIX_FMT_YUV422P: | |
439 yuv422p_to_rgb24(dst, src, width, height); | |
440 break; | |
441 default: | |
442 return -1; | |
443 } | |
444 } else { | |
445 return -1; | |
446 } | |
447 return 0; | |
448 } | |
449 | |
450 /* filter parameters: [-1 4 2 4 -1] // 8 */ | |
451 static void deinterlace_line(UINT8 *dst, UINT8 *src, int src_wrap, | |
452 int size) | |
453 { | |
454 UINT8 *cm = cropTbl + MAX_NEG_CROP; | |
455 int sum; | |
456 UINT8 *s; | |
457 | |
458 for(;size > 0;size--) { | |
459 s = src; | |
460 sum = -s[0]; | |
461 s += src_wrap; | |
462 sum += s[0] << 2; | |
463 s += src_wrap; | |
464 sum += s[0] << 1; | |
465 s += src_wrap; | |
466 sum += s[0] << 2; | |
467 s += src_wrap; | |
468 sum += -s[0]; | |
469 dst[0] = cm[(sum + 4) >> 3]; | |
470 dst++; | |
471 src++; | |
472 } | |
473 } | |
474 | |
475 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The | |
476 top field is copied as is, but the bottom field is deinterlaced | |
477 against the top field. */ | |
478 static void deinterlace_bottom_field(UINT8 *dst, int dst_wrap, | |
479 UINT8 *src1, int src_wrap, | |
480 int width, int height) | |
481 { | |
482 UINT8 *src, *ptr; | |
483 int y, y1, i; | |
484 UINT8 buf[5 * width]; | |
485 | |
486 src = src1; | |
487 for(y=0;y<height;y+=2) { | |
488 /* copy top field line */ | |
489 memcpy(dst, src, width); | |
490 dst += dst_wrap; | |
491 src += (1 - 2) * src_wrap; | |
492 y1 = y - 2; | |
493 if (y1 >= 0 && (y1 + 4) < height) { | |
494 /* fast case : no edges */ | |
495 deinterlace_line(dst, src, src_wrap, width); | |
496 } else { | |
497 /* in order to use the same function, we use an intermediate buffer */ | |
498 ptr = buf; | |
499 for(i=0;i<5;i++) { | |
500 if (y1 < 0) | |
501 memcpy(ptr, src1, width); | |
502 else if (y1 >= height) | |
503 memcpy(ptr, src1 + (height - 1) * src_wrap, width); | |
504 else | |
505 memcpy(ptr, src1 + y1 * src_wrap, width); | |
506 y1++; | |
507 ptr += width; | |
508 } | |
509 deinterlace_line(dst, buf, width, width); | |
510 } | |
511 dst += dst_wrap; | |
512 src += (2 + 1) * src_wrap; | |
513 } | |
514 } | |
515 | |
516 | |
517 /* deinterlace, return -1 if format not handled */ | |
518 int avpicture_deinterlace(AVPicture *dst, AVPicture *src, | |
186 int pix_fmt, int width, int height) | 519 int pix_fmt, int width, int height) |
187 { | 520 { |
188 UINT8 *pict; | 521 int i; |
189 int size, size_out; | 522 |
190 UINT8 *picture[3]; | 523 if (pix_fmt != PIX_FMT_YUV420P && |
191 | 524 pix_fmt != PIX_FMT_YUV422P && |
192 pict = img_out; | 525 pix_fmt != PIX_FMT_YUV444P) |
193 size = width * height; | 526 return -1; |
194 size_out = (size * 3) / 2; | 527 if ((width & 1) != 0 || (height & 3) != 0) |
195 picture[0] = pict; | 528 return -1; |
196 picture[1] = pict + size; | 529 |
197 picture[2] = picture[1] + (size / 4); | 530 for(i=0;i<3;i++) { |
198 | 531 if (i == 1) { |
199 switch(pix_fmt) { | 532 switch(pix_fmt) { |
200 case PIX_FMT_YUV420P: | 533 case PIX_FMT_YUV420P: |
201 memcpy(pict, img, size_out); | 534 width >>= 1; |
202 break; | 535 height >>= 1; |
203 case PIX_FMT_YUV422: | 536 break; |
204 yuv422_to_yuv420p(picture[0], picture[1], picture[2], | 537 case PIX_FMT_YUV422P: |
205 img, width, height); | 538 width >>= 1; |
206 break; | 539 break; |
207 case PIX_FMT_RGB24: | 540 default: |
208 rgb24_to_yuv420p(picture[0], picture[1], picture[2], | 541 break; |
209 img, width, height); | 542 } |
210 break; | 543 } |
211 case PIX_FMT_BGR24: | 544 deinterlace_bottom_field(dst->data[i], dst->linesize[i], |
212 bgr24_to_yuv420p(picture[0], picture[1], picture[2], | 545 src->data[i], src->linesize[i], |
213 img, width, height); | 546 width, height); |
214 break; | 547 } |
215 } | 548 return 0; |
216 return size_out; | 549 } |
217 } |