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

          Line data    Source code
       1             : /*
       2             :  * Mandsoft Screen Capture Codec decoder
       3             :  *
       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 <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : 
      27             : #include "avcodec.h"
      28             : #include "bytestream.h"
      29             : #include "internal.h"
      30             : 
      31             : #include <zlib.h>
      32             : 
      33             : typedef struct MSCCContext {
      34             :     unsigned          bpp;
      35             :     unsigned int      decomp_size;
      36             :     uint8_t          *decomp_buf;
      37             :     unsigned int      uncomp_size;
      38             :     uint8_t          *uncomp_buf;
      39             :     z_stream          zstream;
      40             : } MSCCContext;
      41             : 
      42           0 : static int rle_uncompress(AVCodecContext *avctx, GetByteContext *gb, PutByteContext *pb, int bpp)
      43             : {
      44           0 :     while (bytestream2_get_bytes_left(gb) > 0) {
      45             :         uint32_t fill;
      46             :         int j;
      47           0 :         unsigned run = bytestream2_get_byte(gb);
      48             : 
      49           0 :         if (run) {
      50           0 :             switch (avctx->bits_per_coded_sample) {
      51           0 :             case 8:
      52           0 :                 fill = bytestream2_get_byte(gb);
      53           0 :                 break;
      54           0 :             case 16:
      55           0 :                 fill = bytestream2_get_le16(gb);
      56           0 :                 break;
      57           0 :             case 24:
      58           0 :                 fill = bytestream2_get_le24(gb);
      59           0 :                 break;
      60           0 :             case 32:
      61           0 :                 fill = bytestream2_get_le32(gb);
      62           0 :                 break;
      63             :             }
      64             : 
      65           0 :             for (j = 0; j < run; j++) {
      66           0 :                 switch (avctx->bits_per_coded_sample) {
      67           0 :                 case 8:
      68           0 :                     bytestream2_put_byte(pb, fill);
      69           0 :                     break;
      70           0 :                 case 16:
      71           0 :                     bytestream2_put_le16(pb, fill);
      72           0 :                     break;
      73           0 :                 case 24:
      74           0 :                     bytestream2_put_le24(pb, fill);
      75           0 :                     break;
      76           0 :                 case 32:
      77           0 :                     bytestream2_put_le32(pb, fill);
      78           0 :                     break;
      79             :                 }
      80             :             }
      81             :         } else {
      82           0 :             unsigned copy = bytestream2_get_byte(gb);
      83             : 
      84           0 :             if (copy == 1) {
      85           0 :                 return 0;
      86           0 :             } else if (copy == 2) {
      87             :                 unsigned x, y;
      88             : 
      89           0 :                 x = bytestream2_get_byte(gb);
      90           0 :                 y = bytestream2_get_byte(gb);
      91             : 
      92           0 :                 bytestream2_skip_p(pb, x * bpp);
      93           0 :                 bytestream2_skip_p(pb, y * bpp * avctx->width);
      94             :             } else {
      95           0 :                 for (j = 0; j < copy; j++) {
      96           0 :                     switch (avctx->bits_per_coded_sample) {
      97           0 :                     case 8:
      98           0 :                         bytestream2_put_byte(pb, bytestream2_get_byte(gb));
      99           0 :                         break;
     100           0 :                     case 16:
     101           0 :                         bytestream2_put_le16(pb, bytestream2_get_le16(gb));
     102           0 :                         break;
     103           0 :                     case 24:
     104           0 :                         bytestream2_put_le24(pb, bytestream2_get_le24(gb));
     105           0 :                         break;
     106           0 :                     case 32:
     107           0 :                         bytestream2_put_le32(pb, bytestream2_get_le32(gb));
     108           0 :                         break;
     109             :                     }
     110             :                 }
     111             :             }
     112             :         }
     113             :     }
     114             : 
     115           0 :     return AVERROR_INVALIDDATA;
     116             : }
     117             : 
     118           0 : static int decode_frame(AVCodecContext *avctx,
     119             :                         void *data, int *got_frame,
     120             :                         AVPacket *avpkt)
     121             : {
     122           0 :     MSCCContext *s = avctx->priv_data;
     123           0 :     AVFrame *frame = data;
     124           0 :     uint8_t *buf = avpkt->data;
     125           0 :     int buf_size = avpkt->size;
     126             :     GetByteContext gb;
     127             :     PutByteContext pb;
     128             :     int ret, j;
     129             : 
     130           0 :     if (avpkt->size < 3)
     131           0 :         return AVERROR_INVALIDDATA;
     132           0 :     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
     133           0 :         return ret;
     134             : 
     135           0 :     if (avctx->codec_id == AV_CODEC_ID_MSCC) {
     136           0 :         avpkt->data[2] ^= avpkt->data[0];
     137           0 :         buf += 2;
     138           0 :         buf_size -= 2;
     139             :     }
     140             : 
     141           0 :     ret = inflateReset(&s->zstream);
     142           0 :     if (ret != Z_OK) {
     143           0 :         av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);
     144           0 :         return AVERROR_UNKNOWN;
     145             :     }
     146           0 :     s->zstream.next_in   = buf;
     147           0 :     s->zstream.avail_in  = buf_size;
     148           0 :     s->zstream.next_out  = s->decomp_buf;
     149           0 :     s->zstream.avail_out = s->decomp_size;
     150           0 :     ret = inflate(&s->zstream, Z_FINISH);
     151           0 :     if (ret != Z_STREAM_END) {
     152           0 :         av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret);
     153           0 :         return AVERROR_UNKNOWN;
     154             :     }
     155             : 
     156           0 :     bytestream2_init(&gb, s->decomp_buf, s->zstream.total_out);
     157           0 :     bytestream2_init_writer(&pb, s->uncomp_buf, s->uncomp_size);
     158             : 
     159           0 :     ret = rle_uncompress(avctx, &gb, &pb, s->bpp);
     160           0 :     if (ret)
     161           0 :         return ret;
     162             : 
     163           0 :     for (j = 0; j < avctx->height; j++) {
     164           0 :         memcpy(frame->data[0] + (avctx->height - j - 1) * frame->linesize[0],
     165           0 :                s->uncomp_buf + s->bpp * j * avctx->width, s->bpp * avctx->width);
     166             :     }
     167             : 
     168           0 :     frame->key_frame = 1;
     169           0 :     frame->pict_type = AV_PICTURE_TYPE_I;
     170             : 
     171           0 :     *got_frame = 1;
     172             : 
     173           0 :     return avpkt->size;
     174             : }
     175             : 
     176           0 : static av_cold int decode_init(AVCodecContext *avctx)
     177             : {
     178           0 :     MSCCContext *s = avctx->priv_data;
     179             :     int zret;
     180             : 
     181           0 :     switch (avctx->bits_per_coded_sample) {
     182           0 :     case  8: avctx->pix_fmt = AV_PIX_FMT_GRAY8;  break;
     183           0 :     case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
     184           0 :     case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24;  break;
     185           0 :     case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA;   break;
     186           0 :     default:
     187           0 :         av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", avctx->bits_per_coded_sample);
     188           0 :         return AVERROR_INVALIDDATA;
     189             :     }
     190             : 
     191           0 :     s->bpp = avctx->bits_per_coded_sample >> 3;
     192           0 :     memset(&s->zstream, 0, sizeof(z_stream));
     193             : 
     194           0 :     s->decomp_size = 4 * avctx->height * ((avctx->width * avctx->bits_per_coded_sample + 31) / 32);
     195           0 :     if (!(s->decomp_buf = av_malloc(s->decomp_size)))
     196           0 :         return AVERROR(ENOMEM);
     197             : 
     198           0 :     s->uncomp_size = 4 * avctx->height * ((avctx->width * avctx->bits_per_coded_sample + 31) / 32);
     199           0 :     if (!(s->uncomp_buf = av_malloc(s->uncomp_size)))
     200           0 :         return AVERROR(ENOMEM);
     201             : 
     202           0 :     s->zstream.zalloc = Z_NULL;
     203           0 :     s->zstream.zfree = Z_NULL;
     204           0 :     s->zstream.opaque = Z_NULL;
     205           0 :     zret = inflateInit(&s->zstream);
     206           0 :     if (zret != Z_OK) {
     207           0 :         av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
     208           0 :         return AVERROR_UNKNOWN;
     209             :     }
     210             : 
     211           0 :     return 0;
     212             : }
     213             : 
     214           0 : static av_cold int decode_close(AVCodecContext *avctx)
     215             : {
     216           0 :     MSCCContext *s = avctx->priv_data;
     217             : 
     218           0 :     av_freep(&s->decomp_buf);
     219           0 :     s->decomp_size = 0;
     220           0 :     av_freep(&s->uncomp_buf);
     221           0 :     s->uncomp_size = 0;
     222           0 :     inflateEnd(&s->zstream);
     223             : 
     224           0 :     return 0;
     225             : }
     226             : 
     227             : AVCodec ff_mscc_decoder = {
     228             :     .name             = "mscc",
     229             :     .long_name        = NULL_IF_CONFIG_SMALL("Mandsoft Screen Capture Codec"),
     230             :     .type             = AVMEDIA_TYPE_VIDEO,
     231             :     .id               = AV_CODEC_ID_MSCC,
     232             :     .priv_data_size   = sizeof(MSCCContext),
     233             :     .init             = decode_init,
     234             :     .close            = decode_close,
     235             :     .decode           = decode_frame,
     236             :     .capabilities     = AV_CODEC_CAP_DR1,
     237             : };
     238             : 
     239             : AVCodec ff_srgc_decoder = {
     240             :     .name             = "srgc",
     241             :     .long_name        = NULL_IF_CONFIG_SMALL("Screen Recorder Gold Codec"),
     242             :     .type             = AVMEDIA_TYPE_VIDEO,
     243             :     .id               = AV_CODEC_ID_SRGC,
     244             :     .priv_data_size   = sizeof(MSCCContext),
     245             :     .init             = decode_init,
     246             :     .close            = decode_close,
     247             :     .decode           = decode_frame,
     248             :     .capabilities     = AV_CODEC_CAP_DR1,
     249             : };

Generated by: LCOV version 1.13