LCOV - code coverage report
Current view: top level - libavcodec - magicyuvenc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 278 0.0 %
Date: 2017-12-13 02:34:56 Functions: 0 14 0.0 %

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

Generated by: LCOV version 1.13