imgconvert.c 28.7 KB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
1
/*
Diego Biurrun's avatar
Diego Biurrun committed
2
 * Misc image conversion routines
3
 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
Fabrice Bellard's avatar
Fabrice Bellard committed
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
Fabrice Bellard committed
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Fabrice Bellard's avatar
Fabrice Bellard committed
20
 */
Michael Niedermayer's avatar
Michael Niedermayer committed
21 22

/**
23
 * @file
Diego Biurrun's avatar
Diego Biurrun committed
24
 * misc image conversion routines
Michael Niedermayer's avatar
Michael Niedermayer committed
25 26
 */

27 28 29 30 31
/* TODO:
 * - write 'ffimg' program to test all the image related stuff
 * - move all api to slice based system
 * - integrate deinterlacing, postprocessing and scaling in the conversion process
 */
Michael Niedermayer's avatar
Michael Niedermayer committed
32

Fabrice Bellard's avatar
Fabrice Bellard committed
33
#include "avcodec.h"
34
#include "dsputil.h"
35 36
#include "internal.h"
#include "imgconvert.h"
37
#include "libavutil/colorspace.h"
38
#include "libavutil/common.h"
39
#include "libavutil/pixdesc.h"
40
#include "libavutil/imgutils.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
41

42
#if HAVE_MMX_EXTERNAL
43
#include "x86/dsputil_mmx.h"
Fred's avatar
Fred committed
44
#endif
45

46 47 48 49
#define FF_COLOR_RGB      0 /**< RGB color space */
#define FF_COLOR_GRAY     1 /**< gray color space */
#define FF_COLOR_YUV      2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */
#define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */
50

51
#if HAVE_MMX_EXTERNAL
52 53 54 55 56 57 58
#define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx
#define deinterlace_line         ff_deinterlace_line_mmx
#else
#define deinterlace_line_inplace deinterlace_line_inplace_c
#define deinterlace_line         deinterlace_line_c
#endif

59 60 61
#define pixdesc_has_alpha(pixdesc) \
    ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & PIX_FMT_PAL)

62
typedef struct PixFmtInfo {
63
    uint8_t color_type;      /**< color type (see FF_COLOR_xxx constants) */
64
    uint8_t padded_size;     /**< padded size in bits if different from the non-padded size */
65 66 67
} PixFmtInfo;

/* this table gives more information about formats */
68
static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
69 70
    /* YUV formats */
    [PIX_FMT_YUV420P] = {
71
        .color_type = FF_COLOR_YUV,
72 73
    },
    [PIX_FMT_YUV422P] = {
74
        .color_type = FF_COLOR_YUV,
75 76
    },
    [PIX_FMT_YUV444P] = {
77
        .color_type = FF_COLOR_YUV,
78
    },
79
    [PIX_FMT_YUYV422] = {
80
        .color_type = FF_COLOR_YUV,
81
    },
82 83 84
    [PIX_FMT_UYVY422] = {
        .color_type = FF_COLOR_YUV,
    },
85
    [PIX_FMT_YUV410P] = {
86
        .color_type = FF_COLOR_YUV,
87 88
    },
    [PIX_FMT_YUV411P] = {
89
        .color_type = FF_COLOR_YUV,
90
    },
91 92 93
    [PIX_FMT_YUV440P] = {
        .color_type = FF_COLOR_YUV,
    },
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    [PIX_FMT_YUV420P9LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV422P9LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV444P9LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV420P9BE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV422P9BE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV444P9BE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV420P10LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV422P10LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV444P10LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV420P10BE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV422P10BE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV444P10BE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV420P12LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV422P12LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV444P12LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV420P12BE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV422P12BE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV444P12BE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV420P14LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV422P14LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV444P14LE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV420P14BE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV422P14BE] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_YUV444P14BE] = {
        .color_type = FF_COLOR_YUV,
    },
166
    [PIX_FMT_YUV420P16LE] = {
167 168
        .color_type = FF_COLOR_YUV,
    },
169
    [PIX_FMT_YUV422P16LE] = {
170 171
        .color_type = FF_COLOR_YUV,
    },
172
    [PIX_FMT_YUV444P16LE] = {
173 174
        .color_type = FF_COLOR_YUV,
    },
175
    [PIX_FMT_YUV420P16BE] = {
176 177
        .color_type = FF_COLOR_YUV,
    },
178
    [PIX_FMT_YUV422P16BE] = {
179 180
        .color_type = FF_COLOR_YUV,
    },
181
    [PIX_FMT_YUV444P16BE] = {
182 183 184
        .color_type = FF_COLOR_YUV,
    },

185 186 187 188 189
    /* YUV formats with alpha plane */
    [PIX_FMT_YUVA420P] = {
        .color_type = FF_COLOR_YUV,
    },

Carl Eugen Hoyos's avatar
Carl Eugen Hoyos committed
190 191 192 193
    [PIX_FMT_YUVA422P] = {
        .color_type = FF_COLOR_YUV,
    },

194 195 196 197
    [PIX_FMT_YUVA444P] = {
        .color_type = FF_COLOR_YUV,
    },

198 199 200 201 202 203 204 205 206 207
    /* JPEG YUV */
    [PIX_FMT_YUVJ420P] = {
        .color_type = FF_COLOR_YUV_JPEG,
    },
    [PIX_FMT_YUVJ422P] = {
        .color_type = FF_COLOR_YUV_JPEG,
    },
    [PIX_FMT_YUVJ444P] = {
        .color_type = FF_COLOR_YUV_JPEG,
    },
208 209 210
    [PIX_FMT_YUVJ440P] = {
        .color_type = FF_COLOR_YUV_JPEG,
    },
211

212 213
    /* RGB formats */
    [PIX_FMT_RGB24] = {
214
        .color_type = FF_COLOR_RGB,
215 216
    },
    [PIX_FMT_BGR24] = {
217
        .color_type = FF_COLOR_RGB,
218
    },
219
    [PIX_FMT_ARGB] = {
220
        .color_type = FF_COLOR_RGB,
221
    },
222 223 224 225 226 227
    [PIX_FMT_RGB48BE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_RGB48LE] = {
        .color_type = FF_COLOR_RGB,
    },
Jean First's avatar
Jean First committed
228 229 230 231 232 233
    [PIX_FMT_RGBA64BE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_RGBA64LE] = {
        .color_type = FF_COLOR_RGB,
    },
234
    [PIX_FMT_RGB565BE] = {
235
        .color_type = FF_COLOR_RGB,
236
    },
237 238 239 240 241
    [PIX_FMT_RGB565LE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_RGB555BE] = {
        .color_type = FF_COLOR_RGB,
242
        .padded_size = 16,
243 244
    },
    [PIX_FMT_RGB555LE] = {
245
        .color_type = FF_COLOR_RGB,
246
        .padded_size = 16,
247
    },
248 249
    [PIX_FMT_RGB444BE] = {
        .color_type = FF_COLOR_RGB,
250
        .padded_size = 16,
251 252 253
    },
    [PIX_FMT_RGB444LE] = {
        .color_type = FF_COLOR_RGB,
254
        .padded_size = 16,
255
    },
256 257

    /* gray / mono formats */
258 259 260 261 262 263
    [PIX_FMT_GRAY16BE] = {
        .color_type = FF_COLOR_GRAY,
    },
    [PIX_FMT_GRAY16LE] = {
        .color_type = FF_COLOR_GRAY,
    },
264
    [PIX_FMT_GRAY8] = {
265
        .color_type = FF_COLOR_GRAY,
266
    },
267 268 269
    [PIX_FMT_GRAY8A] = {
        .color_type = FF_COLOR_GRAY,
    },
270
    [PIX_FMT_MONOWHITE] = {
271
        .color_type = FF_COLOR_GRAY,
272 273
    },
    [PIX_FMT_MONOBLACK] = {
274
        .color_type = FF_COLOR_GRAY,
275
    },
276 277 278

    /* paletted formats */
    [PIX_FMT_PAL8] = {
279
        .color_type = FF_COLOR_RGB,
280
    },
281
    [PIX_FMT_UYYVYY411] = {
282 283
        .color_type = FF_COLOR_YUV,
    },
284
    [PIX_FMT_ABGR] = {
285 286
        .color_type = FF_COLOR_RGB,
    },
Jean First's avatar
Jean First committed
287 288 289 290 291 292 293 294 295 296 297 298
    [PIX_FMT_BGR48BE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_BGR48LE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_BGRA64BE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_BGRA64LE] = {
        .color_type = FF_COLOR_RGB,
    },
299 300
    [PIX_FMT_BGR565BE] = {
        .color_type = FF_COLOR_RGB,
301
        .padded_size = 16,
302 303 304
    },
    [PIX_FMT_BGR565LE] = {
        .color_type = FF_COLOR_RGB,
305
        .padded_size = 16,
306 307
    },
    [PIX_FMT_BGR555BE] = {
308
        .color_type = FF_COLOR_RGB,
309
        .padded_size = 16,
310
    },
311
    [PIX_FMT_BGR555LE] = {
312
        .color_type = FF_COLOR_RGB,
313
        .padded_size = 16,
314
    },
315 316
    [PIX_FMT_BGR444BE] = {
        .color_type = FF_COLOR_RGB,
317
        .padded_size = 16,
318 319 320
    },
    [PIX_FMT_BGR444LE] = {
        .color_type = FF_COLOR_RGB,
321
        .padded_size = 16,
322
    },
323 324 325 326 327 328 329 330
    [PIX_FMT_RGB8] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_RGB4] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_RGB4_BYTE] = {
        .color_type = FF_COLOR_RGB,
331
        .padded_size = 8,
332 333 334 335 336 337 338 339 340
    },
    [PIX_FMT_BGR8] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_BGR4] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_BGR4_BYTE] = {
        .color_type = FF_COLOR_RGB,
341
        .padded_size = 8,
342 343 344 345 346 347 348 349
    },
    [PIX_FMT_NV12] = {
        .color_type = FF_COLOR_YUV,
    },
    [PIX_FMT_NV21] = {
        .color_type = FF_COLOR_YUV,
    },

350
    [PIX_FMT_BGRA] = {
351 352
        .color_type = FF_COLOR_RGB,
    },
353
    [PIX_FMT_RGBA] = {
354 355
        .color_type = FF_COLOR_RGB,
    },
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389

    [PIX_FMT_GBRP] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_GBRP9BE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_GBRP9LE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_GBRP10BE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_GBRP10LE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_GBRP12BE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_GBRP12LE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_GBRP14BE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_GBRP14LE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_GBRP16BE] = {
        .color_type = FF_COLOR_RGB,
    },
    [PIX_FMT_GBRP16LE] = {
        .color_type = FF_COLOR_RGB,
    },
390 391
};

392
void avcodec_get_chroma_sub_sample(enum PixelFormat pix_fmt, int *h_shift, int *v_shift)
393
{
394 395
    *h_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
    *v_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
396 397
}

398 399
int ff_is_hwaccel_pix_fmt(enum PixelFormat pix_fmt)
{
400
    return av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL;
401 402
}

403
int avpicture_fill(AVPicture *picture, uint8_t *ptr,
404
                   enum PixelFormat pix_fmt, int width, int height)
405
{
406 407
    return av_image_fill_arrays(picture->data, picture->linesize,
                                ptr, pix_fmt, width, height, 1);
408 409
}

410
int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, int height,
411 412
                     unsigned char *dest, int dest_size)
{
413
    return av_image_copy_to_buffer(dest, dest_size,
414
                                   (const uint8_t * const*)src->data, src->linesize,
415
                                   pix_fmt, width, height, 1);
416 417
}

418
int avpicture_get_size(enum PixelFormat pix_fmt, int width, int height)
419
{
420
    return av_image_get_buffer_size(pix_fmt, width, height, 1);
421 422
}

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
static int get_pix_fmt_depth(int *min, int *max, enum PixelFormat pix_fmt)
{
    const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
    int i;

    if (!desc->nb_components) {
        *min = *max = 0;
        return AVERROR(EINVAL);
    }

    *min = INT_MAX, *max = -INT_MAX;
    for (i = 0; i < desc->nb_components; i++) {
        *min = FFMIN(desc->comp[i].depth_minus1+1, *min);
        *max = FFMAX(desc->comp[i].depth_minus1+1, *max);
    }
    return 0;
}

441
int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt,
442 443 444
                             int has_alpha)
{
    const PixFmtInfo *pf, *ps;
445 446
    const AVPixFmtDescriptor *src_desc;
    const AVPixFmtDescriptor *dst_desc;
447 448
    int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth;
    int ret, loss;
449

450 451 452 453 454
    if (dst_pix_fmt >= PIX_FMT_NB || dst_pix_fmt <= PIX_FMT_NONE)
        return ~0;

    src_desc = &av_pix_fmt_descriptors[src_pix_fmt];
    dst_desc = &av_pix_fmt_descriptors[dst_pix_fmt];
455 456 457 458
    ps = &pix_fmt_info[src_pix_fmt];

    /* compute loss */
    loss = 0;
459 460 461 462 463 464 465

    if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0)
        return ret;
    if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0)
        return ret;
    if (dst_min_depth < src_min_depth ||
        dst_max_depth < src_max_depth)
466
        loss |= FF_LOSS_DEPTH;
467 468
    if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w ||
        dst_desc->log2_chroma_h > src_desc->log2_chroma_h)
469
        loss |= FF_LOSS_RESOLUTION;
470 471

    pf = &pix_fmt_info[dst_pix_fmt];
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
    switch(pf->color_type) {
    case FF_COLOR_RGB:
        if (ps->color_type != FF_COLOR_RGB &&
            ps->color_type != FF_COLOR_GRAY)
            loss |= FF_LOSS_COLORSPACE;
        break;
    case FF_COLOR_GRAY:
        if (ps->color_type != FF_COLOR_GRAY)
            loss |= FF_LOSS_COLORSPACE;
        break;
    case FF_COLOR_YUV:
        if (ps->color_type != FF_COLOR_YUV)
            loss |= FF_LOSS_COLORSPACE;
        break;
    case FF_COLOR_YUV_JPEG:
        if (ps->color_type != FF_COLOR_YUV_JPEG &&
488
            ps->color_type != FF_COLOR_YUV &&
489
            ps->color_type != FF_COLOR_GRAY)
490 491 492 493 494 495 496 497 498 499 500
            loss |= FF_LOSS_COLORSPACE;
        break;
    default:
        /* fail safe test */
        if (ps->color_type != pf->color_type)
            loss |= FF_LOSS_COLORSPACE;
        break;
    }
    if (pf->color_type == FF_COLOR_GRAY &&
        ps->color_type != FF_COLOR_GRAY)
        loss |= FF_LOSS_CHROMA;
501
    if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && has_alpha))
502
        loss |= FF_LOSS_ALPHA;
503
    if (dst_pix_fmt == PIX_FMT_PAL8 &&
504
        (src_pix_fmt != PIX_FMT_PAL8 && (ps->color_type != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && has_alpha))))
505
        loss |= FF_LOSS_COLORQUANT;
506

507 508 509
    return loss;
}

510
static int avg_bits_per_pixel(enum PixelFormat pix_fmt)
511
{
512
    const PixFmtInfo *info = &pix_fmt_info[pix_fmt];
513
    const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
514

515 516
    return info->padded_size ?
        info->padded_size : av_get_bits_per_pixel(desc);
517 518
}

519
#if FF_API_FIND_BEST_PIX_FMT
520
enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt,
521
                                            int has_alpha, int *loss_ptr)
522
{
523
    enum PixelFormat dst_pix_fmt;
524 525 526 527 528 529 530 531
    int i;

    if (loss_ptr) /* all losses count (for backward compatibility) */
        *loss_ptr = 0;

    dst_pix_fmt = PIX_FMT_NONE; /* so first iteration doesn't have to be treated special */
    for(i = 0; i< FFMIN(PIX_FMT_NB, 64); i++){
        if (pix_fmt_mask & (1ULL << i))
532
            dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt, i, src_pix_fmt, has_alpha, loss_ptr);
533 534 535
    }
    return dst_pix_fmt;
}
536
#endif /* FF_API_FIND_BEST_PIX_FMT */
537

538
enum PixelFormat avcodec_find_best_pix_fmt_of_2(enum PixelFormat dst_pix_fmt1, enum PixelFormat dst_pix_fmt2,
539 540 541 542
                                            enum PixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
{
    enum PixelFormat dst_pix_fmt;
    int loss1, loss2, loss_order1, loss_order2, i, loss_mask;
543 544 545 546
    static const int loss_mask_order[] = {
        ~0, /* no loss first */
        ~FF_LOSS_ALPHA,
        ~FF_LOSS_RESOLUTION,
547
        ~FF_LOSS_COLORSPACE,
548 549 550
        ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
        ~FF_LOSS_COLORQUANT,
        ~FF_LOSS_DEPTH,
551
        ~(FF_LOSS_DEPTH|FF_LOSS_COLORSPACE),
552 553
        ~(FF_LOSS_RESOLUTION | FF_LOSS_DEPTH | FF_LOSS_COLORSPACE | FF_LOSS_ALPHA |
          FF_LOSS_COLORQUANT | FF_LOSS_CHROMA),
554
        0x80000, //non zero entry that combines all loss variants including future additions
555 556 557
        0,
    };

558 559 560 561 562
    loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */
    dst_pix_fmt = PIX_FMT_NONE;
    loss1 = avcodec_get_pix_fmt_loss(dst_pix_fmt1, src_pix_fmt, has_alpha) & loss_mask;
    loss2 = avcodec_get_pix_fmt_loss(dst_pix_fmt2, src_pix_fmt, has_alpha) & loss_mask;

563
    /* try with successive loss */
564 565 566 567 568 569 570 571 572
    for(i = 0;loss_mask_order[i] != 0 && dst_pix_fmt == PIX_FMT_NONE;i++) {
        loss_order1 = loss1 & loss_mask_order[i];
        loss_order2 = loss2 & loss_mask_order[i];

        if (loss_order1 == 0 && loss_order2 == 0){ /* use format with smallest depth */
            dst_pix_fmt = avg_bits_per_pixel(dst_pix_fmt2) < avg_bits_per_pixel(dst_pix_fmt1) ? dst_pix_fmt2 : dst_pix_fmt1;
        } else if (loss_order1 == 0 || loss_order2 == 0) { /* use format with no loss */
            dst_pix_fmt = loss_order2 ? dst_pix_fmt1 : dst_pix_fmt2;
        }
573
    }
574

575 576 577 578 579
    if (loss_ptr)
        *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
    return dst_pix_fmt;
}

580 581 582 583 584 585 586
#if AV_HAVE_INCOMPATIBLE_FORK_ABI
enum PixelFormat avcodec_find_best_pix_fmt2(enum PixelFormat *pix_fmt_list,
                                            enum PixelFormat src_pix_fmt,
                                            int has_alpha, int *loss_ptr){
    return avcodec_find_best_pix_fmt_of_list(pix_fmt_list, src_pix_fmt, has_alpha, loss_ptr);
}
#else
587 588 589 590 591
enum PixelFormat avcodec_find_best_pix_fmt2(enum PixelFormat dst_pix_fmt1, enum PixelFormat dst_pix_fmt2,
                                            enum PixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
{
    return avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr);
}
592
#endif
593

594 595 596 597 598 599 600 601
enum PixelFormat avcodec_find_best_pix_fmt_of_list(enum PixelFormat *pix_fmt_list,
                                            enum PixelFormat src_pix_fmt,
                                            int has_alpha, int *loss_ptr){
    int i;

    enum PixelFormat best = PIX_FMT_NONE;

    for(i=0; pix_fmt_list[i] != PIX_FMT_NONE; i++)
602
        best = avcodec_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, loss_ptr);
603 604 605 606

    return best;
}

607 608 609
void av_picture_copy(AVPicture *dst, const AVPicture *src,
                     enum PixelFormat pix_fmt, int width, int height)
{
610
    av_image_copy(dst->data, dst->linesize, (const uint8_t **)src->data,
Stefano Sabatini's avatar
Stefano Sabatini committed
611
                  src->linesize, pix_fmt, width, height);
612 613
}

614
/* 2x2 -> 1x1 */
615
void ff_shrink22(uint8_t *dst, int dst_wrap,
616
                     const uint8_t *src, int src_wrap,
617 618 619
                     int width, int height)
{
    int w;
620 621
    const uint8_t *s1, *s2;
    uint8_t *d;
622 623 624 625 626 627

    for(;height > 0; height--) {
        s1 = src;
        s2 = s1 + src_wrap;
        d = dst;
        for(w = width;w >= 4; w-=4) {
628 629 630 631
            d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
            d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
            d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
            d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
632 633 634 635 636
            s1 += 8;
            s2 += 8;
            d += 4;
        }
        for(;w > 0; w--) {
637
            d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
638 639 640 641 642 643 644 645 646
            s1 += 2;
            s2 += 2;
            d++;
        }
        src += 2 * src_wrap;
        dst += dst_wrap;
    }
}

647
/* 4x4 -> 1x1 */
648
void ff_shrink44(uint8_t *dst, int dst_wrap,
649
                     const uint8_t *src, int src_wrap,
650 651 652
                     int width, int height)
{
    int w;
653 654
    const uint8_t *s1, *s2, *s3, *s4;
    uint8_t *d;
655 656 657

    for(;height > 0; height--) {
        s1 = src;
658 659 660
        s2 = s1 + src_wrap;
        s3 = s2 + src_wrap;
        s4 = s3 + src_wrap;
661
        d = dst;
662 663 664 665 666 667 668 669 670
        for(w = width;w > 0; w--) {
            d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
                    s2[0] + s2[1] + s2[2] + s2[3] +
                    s3[0] + s3[1] + s3[2] + s3[3] +
                    s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
            s1 += 4;
            s2 += 4;
            s3 += 4;
            s4 += 4;
671 672
            d++;
        }
673 674 675 676 677
        src += 4 * src_wrap;
        dst += dst_wrap;
    }
}

678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
/* 8x8 -> 1x1 */
void ff_shrink88(uint8_t *dst, int dst_wrap,
                     const uint8_t *src, int src_wrap,
                     int width, int height)
{
    int w, i;

    for(;height > 0; height--) {
        for(w = width;w > 0; w--) {
            int tmp=0;
            for(i=0; i<8; i++){
                tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
                src += src_wrap;
            }
            *(dst++) = (tmp + 32)>>6;
            src += 8 - 8*src_wrap;
        }
        src += 8*src_wrap - 8*width;
        dst += dst_wrap - width;
    }
}

700

Drew Hess's avatar
Drew Hess committed
701
int avpicture_alloc(AVPicture *picture,
702
                    enum PixelFormat pix_fmt, int width, int height)
703
{
704 705
    int ret;

706
    if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
Stefano Sabatini's avatar
Stefano Sabatini committed
707
        memset(picture, 0, sizeof(AVPicture));
708
        return ret;
709 710 711
    }

    return 0;
712 713
}

Drew Hess's avatar
Drew Hess committed
714
void avpicture_free(AVPicture *picture)
715
{
716
    av_free(picture->data[0]);
717 718
}

719
/* return true if yuv planar */
720
static inline int is_yuv_planar(enum PixelFormat fmt)
721
{
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
    const PixFmtInfo         *info = &pix_fmt_info[fmt];
    const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[fmt];
    int i;
    int planes[4] = { 0 };

    if (info->color_type != FF_COLOR_YUV &&
        info->color_type != FF_COLOR_YUV_JPEG)
        return 0;

    /* set the used planes */
    for (i = 0; i < desc->nb_components; i++)
        planes[desc->comp[i].plane] = 1;

    /* if there is an unused plane, the format is not planar */
    for (i = 0; i < desc->nb_components; i++)
        if (!planes[i])
            return 0;
    return 1;
740 741
}

742
int av_picture_crop(AVPicture *dst, const AVPicture *src,
743
                    enum PixelFormat pix_fmt, int top_band, int left_band)
744 745 746 747
{
    int y_shift;
    int x_shift;

748
    if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
749 750
        return -1;

751 752
    y_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
    x_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
753

754
    if (is_yuv_planar(pix_fmt)) {
755 756 757
    dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
    dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
    dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
758 759 760 761 762 763 764
    } else{
        if(top_band % (1<<y_shift) || left_band % (1<<x_shift))
            return -1;
        if(left_band) //FIXME add support for this too
            return -1;
        dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
    }
765 766 767 768 769 770 771

    dst->linesize[0] = src->linesize[0];
    dst->linesize[1] = src->linesize[1];
    dst->linesize[2] = src->linesize[2];
    return 0;
}

772
int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
773
                   enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
Luca Barbato's avatar
Luca Barbato committed
774
            int *color)
775
{
776
    uint8_t *optr;
777 778 779 780 781
    int y_shift;
    int x_shift;
    int yheight;
    int i, y;

Luca Barbato's avatar
Luca Barbato committed
782
    if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
783
        !is_yuv_planar(pix_fmt)) return -1;
784 785

    for (i = 0; i < 3; i++) {
786 787
        x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0;
        y_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_h : 0;
788 789

        if (padtop || padleft) {
Luca Barbato's avatar
Luca Barbato committed
790 791
            memset(dst->data[i], color[i],
                dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
792 793
        }

794 795 796 797 798 799 800
        if (padleft || padright) {
            optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
                (dst->linesize[i] - (padright >> x_shift));
            yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
            for (y = 0; y < yheight; y++) {
                memset(optr, color[i], (padleft + padright) >> x_shift);
                optr += dst->linesize[i];
801
            }
802 803 804 805 806 807
        }

        if (src) { /* first line */
            uint8_t *iptr = src->data[i];
            optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
                    (padleft >> x_shift);
808
            memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
809
            iptr += src->linesize[i];
Luca Barbato's avatar
Luca Barbato committed
810 811
            optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
                (dst->linesize[i] - (padright >> x_shift));
812 813 814
            yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
            for (y = 0; y < yheight; y++) {
                memset(optr, color[i], (padleft + padright) >> x_shift);
815
                memcpy(optr + ((padleft + padright) >> x_shift), iptr,
816
                       (width - padleft - padright) >> x_shift);
817
                iptr += src->linesize[i];
818 819 820 821 822
                optr += dst->linesize[i];
            }
        }

        if (padbottom || padright) {
Luca Barbato's avatar
Luca Barbato committed
823 824 825 826
            optr = dst->data[i] + dst->linesize[i] *
                ((height - padbottom) >> y_shift) - (padright >> x_shift);
            memset(optr, color[i],dst->linesize[i] *
                (padbottom >> y_shift) + (padright >> x_shift));
827 828 829 830 831
        }
    }
    return 0;
}

832
#if !HAVE_MMX_EXTERNAL
833
/* filter parameters: [-1 4 2 4 -1] // 8 */
834
static void deinterlace_line_c(uint8_t *dst,
835 836 837 838
                             const uint8_t *lum_m4, const uint8_t *lum_m3,
                             const uint8_t *lum_m2, const uint8_t *lum_m1,
                             const uint8_t *lum,
                             int size)
839
{
840
    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
841 842 843
    int sum;

    for(;size > 0;size--) {
Fred's avatar
Fred committed
844 845 846 847 848
        sum = -lum_m4[0];
        sum += lum_m3[0] << 2;
        sum += lum_m2[0] << 1;
        sum += lum_m1[0] << 2;
        sum += -lum[0];
849
        dst[0] = cm[(sum + 4) >> 3];
Fred's avatar
Fred committed
850 851 852 853 854
        lum_m4++;
        lum_m3++;
        lum_m2++;
        lum_m1++;
        lum++;
855 856
        dst++;
    }
Fred's avatar
Fred committed
857
}
858 859 860 861

static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
                                       uint8_t *lum_m2, uint8_t *lum_m1,
                                       uint8_t *lum, int size)
Fred's avatar
Fred committed
862
{
863
    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
Fred's avatar
Fred committed
864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
    int sum;

    for(;size > 0;size--) {
        sum = -lum_m4[0];
        sum += lum_m3[0] << 2;
        sum += lum_m2[0] << 1;
        lum_m4[0]=lum_m2[0];
        sum += lum_m1[0] << 2;
        sum += -lum[0];
        lum_m2[0] = cm[(sum + 4) >> 3];
        lum_m4++;
        lum_m3++;
        lum_m2++;
        lum_m1++;
        lum++;
    }
880
}
881
#endif /* !HAVE_MMX_EXTERNAL */
882 883 884 885

/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
   top field is copied as is, but the bottom field is deinterlaced
   against the top field. */
886
static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
887
                                    const uint8_t *src1, int src_wrap,
Fred's avatar
Fred committed
888
                                    int width, int height)
889
{
890
    const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
Fred's avatar
Fred committed
891 892 893 894 895 896 897 898 899
    int y;

    src_m2 = src1;
    src_m1 = src1;
    src_0=&src_m1[src_wrap];
    src_p1=&src_0[src_wrap];
    src_p2=&src_p1[src_wrap];
    for(y=0;y<(height-2);y+=2) {
        memcpy(dst,src_m1,width);
900
        dst += dst_wrap;
Fred's avatar
Fred committed
901 902 903 904 905 906
        deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
        src_m2 = src_0;
        src_m1 = src_p1;
        src_0 = src_p2;
        src_p1 += 2*src_wrap;
        src_p2 += 2*src_wrap;
907 908
        dst += dst_wrap;
    }
Fred's avatar
Fred committed
909 910 911 912 913 914
    memcpy(dst,src_m1,width);
    dst += dst_wrap;
    /* do last line */
    deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
}

915
static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
916
                                             int width, int height)
Fred's avatar
Fred committed
917
{
918
    uint8_t *src_m1, *src_0, *src_p1, *src_p2;
Fred's avatar
Fred committed
919
    int y;
920
    uint8_t *buf;
921
    buf = av_malloc(width);
Fred's avatar
Fred committed
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936

    src_m1 = src1;
    memcpy(buf,src_m1,width);
    src_0=&src_m1[src_wrap];
    src_p1=&src_0[src_wrap];
    src_p2=&src_p1[src_wrap];
    for(y=0;y<(height-2);y+=2) {
        deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
        src_m1 = src_p1;
        src_0 = src_p2;
        src_p1 += 2*src_wrap;
        src_p2 += 2*src_wrap;
    }
    /* do last line */
    deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
937
    av_free(buf);
938 939
}

940
int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
941
                          enum PixelFormat pix_fmt, int width, int height)
Fabrice Bellard's avatar
Fabrice Bellard committed
942
{
943 944 945
    int i;

    if (pix_fmt != PIX_FMT_YUV420P &&
946
        pix_fmt != PIX_FMT_YUVJ420P &&
947
        pix_fmt != PIX_FMT_YUV422P &&
948
        pix_fmt != PIX_FMT_YUVJ422P &&
949
        pix_fmt != PIX_FMT_YUV444P &&
950 951
        pix_fmt != PIX_FMT_YUV411P &&
        pix_fmt != PIX_FMT_GRAY8)
952
        return -1;
Fred's avatar
Fred committed
953
    if ((width & 3) != 0 || (height & 3) != 0)
954
        return -1;
Fred's avatar
Fred committed
955

956 957 958
    for(i=0;i<3;i++) {
        if (i == 1) {
            switch(pix_fmt) {
959
            case PIX_FMT_YUVJ420P:
960 961 962 963 964
            case PIX_FMT_YUV420P:
                width >>= 1;
                height >>= 1;
                break;
            case PIX_FMT_YUV422P:
965
            case PIX_FMT_YUVJ422P:
966 967
                width >>= 1;
                break;
968 969 970
            case PIX_FMT_YUV411P:
                width >>= 2;
                break;
971 972 973
            default:
                break;
            }
974 975 976
            if (pix_fmt == PIX_FMT_GRAY8) {
                break;
            }
977
        }
Fred's avatar
Fred committed
978
        if (src == dst) {
979
            deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
980
                                 width, height);
Fred's avatar
Fred committed
981 982 983 984 985
        } else {
            deinterlace_bottom_field(dst->data[i],dst->linesize[i],
                                        src->data[i], src->linesize[i],
                                        width, height);
        }
Fabrice Bellard's avatar
Fabrice Bellard committed
986
    }
987
    emms_c();
988
    return 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
989
}