Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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