annotate ffmpeg/libavcodec/imgconvert.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Misc image conversion routines
yading@10 3 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file
yading@10 24 * misc image conversion routines
yading@10 25 */
yading@10 26
yading@10 27 /* TODO:
yading@10 28 * - write 'ffimg' program to test all the image related stuff
yading@10 29 * - move all api to slice based system
yading@10 30 * - integrate deinterlacing, postprocessing and scaling in the conversion process
yading@10 31 */
yading@10 32
yading@10 33 #include "avcodec.h"
yading@10 34 #include "dsputil.h"
yading@10 35 #include "imgconvert.h"
yading@10 36 #include "internal.h"
yading@10 37 #include "libavutil/avassert.h"
yading@10 38 #include "libavutil/colorspace.h"
yading@10 39 #include "libavutil/common.h"
yading@10 40 #include "libavutil/pixdesc.h"
yading@10 41 #include "libavutil/imgutils.h"
yading@10 42
yading@10 43 #if HAVE_MMX_EXTERNAL
yading@10 44 #include "x86/dsputil_mmx.h"
yading@10 45 #endif
yading@10 46
yading@10 47 #define FF_COLOR_NA -1
yading@10 48 #define FF_COLOR_RGB 0 /**< RGB color space */
yading@10 49 #define FF_COLOR_GRAY 1 /**< gray color space */
yading@10 50 #define FF_COLOR_YUV 2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */
yading@10 51 #define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */
yading@10 52
yading@10 53 #if HAVE_MMX_EXTERNAL
yading@10 54 #define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx
yading@10 55 #define deinterlace_line ff_deinterlace_line_mmx
yading@10 56 #else
yading@10 57 #define deinterlace_line_inplace deinterlace_line_inplace_c
yading@10 58 #define deinterlace_line deinterlace_line_c
yading@10 59 #endif
yading@10 60
yading@10 61 #define pixdesc_has_alpha(pixdesc) \
yading@10 62 ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & PIX_FMT_PAL)
yading@10 63
yading@10 64
yading@10 65 void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift)
yading@10 66 {
yading@10 67 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
yading@10 68 av_assert0(desc);
yading@10 69 *h_shift = desc->log2_chroma_w;
yading@10 70 *v_shift = desc->log2_chroma_h;
yading@10 71 }
yading@10 72
yading@10 73 static int get_color_type(const AVPixFmtDescriptor *desc) {
yading@10 74 if(desc->nb_components == 1 || desc->nb_components == 2)
yading@10 75 return FF_COLOR_GRAY;
yading@10 76
yading@10 77 if(desc->name && !strncmp(desc->name, "yuvj", 4))
yading@10 78 return FF_COLOR_YUV_JPEG;
yading@10 79
yading@10 80 if(desc->flags & PIX_FMT_RGB)
yading@10 81 return FF_COLOR_RGB;
yading@10 82
yading@10 83 if(desc->nb_components == 0)
yading@10 84 return FF_COLOR_NA;
yading@10 85
yading@10 86 return FF_COLOR_YUV;
yading@10 87 }
yading@10 88
yading@10 89 static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt)
yading@10 90 {
yading@10 91 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
yading@10 92 int i;
yading@10 93
yading@10 94 if (!desc || !desc->nb_components) {
yading@10 95 *min = *max = 0;
yading@10 96 return AVERROR(EINVAL);
yading@10 97 }
yading@10 98
yading@10 99 *min = INT_MAX, *max = -INT_MAX;
yading@10 100 for (i = 0; i < desc->nb_components; i++) {
yading@10 101 *min = FFMIN(desc->comp[i].depth_minus1+1, *min);
yading@10 102 *max = FFMAX(desc->comp[i].depth_minus1+1, *max);
yading@10 103 }
yading@10 104 return 0;
yading@10 105 }
yading@10 106
yading@10 107 static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt,
yading@10 108 enum AVPixelFormat src_pix_fmt,
yading@10 109 unsigned *lossp, unsigned consider)
yading@10 110 {
yading@10 111 const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
yading@10 112 const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
yading@10 113 int src_color, dst_color;
yading@10 114 int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth;
yading@10 115 int ret, loss, i, nb_components;
yading@10 116 int score = INT_MAX;
yading@10 117
yading@10 118 if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE)
yading@10 119 return ~0;
yading@10 120
yading@10 121 /* compute loss */
yading@10 122 *lossp = loss = 0;
yading@10 123
yading@10 124 if (dst_pix_fmt == src_pix_fmt)
yading@10 125 return INT_MAX;
yading@10 126
yading@10 127 if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0)
yading@10 128 return ret;
yading@10 129 if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0)
yading@10 130 return ret;
yading@10 131
yading@10 132 src_color = get_color_type(src_desc);
yading@10 133 dst_color = get_color_type(dst_desc);
yading@10 134 nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components);
yading@10 135
yading@10 136 for (i = 0; i < nb_components; i++)
yading@10 137 if (src_desc->comp[i].depth_minus1 > dst_desc->comp[i].depth_minus1 && (consider & FF_LOSS_DEPTH)) {
yading@10 138 loss |= FF_LOSS_DEPTH;
yading@10 139 score -= 65536 >> dst_desc->comp[i].depth_minus1;
yading@10 140 }
yading@10 141
yading@10 142 if (consider & FF_LOSS_RESOLUTION) {
yading@10 143 if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w) {
yading@10 144 loss |= FF_LOSS_RESOLUTION;
yading@10 145 score -= 256 << dst_desc->log2_chroma_w;
yading@10 146 }
yading@10 147 if (dst_desc->log2_chroma_h > src_desc->log2_chroma_h) {
yading@10 148 loss |= FF_LOSS_RESOLUTION;
yading@10 149 score -= 256 << dst_desc->log2_chroma_h;
yading@10 150 }
yading@10 151 // dont favor 422 over 420 if downsampling is needed, because 420 has much better support on the decoder side
yading@10 152 if (dst_desc->log2_chroma_w == 1 && src_desc->log2_chroma_w == 0 &&
yading@10 153 dst_desc->log2_chroma_h == 1 && src_desc->log2_chroma_h == 0 ) {
yading@10 154 score += 512;
yading@10 155 }
yading@10 156 }
yading@10 157
yading@10 158 if(consider & FF_LOSS_COLORSPACE)
yading@10 159 switch(dst_color) {
yading@10 160 case FF_COLOR_RGB:
yading@10 161 if (src_color != FF_COLOR_RGB &&
yading@10 162 src_color != FF_COLOR_GRAY)
yading@10 163 loss |= FF_LOSS_COLORSPACE;
yading@10 164 break;
yading@10 165 case FF_COLOR_GRAY:
yading@10 166 if (src_color != FF_COLOR_GRAY)
yading@10 167 loss |= FF_LOSS_COLORSPACE;
yading@10 168 break;
yading@10 169 case FF_COLOR_YUV:
yading@10 170 if (src_color != FF_COLOR_YUV)
yading@10 171 loss |= FF_LOSS_COLORSPACE;
yading@10 172 break;
yading@10 173 case FF_COLOR_YUV_JPEG:
yading@10 174 if (src_color != FF_COLOR_YUV_JPEG &&
yading@10 175 src_color != FF_COLOR_YUV &&
yading@10 176 src_color != FF_COLOR_GRAY)
yading@10 177 loss |= FF_LOSS_COLORSPACE;
yading@10 178 break;
yading@10 179 default:
yading@10 180 /* fail safe test */
yading@10 181 if (src_color != dst_color)
yading@10 182 loss |= FF_LOSS_COLORSPACE;
yading@10 183 break;
yading@10 184 }
yading@10 185 if(loss & FF_LOSS_COLORSPACE)
yading@10 186 score -= (nb_components * 65536) >> FFMIN(dst_desc->comp[0].depth_minus1, src_desc->comp[0].depth_minus1);
yading@10 187
yading@10 188 if (dst_color == FF_COLOR_GRAY &&
yading@10 189 src_color != FF_COLOR_GRAY && (consider & FF_LOSS_CHROMA)) {
yading@10 190 loss |= FF_LOSS_CHROMA;
yading@10 191 score -= 2 * 65536;
yading@10 192 }
yading@10 193 if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) {
yading@10 194 loss |= FF_LOSS_ALPHA;
yading@10 195 score -= 65536;
yading@10 196 }
yading@10 197 if (dst_pix_fmt == AV_PIX_FMT_PAL8 && (consider & FF_LOSS_COLORQUANT) &&
yading@10 198 (src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))))) {
yading@10 199 loss |= FF_LOSS_COLORQUANT;
yading@10 200 score -= 65536;
yading@10 201 }
yading@10 202
yading@10 203 *lossp = loss;
yading@10 204 return score;
yading@10 205 }
yading@10 206
yading@10 207 int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,
yading@10 208 enum AVPixelFormat src_pix_fmt,
yading@10 209 int has_alpha)
yading@10 210 {
yading@10 211 int loss;
yading@10 212 int ret = get_pix_fmt_score(dst_pix_fmt, src_pix_fmt, &loss, has_alpha ? ~0 : ~FF_LOSS_ALPHA);
yading@10 213 if (ret < 0)
yading@10 214 return ret;
yading@10 215 return loss;
yading@10 216 }
yading@10 217
yading@10 218 enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
yading@10 219 enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
yading@10 220 {
yading@10 221 enum AVPixelFormat dst_pix_fmt;
yading@10 222 int loss1, loss2, loss_mask;
yading@10 223 const AVPixFmtDescriptor *desc1 = av_pix_fmt_desc_get(dst_pix_fmt1);
yading@10 224 const AVPixFmtDescriptor *desc2 = av_pix_fmt_desc_get(dst_pix_fmt2);
yading@10 225 int score1, score2;
yading@10 226
yading@10 227 loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */
yading@10 228 if(!has_alpha)
yading@10 229 loss_mask &= ~FF_LOSS_ALPHA;
yading@10 230
yading@10 231 dst_pix_fmt = AV_PIX_FMT_NONE;
yading@10 232 score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask);
yading@10 233 score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask);
yading@10 234
yading@10 235 if (score1 == score2) {
yading@10 236 if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) {
yading@10 237 dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1;
yading@10 238 } else {
yading@10 239 dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1;
yading@10 240 }
yading@10 241 } else {
yading@10 242 dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1;
yading@10 243 }
yading@10 244
yading@10 245 if (loss_ptr)
yading@10 246 *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
yading@10 247 return dst_pix_fmt;
yading@10 248 }
yading@10 249
yading@10 250 #if AV_HAVE_INCOMPATIBLE_FORK_ABI
yading@10 251 enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat *pix_fmt_list,
yading@10 252 enum AVPixelFormat src_pix_fmt,
yading@10 253 int has_alpha, int *loss_ptr){
yading@10 254 return avcodec_find_best_pix_fmt_of_list(pix_fmt_list, src_pix_fmt, has_alpha, loss_ptr);
yading@10 255 }
yading@10 256 #else
yading@10 257 enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
yading@10 258 enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
yading@10 259 {
yading@10 260 return avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr);
yading@10 261 }
yading@10 262 #endif
yading@10 263
yading@10 264 enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(enum AVPixelFormat *pix_fmt_list,
yading@10 265 enum AVPixelFormat src_pix_fmt,
yading@10 266 int has_alpha, int *loss_ptr){
yading@10 267 int i;
yading@10 268
yading@10 269 enum AVPixelFormat best = AV_PIX_FMT_NONE;
yading@10 270
yading@10 271 for(i=0; pix_fmt_list[i] != AV_PIX_FMT_NONE; i++)
yading@10 272 best = avcodec_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, loss_ptr);
yading@10 273
yading@10 274 return best;
yading@10 275 }
yading@10 276
yading@10 277 /* 2x2 -> 1x1 */
yading@10 278 void ff_shrink22(uint8_t *dst, int dst_wrap,
yading@10 279 const uint8_t *src, int src_wrap,
yading@10 280 int width, int height)
yading@10 281 {
yading@10 282 int w;
yading@10 283 const uint8_t *s1, *s2;
yading@10 284 uint8_t *d;
yading@10 285
yading@10 286 for(;height > 0; height--) {
yading@10 287 s1 = src;
yading@10 288 s2 = s1 + src_wrap;
yading@10 289 d = dst;
yading@10 290 for(w = width;w >= 4; w-=4) {
yading@10 291 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
yading@10 292 d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
yading@10 293 d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
yading@10 294 d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
yading@10 295 s1 += 8;
yading@10 296 s2 += 8;
yading@10 297 d += 4;
yading@10 298 }
yading@10 299 for(;w > 0; w--) {
yading@10 300 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
yading@10 301 s1 += 2;
yading@10 302 s2 += 2;
yading@10 303 d++;
yading@10 304 }
yading@10 305 src += 2 * src_wrap;
yading@10 306 dst += dst_wrap;
yading@10 307 }
yading@10 308 }
yading@10 309
yading@10 310 /* 4x4 -> 1x1 */
yading@10 311 void ff_shrink44(uint8_t *dst, int dst_wrap,
yading@10 312 const uint8_t *src, int src_wrap,
yading@10 313 int width, int height)
yading@10 314 {
yading@10 315 int w;
yading@10 316 const uint8_t *s1, *s2, *s3, *s4;
yading@10 317 uint8_t *d;
yading@10 318
yading@10 319 for(;height > 0; height--) {
yading@10 320 s1 = src;
yading@10 321 s2 = s1 + src_wrap;
yading@10 322 s3 = s2 + src_wrap;
yading@10 323 s4 = s3 + src_wrap;
yading@10 324 d = dst;
yading@10 325 for(w = width;w > 0; w--) {
yading@10 326 d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
yading@10 327 s2[0] + s2[1] + s2[2] + s2[3] +
yading@10 328 s3[0] + s3[1] + s3[2] + s3[3] +
yading@10 329 s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
yading@10 330 s1 += 4;
yading@10 331 s2 += 4;
yading@10 332 s3 += 4;
yading@10 333 s4 += 4;
yading@10 334 d++;
yading@10 335 }
yading@10 336 src += 4 * src_wrap;
yading@10 337 dst += dst_wrap;
yading@10 338 }
yading@10 339 }
yading@10 340
yading@10 341 /* 8x8 -> 1x1 */
yading@10 342 void ff_shrink88(uint8_t *dst, int dst_wrap,
yading@10 343 const uint8_t *src, int src_wrap,
yading@10 344 int width, int height)
yading@10 345 {
yading@10 346 int w, i;
yading@10 347
yading@10 348 for(;height > 0; height--) {
yading@10 349 for(w = width;w > 0; w--) {
yading@10 350 int tmp=0;
yading@10 351 for(i=0; i<8; i++){
yading@10 352 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
yading@10 353 src += src_wrap;
yading@10 354 }
yading@10 355 *(dst++) = (tmp + 32)>>6;
yading@10 356 src += 8 - 8*src_wrap;
yading@10 357 }
yading@10 358 src += 8*src_wrap - 8*width;
yading@10 359 dst += dst_wrap - width;
yading@10 360 }
yading@10 361 }
yading@10 362
yading@10 363 /* return true if yuv planar */
yading@10 364 static inline int is_yuv_planar(const AVPixFmtDescriptor *desc)
yading@10 365 {
yading@10 366 int i;
yading@10 367 int planes[4] = { 0 };
yading@10 368
yading@10 369 if ( desc->flags & PIX_FMT_RGB
yading@10 370 || !(desc->flags & PIX_FMT_PLANAR))
yading@10 371 return 0;
yading@10 372
yading@10 373 /* set the used planes */
yading@10 374 for (i = 0; i < desc->nb_components; i++)
yading@10 375 planes[desc->comp[i].plane] = 1;
yading@10 376
yading@10 377 /* if there is an unused plane, the format is not planar */
yading@10 378 for (i = 0; i < desc->nb_components; i++)
yading@10 379 if (!planes[i])
yading@10 380 return 0;
yading@10 381 return 1;
yading@10 382 }
yading@10 383
yading@10 384 int av_picture_crop(AVPicture *dst, const AVPicture *src,
yading@10 385 enum AVPixelFormat pix_fmt, int top_band, int left_band)
yading@10 386 {
yading@10 387 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
yading@10 388 int y_shift;
yading@10 389 int x_shift;
yading@10 390
yading@10 391 if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB)
yading@10 392 return -1;
yading@10 393
yading@10 394 y_shift = desc->log2_chroma_h;
yading@10 395 x_shift = desc->log2_chroma_w;
yading@10 396
yading@10 397 if (is_yuv_planar(desc)) {
yading@10 398 dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
yading@10 399 dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
yading@10 400 dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
yading@10 401 } else{
yading@10 402 if(top_band % (1<<y_shift) || left_band % (1<<x_shift))
yading@10 403 return -1;
yading@10 404 if(left_band) //FIXME add support for this too
yading@10 405 return -1;
yading@10 406 dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
yading@10 407 }
yading@10 408
yading@10 409 dst->linesize[0] = src->linesize[0];
yading@10 410 dst->linesize[1] = src->linesize[1];
yading@10 411 dst->linesize[2] = src->linesize[2];
yading@10 412 return 0;
yading@10 413 }
yading@10 414
yading@10 415 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
yading@10 416 enum AVPixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
yading@10 417 int *color)
yading@10 418 {
yading@10 419 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
yading@10 420 uint8_t *optr;
yading@10 421 int y_shift;
yading@10 422 int x_shift;
yading@10 423 int yheight;
yading@10 424 int i, y;
yading@10 425
yading@10 426 if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB ||
yading@10 427 !is_yuv_planar(desc)) return -1;
yading@10 428
yading@10 429 for (i = 0; i < 3; i++) {
yading@10 430 x_shift = i ? desc->log2_chroma_w : 0;
yading@10 431 y_shift = i ? desc->log2_chroma_h : 0;
yading@10 432
yading@10 433 if (padtop || padleft) {
yading@10 434 memset(dst->data[i], color[i],
yading@10 435 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
yading@10 436 }
yading@10 437
yading@10 438 if (padleft || padright) {
yading@10 439 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
yading@10 440 (dst->linesize[i] - (padright >> x_shift));
yading@10 441 yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
yading@10 442 for (y = 0; y < yheight; y++) {
yading@10 443 memset(optr, color[i], (padleft + padright) >> x_shift);
yading@10 444 optr += dst->linesize[i];
yading@10 445 }
yading@10 446 }
yading@10 447
yading@10 448 if (src) { /* first line */
yading@10 449 uint8_t *iptr = src->data[i];
yading@10 450 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
yading@10 451 (padleft >> x_shift);
yading@10 452 memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
yading@10 453 iptr += src->linesize[i];
yading@10 454 optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
yading@10 455 (dst->linesize[i] - (padright >> x_shift));
yading@10 456 yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
yading@10 457 for (y = 0; y < yheight; y++) {
yading@10 458 memset(optr, color[i], (padleft + padright) >> x_shift);
yading@10 459 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
yading@10 460 (width - padleft - padright) >> x_shift);
yading@10 461 iptr += src->linesize[i];
yading@10 462 optr += dst->linesize[i];
yading@10 463 }
yading@10 464 }
yading@10 465
yading@10 466 if (padbottom || padright) {
yading@10 467 optr = dst->data[i] + dst->linesize[i] *
yading@10 468 ((height - padbottom) >> y_shift) - (padright >> x_shift);
yading@10 469 memset(optr, color[i],dst->linesize[i] *
yading@10 470 (padbottom >> y_shift) + (padright >> x_shift));
yading@10 471 }
yading@10 472 }
yading@10 473 return 0;
yading@10 474 }
yading@10 475
yading@10 476 #if FF_API_DEINTERLACE
yading@10 477
yading@10 478 #if !HAVE_MMX_EXTERNAL
yading@10 479 /* filter parameters: [-1 4 2 4 -1] // 8 */
yading@10 480 static void deinterlace_line_c(uint8_t *dst,
yading@10 481 const uint8_t *lum_m4, const uint8_t *lum_m3,
yading@10 482 const uint8_t *lum_m2, const uint8_t *lum_m1,
yading@10 483 const uint8_t *lum,
yading@10 484 int size)
yading@10 485 {
yading@10 486 const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
yading@10 487 int sum;
yading@10 488
yading@10 489 for(;size > 0;size--) {
yading@10 490 sum = -lum_m4[0];
yading@10 491 sum += lum_m3[0] << 2;
yading@10 492 sum += lum_m2[0] << 1;
yading@10 493 sum += lum_m1[0] << 2;
yading@10 494 sum += -lum[0];
yading@10 495 dst[0] = cm[(sum + 4) >> 3];
yading@10 496 lum_m4++;
yading@10 497 lum_m3++;
yading@10 498 lum_m2++;
yading@10 499 lum_m1++;
yading@10 500 lum++;
yading@10 501 dst++;
yading@10 502 }
yading@10 503 }
yading@10 504
yading@10 505 static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
yading@10 506 uint8_t *lum_m2, uint8_t *lum_m1,
yading@10 507 uint8_t *lum, int size)
yading@10 508 {
yading@10 509 const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
yading@10 510 int sum;
yading@10 511
yading@10 512 for(;size > 0;size--) {
yading@10 513 sum = -lum_m4[0];
yading@10 514 sum += lum_m3[0] << 2;
yading@10 515 sum += lum_m2[0] << 1;
yading@10 516 lum_m4[0]=lum_m2[0];
yading@10 517 sum += lum_m1[0] << 2;
yading@10 518 sum += -lum[0];
yading@10 519 lum_m2[0] = cm[(sum + 4) >> 3];
yading@10 520 lum_m4++;
yading@10 521 lum_m3++;
yading@10 522 lum_m2++;
yading@10 523 lum_m1++;
yading@10 524 lum++;
yading@10 525 }
yading@10 526 }
yading@10 527 #endif /* !HAVE_MMX_EXTERNAL */
yading@10 528
yading@10 529 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
yading@10 530 top field is copied as is, but the bottom field is deinterlaced
yading@10 531 against the top field. */
yading@10 532 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
yading@10 533 const uint8_t *src1, int src_wrap,
yading@10 534 int width, int height)
yading@10 535 {
yading@10 536 const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
yading@10 537 int y;
yading@10 538
yading@10 539 src_m2 = src1;
yading@10 540 src_m1 = src1;
yading@10 541 src_0=&src_m1[src_wrap];
yading@10 542 src_p1=&src_0[src_wrap];
yading@10 543 src_p2=&src_p1[src_wrap];
yading@10 544 for(y=0;y<(height-2);y+=2) {
yading@10 545 memcpy(dst,src_m1,width);
yading@10 546 dst += dst_wrap;
yading@10 547 deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
yading@10 548 src_m2 = src_0;
yading@10 549 src_m1 = src_p1;
yading@10 550 src_0 = src_p2;
yading@10 551 src_p1 += 2*src_wrap;
yading@10 552 src_p2 += 2*src_wrap;
yading@10 553 dst += dst_wrap;
yading@10 554 }
yading@10 555 memcpy(dst,src_m1,width);
yading@10 556 dst += dst_wrap;
yading@10 557 /* do last line */
yading@10 558 deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
yading@10 559 }
yading@10 560
yading@10 561 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
yading@10 562 int width, int height)
yading@10 563 {
yading@10 564 uint8_t *src_m1, *src_0, *src_p1, *src_p2;
yading@10 565 int y;
yading@10 566 uint8_t *buf;
yading@10 567 buf = av_malloc(width);
yading@10 568
yading@10 569 src_m1 = src1;
yading@10 570 memcpy(buf,src_m1,width);
yading@10 571 src_0=&src_m1[src_wrap];
yading@10 572 src_p1=&src_0[src_wrap];
yading@10 573 src_p2=&src_p1[src_wrap];
yading@10 574 for(y=0;y<(height-2);y+=2) {
yading@10 575 deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
yading@10 576 src_m1 = src_p1;
yading@10 577 src_0 = src_p2;
yading@10 578 src_p1 += 2*src_wrap;
yading@10 579 src_p2 += 2*src_wrap;
yading@10 580 }
yading@10 581 /* do last line */
yading@10 582 deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
yading@10 583 av_free(buf);
yading@10 584 }
yading@10 585
yading@10 586 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
yading@10 587 enum AVPixelFormat pix_fmt, int width, int height)
yading@10 588 {
yading@10 589 int i;
yading@10 590
yading@10 591 if (pix_fmt != AV_PIX_FMT_YUV420P &&
yading@10 592 pix_fmt != AV_PIX_FMT_YUVJ420P &&
yading@10 593 pix_fmt != AV_PIX_FMT_YUV422P &&
yading@10 594 pix_fmt != AV_PIX_FMT_YUVJ422P &&
yading@10 595 pix_fmt != AV_PIX_FMT_YUV444P &&
yading@10 596 pix_fmt != AV_PIX_FMT_YUV411P &&
yading@10 597 pix_fmt != AV_PIX_FMT_GRAY8)
yading@10 598 return -1;
yading@10 599 if ((width & 3) != 0 || (height & 3) != 0)
yading@10 600 return -1;
yading@10 601
yading@10 602 for(i=0;i<3;i++) {
yading@10 603 if (i == 1) {
yading@10 604 switch(pix_fmt) {
yading@10 605 case AV_PIX_FMT_YUVJ420P:
yading@10 606 case AV_PIX_FMT_YUV420P:
yading@10 607 width >>= 1;
yading@10 608 height >>= 1;
yading@10 609 break;
yading@10 610 case AV_PIX_FMT_YUV422P:
yading@10 611 case AV_PIX_FMT_YUVJ422P:
yading@10 612 width >>= 1;
yading@10 613 break;
yading@10 614 case AV_PIX_FMT_YUV411P:
yading@10 615 width >>= 2;
yading@10 616 break;
yading@10 617 default:
yading@10 618 break;
yading@10 619 }
yading@10 620 if (pix_fmt == AV_PIX_FMT_GRAY8) {
yading@10 621 break;
yading@10 622 }
yading@10 623 }
yading@10 624 if (src == dst) {
yading@10 625 deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
yading@10 626 width, height);
yading@10 627 } else {
yading@10 628 deinterlace_bottom_field(dst->data[i],dst->linesize[i],
yading@10 629 src->data[i], src->linesize[i],
yading@10 630 width, height);
yading@10 631 }
yading@10 632 }
yading@10 633 emms_c();
yading@10 634 return 0;
yading@10 635 }
yading@10 636
yading@10 637 #endif /* FF_API_DEINTERLACE */
yading@10 638
yading@10 639 #ifdef TEST
yading@10 640
yading@10 641 int main(void){
yading@10 642 int i;
yading@10 643 int err=0;
yading@10 644 int skip = 0;
yading@10 645
yading@10 646 for (i=0; i<AV_PIX_FMT_NB*2; i++) {
yading@10 647 AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i);
yading@10 648 if(!desc || !desc->name) {
yading@10 649 skip ++;
yading@10 650 continue;
yading@10 651 }
yading@10 652 if (skip) {
yading@10 653 av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip);
yading@10 654 skip = 0;
yading@10 655 }
yading@10 656 av_log(NULL, AV_LOG_INFO, "pix fmt %s yuv_plan:%d avg_bpp:%d colortype:%d\n", desc->name, is_yuv_planar(desc), av_get_padded_bits_per_pixel(desc), get_color_type(desc));
yading@10 657 if ((!(desc->flags & PIX_FMT_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) {
yading@10 658 av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n");
yading@10 659 err = 1;
yading@10 660 }
yading@10 661 }
yading@10 662 return err;
yading@10 663 }
yading@10 664
yading@10 665 #endif