LCOV - code coverage report
Current view: top level - libavcodec - gdv.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 285 0.0 %
Date: 2017-12-15 11:05:35 Functions: 0 11 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Gremlin Digital Video (GDV) decoder
       3             :  * Copyright (c) 2017 Konstantin Shishkov
       4             :  * Copyright (c) 2017 Paul B Mahol
       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             : #include "libavutil/common.h"
      24             : #include "avcodec.h"
      25             : #include "bytestream.h"
      26             : #include "internal.h"
      27             : 
      28             : typedef struct GDVContext {
      29             :     AVCodecContext *avctx;
      30             : 
      31             :     GetByteContext gb;
      32             :     GetByteContext g2;
      33             :     PutByteContext pb;
      34             : 
      35             :     uint32_t pal[256];
      36             :     uint8_t *frame;
      37             :     unsigned frame_size;
      38             :     unsigned scale_h, scale_v;
      39             : } GDVContext;
      40             : 
      41             : typedef struct Bits8 {
      42             :     uint8_t queue;
      43             :     uint8_t fill;
      44             : } Bits8;
      45             : 
      46             : typedef struct Bits32 {
      47             :     uint32_t queue;
      48             :     uint8_t  fill;
      49             : } Bits32;
      50             : 
      51             : #define PREAMBLE_SIZE 4096
      52             : 
      53           0 : static av_cold int gdv_decode_init(AVCodecContext *avctx)
      54             : {
      55           0 :     GDVContext *gdv = avctx->priv_data;
      56             :     int i, j, k;
      57             : 
      58           0 :     avctx->pix_fmt  = AV_PIX_FMT_PAL8;
      59           0 :     gdv->frame_size = avctx->width * avctx->height + PREAMBLE_SIZE;
      60           0 :     gdv->frame = av_calloc(gdv->frame_size, 1);
      61           0 :     if (!gdv->frame)
      62           0 :         return AVERROR(ENOMEM);
      63             : 
      64           0 :     for (i = 0; i < 2; i++) {
      65           0 :         for (j = 0; j < 256; j++) {
      66           0 :             for (k = 0; k < 8; k++) {
      67           0 :                 gdv->frame[i * 2048 + j * 8 + k] = j;
      68             :             }
      69             :         }
      70             :     }
      71             : 
      72           0 :     return 0;
      73             : }
      74             : 
      75           0 : static void rescale(GDVContext *gdv, uint8_t *dst, int w, int h, int scale_v, int scale_h)
      76             : {
      77             :     int i, j, y, x;
      78             : 
      79           0 :     if ((gdv->scale_v == scale_v) && (gdv->scale_h == scale_h)) {
      80           0 :         return;
      81             :     }
      82             : 
      83           0 :     if (gdv->scale_h && gdv->scale_v) {
      84           0 :         for (j = 0; j < h; j++) {
      85           0 :             int y = h - j - 1;
      86           0 :             for (i = 0; i < w; i++) {
      87           0 :                 int x = w - i - 1;
      88           0 :                 dst[PREAMBLE_SIZE + x + y * w] = dst[PREAMBLE_SIZE + x/2 + (y/2) * (w/2)];
      89             :             }
      90             :         }
      91           0 :     } else if (gdv->scale_h) {
      92           0 :         for (j = 0; j < h; j++) {
      93           0 :             int y = h - j - 1;
      94           0 :             for (x = 0; x < w; x++) {
      95           0 :                 dst[PREAMBLE_SIZE + x + y * w] = dst[PREAMBLE_SIZE + x + (y/2) * w];
      96             :             }
      97             :         }
      98           0 :     } else if (gdv->scale_v) {
      99           0 :         for (j = 0; j < h; j++) {
     100           0 :             int y = h - j - 1;
     101           0 :             for (i = 0; i < w; i++) {
     102           0 :                 int x = w - i - 1;
     103           0 :                 dst[PREAMBLE_SIZE + x + y * w] = dst[PREAMBLE_SIZE + x/2 + y * (w/2)];
     104             :             }
     105             :         }
     106             :     }
     107             : 
     108           0 :     if (scale_h && scale_v) {
     109           0 :         for (y = 0; y < h/2; y++) {
     110           0 :             for (x = 0; x < w/2; x++) {
     111           0 :                 dst[PREAMBLE_SIZE + x + y * (w/2)] = dst[PREAMBLE_SIZE + x*2 + y*2 * w];
     112             :             }
     113             :         }
     114           0 :     } else if (scale_h) {
     115           0 :         for (y = 0; y < h/2; y++) {
     116           0 :             for (x = 0; x < w; x++) {
     117           0 :                 dst[PREAMBLE_SIZE + x + y * w] = dst[PREAMBLE_SIZE + x + y*2 * w];
     118             :             }
     119             :         }
     120           0 :     } else if (scale_v) {
     121           0 :         for (y = 0; y < h; y++) {
     122           0 :             for (x = 0; x < w/2; x++) {
     123           0 :                 dst[PREAMBLE_SIZE + x + y * w] = dst[PREAMBLE_SIZE + x*2 + y * w];
     124             :             }
     125             :         }
     126             :     }
     127             : 
     128           0 :     gdv->scale_v = scale_v;
     129           0 :     gdv->scale_h = scale_h;
     130             : }
     131             : 
     132           0 : static int read_bits2(Bits8 *bits, GetByteContext *gb)
     133             : {
     134             :     int res;
     135             : 
     136           0 :     if (bits->fill == 0) {
     137           0 :         bits->queue |= bytestream2_get_byte(gb);
     138           0 :         bits->fill   = 8;
     139             :     }
     140           0 :     res = bits->queue >> 6;
     141           0 :     bits->queue <<= 2;
     142           0 :     bits->fill   -= 2;
     143             : 
     144           0 :     return res;
     145             : }
     146             : 
     147           0 : static void fill_bits32(Bits32 *bits, GetByteContext *gb)
     148             : {
     149           0 :     bits->queue = bytestream2_get_le32(gb);
     150           0 :     bits->fill  = 32;
     151           0 : }
     152             : 
     153           0 : static int read_bits32(Bits32 *bits, GetByteContext *gb, int nbits)
     154             : {
     155           0 :     int res = bits->queue & ((1 << nbits) - 1);
     156             : 
     157           0 :     bits->queue >>= nbits;
     158           0 :     bits->fill   -= nbits;
     159           0 :     if (bits->fill <= 16) {
     160           0 :         bits->queue |= bytestream2_get_le16(gb) << bits->fill;
     161           0 :         bits->fill  += 16;
     162             :     }
     163             : 
     164           0 :     return res;
     165             : }
     166             : 
     167           0 : static void lz_copy(PutByteContext *pb, GetByteContext *g2, int offset, unsigned len)
     168             : {
     169             :     int i;
     170             : 
     171           0 :     if (offset == -1) {
     172             :         int c;
     173             : 
     174           0 :         bytestream2_seek(g2, bytestream2_tell_p(pb) - 1, SEEK_SET);
     175           0 :         c = bytestream2_get_byte(g2);
     176           0 :         for (i = 0; i < len; i++) {
     177           0 :             bytestream2_put_byte(pb, c);
     178             :         }
     179           0 :     } else if (offset < 0) {
     180           0 :         int start = bytestream2_tell_p(pb) - (-offset);
     181             : 
     182           0 :         bytestream2_seek(g2, start, SEEK_SET);
     183           0 :         for (i = 0; i < len; i++) {
     184           0 :             bytestream2_put_byte(pb, bytestream2_get_byte(g2));
     185             :         }
     186             :     } else {
     187           0 :         int start = bytestream2_tell_p(pb) + offset;
     188             : 
     189           0 :         bytestream2_seek(g2, start, SEEK_SET);
     190           0 :         for (i = 0; i < len; i++) {
     191           0 :             bytestream2_put_byte(pb, bytestream2_get_byte(g2));
     192             :         }
     193             :     }
     194           0 : }
     195             : 
     196           0 : static int decompress_2(AVCodecContext *avctx)
     197             : {
     198           0 :     GDVContext *gdv = avctx->priv_data;
     199           0 :     GetByteContext *gb = &gdv->gb;
     200           0 :     GetByteContext *g2 = &gdv->g2;
     201           0 :     PutByteContext *pb = &gdv->pb;
     202           0 :     Bits8 bits = { 0 };
     203             :     int c, i;
     204             : 
     205           0 :     bytestream2_init(g2, gdv->frame, gdv->frame_size);
     206           0 :     bytestream2_skip_p(pb, PREAMBLE_SIZE);
     207             : 
     208           0 :     for (c = 0; c < 256; c++) {
     209           0 :         for (i = 0; i < 16; i++) {
     210           0 :             gdv->frame[c * 16 + i] = c;
     211             :         }
     212             :     }
     213             : 
     214           0 :     while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) {
     215           0 :         int tag = read_bits2(&bits, gb);
     216           0 :         if (tag == 0) {
     217           0 :             bytestream2_put_byte(pb, bytestream2_get_byte(gb));
     218           0 :         } else if (tag == 1) {
     219           0 :             int b = bytestream2_get_byte(gb);
     220           0 :             int len = (b & 0xF) + 3;
     221           0 :             int top = (b >> 4) & 0xF;
     222           0 :             int off = (bytestream2_get_byte(gb) << 4) + top - 4096;
     223           0 :             lz_copy(pb, g2, off, len);
     224           0 :         } else if (tag == 2) {
     225           0 :             int len = (bytestream2_get_byte(gb)) + 2;
     226           0 :             bytestream2_skip_p(pb, len);
     227             :         } else {
     228           0 :             break;
     229             :         }
     230             :     }
     231           0 :     return 0;
     232             : }
     233             : 
     234           0 : static int decompress_5(AVCodecContext *avctx, unsigned skip)
     235             : {
     236           0 :     GDVContext *gdv = avctx->priv_data;
     237           0 :     GetByteContext *gb = &gdv->gb;
     238           0 :     GetByteContext *g2 = &gdv->g2;
     239           0 :     PutByteContext *pb = &gdv->pb;
     240           0 :     Bits8 bits = { 0 };
     241             : 
     242           0 :     bytestream2_init(g2, gdv->frame, gdv->frame_size);
     243           0 :     bytestream2_skip_p(pb, skip + PREAMBLE_SIZE);
     244             : 
     245           0 :     while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) {
     246           0 :         int tag = read_bits2(&bits, gb);
     247           0 :         if (tag == 0) {
     248           0 :             bytestream2_put_byte(pb, bytestream2_get_byte(gb));
     249           0 :         } else if (tag == 1) {
     250           0 :             int b = bytestream2_get_byte(gb);
     251           0 :             int len = (b & 0xF) + 3;
     252           0 :             int top = b >> 4;
     253           0 :             int off = (bytestream2_get_byte(gb) << 4) + top - 4096;
     254           0 :             lz_copy(pb, g2, off, len);
     255           0 :         } else if (tag == 2) {
     256             :             int len;
     257           0 :             int b = bytestream2_get_byte(gb);
     258           0 :             if (b == 0) {
     259           0 :                 break;
     260             :             }
     261           0 :             if (b != 0xFF) {
     262           0 :                 len = b;
     263             :             } else {
     264           0 :                 len = bytestream2_get_le16(gb);
     265             :             }
     266           0 :             bytestream2_skip_p(pb, len + 1);
     267             :         } else {
     268           0 :             int b = bytestream2_get_byte(gb);
     269           0 :             int len = (b & 0x3) + 2;
     270           0 :             int off = -(b >> 2) - 1;
     271           0 :             lz_copy(pb, g2, off, len);
     272             :         }
     273             :     }
     274           0 :     return 0;
     275             : }
     276             : 
     277           0 : static int decompress_68(AVCodecContext *avctx, unsigned skip, unsigned use8)
     278             : {
     279           0 :     GDVContext *gdv = avctx->priv_data;
     280           0 :     GetByteContext *gb = &gdv->gb;
     281           0 :     GetByteContext *g2 = &gdv->g2;
     282           0 :     PutByteContext *pb = &gdv->pb;
     283             :     Bits32 bits;
     284             : 
     285           0 :     bytestream2_init(g2, gdv->frame, gdv->frame_size);
     286           0 :     bytestream2_skip_p(pb, skip + PREAMBLE_SIZE);
     287           0 :     fill_bits32(&bits, gb);
     288             : 
     289           0 :     while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) {
     290           0 :         int tag = read_bits32(&bits, gb, 2);
     291           0 :         if (tag == 0) {
     292           0 :             int b = read_bits32(&bits, gb, 1);
     293           0 :             if (b == 0) {
     294           0 :                 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
     295             :             } else {
     296           0 :                 int i, len = 2;
     297           0 :                 int lbits = 0;
     298           0 :                 while (1) {
     299             :                     int val;
     300             : 
     301           0 :                     lbits += 1;
     302           0 :                     val = read_bits32(&bits, gb, lbits);
     303           0 :                     len += val;
     304           0 :                     if (val != ((1 << lbits) - 1)) {
     305           0 :                         break;
     306             :                     }
     307             :                     assert(lbits < 16);
     308             :                 }
     309           0 :                 for (i = 0; i < len; i++) {
     310           0 :                     bytestream2_put_byte(pb, bytestream2_get_byte(gb));
     311             :                 }
     312             :             }
     313           0 :         } else if (tag == 1) {
     314           0 :             int b = read_bits32(&bits, gb, 1);
     315             :             int len;
     316             : 
     317           0 :             if (b == 0) {
     318           0 :                 len = (read_bits32(&bits, gb, 4)) + 2;
     319             :             } else {
     320           0 :                 int bb = bytestream2_get_byte(gb);
     321           0 :                 if ((bb & 0x80) == 0) {
     322           0 :                     len = bb + 18;
     323             :                 } else {
     324           0 :                     int top = (bb & 0x7F) << 8;
     325           0 :                     len = top + bytestream2_get_byte(gb) + 146;
     326             :                 }
     327             :             }
     328           0 :             bytestream2_skip_p(pb, len);
     329           0 :         } else if (tag == 2) {
     330           0 :             int i, subtag = read_bits32(&bits, gb, 2);
     331             : 
     332           0 :             if (subtag != 3) {
     333           0 :                 int top = (read_bits32(&bits, gb, 4)) << 8;
     334           0 :                 int offs = top + bytestream2_get_byte(gb);
     335           0 :                 if ((subtag != 0) || (offs <= 0xF80)) {
     336           0 :                     int len = (subtag) + 3;
     337           0 :                     lz_copy(pb, g2, (offs) - 4096, len);
     338             :                 } else {
     339             :                     int real_off, len, c1, c2;
     340             : 
     341           0 :                     if (offs == 0xFFF) {
     342           0 :                         return 0;
     343             :                     }
     344             : 
     345           0 :                     real_off = ((offs >> 4) & 0x7) + 1;
     346           0 :                     len = ((offs & 0xF) + 2) * 2;
     347           0 :                     c1 = gdv->frame[bytestream2_tell_p(pb) - real_off];
     348           0 :                     c2 = gdv->frame[bytestream2_tell_p(pb) - real_off + 1];
     349           0 :                     for (i = 0; i < len/2; i++) {
     350           0 :                         bytestream2_put_byte(pb, c1);
     351           0 :                         bytestream2_put_byte(pb, c2);
     352             :                     }
     353             :                 }
     354             :             } else {
     355           0 :                 int b = bytestream2_get_byte(gb);
     356           0 :                 int off = ((b & 0x7F)) + 1;
     357           0 :                 int len = ((b & 0x80) == 0) ? 2 : 3;
     358             : 
     359           0 :                 lz_copy(pb, g2, -off, len);
     360             :             }
     361             :         } else {
     362             :             int len;
     363             :             int off;
     364           0 :             if (use8) {
     365           0 :                 int q, b = bytestream2_get_byte(gb);
     366           0 :                 if ((b & 0xC0) == 0xC0) {
     367           0 :                     len = ((b & 0x3F)) + 8;
     368           0 :                     q = read_bits32(&bits, gb, 4);
     369           0 :                     off = (q << 8) + (bytestream2_get_byte(gb)) + 1;
     370             :                 } else {
     371             :                     int ofs1;
     372           0 :                     if ((b & 0x80) == 0) {
     373           0 :                         len = ((b >> 4)) + 6;
     374           0 :                         ofs1 = (b & 0xF);
     375             :                     } else {
     376           0 :                         len = ((b & 0x3F)) + 14;
     377           0 :                         ofs1 = read_bits32(&bits, gb, 4);
     378             :                     }
     379           0 :                     off = (ofs1 << 8) + (bytestream2_get_byte(gb)) - 4096;
     380             :                 }
     381             :             } else {
     382           0 :                 int ofs1, b = bytestream2_get_byte(gb);
     383             : 
     384           0 :                 if ((b >> 4) == 0xF) {
     385           0 :                     len = bytestream2_get_byte(gb) + 21;
     386             :                 } else {
     387           0 :                     len = (b >> 4) + 6;
     388             :                 }
     389           0 :                 ofs1 = (b & 0xF);
     390           0 :                 off = (ofs1 << 8) + bytestream2_get_byte(gb) - 4096;
     391             :             }
     392           0 :             lz_copy(pb, g2, off, len);
     393             :         }
     394             :     }
     395             : 
     396           0 :     return 0;
     397             : }
     398             : 
     399           0 : static int gdv_decode_frame(AVCodecContext *avctx, void *data,
     400             :                             int *got_frame, AVPacket *avpkt)
     401             : {
     402           0 :     GDVContext *gdv = avctx->priv_data;
     403           0 :     GetByteContext *gb = &gdv->gb;
     404           0 :     PutByteContext *pb = &gdv->pb;
     405           0 :     AVFrame *frame = data;
     406             :     int ret, i, pal_size;
     407           0 :     const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size);
     408             :     int compression;
     409             :     unsigned flags;
     410             :     uint8_t *dst;
     411             : 
     412           0 :     bytestream2_init(gb, avpkt->data, avpkt->size);
     413           0 :     bytestream2_init_writer(pb, gdv->frame, gdv->frame_size);
     414             : 
     415           0 :     flags = bytestream2_get_le32(gb);
     416           0 :     compression = flags & 0xF;
     417             : 
     418           0 :     if (compression == 4 || compression == 7 || compression > 8)
     419           0 :         return AVERROR_INVALIDDATA;
     420             : 
     421           0 :     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
     422           0 :         return ret;
     423           0 :     if (pal && pal_size == AVPALETTE_SIZE)
     424           0 :         memcpy(gdv->pal, pal, AVPALETTE_SIZE);
     425             : 
     426           0 :     rescale(gdv, gdv->frame, avctx->width, avctx->height,
     427           0 :             !!(flags & 0x10), !!(flags & 0x20));
     428             : 
     429           0 :     switch (compression) {
     430           0 :     case 1:
     431           0 :         memset(gdv->frame + PREAMBLE_SIZE, 0, gdv->frame_size - PREAMBLE_SIZE);
     432           0 :     case 0:
     433           0 :         if (bytestream2_get_bytes_left(gb) < 256*3)
     434           0 :             return AVERROR_INVALIDDATA;
     435           0 :         for (i = 0; i < 256; i++) {
     436           0 :             unsigned r = bytestream2_get_byte(gb);
     437           0 :             unsigned g = bytestream2_get_byte(gb);
     438           0 :             unsigned b = bytestream2_get_byte(gb);
     439           0 :             gdv->pal[i] = 0xFFU << 24 | r << 18 | g << 10 | b << 2;
     440             :         }
     441           0 :         break;
     442           0 :     case 2:
     443           0 :         ret = decompress_2(avctx);
     444           0 :         break;
     445           0 :     case 3:
     446           0 :         break;
     447           0 :     case 5:
     448           0 :         ret = decompress_5(avctx, flags >> 8);
     449           0 :         break;
     450           0 :     case 6:
     451           0 :         ret = decompress_68(avctx, flags >> 8, 0);
     452           0 :         break;
     453           0 :     case 8:
     454           0 :         ret = decompress_68(avctx, flags >> 8, 1);
     455           0 :         break;
     456           0 :     default:
     457           0 :         av_assert0(0);
     458             :     }
     459             : 
     460           0 :     memcpy(frame->data[1], gdv->pal, AVPALETTE_SIZE);
     461           0 :     dst = frame->data[0];
     462             : 
     463           0 :     if (!gdv->scale_v && !gdv->scale_h) {
     464           0 :         int sidx = PREAMBLE_SIZE, didx = 0;
     465             :         int y, x;
     466             : 
     467           0 :         for (y = 0; y < avctx->height; y++) {
     468           0 :             for (x = 0; x < avctx->width; x++) {
     469           0 :                 dst[x+didx] = gdv->frame[x+sidx];
     470             :             }
     471           0 :             sidx += avctx->width;
     472           0 :             didx += frame->linesize[0];
     473             :         }
     474             :     } else {
     475           0 :         int sidx = PREAMBLE_SIZE, didx = 0;
     476             :         int y, x;
     477             : 
     478           0 :         for (y = 0; y < avctx->height; y++) {
     479           0 :             if (!gdv->scale_v) {
     480           0 :                 for (x = 0; x < avctx->width; x++) {
     481           0 :                     dst[didx + x] = gdv->frame[sidx + x];
     482             :                 }
     483             :             } else {
     484           0 :                 for (x = 0; x < avctx->width; x++) {
     485           0 :                     dst[didx + x] = gdv->frame[sidx + x/2];
     486             :                 }
     487             :             }
     488           0 :             if (!gdv->scale_h || ((y & 1) == 1)) {
     489           0 :                 sidx += !gdv->scale_v ? avctx->width : avctx->width/2;
     490             :             }
     491           0 :             didx += frame->linesize[0];
     492             :         }
     493             :     }
     494             : 
     495           0 :     *got_frame = 1;
     496             : 
     497           0 :     return ret < 0 ? ret : avpkt->size;
     498             : }
     499             : 
     500           0 : static av_cold int gdv_decode_close(AVCodecContext *avctx)
     501             : {
     502           0 :     GDVContext *gdv = avctx->priv_data;
     503           0 :     av_freep(&gdv->frame);
     504           0 :     return 0;
     505             : }
     506             : 
     507             : AVCodec ff_gdv_decoder = {
     508             :     .name           = "gdv",
     509             :     .long_name      = NULL_IF_CONFIG_SMALL("Gremlin Digital Video"),
     510             :     .type           = AVMEDIA_TYPE_VIDEO,
     511             :     .id             = AV_CODEC_ID_GDV,
     512             :     .priv_data_size = sizeof(GDVContext),
     513             :     .init           = gdv_decode_init,
     514             :     .close          = gdv_decode_close,
     515             :     .decode         = gdv_decode_frame,
     516             :     .capabilities   = AV_CODEC_CAP_DR1,
     517             :     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     518             : };

Generated by: LCOV version 1.13