imgconvert.c 30.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
 * This file is part of Libav.
6
 *
7
 * Libav 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
 * Libav 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 Libav; 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/pixdesc.h"
39
#include "libavutil/imgutils.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
40

41
#if HAVE_MMX && HAVE_YASM
42
#include "x86/dsputil_mmx.h"
Fred's avatar
Fred committed
43
#endif
44

45 46 47
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)

48 49 50 51
#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 */
52

53 54 55
#define FF_PIXEL_PLANAR   0 /**< each channel has one component in AVPicture */
#define FF_PIXEL_PACKED   1 /**< only one components containing all the channels */
#define FF_PIXEL_PALETTE  2  /**< one components containing indexes for a palette */
56

57
#if HAVE_MMX && HAVE_YASM
58 59 60 61 62 63 64
#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

65
typedef struct PixFmtInfo {
66 67 68 69 70
    uint8_t nb_channels;     /**< number of channels (including alpha) */
    uint8_t color_type;      /**< color type (see FF_COLOR_xxx constants) */
    uint8_t pixel_type;      /**< pixel storage type (see FF_PIXEL_xxx constants) */
    uint8_t is_alpha : 1;    /**< true if alpha can be specified */
    uint8_t depth;           /**< bit depth of the color components */
71 72 73
} PixFmtInfo;

/* this table gives more information about formats */
74
static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
75 76
    /* YUV formats */
    [PIX_FMT_YUV420P] = {
77
        .nb_channels = 3,
78
        .color_type = FF_COLOR_YUV,
79
        .pixel_type = FF_PIXEL_PLANAR,
80
        .depth = 8,
81 82
    },
    [PIX_FMT_YUV422P] = {
83
        .nb_channels = 3,
84
        .color_type = FF_COLOR_YUV,
85
        .pixel_type = FF_PIXEL_PLANAR,
86
        .depth = 8,
87 88
    },
    [PIX_FMT_YUV444P] = {
89
        .nb_channels = 3,
90
        .color_type = FF_COLOR_YUV,
91
        .pixel_type = FF_PIXEL_PLANAR,
92
        .depth = 8,
93
    },
94
    [PIX_FMT_YUYV422] = {
95
        .nb_channels = 1,
96
        .color_type = FF_COLOR_YUV,
97
        .pixel_type = FF_PIXEL_PACKED,
98
        .depth = 8,
99
    },
100 101 102 103 104 105
    [PIX_FMT_UYVY422] = {
        .nb_channels = 1,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
106
    [PIX_FMT_YUV410P] = {
107
        .nb_channels = 3,
108
        .color_type = FF_COLOR_YUV,
109
        .pixel_type = FF_PIXEL_PLANAR,
110
        .depth = 8,
111 112
    },
    [PIX_FMT_YUV411P] = {
113
        .nb_channels = 3,
114
        .color_type = FF_COLOR_YUV,
115
        .pixel_type = FF_PIXEL_PLANAR,
116
        .depth = 8,
117
    },
118 119 120 121 122 123
    [PIX_FMT_YUV440P] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
    },
124
    [PIX_FMT_YUV420P16LE] = {
125 126 127 128 129
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
130
    [PIX_FMT_YUV422P16LE] = {
131 132 133 134 135
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
136
    [PIX_FMT_YUV444P16LE] = {
137 138 139 140 141
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
142
    [PIX_FMT_YUV420P16BE] = {
143 144 145 146 147
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
148
    [PIX_FMT_YUV422P16BE] = {
149 150 151 152 153
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
154
    [PIX_FMT_YUV444P16BE] = {
155 156 157 158 159 160
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },

161

162 163 164 165 166 167 168 169
    /* YUV formats with alpha plane */
    [PIX_FMT_YUVA420P] = {
        .nb_channels = 4,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
    },

170 171
    /* JPEG YUV */
    [PIX_FMT_YUVJ420P] = {
172
        .nb_channels = 3,
173
        .color_type = FF_COLOR_YUV_JPEG,
174
        .pixel_type = FF_PIXEL_PLANAR,
175 176 177
        .depth = 8,
    },
    [PIX_FMT_YUVJ422P] = {
178
        .nb_channels = 3,
179
        .color_type = FF_COLOR_YUV_JPEG,
180
        .pixel_type = FF_PIXEL_PLANAR,
181 182 183
        .depth = 8,
    },
    [PIX_FMT_YUVJ444P] = {
184
        .nb_channels = 3,
185
        .color_type = FF_COLOR_YUV_JPEG,
186
        .pixel_type = FF_PIXEL_PLANAR,
187 188
        .depth = 8,
    },
189 190 191 192 193 194
    [PIX_FMT_YUVJ440P] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV_JPEG,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
    },
195

196 197
    /* RGB formats */
    [PIX_FMT_RGB24] = {
198
        .nb_channels = 3,
199
        .color_type = FF_COLOR_RGB,
200
        .pixel_type = FF_PIXEL_PACKED,
201
        .depth = 8,
202 203
    },
    [PIX_FMT_BGR24] = {
204
        .nb_channels = 3,
205
        .color_type = FF_COLOR_RGB,
206
        .pixel_type = FF_PIXEL_PACKED,
207
        .depth = 8,
208
    },
209
    [PIX_FMT_ARGB] = {
210
        .nb_channels = 4, .is_alpha = 1,
211
        .color_type = FF_COLOR_RGB,
212
        .pixel_type = FF_PIXEL_PACKED,
213
        .depth = 8,
214
    },
215 216 217 218 219 220 221 222 223 224 225 226
    [PIX_FMT_RGB48BE] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 16,
    },
    [PIX_FMT_RGB48LE] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 16,
    },
227
    [PIX_FMT_RGB565BE] = {
228
        .nb_channels = 3,
229
        .color_type = FF_COLOR_RGB,
230
        .pixel_type = FF_PIXEL_PACKED,
231
        .depth = 5,
232
    },
233 234 235 236 237 238 239 240 241 242 243 244 245
    [PIX_FMT_RGB565LE] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
    [PIX_FMT_RGB555BE] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
    [PIX_FMT_RGB555LE] = {
246
        .nb_channels = 3,
247
        .color_type = FF_COLOR_RGB,
248
        .pixel_type = FF_PIXEL_PACKED,
249
        .depth = 5,
250
    },
251 252 253 254 255 256 257 258 259 260 261 262
    [PIX_FMT_RGB444BE] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
    [PIX_FMT_RGB444LE] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
263 264

    /* gray / mono formats */
265 266 267 268 269 270 271 272 273 274 275 276
    [PIX_FMT_GRAY16BE] = {
        .nb_channels = 1,
        .color_type = FF_COLOR_GRAY,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
    [PIX_FMT_GRAY16LE] = {
        .nb_channels = 1,
        .color_type = FF_COLOR_GRAY,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
277
    [PIX_FMT_GRAY8] = {
278
        .nb_channels = 1,
279
        .color_type = FF_COLOR_GRAY,
280
        .pixel_type = FF_PIXEL_PLANAR,
281
        .depth = 8,
282 283
    },
    [PIX_FMT_MONOWHITE] = {
284
        .nb_channels = 1,
285
        .color_type = FF_COLOR_GRAY,
286
        .pixel_type = FF_PIXEL_PLANAR,
287
        .depth = 1,
288 289
    },
    [PIX_FMT_MONOBLACK] = {
290
        .nb_channels = 1,
291
        .color_type = FF_COLOR_GRAY,
292
        .pixel_type = FF_PIXEL_PLANAR,
293
        .depth = 1,
294
    },
295 296 297

    /* paletted formats */
    [PIX_FMT_PAL8] = {
298
        .nb_channels = 4, .is_alpha = 1,
299
        .color_type = FF_COLOR_RGB,
300
        .pixel_type = FF_PIXEL_PALETTE,
301
        .depth = 8,
302
    },
303
    [PIX_FMT_UYYVYY411] = {
304 305 306 307 308
        .nb_channels = 1,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
309
    [PIX_FMT_ABGR] = {
310 311 312 313 314
        .nb_channels = 4, .is_alpha = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
315 316 317 318 319 320 321 322 323 324 325 326 327
    [PIX_FMT_BGR565BE] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
    [PIX_FMT_BGR565LE] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
    [PIX_FMT_BGR555BE] = {
328 329 330 331 332
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
333
    [PIX_FMT_BGR555LE] = {
334
        .nb_channels = 3,
335 336 337 338
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
339 340 341 342 343 344 345 346 347 348 349 350
    [PIX_FMT_BGR444BE] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
    [PIX_FMT_BGR444LE] = {
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
351 352 353 354 355 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 390 391 392 393 394 395 396 397 398 399
    [PIX_FMT_RGB8] = {
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
    [PIX_FMT_RGB4] = {
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
    [PIX_FMT_RGB4_BYTE] = {
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
    [PIX_FMT_BGR8] = {
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
    [PIX_FMT_BGR4] = {
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
    [PIX_FMT_BGR4_BYTE] = {
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
    [PIX_FMT_NV12] = {
        .nb_channels = 2,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
    },
    [PIX_FMT_NV21] = {
        .nb_channels = 2,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
    },

400
    [PIX_FMT_BGRA] = {
401 402 403 404 405
        .nb_channels = 4, .is_alpha = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
406
    [PIX_FMT_RGBA] = {
407 408 409 410 411
        .nb_channels = 4, .is_alpha = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
412 413
};

414
void avcodec_get_chroma_sub_sample(enum PixelFormat pix_fmt, int *h_shift, int *v_shift)
415
{
416 417
    *h_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
    *v_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
418 419
}

420
#if FF_API_GET_PIX_FMT_NAME
421
const char *avcodec_get_pix_fmt_name(enum PixelFormat pix_fmt)
422
{
423
    return av_get_pix_fmt_name(pix_fmt);
424
}
425
#endif
426

427 428
int ff_is_hwaccel_pix_fmt(enum PixelFormat pix_fmt)
{
429
    return av_pix_fmt_descriptors[pix_fmt].flags & PIX_FMT_HWACCEL;
430 431
}

432
int avpicture_fill(AVPicture *picture, uint8_t *ptr,
433
                   enum PixelFormat pix_fmt, int width, int height)
434
{
435
    int ret;
436

437 438
    if ((ret = av_image_check_size(width, height, 0, NULL)) < 0)
        return ret;
439

440 441
    if ((ret = av_image_fill_linesizes(picture->linesize, pix_fmt, width)) < 0)
        return ret;
442

443
    return av_image_fill_pointers(picture->data, pix_fmt, height, ptr, picture->linesize);
444 445
}

446
int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, int height,
447 448
                     unsigned char *dest, int dest_size)
{
449
    int i, j, nb_planes = 0, linesizes[4];
450
    const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
451 452
    int size = avpicture_get_size(pix_fmt, width, height);

453
    if (size > dest_size || size < 0)
454
        return AVERROR(EINVAL);
455

456 457 458 459 460 461
    for (i = 0; i < desc->nb_components; i++)
        nb_planes = FFMAX(desc->comp[i].plane, nb_planes);
    nb_planes++;

    av_image_fill_linesizes(linesizes, pix_fmt, width);
    for (i = 0; i < nb_planes; i++) {
462 463 464
        int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
        const unsigned char *s = src->data[i];
        h = (height + (1 << shift) - 1) >> shift;
465

466 467 468
        for (j = 0; j < h; j++) {
            memcpy(dest, s, linesizes[i]);
            dest += linesizes[i];
Ramiro Polla's avatar
Ramiro Polla committed
469 470
            s += src->linesize[i];
        }
471
    }
472

473
    if (desc->flags & PIX_FMT_PAL)
474
        memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
475

476 477 478
    return size;
}

479
int avpicture_get_size(enum PixelFormat pix_fmt, int width, int height)
480 481
{
    AVPicture dummy_pict;
482
    if(av_image_check_size(width, height, 0, NULL))
483 484 485 486 487 488 489 490 491 492
        return -1;
    switch (pix_fmt) {
    case PIX_FMT_RGB8:
    case PIX_FMT_BGR8:
    case PIX_FMT_RGB4_BYTE:
    case PIX_FMT_BGR4_BYTE:
    case PIX_FMT_GRAY8:
        // do not include palette for these pseudo-paletted formats
        return width * height;
    }
493 494 495
    return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
}

496
int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt,
497 498 499
                             int has_alpha)
{
    const PixFmtInfo *pf, *ps;
500 501
    const AVPixFmtDescriptor *src_desc = &av_pix_fmt_descriptors[src_pix_fmt];
    const AVPixFmtDescriptor *dst_desc = &av_pix_fmt_descriptors[dst_pix_fmt];
502 503 504 505 506 507 508
    int loss;

    ps = &pix_fmt_info[src_pix_fmt];

    /* compute loss */
    loss = 0;
    pf = &pix_fmt_info[dst_pix_fmt];
509
    if (pf->depth < ps->depth ||
510 511 512 513
        ((dst_pix_fmt == PIX_FMT_RGB555BE || dst_pix_fmt == PIX_FMT_RGB555LE ||
          dst_pix_fmt == PIX_FMT_BGR555BE || dst_pix_fmt == PIX_FMT_BGR555LE) &&
         (src_pix_fmt == PIX_FMT_RGB565BE || src_pix_fmt == PIX_FMT_RGB565LE ||
          src_pix_fmt == PIX_FMT_BGR565BE || src_pix_fmt == PIX_FMT_BGR565LE)))
514
        loss |= FF_LOSS_DEPTH;
515 516
    if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w ||
        dst_desc->log2_chroma_h > src_desc->log2_chroma_h)
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
        loss |= FF_LOSS_RESOLUTION;
    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 &&
534
            ps->color_type != FF_COLOR_YUV &&
535
            ps->color_type != FF_COLOR_GRAY)
536 537 538 539 540 541 542 543 544 545 546 547 548
            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;
    if (!pf->is_alpha && (ps->is_alpha && has_alpha))
        loss |= FF_LOSS_ALPHA;
549
    if (pf->pixel_type == FF_PIXEL_PALETTE &&
550
        (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
551 552 553 554
        loss |= FF_LOSS_COLORQUANT;
    return loss;
}

555
static int avg_bits_per_pixel(enum PixelFormat pix_fmt)
556 557 558
{
    int bits;
    const PixFmtInfo *pf;
559
    const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
560 561

    pf = &pix_fmt_info[pix_fmt];
562 563
    switch(pf->pixel_type) {
    case FF_PIXEL_PACKED:
564
        switch(pix_fmt) {
565
        case PIX_FMT_YUYV422:
566
        case PIX_FMT_UYVY422:
567 568 569 570
        case PIX_FMT_RGB565BE:
        case PIX_FMT_RGB565LE:
        case PIX_FMT_RGB555BE:
        case PIX_FMT_RGB555LE:
571 572
        case PIX_FMT_RGB444BE:
        case PIX_FMT_RGB444LE:
573 574 575 576
        case PIX_FMT_BGR565BE:
        case PIX_FMT_BGR565LE:
        case PIX_FMT_BGR555BE:
        case PIX_FMT_BGR555LE:
577 578
        case PIX_FMT_BGR444BE:
        case PIX_FMT_BGR444LE:
579 580
            bits = 16;
            break;
581
        case PIX_FMT_UYYVYY411:
582 583
            bits = 12;
            break;
584
        default:
585
            bits = pf->depth * pf->nb_channels;
586 587
            break;
        }
588 589
        break;
    case FF_PIXEL_PLANAR:
590
        if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) {
591 592
            bits = pf->depth * pf->nb_channels;
        } else {
593
            bits = pf->depth + ((2 * pf->depth) >>
594
                                (desc->log2_chroma_w + desc->log2_chroma_h));
595 596 597 598 599 600 601 602
        }
        break;
    case FF_PIXEL_PALETTE:
        bits = 8;
        break;
    default:
        bits = -1;
        break;
603 604 605 606
    }
    return bits;
}

607 608
static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask,
                                      enum PixelFormat src_pix_fmt,
609 610 611
                                      int has_alpha,
                                      int loss_mask)
{
612 613
    int dist, i, loss, min_dist;
    enum PixelFormat dst_pix_fmt;
614 615

    /* find exact color match with smallest size */
616
    dst_pix_fmt = PIX_FMT_NONE;
617 618
    min_dist = 0x7fffffff;
    for(i = 0;i < PIX_FMT_NB; i++) {
619
        if (pix_fmt_mask & (1ULL << i)) {
620 621 622 623 624 625 626 627 628 629 630 631 632
            loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
            if (loss == 0) {
                dist = avg_bits_per_pixel(i);
                if (dist < min_dist) {
                    min_dist = dist;
                    dst_pix_fmt = i;
                }
            }
        }
    }
    return dst_pix_fmt;
}

633
enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt,
634 635
                              int has_alpha, int *loss_ptr)
{
636 637
    enum PixelFormat dst_pix_fmt;
    int loss_mask, i;
638 639 640 641 642 643 644 645 646 647 648 649 650 651
    static const int loss_mask_order[] = {
        ~0, /* no loss first */
        ~FF_LOSS_ALPHA,
        ~FF_LOSS_RESOLUTION,
        ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
        ~FF_LOSS_COLORQUANT,
        ~FF_LOSS_DEPTH,
        0,
    };

    /* try with successive loss */
    i = 0;
    for(;;) {
        loss_mask = loss_mask_order[i++];
652
        dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
653 654 655 656 657 658
                                                 has_alpha, loss_mask);
        if (dst_pix_fmt >= 0)
            goto found;
        if (loss_mask == 0)
            break;
    }
659
    return PIX_FMT_NONE;
660 661 662 663 664 665
 found:
    if (loss_ptr)
        *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
    return dst_pix_fmt;
}

666 667 668
void av_picture_copy(AVPicture *dst, const AVPicture *src,
                     enum PixelFormat pix_fmt, int width, int height)
{
669
    av_image_copy(dst->data, dst->linesize, src->data,
Stefano Sabatini's avatar
Stefano Sabatini committed
670
                  src->linesize, pix_fmt, width, height);
671 672
}

673
/* 2x2 -> 1x1 */
674
void ff_shrink22(uint8_t *dst, int dst_wrap,
675
                     const uint8_t *src, int src_wrap,
676 677 678
                     int width, int height)
{
    int w;
679 680
    const uint8_t *s1, *s2;
    uint8_t *d;
681 682 683 684 685 686

    for(;height > 0; height--) {
        s1 = src;
        s2 = s1 + src_wrap;
        d = dst;
        for(w = width;w >= 4; w-=4) {
687 688 689 690
            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;
691 692 693 694 695
            s1 += 8;
            s2 += 8;
            d += 4;
        }
        for(;w > 0; w--) {
696
            d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
697 698 699 700 701 702 703 704 705
            s1 += 2;
            s2 += 2;
            d++;
        }
        src += 2 * src_wrap;
        dst += dst_wrap;
    }
}

706
/* 4x4 -> 1x1 */
707
void ff_shrink44(uint8_t *dst, int dst_wrap,
708
                     const uint8_t *src, int src_wrap,
709 710 711
                     int width, int height)
{
    int w;
712 713
    const uint8_t *s1, *s2, *s3, *s4;
    uint8_t *d;
714 715 716

    for(;height > 0; height--) {
        s1 = src;
717 718 719
        s2 = s1 + src_wrap;
        s3 = s2 + src_wrap;
        s4 = s3 + src_wrap;
720
        d = dst;
721 722 723 724 725 726 727 728 729
        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;
730 731
            d++;
        }
732 733 734 735 736
        src += 4 * src_wrap;
        dst += dst_wrap;
    }
}

737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
/* 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;
    }
}

759

Drew Hess's avatar
Drew Hess committed
760
int avpicture_alloc(AVPicture *picture,
761
                    enum PixelFormat pix_fmt, int width, int height)
762
{
763 764
    int ret;

765
    if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
Stefano Sabatini's avatar
Stefano Sabatini committed
766
        memset(picture, 0, sizeof(AVPicture));
767
        return ret;
768 769 770
    }

    return 0;
771 772
}

Drew Hess's avatar
Drew Hess committed
773
void avpicture_free(AVPicture *picture)
774
{
775
    av_free(picture->data[0]);
776 777
}

778
/* return true if yuv planar */
779
static inline int is_yuv_planar(const PixFmtInfo *ps)
780 781
{
    return (ps->color_type == FF_COLOR_YUV ||
782
            ps->color_type == FF_COLOR_YUV_JPEG) &&
783
        ps->pixel_type == FF_PIXEL_PLANAR;
784 785
}

786
int av_picture_crop(AVPicture *dst, const AVPicture *src,
787
                    enum PixelFormat pix_fmt, int top_band, int left_band)
788 789 790 791 792 793 794
{
    int y_shift;
    int x_shift;

    if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt]))
        return -1;

795 796
    y_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
    x_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
797 798 799 800 801 802 803 804 805 806 807

    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);

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

808
int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
809
                   enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
Luca Barbato's avatar
Luca Barbato committed
810
            int *color)
811
{
812
    uint8_t *optr;
813 814 815 816 817
    int y_shift;
    int x_shift;
    int yheight;
    int i, y;

Luca Barbato's avatar
Luca Barbato committed
818 819
    if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
        !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1;
820 821

    for (i = 0; i < 3; i++) {
822 823
        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;
824 825

        if (padtop || padleft) {
Luca Barbato's avatar
Luca Barbato committed
826 827
            memset(dst->data[i], color[i],
                dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
828 829
        }

830 831 832 833 834 835 836
        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];
837
            }
838 839 840 841 842 843
        }

        if (src) { /* first line */
            uint8_t *iptr = src->data[i];
            optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
                    (padleft >> x_shift);
844
            memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
845
            iptr += src->linesize[i];
Luca Barbato's avatar
Luca Barbato committed
846 847
            optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
                (dst->linesize[i] - (padright >> x_shift));
848 849 850
            yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
            for (y = 0; y < yheight; y++) {
                memset(optr, color[i], (padleft + padright) >> x_shift);
851
                memcpy(optr + ((padleft + padright) >> x_shift), iptr,
852
                       (width - padleft - padright) >> x_shift);
853
                iptr += src->linesize[i];
854 855 856 857 858
                optr += dst->linesize[i];
            }
        }

        if (padbottom || padright) {
Luca Barbato's avatar
Luca Barbato committed
859 860 861 862
            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));
863 864 865 866 867
        }
    }
    return 0;
}

868
/* NOTE: we scan all the pixels to have an exact information */
869
static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
870 871 872 873 874
{
    const unsigned char *p;
    int src_wrap, ret, x, y;
    unsigned int a;
    uint32_t *palette = (uint32_t *)src->data[1];
875

876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
    p = src->data[0];
    src_wrap = src->linesize[0] - width;
    ret = 0;
    for(y=0;y<height;y++) {
        for(x=0;x<width;x++) {
            a = palette[p[0]] >> 24;
            if (a == 0x00) {
                ret |= FF_ALPHA_TRANSP;
            } else if (a != 0xff) {
                ret |= FF_ALPHA_SEMI_TRANSP;
            }
            p++;
        }
        p += src_wrap;
    }
    return ret;
}

894
int img_get_alpha_info(const AVPicture *src,
895
                       enum PixelFormat pix_fmt, int width, int height)
896
{
897
    const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
    int ret;

    /* no alpha can be represented in format */
    if (!pf->is_alpha)
        return 0;
    switch(pix_fmt) {
    case PIX_FMT_PAL8:
        ret = get_alpha_info_pal8(src, width, height);
        break;
    default:
        /* we do not know, so everything is indicated */
        ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
        break;
    }
    return ret;
}
Fred's avatar
Fred committed
914

915
#if !(HAVE_MMX && HAVE_YASM)
916
/* filter parameters: [-1 4 2 4 -1] // 8 */
917
static void deinterlace_line_c(uint8_t *dst,
918 919 920 921
                             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)
922
{
923
    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
924 925 926
    int sum;

    for(;size > 0;size--) {
Fred's avatar
Fred committed
927 928 929 930 931
        sum = -lum_m4[0];
        sum += lum_m3[0] << 2;
        sum += lum_m2[0] << 1;
        sum += lum_m1[0] << 2;
        sum += -lum[0];
932
        dst[0] = cm[(sum + 4) >> 3];
Fred's avatar
Fred committed
933 934 935 936 937
        lum_m4++;
        lum_m3++;
        lum_m2++;
        lum_m1++;
        lum++;
938 939
        dst++;
    }
Fred's avatar
Fred committed
940
}
941 942 943 944

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
945
{
946
    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
Fred's avatar
Fred committed
947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
    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++;
    }
963
}
964
#endif
965 966 967 968

/* 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. */
969
static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
970
                                    const uint8_t *src1, int src_wrap,
Fred's avatar
Fred committed
971
                                    int width, int height)
972
{
973
    const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
Fred's avatar
Fred committed
974 975 976 977 978 979 980 981 982
    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);
983
        dst += dst_wrap;
Fred's avatar
Fred committed
984 985 986 987 988 989
        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;
990 991
        dst += dst_wrap;
    }
Fred's avatar
Fred committed
992 993 994 995 996 997
    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);
}

998
static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
999
                                             int width, int height)
Fred's avatar
Fred committed
1000
{
1001
    uint8_t *src_m1, *src_0, *src_p1, *src_p2;
Fred's avatar
Fred committed
1002
    int y;
1003 1004
    uint8_t *buf;
    buf = (uint8_t*)av_malloc(width);
Fred's avatar
Fred committed
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019

    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);
1020
    av_free(buf);
1021 1022
}

1023
int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
1024
                          enum PixelFormat pix_fmt, int width, int height)
Fabrice Bellard's avatar
Fabrice Bellard committed
1025
{
1026 1027 1028
    int i;

    if (pix_fmt != PIX_FMT_YUV420P &&
1029
        pix_fmt != PIX_FMT_YUVJ420P &&
1030
        pix_fmt != PIX_FMT_YUV422P &&
1031
        pix_fmt != PIX_FMT_YUVJ422P &&
1032
        pix_fmt != PIX_FMT_YUV444P &&
1033 1034
        pix_fmt != PIX_FMT_YUV411P &&
        pix_fmt != PIX_FMT_GRAY8)
1035
        return -1;
Fred's avatar
Fred committed
1036
    if ((width & 3) != 0 || (height & 3) != 0)
1037
        return -1;
Fred's avatar
Fred committed
1038

1039 1040 1041
    for(i=0;i<3;i++) {
        if (i == 1) {
            switch(pix_fmt) {
1042
            case PIX_FMT_YUVJ420P:
1043 1044 1045 1046 1047
            case PIX_FMT_YUV420P:
                width >>= 1;
                height >>= 1;
                break;
            case PIX_FMT_YUV422P:
1048
            case PIX_FMT_YUVJ422P:
1049 1050
                width >>= 1;
                break;
1051 1052 1053
            case PIX_FMT_YUV411P:
                width >>= 2;
                break;
1054 1055 1056
            default:
                break;
            }
1057 1058 1059
            if (pix_fmt == PIX_FMT_GRAY8) {
                break;
            }
1060
        }
Fred's avatar
Fred committed
1061
        if (src == dst) {
1062
            deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
1063
                                 width, height);
Fred's avatar
Fred committed
1064 1065 1066 1067 1068
        } 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
1069
    }
1070
    emms_c();
1071
    return 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
1072
}
1073