LCOV - code coverage report
Current view: top level - libavcodec - qdrw.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 148 293 50.5 %
Date: 2018-05-20 11:54:08 Functions: 4 7 57.1 %

          Line data    Source code
       1             : /*
       2             :  * QuickDraw (qdrw) codec
       3             :  * Copyright (c) 2004 Konstantin Shishkov
       4             :  * Copyright (c) 2015 Vittorio Giovara
       5             :  *
       6             :  * This file is part of FFmpeg.
       7             :  *
       8             :  * FFmpeg is free software; you can redistribute it and/or
       9             :  * modify it under the terms of the GNU Lesser General Public
      10             :  * License as published by the Free Software Foundation; either
      11             :  * version 2.1 of the License, or (at your option) any later version.
      12             :  *
      13             :  * FFmpeg is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with FFmpeg; if not, write to the Free Software
      20             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      21             :  */
      22             : 
      23             : /**
      24             :  * @file
      25             :  * Apple QuickDraw codec.
      26             :  * https://developer.apple.com/legacy/library/documentation/mac/QuickDraw/QuickDraw-461.html
      27             :  */
      28             : 
      29             : #include "libavutil/common.h"
      30             : #include "libavutil/intreadwrite.h"
      31             : #include "avcodec.h"
      32             : #include "bytestream.h"
      33             : #include "internal.h"
      34             : 
      35             : enum QuickdrawOpcodes {
      36             :     CLIP = 0x0001,
      37             :     PACKBITSRECT = 0x0098,
      38             :     PACKBITSRGN,
      39             :     DIRECTBITSRECT,
      40             :     DIRECTBITSRGN,
      41             :     SHORTCOMMENT = 0x00A0,
      42             :     LONGCOMMENT,
      43             : 
      44             :     EOP = 0x00FF,
      45             : };
      46             : 
      47          13 : static int parse_palette(AVCodecContext *avctx, GetByteContext *gbc,
      48             :                          uint32_t *pal, int colors, int pixmap)
      49             : {
      50             :     int i;
      51             : 
      52        3341 :     for (i = 0; i <= colors; i++) {
      53             :         uint8_t r, g, b;
      54        3328 :         unsigned int idx = bytestream2_get_be16(gbc); /* color index */
      55        3328 :         if (idx > 255 && !pixmap) {
      56           0 :             av_log(avctx, AV_LOG_WARNING,
      57             :                    "Palette index out of range: %u\n", idx);
      58           0 :             bytestream2_skip(gbc, 6);
      59           0 :             continue;
      60             :         }
      61        3328 :         if (avctx->pix_fmt != AV_PIX_FMT_PAL8)
      62           0 :             return AVERROR_INVALIDDATA;
      63        3328 :         r = bytestream2_get_byte(gbc);
      64        3328 :         bytestream2_skip(gbc, 1);
      65        3328 :         g = bytestream2_get_byte(gbc);
      66        3328 :         bytestream2_skip(gbc, 1);
      67        3328 :         b = bytestream2_get_byte(gbc);
      68        3328 :         bytestream2_skip(gbc, 1);
      69        3328 :         pal[pixmap ? i : idx] = (0xFFU << 24) | (r << 16) | (g << 8) | b;
      70             :     }
      71          13 :     return 0;
      72             : }
      73             : 
      74           0 : static int decode_rle_bpp2(AVCodecContext *avctx, AVFrame *p, GetByteContext *gbc)
      75             : {
      76           0 :     int offset = avctx->width;
      77           0 :     uint8_t *outdata = p->data[0];
      78             :     int i, j;
      79             : 
      80           0 :     for (i = 0; i < avctx->height; i++) {
      81             :         int size, left, code, pix;
      82           0 :         uint8_t *out = outdata;
      83           0 :         int pos = 0;
      84             : 
      85             :         /* size of packed line */
      86           0 :         if (offset / 4 > 200)
      87           0 :             size = left = bytestream2_get_be16(gbc);
      88             :         else
      89           0 :             size = left = bytestream2_get_byte(gbc);
      90           0 :         if (bytestream2_get_bytes_left(gbc) < size)
      91           0 :             return AVERROR_INVALIDDATA;
      92             : 
      93             :         /* decode line */
      94           0 :         while (left > 0) {
      95           0 :             code = bytestream2_get_byte(gbc);
      96           0 :             if (code & 0x80 ) { /* run */
      97           0 :                 pix = bytestream2_get_byte(gbc);
      98           0 :                 for (j = 0; j < 257 - code; j++) {
      99           0 :                     if (pos < offset)
     100           0 :                         out[pos++] = (pix & 0xC0) >> 6;
     101           0 :                     if (pos < offset)
     102           0 :                         out[pos++] = (pix & 0x30) >> 4;
     103           0 :                     if (pos < offset)
     104           0 :                         out[pos++] = (pix & 0x0C) >> 2;
     105           0 :                     if (pos < offset)
     106           0 :                         out[pos++] = (pix & 0x03);
     107             :                 }
     108           0 :                 left  -= 2;
     109             :             } else { /* copy */
     110           0 :                 for (j = 0; j < code + 1; j++) {
     111           0 :                     pix = bytestream2_get_byte(gbc);
     112           0 :                     if (pos < offset)
     113           0 :                         out[pos++] = (pix & 0xC0) >> 6;
     114           0 :                     if (pos < offset)
     115           0 :                         out[pos++] = (pix & 0x30) >> 4;
     116           0 :                     if (pos < offset)
     117           0 :                         out[pos++] = (pix & 0x0C) >> 2;
     118           0 :                     if (pos < offset)
     119           0 :                         out[pos++] = (pix & 0x03);
     120             :                 }
     121           0 :                 left  -= 1 + (code + 1);
     122             :             }
     123             :         }
     124           0 :         outdata += p->linesize[0];
     125             :     }
     126           0 :     return 0;
     127             : }
     128             : 
     129           0 : static int decode_rle_bpp4(AVCodecContext *avctx, AVFrame *p, GetByteContext *gbc)
     130             : {
     131           0 :     int offset = avctx->width;
     132           0 :     uint8_t *outdata = p->data[0];
     133             :     int i, j;
     134             : 
     135           0 :     for (i = 0; i < avctx->height; i++) {
     136             :         int size, left, code, pix;
     137           0 :         uint8_t *out = outdata;
     138           0 :         int pos = 0;
     139             : 
     140             :         /* size of packed line */
     141           0 :         size = left = bytestream2_get_be16(gbc);
     142           0 :         if (bytestream2_get_bytes_left(gbc) < size)
     143           0 :             return AVERROR_INVALIDDATA;
     144             : 
     145             :         /* decode line */
     146           0 :         while (left > 0) {
     147           0 :             code = bytestream2_get_byte(gbc);
     148           0 :             if (code & 0x80 ) { /* run */
     149           0 :                 pix = bytestream2_get_byte(gbc);
     150           0 :                 for (j = 0; j < 257 - code; j++) {
     151           0 :                     if (pos < offset)
     152           0 :                         out[pos++] = (pix & 0xF0) >> 4;
     153           0 :                     if (pos < offset)
     154           0 :                         out[pos++] = pix & 0xF;
     155             :                 }
     156           0 :                 left  -= 2;
     157             :             } else { /* copy */
     158           0 :                 for (j = 0; j < code + 1; j++) {
     159           0 :                     pix = bytestream2_get_byte(gbc);
     160           0 :                     if (pos < offset)
     161           0 :                         out[pos++] = (pix & 0xF0) >> 4;
     162           0 :                     if (pos < offset)
     163           0 :                         out[pos++] = pix & 0xF;
     164             :                 }
     165           0 :                 left  -= 1 + (code + 1);
     166             :             }
     167             :         }
     168           0 :         outdata += p->linesize[0];
     169             :     }
     170           0 :     return 0;
     171             : }
     172             : 
     173           0 : static int decode_rle16(AVCodecContext *avctx, AVFrame *p, GetByteContext *gbc)
     174             : {
     175           0 :     int offset = avctx->width;
     176           0 :     uint8_t *outdata = p->data[0];
     177             :     int i, j;
     178             : 
     179           0 :     for (i = 0; i < avctx->height; i++) {
     180             :         int size, left, code, pix;
     181           0 :         uint16_t *out = (uint16_t *)outdata;
     182           0 :         int pos = 0;
     183             : 
     184             :         /* size of packed line */
     185           0 :         size = left = bytestream2_get_be16(gbc);
     186           0 :         if (bytestream2_get_bytes_left(gbc) < size)
     187           0 :             return AVERROR_INVALIDDATA;
     188             : 
     189             :         /* decode line */
     190           0 :         while (left > 0) {
     191           0 :             code = bytestream2_get_byte(gbc);
     192           0 :             if (code & 0x80 ) { /* run */
     193           0 :                 pix = bytestream2_get_be16(gbc);
     194           0 :                 for (j = 0; j < 257 - code; j++) {
     195           0 :                     if (pos < offset) {
     196           0 :                         out[pos++] = pix;
     197             :                     }
     198             :                 }
     199           0 :                 left  -= 3;
     200             :             } else { /* copy */
     201           0 :                 for (j = 0; j < code + 1; j++) {
     202           0 :                     if (pos < offset) {
     203           0 :                         out[pos++] = bytestream2_get_be16(gbc);
     204             :                     } else {
     205           0 :                         bytestream2_skip(gbc, 2);
     206             :                     }
     207             :                 }
     208           0 :                 left  -= 1 + (code + 1) * 2;
     209             :             }
     210             :         }
     211           0 :         outdata += p->linesize[0];
     212             :     }
     213           0 :     return 0;
     214             : }
     215             : 
     216          15 : static int decode_rle(AVCodecContext *avctx, AVFrame *p, GetByteContext *gbc,
     217             :                       int step)
     218             : {
     219             :     int i, j;
     220          15 :     int offset = avctx->width * step;
     221          15 :     uint8_t *outdata = p->data[0];
     222             : 
     223        6383 :     for (i = 0; i < avctx->height; i++) {
     224             :         int size, left, code, pix;
     225        6368 :         uint8_t *out = outdata;
     226        6368 :         int pos = 0;
     227             : 
     228             :         /* size of packed line */
     229        6368 :         size = left = bytestream2_get_be16(gbc);
     230        6368 :         if (bytestream2_get_bytes_left(gbc) < size)
     231           0 :             return AVERROR_INVALIDDATA;
     232             : 
     233             :         /* decode line */
     234      484305 :         while (left > 0) {
     235      471569 :             code = bytestream2_get_byte(gbc);
     236      471569 :             if (code & 0x80 ) { /* run */
     237      246815 :                 pix = bytestream2_get_byte(gbc);
     238     1602325 :                 for (j = 0; j < 257 - code; j++) {
     239     1355510 :                     if (pos < offset)
     240     1355510 :                         out[pos] = pix;
     241     1355510 :                     pos += step;
     242     1355510 :                     if (pos >= offset && step > 1) {
     243         384 :                         pos -= offset;
     244         384 :                         pos++;
     245             :                     }
     246             :                 }
     247      246815 :                 left  -= 2;
     248             :             } else { /* copy */
     249     2961148 :                 for (j = 0; j < code + 1; j++) {
     250     2736394 :                     pix = bytestream2_get_byte(gbc);
     251     2736394 :                     if (pos < offset)
     252     2736394 :                         out[pos] = pix;
     253     2736394 :                     pos += step;
     254     2736394 :                     if (pos >= offset && step > 1) {
     255           0 :                         pos -= offset;
     256           0 :                         pos++;
     257             :                     }
     258             :                 }
     259      224754 :                 left  -= 2 + code;
     260             :             }
     261             :         }
     262        6368 :         outdata += p->linesize[0];
     263             :     }
     264          15 :     return 0;
     265             : }
     266             : 
     267          40 : static int check_header(const char *buf, int buf_size)
     268             : {
     269             :     unsigned w, h, v0, v1;
     270             : 
     271          40 :     if (buf_size < 40)
     272           0 :         return 0;
     273             : 
     274          40 :     w = AV_RB16(buf+6);
     275          40 :     h = AV_RB16(buf+8);
     276          40 :     v0 = AV_RB16(buf+10);
     277          40 :     v1 = AV_RB16(buf+12);
     278             : 
     279          40 :     if (!w || !h)
     280           0 :         return 0;
     281             : 
     282          40 :     if (v0 == 0x1101)
     283           0 :         return 1;
     284          40 :     if (v0 == 0x0011 && v1 == 0x02FF)
     285          20 :         return 2;
     286          20 :     return 0;
     287             : }
     288             : 
     289             : 
     290          20 : static int decode_frame(AVCodecContext *avctx,
     291             :                         void *data, int *got_frame,
     292             :                         AVPacket *avpkt)
     293             : {
     294          20 :     AVFrame * const p      = data;
     295             :     GetByteContext gbc;
     296             :     int colors;
     297             :     int w, h, ret;
     298             :     int ver;
     299             : 
     300          20 :     bytestream2_init(&gbc, avpkt->data, avpkt->size);
     301          20 :     if (   bytestream2_get_bytes_left(&gbc) >= 552
     302          20 :            &&  check_header(gbc.buffer + 512, bytestream2_get_bytes_left(&gbc) - 512)
     303             :        )
     304           0 :         bytestream2_skip(&gbc, 512);
     305             : 
     306          20 :     ver = check_header(gbc.buffer, bytestream2_get_bytes_left(&gbc));
     307             : 
     308             :     /* smallest PICT header */
     309          20 :     if (bytestream2_get_bytes_left(&gbc) < 40) {
     310           0 :         av_log(avctx, AV_LOG_ERROR, "Frame is too small %d\n",
     311             :                bytestream2_get_bytes_left(&gbc));
     312           0 :         return AVERROR_INVALIDDATA;
     313             :     }
     314             : 
     315          20 :     bytestream2_skip(&gbc, 6);
     316          20 :     h = bytestream2_get_be16(&gbc);
     317          20 :     w = bytestream2_get_be16(&gbc);
     318             : 
     319          20 :     ret = ff_set_dimensions(avctx, w, h);
     320          20 :     if (ret < 0)
     321           0 :         return ret;
     322             : 
     323             :     /* version 1 is identified by 0x1101
     324             :      * it uses byte-aligned opcodes rather than word-aligned */
     325          20 :     if (ver == 1) {
     326           0 :         avpriv_request_sample(avctx, "QuickDraw version 1");
     327           0 :         return AVERROR_PATCHWELCOME;
     328          20 :     } else if (ver != 2) {
     329           0 :         avpriv_request_sample(avctx, "QuickDraw version unknown (%X)", bytestream2_get_be32(&gbc));
     330           0 :         return AVERROR_PATCHWELCOME;
     331             :     }
     332             : 
     333          20 :     bytestream2_skip(&gbc, 4+26);
     334             : 
     335          20 :     while (bytestream2_get_bytes_left(&gbc) >= 4) {
     336             :         int bppcnt, bpp;
     337             :         int rowbytes, pack_type;
     338             :         int flags;
     339         710 :         int opcode = bytestream2_get_be16(&gbc);
     340             : 
     341         710 :         switch(opcode) {
     342          30 :         case CLIP:
     343          30 :             bytestream2_skip(&gbc, 10);
     344          30 :             break;
     345          13 :         case PACKBITSRECT:
     346             :         case PACKBITSRGN:
     347          13 :             av_log(avctx, AV_LOG_DEBUG, "Parsing Packbit opcode\n");
     348             : 
     349          13 :             flags = bytestream2_get_be16(&gbc) & 0xC000;
     350          13 :             bytestream2_skip(&gbc, 28);
     351          13 :             bppcnt = bytestream2_get_be16(&gbc); /* cmpCount */
     352          13 :             bpp    = bytestream2_get_be16(&gbc); /* cmpSize */
     353             : 
     354          13 :             av_log(avctx, AV_LOG_DEBUG, "bppcount %d bpp %d\n", bppcnt, bpp);
     355          13 :             if (bppcnt == 1 && bpp == 8) {
     356          13 :                 avctx->pix_fmt = AV_PIX_FMT_PAL8;
     357           0 :             } else if (bppcnt == 1 && (bpp == 4 || bpp == 2)) {
     358           0 :                 avctx->pix_fmt = AV_PIX_FMT_PAL8;
     359           0 :             } else if (bppcnt == 3 && bpp == 5) {
     360           0 :                 avctx->pix_fmt = AV_PIX_FMT_RGB555;
     361             :             } else {
     362           0 :                 av_log(avctx, AV_LOG_ERROR,
     363             :                        "Invalid pixel format (bppcnt %d bpp %d) in Packbit\n",
     364             :                        bppcnt, bpp);
     365           0 :                 return AVERROR_INVALIDDATA;
     366             :             }
     367             : 
     368             :             /* jump to palette */
     369          13 :             bytestream2_skip(&gbc, 18);
     370          13 :             colors = bytestream2_get_be16(&gbc);
     371             : 
     372          13 :             if (colors < 0 || colors > 256) {
     373           0 :                 av_log(avctx, AV_LOG_ERROR,
     374             :                        "Error color count - %i(0x%X)\n", colors, colors);
     375           0 :                 return AVERROR_INVALIDDATA;
     376             :             }
     377          13 :             if (bytestream2_get_bytes_left(&gbc) < (colors + 1) * 8) {
     378           0 :                 av_log(avctx, AV_LOG_ERROR, "Palette is too small %d\n",
     379             :                        bytestream2_get_bytes_left(&gbc));
     380           0 :                 return AVERROR_INVALIDDATA;
     381             :             }
     382          13 :             if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
     383           0 :                 return ret;
     384             : 
     385          13 :             ret = parse_palette(avctx, &gbc, (uint32_t *)p->data[1], colors, flags & 0x8000);
     386          13 :             if (ret < 0)
     387           0 :                 return ret;
     388          13 :             p->palette_has_changed = 1;
     389             : 
     390             :             /* jump to image data */
     391          13 :             bytestream2_skip(&gbc, 18);
     392             : 
     393          13 :             if (opcode == PACKBITSRGN) {
     394           0 :                 bytestream2_skip(&gbc, 2 + 8); /* size + rect */
     395           0 :                 avpriv_report_missing_feature(avctx, "Packbit mask region");
     396             :             }
     397             : 
     398          13 :             if (avctx->pix_fmt == AV_PIX_FMT_RGB555)
     399           0 :                 ret = decode_rle16(avctx, p, &gbc);
     400          13 :             else if (bpp == 2)
     401           0 :                 ret = decode_rle_bpp2(avctx, p, &gbc);
     402          13 :             else if (bpp == 4)
     403           0 :                 ret = decode_rle_bpp4(avctx, p, &gbc);
     404             :             else
     405          13 :                 ret = decode_rle(avctx, p, &gbc, bppcnt);
     406          13 :             if (ret < 0)
     407           0 :                 return ret;
     408          13 :             *got_frame = 1;
     409          13 :             break;
     410           2 :         case DIRECTBITSRECT:
     411             :         case DIRECTBITSRGN:
     412           2 :             av_log(avctx, AV_LOG_DEBUG, "Parsing Directbit opcode\n");
     413             : 
     414           2 :             bytestream2_skip(&gbc, 4);
     415           2 :             rowbytes = bytestream2_get_be16(&gbc) & 0x3FFF;
     416           2 :             if (rowbytes <= 250) {
     417           0 :                 avpriv_report_missing_feature(avctx, "Short rowbytes");
     418           0 :                 return AVERROR_PATCHWELCOME;
     419             :             }
     420             : 
     421           2 :             bytestream2_skip(&gbc, 4);
     422           2 :             h = bytestream2_get_be16(&gbc);
     423           2 :             w = bytestream2_get_be16(&gbc);
     424           2 :             bytestream2_skip(&gbc, 2);
     425             : 
     426           2 :             ret = ff_set_dimensions(avctx, w, h);
     427           2 :             if (ret < 0)
     428           0 :                 return ret;
     429             : 
     430           2 :             pack_type = bytestream2_get_be16(&gbc);
     431             : 
     432           2 :             bytestream2_skip(&gbc, 16);
     433           2 :             bppcnt = bytestream2_get_be16(&gbc); /* cmpCount */
     434           2 :             bpp    = bytestream2_get_be16(&gbc); /* cmpSize */
     435             : 
     436           2 :             av_log(avctx, AV_LOG_DEBUG, "bppcount %d bpp %d\n", bppcnt, bpp);
     437           2 :             if (bppcnt == 3 && bpp == 8) {
     438           2 :                 avctx->pix_fmt = AV_PIX_FMT_RGB24;
     439           0 :             } else if (bppcnt == 3 && bpp == 5 || bppcnt == 2 && bpp == 8) {
     440           0 :                 avctx->pix_fmt = AV_PIX_FMT_RGB555;
     441           0 :             } else if (bppcnt == 4 && bpp == 8) {
     442           0 :                 avctx->pix_fmt = AV_PIX_FMT_ARGB;
     443             :             } else {
     444           0 :                 av_log(avctx, AV_LOG_ERROR,
     445             :                        "Invalid pixel format (bppcnt %d bpp %d) in Directbit\n",
     446             :                        bppcnt, bpp);
     447           0 :                 return AVERROR_INVALIDDATA;
     448             :             }
     449             : 
     450             :             /* set packing when default is selected */
     451           2 :             if (pack_type == 0)
     452           0 :                 pack_type = bppcnt;
     453             : 
     454           2 :             if (pack_type != 3 && pack_type != 4) {
     455           0 :                 avpriv_request_sample(avctx, "Pack type %d", pack_type);
     456           0 :                 return AVERROR_PATCHWELCOME;
     457             :             }
     458           2 :             if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
     459           0 :                 return ret;
     460             : 
     461             :             /* jump to data */
     462           2 :             bytestream2_skip(&gbc, 30);
     463             : 
     464           2 :             if (opcode == DIRECTBITSRGN) {
     465           0 :                 bytestream2_skip(&gbc, 2 + 8); /* size + rect */
     466           0 :                 avpriv_report_missing_feature(avctx, "DirectBit mask region");
     467             :             }
     468             : 
     469           2 :             if (avctx->pix_fmt == AV_PIX_FMT_RGB555)
     470           0 :                 ret = decode_rle16(avctx, p, &gbc);
     471             :             else
     472           2 :                 ret = decode_rle(avctx, p, &gbc, bppcnt);
     473           2 :             if (ret < 0)
     474           0 :                 return ret;
     475           2 :             *got_frame = 1;
     476           2 :             break;
     477          10 :         case LONGCOMMENT:
     478          10 :             bytestream2_get_be16(&gbc);
     479          10 :             bytestream2_skip(&gbc, bytestream2_get_be16(&gbc));
     480          10 :             break;
     481         655 :         default:
     482         655 :             av_log(avctx, AV_LOG_TRACE, "Unknown 0x%04X opcode\n", opcode);
     483         655 :             break;
     484             :         }
     485             :         /* exit the loop when a known pixel block has been found */
     486         710 :         if (*got_frame) {
     487             :             int eop, trail;
     488             : 
     489             :             /* re-align to a word */
     490          15 :             bytestream2_skip(&gbc, bytestream2_get_bytes_left(&gbc) % 2);
     491             : 
     492          15 :             eop = bytestream2_get_be16(&gbc);
     493          15 :             trail = bytestream2_get_bytes_left(&gbc);
     494          15 :             if (eop != EOP)
     495           0 :                 av_log(avctx, AV_LOG_WARNING,
     496             :                        "Missing end of picture opcode (found 0x%04X)\n", eop);
     497          15 :             if (trail)
     498           0 :                 av_log(avctx, AV_LOG_WARNING, "Got %d trailing bytes\n", trail);
     499          15 :             break;
     500             :         }
     501             :     }
     502             : 
     503          20 :     if (*got_frame) {
     504          15 :         p->pict_type = AV_PICTURE_TYPE_I;
     505          15 :         p->key_frame = 1;
     506             : 
     507          15 :         return avpkt->size;
     508             :     } else {
     509           5 :         av_log(avctx, AV_LOG_ERROR, "Frame contained no usable data\n");
     510             : 
     511           5 :         return AVERROR_INVALIDDATA;
     512             :     }
     513             : }
     514             : 
     515             : AVCodec ff_qdraw_decoder = {
     516             :     .name           = "qdraw",
     517             :     .long_name      = NULL_IF_CONFIG_SMALL("Apple QuickDraw"),
     518             :     .type           = AVMEDIA_TYPE_VIDEO,
     519             :     .id             = AV_CODEC_ID_QDRAW,
     520             :     .decode         = decode_frame,
     521             :     .capabilities   = AV_CODEC_CAP_DR1,
     522             : };

Generated by: LCOV version 1.13