imgconvert.c 30.5 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
Fabrice Bellard's avatar
Fabrice Bellard committed
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
Fabrice Bellard's avatar
Fabrice Bellard committed
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
 *
Fabrice Bellard's avatar
Fabrice Bellard committed
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
#include "internal.h"
36
#include "libavutil/colorspace.h"
37
#include "libavutil/common.h"
38
#include "libavutil/pixdesc.h"
39
#include "libavutil/imgutils.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
40

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

45 46 47 48
#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 */
49

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

54
#if HAVE_MMX_EXTERNAL
55 56 57 58 59 60 61
#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

62
typedef struct PixFmtInfo {
63 64 65 66 67
    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 */
68 69 70
} PixFmtInfo;

/* this table gives more information about formats */
71
static const PixFmtInfo pix_fmt_info[AV_PIX_FMT_NB] = {
72
    /* YUV formats */
73
    [AV_PIX_FMT_YUV420P] = {
74
        .nb_channels = 3,
75
        .color_type = FF_COLOR_YUV,
76
        .pixel_type = FF_PIXEL_PLANAR,
77
        .depth = 8,
78
    },
79
    [AV_PIX_FMT_YUV422P] = {
80
        .nb_channels = 3,
81
        .color_type = FF_COLOR_YUV,
82
        .pixel_type = FF_PIXEL_PLANAR,
83
        .depth = 8,
84
    },
85
    [AV_PIX_FMT_YUV444P] = {
86
        .nb_channels = 3,
87
        .color_type = FF_COLOR_YUV,
88
        .pixel_type = FF_PIXEL_PLANAR,
89
        .depth = 8,
90
    },
91
    [AV_PIX_FMT_YUYV422] = {
92
        .nb_channels = 1,
93
        .color_type = FF_COLOR_YUV,
94
        .pixel_type = FF_PIXEL_PACKED,
95
        .depth = 8,
96
    },
97
    [AV_PIX_FMT_UYVY422] = {
98 99 100 101 102
        .nb_channels = 1,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
103
    [AV_PIX_FMT_YUV410P] = {
104
        .nb_channels = 3,
105
        .color_type = FF_COLOR_YUV,
106
        .pixel_type = FF_PIXEL_PLANAR,
107
        .depth = 8,
108
    },
109
    [AV_PIX_FMT_YUV411P] = {
110
        .nb_channels = 3,
111
        .color_type = FF_COLOR_YUV,
112
        .pixel_type = FF_PIXEL_PLANAR,
113
        .depth = 8,
114
    },
115
    [AV_PIX_FMT_YUV440P] = {
116 117 118 119 120
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
    },
121
    [AV_PIX_FMT_YUV420P16LE] = {
122 123 124 125 126
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
127
    [AV_PIX_FMT_YUV422P16LE] = {
128 129 130 131 132
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
133
    [AV_PIX_FMT_YUV444P16LE] = {
134 135 136 137 138
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
139
    [AV_PIX_FMT_YUV420P16BE] = {
140 141 142 143 144
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
145
    [AV_PIX_FMT_YUV422P16BE] = {
146 147 148 149 150
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
151
    [AV_PIX_FMT_YUV444P16BE] = {
152 153 154 155 156 157
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },

158

159
    /* YUV formats with alpha plane */
160
    [AV_PIX_FMT_YUVA420P] = {
161 162 163 164 165 166
        .nb_channels = 4,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
    },

167
    /* JPEG YUV */
168
    [AV_PIX_FMT_YUVJ420P] = {
169
        .nb_channels = 3,
170
        .color_type = FF_COLOR_YUV_JPEG,
171
        .pixel_type = FF_PIXEL_PLANAR,
172 173
        .depth = 8,
    },
174
    [AV_PIX_FMT_YUVJ422P] = {
175
        .nb_channels = 3,
176
        .color_type = FF_COLOR_YUV_JPEG,
177
        .pixel_type = FF_PIXEL_PLANAR,
178 179
        .depth = 8,
    },
180
    [AV_PIX_FMT_YUVJ444P] = {
181
        .nb_channels = 3,
182
        .color_type = FF_COLOR_YUV_JPEG,
183
        .pixel_type = FF_PIXEL_PLANAR,
184 185
        .depth = 8,
    },
186
    [AV_PIX_FMT_YUVJ440P] = {
187 188 189 190 191
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV_JPEG,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
    },
192

193
    /* RGB formats */
194
    [AV_PIX_FMT_RGB24] = {
195
        .nb_channels = 3,
196
        .color_type = FF_COLOR_RGB,
197
        .pixel_type = FF_PIXEL_PACKED,
198
        .depth = 8,
199
    },
200
    [AV_PIX_FMT_BGR24] = {
201
        .nb_channels = 3,
202
        .color_type = FF_COLOR_RGB,
203
        .pixel_type = FF_PIXEL_PACKED,
204
        .depth = 8,
205
    },
206
    [AV_PIX_FMT_ARGB] = {
207
        .nb_channels = 4, .is_alpha = 1,
208
        .color_type = FF_COLOR_RGB,
209
        .pixel_type = FF_PIXEL_PACKED,
210
        .depth = 8,
211
    },
212
    [AV_PIX_FMT_RGB48BE] = {
213 214 215 216 217
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 16,
    },
218
    [AV_PIX_FMT_RGB48LE] = {
219 220 221 222 223
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 16,
    },
224
    [AV_PIX_FMT_RGB565BE] = {
225
        .nb_channels = 3,
226
        .color_type = FF_COLOR_RGB,
227
        .pixel_type = FF_PIXEL_PACKED,
228
        .depth = 5,
229
    },
230
    [AV_PIX_FMT_RGB565LE] = {
231 232 233 234 235
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
236
    [AV_PIX_FMT_RGB555BE] = {
237 238 239 240 241
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
242
    [AV_PIX_FMT_RGB555LE] = {
243
        .nb_channels = 3,
244
        .color_type = FF_COLOR_RGB,
245
        .pixel_type = FF_PIXEL_PACKED,
246
        .depth = 5,
247
    },
248
    [AV_PIX_FMT_RGB444BE] = {
249 250 251 252 253
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
254
    [AV_PIX_FMT_RGB444LE] = {
255 256 257 258 259
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
260 261

    /* gray / mono formats */
262
    [AV_PIX_FMT_GRAY16BE] = {
Kostya Shishkov's avatar
Kostya Shishkov committed
263 264 265 266 267
        .nb_channels = 1,
        .color_type = FF_COLOR_GRAY,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
268
    [AV_PIX_FMT_GRAY16LE] = {
Kostya Shishkov's avatar
Kostya Shishkov committed
269 270 271 272 273
        .nb_channels = 1,
        .color_type = FF_COLOR_GRAY,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
274
    [AV_PIX_FMT_GRAY8] = {
275
        .nb_channels = 1,
276
        .color_type = FF_COLOR_GRAY,
277
        .pixel_type = FF_PIXEL_PLANAR,
278
        .depth = 8,
279
    },
280
    [AV_PIX_FMT_MONOWHITE] = {
281
        .nb_channels = 1,
282
        .color_type = FF_COLOR_GRAY,
283
        .pixel_type = FF_PIXEL_PLANAR,
284
        .depth = 1,
285
    },
286
    [AV_PIX_FMT_MONOBLACK] = {
287
        .nb_channels = 1,
288
        .color_type = FF_COLOR_GRAY,
289
        .pixel_type = FF_PIXEL_PLANAR,
290
        .depth = 1,
291
    },
292 293

    /* paletted formats */
294
    [AV_PIX_FMT_PAL8] = {
295
        .nb_channels = 4, .is_alpha = 1,
296
        .color_type = FF_COLOR_RGB,
297
        .pixel_type = FF_PIXEL_PALETTE,
298
        .depth = 8,
299
    },
300
    [AV_PIX_FMT_UYYVYY411] = {
301 302 303 304 305
        .nb_channels = 1,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
306
    [AV_PIX_FMT_ABGR] = {
307 308 309 310 311
        .nb_channels = 4, .is_alpha = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
312
    [AV_PIX_FMT_BGR565BE] = {
313 314 315 316 317
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
318
    [AV_PIX_FMT_BGR565LE] = {
319 320 321 322 323
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
324
    [AV_PIX_FMT_BGR555BE] = {
325 326 327 328 329
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
330
    [AV_PIX_FMT_BGR555LE] = {
331
        .nb_channels = 3,
332 333 334 335
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
    },
336
    [AV_PIX_FMT_BGR444BE] = {
337 338 339 340 341
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
342
    [AV_PIX_FMT_BGR444LE] = {
343 344 345 346 347
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
348
    [AV_PIX_FMT_RGB8] = {
349 350 351 352 353
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
354
    [AV_PIX_FMT_RGB4] = {
355 356 357 358 359
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
360
    [AV_PIX_FMT_RGB4_BYTE] = {
361 362 363 364 365
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
366
    [AV_PIX_FMT_BGR8] = {
367 368 369 370 371
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
372
    [AV_PIX_FMT_BGR4] = {
373 374 375 376 377
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
    },
378
    [AV_PIX_FMT_BGR4_BYTE] = {
379 380 381 382 383
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
384
    [AV_PIX_FMT_NV12] = {
385 386 387 388 389
        .nb_channels = 2,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
    },
390
    [AV_PIX_FMT_NV21] = {
391 392 393 394 395 396
        .nb_channels = 2,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
    },

397
    [AV_PIX_FMT_BGRA] = {
398 399 400 401 402
        .nb_channels = 4, .is_alpha = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
403
    [AV_PIX_FMT_RGBA] = {
404 405 406 407 408
        .nb_channels = 4, .is_alpha = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
    },
409 410
};

411
void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift)
412
{
413 414 415
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
    *h_shift = desc->log2_chroma_w;
    *v_shift = desc->log2_chroma_h;
416 417
}

418
int ff_is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt)
419
{
420 421
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
    return desc->flags & PIX_FMT_HWACCEL;
422 423
}

424
int avpicture_fill(AVPicture *picture, uint8_t *ptr,
425
                   enum AVPixelFormat pix_fmt, int width, int height)
426
{
427
    int ret;
428

429 430
    if ((ret = av_image_check_size(width, height, 0, NULL)) < 0)
        return ret;
431

432 433
    if ((ret = av_image_fill_linesizes(picture->linesize, pix_fmt, width)) < 0)
        return ret;
434

435
    return av_image_fill_pointers(picture->data, pix_fmt, height, ptr, picture->linesize);
436 437
}

438
int avpicture_layout(const AVPicture* src, enum AVPixelFormat pix_fmt, int width, int height,
439 440
                     unsigned char *dest, int dest_size)
{
441
    int i, j, nb_planes = 0, linesizes[4];
442
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
443 444
    int size = avpicture_get_size(pix_fmt, width, height);

445
    if (size > dest_size || size < 0)
446
        return AVERROR(EINVAL);
447

448 449 450 451 452 453
    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++) {
454 455 456
        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;
457

458 459 460
        for (j = 0; j < h; j++) {
            memcpy(dest, s, linesizes[i]);
            dest += linesizes[i];
Ramiro Polla's avatar
Indent  
Ramiro Polla committed
461 462
            s += src->linesize[i];
        }
463
    }
464

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

468 469 470
    return size;
}

471
int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height)
472 473
{
    AVPicture dummy_pict;
474 475
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);

476
    if(av_image_check_size(width, height, 0, NULL))
477
        return -1;
478
    if (desc->flags & PIX_FMT_PSEUDOPAL)
479 480
        // do not include palette for these pseudo-paletted formats
        return width * height;
481 482 483
    return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
}

484
int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt,
485 486 487
                             int has_alpha)
{
    const PixFmtInfo *pf, *ps;
488 489
    const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
    const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
490 491 492 493 494 495 496
    int loss;

    ps = &pix_fmt_info[src_pix_fmt];

    /* compute loss */
    loss = 0;
    pf = &pix_fmt_info[dst_pix_fmt];
497
    if (pf->depth < ps->depth ||
498 499 500 501
        ((dst_pix_fmt == AV_PIX_FMT_RGB555BE || dst_pix_fmt == AV_PIX_FMT_RGB555LE ||
          dst_pix_fmt == AV_PIX_FMT_BGR555BE || dst_pix_fmt == AV_PIX_FMT_BGR555LE) &&
         (src_pix_fmt == AV_PIX_FMT_RGB565BE || src_pix_fmt == AV_PIX_FMT_RGB565LE ||
          src_pix_fmt == AV_PIX_FMT_BGR565BE || src_pix_fmt == AV_PIX_FMT_BGR565LE)))
502
        loss |= FF_LOSS_DEPTH;
503 504
    if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w ||
        dst_desc->log2_chroma_h > src_desc->log2_chroma_h)
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
        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 &&
522
            ps->color_type != FF_COLOR_YUV &&
523
            ps->color_type != FF_COLOR_GRAY)
524 525 526 527 528 529 530 531 532 533 534 535 536
            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;
537
    if (pf->pixel_type == FF_PIXEL_PALETTE &&
538
        (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
539 540 541 542
        loss |= FF_LOSS_COLORQUANT;
    return loss;
}

543
static int avg_bits_per_pixel(enum AVPixelFormat pix_fmt)
544 545 546
{
    int bits;
    const PixFmtInfo *pf;
547
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
548 549

    pf = &pix_fmt_info[pix_fmt];
550 551
    switch(pf->pixel_type) {
    case FF_PIXEL_PACKED:
552
        switch(pix_fmt) {
553 554 555 556 557 558 559 560 561 562 563 564 565 566
        case AV_PIX_FMT_YUYV422:
        case AV_PIX_FMT_UYVY422:
        case AV_PIX_FMT_RGB565BE:
        case AV_PIX_FMT_RGB565LE:
        case AV_PIX_FMT_RGB555BE:
        case AV_PIX_FMT_RGB555LE:
        case AV_PIX_FMT_RGB444BE:
        case AV_PIX_FMT_RGB444LE:
        case AV_PIX_FMT_BGR565BE:
        case AV_PIX_FMT_BGR565LE:
        case AV_PIX_FMT_BGR555BE:
        case AV_PIX_FMT_BGR555LE:
        case AV_PIX_FMT_BGR444BE:
        case AV_PIX_FMT_BGR444LE:
567 568
            bits = 16;
            break;
569
        case AV_PIX_FMT_UYYVYY411:
570 571
            bits = 12;
            break;
572
        default:
573
            bits = pf->depth * pf->nb_channels;
574 575
            break;
        }
576 577
        break;
    case FF_PIXEL_PLANAR:
578
        if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) {
579 580
            bits = pf->depth * pf->nb_channels;
        } else {
581
            bits = pf->depth + ((2 * pf->depth) >>
582
                                (desc->log2_chroma_w + desc->log2_chroma_h));
583 584 585 586 587 588 589 590
        }
        break;
    case FF_PIXEL_PALETTE:
        bits = 8;
        break;
    default:
        bits = -1;
        break;
591 592 593 594
    }
    return bits;
}

595 596
static enum AVPixelFormat avcodec_find_best_pix_fmt1(enum AVPixelFormat *pix_fmt_list,
                                      enum AVPixelFormat src_pix_fmt,
597 598 599
                                      int has_alpha,
                                      int loss_mask)
{
600
    int dist, i, loss, min_dist;
601
    enum AVPixelFormat dst_pix_fmt;
602 603

    /* find exact color match with smallest size */
604
    dst_pix_fmt = AV_PIX_FMT_NONE;
605
    min_dist = 0x7fffffff;
606
    i = 0;
607 608
    while (pix_fmt_list[i] != AV_PIX_FMT_NONE) {
        enum AVPixelFormat pix_fmt = pix_fmt_list[i];
609

610
        if (i > AV_PIX_FMT_NB) {
611 612
            av_log(NULL, AV_LOG_ERROR, "Pixel format list longer than expected, "
                   "it is either not properly terminated or contains duplicates\n");
613
            return AV_PIX_FMT_NONE;
614 615 616 617 618 619 620 621
        }

        loss = avcodec_get_pix_fmt_loss(pix_fmt, src_pix_fmt, has_alpha) & loss_mask;
        if (loss == 0) {
            dist = avg_bits_per_pixel(pix_fmt);
            if (dist < min_dist) {
                min_dist = dist;
                dst_pix_fmt = pix_fmt;
622 623
            }
        }
624
        i++;
625 626 627 628
    }
    return dst_pix_fmt;
}

629
#if FF_API_FIND_BEST_PIX_FMT
630
enum AVPixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum AVPixelFormat src_pix_fmt,
631
                              int has_alpha, int *loss_ptr)
632
{
633
    enum AVPixelFormat list[64];
634 635 636 637 638 639 640
    int i, j = 0;

    // test only the first 64 pixel formats to avoid undefined behaviour
    for (i = 0; i < 64; i++) {
        if (pix_fmt_mask & (1ULL << i))
            list[j++] = i;
    }
641
    list[j] = AV_PIX_FMT_NONE;
642 643 644

    return avcodec_find_best_pix_fmt2(list, src_pix_fmt, has_alpha, loss_ptr);
}
645
#endif /* FF_API_FIND_BEST_PIX_FMT */
646

647 648
enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat *pix_fmt_list,
                                            enum AVPixelFormat src_pix_fmt,
649
                                            int has_alpha, int *loss_ptr)
650
{
651
    enum AVPixelFormat dst_pix_fmt;
652
    int loss_mask, i;
653 654 655 656 657 658 659 660 661 662 663 664 665 666
    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++];
667
        dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_list, src_pix_fmt,
668 669 670 671 672 673
                                                 has_alpha, loss_mask);
        if (dst_pix_fmt >= 0)
            goto found;
        if (loss_mask == 0)
            break;
    }
674
    return AV_PIX_FMT_NONE;
675 676 677 678 679 680
 found:
    if (loss_ptr)
        *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
    return dst_pix_fmt;
}

681
void av_picture_copy(AVPicture *dst, const AVPicture *src,
682
                     enum AVPixelFormat pix_fmt, int width, int height)
683
{
684
    av_image_copy(dst->data, dst->linesize, src->data,
Stefano Sabatini's avatar
Stefano Sabatini committed
685
                  src->linesize, pix_fmt, width, height);
686 687
}

688
/* 2x2 -> 1x1 */
689
void ff_shrink22(uint8_t *dst, int dst_wrap,
690
                     const uint8_t *src, int src_wrap,
691 692 693
                     int width, int height)
{
    int w;
694 695
    const uint8_t *s1, *s2;
    uint8_t *d;
696 697 698 699 700 701

    for(;height > 0; height--) {
        s1 = src;
        s2 = s1 + src_wrap;
        d = dst;
        for(w = width;w >= 4; w-=4) {
702 703 704 705
            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;
706 707 708 709 710
            s1 += 8;
            s2 += 8;
            d += 4;
        }
        for(;w > 0; w--) {
711
            d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
712 713 714 715 716 717 718 719 720
            s1 += 2;
            s2 += 2;
            d++;
        }
        src += 2 * src_wrap;
        dst += dst_wrap;
    }
}

721
/* 4x4 -> 1x1 */
722
void ff_shrink44(uint8_t *dst, int dst_wrap,
723
                     const uint8_t *src, int src_wrap,
724 725 726
                     int width, int height)
{
    int w;
727 728
    const uint8_t *s1, *s2, *s3, *s4;
    uint8_t *d;
729 730 731

    for(;height > 0; height--) {
        s1 = src;
732 733 734
        s2 = s1 + src_wrap;
        s3 = s2 + src_wrap;
        s4 = s3 + src_wrap;
735
        d = dst;
736 737 738 739 740 741 742 743 744
        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;
745 746
            d++;
        }
747 748 749 750 751
        src += 4 * src_wrap;
        dst += dst_wrap;
    }
}

752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
/* 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;
    }
}

774

Drew Hess's avatar
Drew Hess committed
775
int avpicture_alloc(AVPicture *picture,
776
                    enum AVPixelFormat pix_fmt, int width, int height)
777
{
778 779
    int ret;

780
    if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
Stefano Sabatini's avatar
Stefano Sabatini committed
781
        memset(picture, 0, sizeof(AVPicture));
782
        return ret;
783 784 785
    }

    return 0;
786 787
}

Drew Hess's avatar
Drew Hess committed
788
void avpicture_free(AVPicture *picture)
789
{
790
    av_free(picture->data[0]);
Fabrice Bellard's avatar