Browse code

avcodec: add MagicYUV encoder

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2017/07/09 02:14:05
Showing 5 changed files
... ...
@@ -6,6 +6,7 @@ version <next>:
6 6
 - Dropped support for OpenJPEG versions 2.0 and below. Using OpenJPEG now
7 7
   requires 2.1 (or later) and pkg-config.
8 8
 - VDA dropped (use VideoToolbox instead)
9
+- MagicYUV encoder
9 10
 
10 11
 
11 12
 version 3.4:
... ...
@@ -792,7 +792,7 @@ following image formats are supported:
792 792
 @item LucasArts SANM/Smush   @tab     @tab  X
793 793
     @tab Used in LucasArts games / SMUSH animations.
794 794
 @item lossless MJPEG         @tab  X  @tab  X
795
-@item MagicYUV Video         @tab     @tab  X
795
+@item MagicYUV Video         @tab  X  @tab  X
796 796
 @item Mandsoft Screen Capture Codec  @tab     @tab  X
797 797
 @item Microsoft ATC Screen   @tab     @tab  X
798 798
     @tab Also known as Microsoft Screen 3.
... ...
@@ -397,6 +397,7 @@ OBJS-$(CONFIG_M101_DECODER)            += m101.o
397 397
 OBJS-$(CONFIG_MACE3_DECODER)           += mace.o
398 398
 OBJS-$(CONFIG_MACE6_DECODER)           += mace.o
399 399
 OBJS-$(CONFIG_MAGICYUV_DECODER)        += magicyuv.o
400
+OBJS-$(CONFIG_MAGICYUV_ENCODER)        += magicyuvenc.o
400 401
 OBJS-$(CONFIG_MDEC_DECODER)            += mdec.o mpeg12.o mpeg12data.o
401 402
 OBJS-$(CONFIG_METASOUND_DECODER)       += metasound.o metasound_data.o \
402 403
                                           twinvq.o
... ...
@@ -240,7 +240,7 @@ static void register_all(void)
240 240
     REGISTER_ENCODER(LJPEG,             ljpeg);
241 241
     REGISTER_DECODER(LOCO,              loco);
242 242
     REGISTER_DECODER(M101,              m101);
243
-    REGISTER_DECODER(MAGICYUV,          magicyuv);
243
+    REGISTER_ENCDEC (MAGICYUV,          magicyuv);
244 244
     REGISTER_DECODER(MDEC,              mdec);
245 245
     REGISTER_DECODER(MIMIC,             mimic);
246 246
     REGISTER_ENCDEC (MJPEG,             mjpeg);
247 247
new file mode 100644
... ...
@@ -0,0 +1,558 @@
0
+/*
1
+ * MagicYUV encoder
2
+ * Copyright (c) 2017 Paul B Mahol
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include <stdlib.h>
22
+#include <string.h>
23
+
24
+#include "libavutil/opt.h"
25
+#include "libavutil/pixdesc.h"
26
+#include "libavutil/qsort.h"
27
+
28
+#include "avcodec.h"
29
+#include "bytestream.h"
30
+#include "put_bits.h"
31
+#include "internal.h"
32
+#include "thread.h"
33
+#include "lossless_videoencdsp.h"
34
+
35
+typedef enum Prediction {
36
+    LEFT = 1,
37
+    GRADIENT,
38
+    MEDIAN,
39
+} Prediction;
40
+
41
+typedef struct HuffEntry {
42
+    uint8_t  sym;
43
+    uint8_t  len;
44
+    uint32_t code;
45
+} HuffEntry;
46
+
47
+typedef struct PTable {
48
+    int     value;  ///< input value
49
+    int64_t prob;   ///< number of occurences of this value in input
50
+} PTable;
51
+
52
+typedef struct MagicYUVContext {
53
+    const AVClass       *class;
54
+    int                  frame_pred;
55
+    PutBitContext        pb;
56
+    int                  planes;
57
+    uint8_t              format;
58
+    AVFrame             *p;
59
+    int                  max;
60
+    int                  slice_height;
61
+    int                  nb_slices;
62
+    int                  correlate;
63
+    int                  hshift[4];
64
+    int                  vshift[4];
65
+    uint8_t             *slices[4];
66
+    unsigned             slice_pos[4];
67
+    unsigned             tables_size;
68
+    HuffEntry            he[4][256];
69
+    LLVidEncDSPContext   llvidencdsp;
70
+    void (*predict)(struct MagicYUVContext *s, uint8_t *src, uint8_t *dst,
71
+                    ptrdiff_t stride, int width, int height);
72
+} MagicYUVContext;
73
+
74
+static void left_predict(MagicYUVContext *s,
75
+                         uint8_t *src, uint8_t *dst, ptrdiff_t stride,
76
+                         int width, int height)
77
+{
78
+    uint8_t prev = 0;
79
+    int i, j;
80
+
81
+    for (i = 0; i < width; i++) {
82
+        dst[i] = src[i] - prev;
83
+        prev   = src[i];
84
+    }
85
+    dst += width;
86
+    src += stride;
87
+    for (j = 1; j < height; j++) {
88
+        prev = src[-stride];
89
+        for (i = 0; i < width; i++) {
90
+            dst[i] = src[i] - prev;
91
+            prev   = src[i];
92
+        }
93
+        dst += width;
94
+        src += stride;
95
+    }
96
+}
97
+
98
+static void gradient_predict(MagicYUVContext *s,
99
+                             uint8_t *src, uint8_t *dst, ptrdiff_t stride,
100
+                             int width, int height)
101
+{
102
+    int left = 0, top, lefttop;
103
+    int i, j;
104
+
105
+    for (i = 0; i < width; i++) {
106
+        dst[i] = src[i] - left;
107
+        left   = src[i];
108
+    }
109
+    dst += width;
110
+    src += stride;
111
+    for (j = 1; j < height; j++) {
112
+        top = src[-stride];
113
+        left = src[0] - top;
114
+        dst[0] = left;
115
+        for (i = 1; i < width; i++) {
116
+            top = src[i - stride];
117
+            lefttop = src[i - (stride + 1)];
118
+            left = src[i-1];
119
+            dst[i] = (src[i] - top) - left + lefttop;
120
+        }
121
+        dst += width;
122
+        src += stride;
123
+    }
124
+}
125
+
126
+static void median_predict(MagicYUVContext *s,
127
+                           uint8_t *src, uint8_t *dst, ptrdiff_t stride,
128
+                           int width, int height)
129
+{
130
+    int left = 0, lefttop;
131
+    int i, j;
132
+
133
+    for (i = 0; i < width; i++) {
134
+        dst[i] = src[i] - left;
135
+        left   = src[i];
136
+    }
137
+    dst += width;
138
+    src += stride;
139
+    for (j = 1; j < height; j++) {
140
+        left = lefttop = src[-stride];
141
+        s->llvidencdsp.sub_median_pred(dst, src - stride, src, width, &left, &lefttop);
142
+        dst += width;
143
+        src += stride;
144
+    }
145
+}
146
+
147
+static av_cold int magy_encode_init(AVCodecContext *avctx)
148
+{
149
+    MagicYUVContext *s = avctx->priv_data;
150
+    int i;
151
+
152
+    switch (avctx->pix_fmt) {
153
+    case AV_PIX_FMT_GBRP:
154
+        avctx->codec_tag = MKTAG('M', '8', 'R', 'G');
155
+        s->correlate = 1;
156
+        s->format = 0x65;
157
+        break;
158
+    case AV_PIX_FMT_GBRAP:
159
+        avctx->codec_tag = MKTAG('M', '8', 'R', 'A');
160
+        s->correlate = 1;
161
+        s->format = 0x66;
162
+        break;
163
+    case AV_PIX_FMT_YUV420P:
164
+        avctx->codec_tag = MKTAG('M', '8', 'Y', '0');
165
+        s->hshift[1] =
166
+        s->vshift[1] =
167
+        s->hshift[2] =
168
+        s->vshift[2] = 1;
169
+        s->format = 0x69;
170
+        break;
171
+    case AV_PIX_FMT_YUV422P:
172
+        avctx->codec_tag = MKTAG('M', '8', 'Y', '2');
173
+        s->hshift[1] =
174
+        s->hshift[2] = 1;
175
+        s->format = 0x68;
176
+        break;
177
+    case AV_PIX_FMT_YUV444P:
178
+        avctx->codec_tag = MKTAG('M', '8', 'Y', '4');
179
+        s->format = 0x67;
180
+        break;
181
+    case AV_PIX_FMT_YUVA444P:
182
+        avctx->codec_tag = MKTAG('M', '8', 'Y', 'A');
183
+        s->format = 0x6a;
184
+        break;
185
+    case AV_PIX_FMT_GRAY8:
186
+        avctx->codec_tag = MKTAG('M', '8', 'G', '0');
187
+        s->format = 0x6b;
188
+        break;
189
+    default:
190
+        av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: %d\n",
191
+               avctx->pix_fmt);
192
+        return AVERROR_INVALIDDATA;
193
+    }
194
+
195
+    ff_llvidencdsp_init(&s->llvidencdsp);
196
+
197
+    s->planes = av_pix_fmt_count_planes(avctx->pix_fmt);
198
+
199
+    s->nb_slices = 1;
200
+
201
+    for (i = 0; i < s->planes; i++) {
202
+        s->slices[i] = av_malloc(avctx->width * (avctx->height + 2) +
203
+                                 AV_INPUT_BUFFER_PADDING_SIZE);
204
+        if (!s->slices[i]) {
205
+            av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer.\n");
206
+            return AVERROR(ENOMEM);
207
+        }
208
+    }
209
+
210
+    switch (s->frame_pred) {
211
+    case LEFT:     s->predict = left_predict;     break;
212
+    case GRADIENT: s->predict = gradient_predict; break;
213
+    case MEDIAN:   s->predict = median_predict;   break;
214
+    }
215
+
216
+    return 0;
217
+}
218
+
219
+static int magy_huff_cmp_len(const void *a, const void *b)
220
+{
221
+    const HuffEntry *aa = a, *bb = b;
222
+    return (aa->len - bb->len) * 256 + aa->sym - bb->sym;
223
+}
224
+
225
+static int huff_cmp_sym(const void *a, const void *b)
226
+{
227
+    const HuffEntry *aa = a, *bb = b;
228
+    return bb->sym - aa->sym;
229
+}
230
+
231
+static void calculate_codes(HuffEntry *he)
232
+{
233
+    uint32_t code;
234
+    int i;
235
+
236
+    AV_QSORT(he, 256, HuffEntry, magy_huff_cmp_len);
237
+
238
+    code = 1;
239
+    for (i = 255; i >= 0; i--) {
240
+        he[i].code  = code >> (32 - he[i].len);
241
+        code       += 0x80000000u >> (he[i].len - 1);
242
+    }
243
+
244
+    AV_QSORT(he, 256, HuffEntry, huff_cmp_sym);
245
+}
246
+
247
+static void count_usage(uint8_t *src, int width,
248
+                        int height, PTable *counts)
249
+{
250
+    int i, j;
251
+
252
+    for (j = 0; j < height; j++) {
253
+        for (i = 0; i < width; i++) {
254
+            counts[src[i]].prob++;
255
+        }
256
+        src += width;
257
+    }
258
+}
259
+
260
+typedef struct PackageMergerList {
261
+    int nitems;             ///< number of items in the list and probability      ex. 4
262
+    int item_idx[515];      ///< index range for each item in items                   0, 2, 5, 9, 13
263
+    int probability[514];   ///< probability of each item                             3, 8, 18, 46
264
+    int items[257 * 16];    ///< chain of all individual values that make up items    A, B, A, B, C, A, B, C, D, C, D, D, E
265
+} PackageMergerList;
266
+
267
+static int compare_by_prob(const void *a, const void *b)
268
+{
269
+    PTable a_val = *(PTable *)a;
270
+    PTable b_val = *(PTable *)b;
271
+    return a_val.prob - b_val.prob;
272
+}
273
+
274
+static void magy_huffman_compute_bits(PTable *prob_table, HuffEntry *distincts,
275
+                                      int size, int max_length)
276
+{
277
+    PackageMergerList list_a, list_b, *to = &list_a, *from = &list_b, *temp;
278
+    int times, i, j, k;
279
+    int nbits[257] = {0};
280
+    int min;
281
+
282
+    av_assert0(max_length > 0);
283
+
284
+    to->nitems = 0;
285
+    from->nitems = 0;
286
+    to->item_idx[0] = 0;
287
+    from->item_idx[0] = 0;
288
+    AV_QSORT(prob_table, size, PTable, compare_by_prob);
289
+
290
+    for (times = 0; times <= max_length; times++) {
291
+        to->nitems = 0;
292
+        to->item_idx[0] = 0;
293
+
294
+        j = 0;
295
+        k = 0;
296
+
297
+        if (times < max_length) {
298
+            i = 0;
299
+        }
300
+        while (i < size || j + 1 < from->nitems) {
301
+            to->nitems++;
302
+            to->item_idx[to->nitems] = to->item_idx[to->nitems - 1];
303
+            if (i < size &&
304
+                (j + 1 >= from->nitems ||
305
+                 prob_table[i].prob <
306
+                     from->probability[j] + from->probability[j + 1])) {
307
+                to->items[to->item_idx[to->nitems]++] = prob_table[i].value;
308
+                to->probability[to->nitems - 1] = prob_table[i].prob;
309
+                i++;
310
+            } else {
311
+                for (k = from->item_idx[j]; k < from->item_idx[j + 2]; k++) {
312
+                    to->items[to->item_idx[to->nitems]++] = from->items[k];
313
+                }
314
+                to->probability[to->nitems - 1] =
315
+                    from->probability[j] + from->probability[j + 1];
316
+                j += 2;
317
+            }
318
+        }
319
+        temp = to;
320
+        to = from;
321
+        from = temp;
322
+    }
323
+
324
+    min = (size - 1 < from->nitems) ? size - 1 : from->nitems;
325
+    for (i = 0; i < from->item_idx[min]; i++) {
326
+        nbits[from->items[i]]++;
327
+    }
328
+
329
+    for (i = 0; i < size; i++) {
330
+        distincts[i].sym = i;
331
+        distincts[i].len = nbits[i];
332
+    }
333
+}
334
+
335
+static int encode_table(AVCodecContext *avctx, uint8_t *dst,
336
+                        int width, int height,
337
+                        PutBitContext *pb, HuffEntry *he)
338
+{
339
+    PTable counts[256] = { 0 };
340
+    int i;
341
+
342
+    count_usage(dst, width, height, counts);
343
+
344
+    for (i = 0; i < 256; i++) {
345
+        counts[i].prob++;
346
+        counts[i].value = i;
347
+    }
348
+
349
+    magy_huffman_compute_bits(counts, he, 256, 16);
350
+
351
+    calculate_codes(he);
352
+
353
+    for (i = 0; i < 256; i++) {
354
+        put_bits(pb, 1, 0);
355
+        put_bits(pb, 7, he[i].len);
356
+    }
357
+
358
+    return 0;
359
+}
360
+
361
+static int encode_slice(uint8_t *src, uint8_t *dst, int dst_size,
362
+                        int width, int height, HuffEntry *he, int prediction)
363
+{
364
+    PutBitContext pb;
365
+    int i, j;
366
+    int count;
367
+
368
+    init_put_bits(&pb, dst, dst_size);
369
+
370
+    put_bits(&pb, 8, 0);
371
+    put_bits(&pb, 8, prediction);
372
+
373
+    for (j = 0; j < height; j++) {
374
+        for (i = 0; i < width; i++) {
375
+            const int idx = src[i];
376
+            put_bits(&pb, he[idx].len, he[idx].code);
377
+        }
378
+
379
+        src += width;
380
+    }
381
+
382
+    count = put_bits_count(&pb) & 0x1F;
383
+
384
+    if (count)
385
+        put_bits(&pb, 32 - count, 0);
386
+
387
+    count = put_bits_count(&pb);
388
+
389
+    flush_put_bits(&pb);
390
+
391
+    return count >> 3;
392
+}
393
+
394
+static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
395
+                             const AVFrame *frame, int *got_packet)
396
+{
397
+    MagicYUVContext *s = avctx->priv_data;
398
+    PutByteContext pb;
399
+    const int width = avctx->width, height = avctx->height;
400
+    int pos, slice, i, j, ret = 0;
401
+
402
+    ret = ff_alloc_packet2(avctx, pkt, (256 + 4 * s->nb_slices + width * height) *
403
+                           s->planes + 256, 0);
404
+    if (ret < 0)
405
+        return ret;
406
+
407
+    bytestream2_init_writer(&pb, pkt->data, pkt->size);
408
+    bytestream2_put_le32(&pb, MKTAG('M', 'A', 'G', 'Y'));
409
+    bytestream2_put_le32(&pb, 32);
410
+    bytestream2_put_byte(&pb, 7);
411
+    bytestream2_put_byte(&pb, s->format);
412
+    bytestream2_put_byte(&pb, 0);
413
+    bytestream2_put_byte(&pb, 0);
414
+    bytestream2_put_le32(&pb, 0);
415
+
416
+    bytestream2_put_le32(&pb, avctx->width);
417
+    bytestream2_put_le32(&pb, avctx->height);
418
+    bytestream2_put_le32(&pb, avctx->width);
419
+    bytestream2_put_le32(&pb, avctx->height);
420
+    bytestream2_put_le32(&pb, 0);
421
+
422
+    for (i = 0; i < s->planes; i++) {
423
+        bytestream2_put_le32(&pb, 0);
424
+        for (j = 1; j < s->nb_slices; j++) {
425
+            bytestream2_put_le32(&pb, 0);
426
+        }
427
+    }
428
+
429
+    bytestream2_put_byte(&pb, s->planes);
430
+
431
+    for (i = 0; i < s->planes; i++) {
432
+        for (slice = 0; slice < s->nb_slices; slice++) {
433
+            bytestream2_put_byte(&pb, i);
434
+        }
435
+    }
436
+
437
+    if (s->correlate) {
438
+        uint8_t *r, *g, *b;
439
+        AVFrame *p = av_frame_clone(frame);
440
+
441
+        g = p->data[0];
442
+        b = p->data[1];
443
+        r = p->data[2];
444
+
445
+        for (i = 0; i < height; i++) {
446
+            s->llvidencdsp.diff_bytes(b, b, g, width);
447
+            s->llvidencdsp.diff_bytes(r, r, g, width);
448
+            g += p->linesize[0];
449
+            b += p->linesize[1];
450
+            r += p->linesize[2];
451
+        }
452
+
453
+        FFSWAP(uint8_t*, p->data[0], p->data[1]);
454
+        FFSWAP(int, p->linesize[0], p->linesize[1]);
455
+
456
+        for (i = 0; i < s->planes; i++) {
457
+            for (slice = 0; slice < s->nb_slices; slice++) {
458
+                s->predict(s, p->data[i], s->slices[i], p->linesize[i],
459
+                               p->width, p->height);
460
+            }
461
+        }
462
+
463
+        av_frame_free(&p);
464
+    } else {
465
+        for (i = 0; i < s->planes; i++) {
466
+            for (slice = 0; slice < s->nb_slices; slice++) {
467
+                s->predict(s, frame->data[i], s->slices[i], frame->linesize[i],
468
+                           AV_CEIL_RSHIFT(frame->width, s->hshift[i]),
469
+                           AV_CEIL_RSHIFT(frame->height, s->vshift[i]));
470
+            }
471
+        }
472
+    }
473
+
474
+    init_put_bits(&s->pb, pkt->data + bytestream2_tell_p(&pb), bytestream2_get_bytes_left_p(&pb));
475
+
476
+    for (i = 0; i < s->planes; i++) {
477
+        encode_table(avctx, s->slices[i],
478
+                     AV_CEIL_RSHIFT(frame->width,  s->hshift[i]),
479
+                     AV_CEIL_RSHIFT(frame->height, s->vshift[i]),
480
+                     &s->pb, s->he[i]);
481
+    }
482
+    s->tables_size = (put_bits_count(&s->pb) + 7) >> 3;
483
+    bytestream2_skip_p(&pb, s->tables_size);
484
+
485
+    for (i = 0; i < s->planes; i++) {
486
+        unsigned slice_size;
487
+
488
+        s->slice_pos[i] = bytestream2_tell_p(&pb);
489
+        slice_size = encode_slice(s->slices[i], pkt->data + bytestream2_tell_p(&pb),
490
+                                  bytestream2_get_bytes_left_p(&pb),
491
+                                  AV_CEIL_RSHIFT(frame->width,  s->hshift[i]),
492
+                                  AV_CEIL_RSHIFT(frame->height, s->vshift[i]),
493
+                                  s->he[i], s->frame_pred);
494
+        bytestream2_skip_p(&pb, slice_size);
495
+    }
496
+
497
+    pos = bytestream2_tell_p(&pb);
498
+    bytestream2_seek_p(&pb, 32, SEEK_SET);
499
+    bytestream2_put_le32(&pb, s->slice_pos[0] - 32);
500
+    for (i = 0; i < s->planes; i++) {
501
+        bytestream2_put_le32(&pb, s->slice_pos[i] - 32);
502
+    }
503
+    bytestream2_seek_p(&pb, pos, SEEK_SET);
504
+
505
+    pkt->size   = bytestream2_tell_p(&pb);
506
+    pkt->flags |= AV_PKT_FLAG_KEY;
507
+
508
+    *got_packet = 1;
509
+
510
+    return 0;
511
+}
512
+
513
+static av_cold int magy_encode_close(AVCodecContext *avctx)
514
+{
515
+    MagicYUVContext *s = avctx->priv_data;
516
+    int i;
517
+
518
+    for (i = 0; i < s->planes; i++)
519
+        av_freep(&s->slices[i]);
520
+
521
+    return 0;
522
+}
523
+
524
+#define OFFSET(x) offsetof(MagicYUVContext, x)
525
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
526
+static const AVOption options[] = {
527
+    { "pred", "Prediction method", OFFSET(frame_pred), AV_OPT_TYPE_INT, {.i64=LEFT}, LEFT, MEDIAN, VE, "pred" },
528
+    { "left",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LEFT },     0, 0, VE, "pred" },
529
+    { "gradient", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = GRADIENT }, 0, 0, VE, "pred" },
530
+    { "median",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MEDIAN },   0, 0, VE, "pred" },
531
+    { NULL},
532
+};
533
+
534
+static const AVClass magicyuv_class = {
535
+    .class_name = "magicyuv",
536
+    .item_name  = av_default_item_name,
537
+    .option     = options,
538
+    .version    = LIBAVUTIL_VERSION_INT,
539
+};
540
+
541
+AVCodec ff_magicyuv_encoder = {
542
+    .name             = "magicyuv",
543
+    .long_name        = NULL_IF_CONFIG_SMALL("MagicYUV video"),
544
+    .type             = AVMEDIA_TYPE_VIDEO,
545
+    .id               = AV_CODEC_ID_MAGICYUV,
546
+    .priv_data_size   = sizeof(MagicYUVContext),
547
+    .priv_class       = &magicyuv_class,
548
+    .init             = magy_encode_init,
549
+    .close            = magy_encode_close,
550
+    .encode2          = magy_encode_frame,
551
+    .capabilities     = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY,
552
+    .pix_fmts         = (const enum AVPixelFormat[]) {
553
+                          AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_YUV422P,
554
+                          AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_GRAY8,
555
+                          AV_PIX_FMT_NONE
556
+                      },
557
+};