FFmpeg  4.0
mscc.c
Go to the documentation of this file.
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;
37  unsigned int uncomp_size;
39  z_stream zstream;
40 } MSCCContext;
41 
43 {
44  while (bytestream2_get_bytes_left(gb) > 0) {
45  uint32_t fill;
46  int j;
47  unsigned run = bytestream2_get_byte(gb);
48 
49  if (run) {
50  switch (avctx->bits_per_coded_sample) {
51  case 8:
52  fill = bytestream2_get_byte(gb);
53  break;
54  case 16:
55  fill = bytestream2_get_le16(gb);
56  break;
57  case 24:
58  fill = bytestream2_get_le24(gb);
59  break;
60  case 32:
61  fill = bytestream2_get_le32(gb);
62  break;
63  }
64 
65  for (j = 0; j < run; j++) {
66  switch (avctx->bits_per_coded_sample) {
67  case 8:
68  bytestream2_put_byte(pb, fill);
69  break;
70  case 16:
71  bytestream2_put_le16(pb, fill);
72  break;
73  case 24:
74  bytestream2_put_le24(pb, fill);
75  break;
76  case 32:
77  bytestream2_put_le32(pb, fill);
78  break;
79  }
80  }
81  } else {
82  unsigned copy = bytestream2_get_byte(gb);
83 
84  if (copy == 1) {
85  return 0;
86  } else if (copy == 2) {
87  unsigned x, y;
88 
89  x = bytestream2_get_byte(gb);
90  y = bytestream2_get_byte(gb);
91 
92  bytestream2_skip_p(pb, x * bpp);
93  bytestream2_skip_p(pb, y * bpp * avctx->width);
94  } else {
95  for (j = 0; j < copy; j++) {
96  switch (avctx->bits_per_coded_sample) {
97  case 8:
98  bytestream2_put_byte(pb, bytestream2_get_byte(gb));
99  break;
100  case 16:
101  bytestream2_put_le16(pb, bytestream2_get_le16(gb));
102  break;
103  case 24:
104  bytestream2_put_le24(pb, bytestream2_get_le24(gb));
105  break;
106  case 32:
107  bytestream2_put_le32(pb, bytestream2_get_le32(gb));
108  break;
109  }
110  }
111  }
112  }
113  }
114 
115  return AVERROR_INVALIDDATA;
116 }
117 
118 static int decode_frame(AVCodecContext *avctx,
119  void *data, int *got_frame,
120  AVPacket *avpkt)
121 {
122  MSCCContext *s = avctx->priv_data;
123  AVFrame *frame = data;
124  uint8_t *buf = avpkt->data;
125  int buf_size = avpkt->size;
126  GetByteContext gb;
127  PutByteContext pb;
128  int ret, j;
129 
130  if (avpkt->size < 3)
131  return AVERROR_INVALIDDATA;
132  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
133  return ret;
134 
135  if (avctx->codec_id == AV_CODEC_ID_MSCC) {
136  avpkt->data[2] ^= avpkt->data[0];
137  buf += 2;
138  buf_size -= 2;
139  }
140 
141  ret = inflateReset(&s->zstream);
142  if (ret != Z_OK) {
143  av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);
144  return AVERROR_UNKNOWN;
145  }
146  s->zstream.next_in = buf;
147  s->zstream.avail_in = buf_size;
148  s->zstream.next_out = s->decomp_buf;
149  s->zstream.avail_out = s->decomp_size;
150  ret = inflate(&s->zstream, Z_FINISH);
151  if (ret != Z_STREAM_END) {
152  av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret);
153  return AVERROR_UNKNOWN;
154  }
155 
156  bytestream2_init(&gb, s->decomp_buf, s->zstream.total_out);
158 
159  ret = rle_uncompress(avctx, &gb, &pb, s->bpp);
160  if (ret)
161  return ret;
162 
163  for (j = 0; j < avctx->height; j++) {
164  memcpy(frame->data[0] + (avctx->height - j - 1) * frame->linesize[0],
165  s->uncomp_buf + s->bpp * j * avctx->width, s->bpp * avctx->width);
166  }
167 
168  frame->key_frame = 1;
169  frame->pict_type = AV_PICTURE_TYPE_I;
170 
171  *got_frame = 1;
172 
173  return avpkt->size;
174 }
175 
177 {
178  MSCCContext *s = avctx->priv_data;
179  int zret;
180 
181  switch (avctx->bits_per_coded_sample) {
182  case 8: avctx->pix_fmt = AV_PIX_FMT_GRAY8; break;
183  case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
184  case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24; break;
185  case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA; break;
186  default:
187  av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", avctx->bits_per_coded_sample);
188  return AVERROR_INVALIDDATA;
189  }
190 
191  s->bpp = avctx->bits_per_coded_sample >> 3;
192  memset(&s->zstream, 0, sizeof(z_stream));
193 
194  s->decomp_size = 4 * avctx->height * ((avctx->width * avctx->bits_per_coded_sample + 31) / 32);
195  if (!(s->decomp_buf = av_malloc(s->decomp_size)))
196  return AVERROR(ENOMEM);
197 
198  s->uncomp_size = 4 * avctx->height * ((avctx->width * avctx->bits_per_coded_sample + 31) / 32);
199  if (!(s->uncomp_buf = av_malloc(s->uncomp_size)))
200  return AVERROR(ENOMEM);
201 
202  s->zstream.zalloc = Z_NULL;
203  s->zstream.zfree = Z_NULL;
204  s->zstream.opaque = Z_NULL;
205  zret = inflateInit(&s->zstream);
206  if (zret != Z_OK) {
207  av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
208  return AVERROR_UNKNOWN;
209  }
210 
211  return 0;
212 }
213 
215 {
216  MSCCContext *s = avctx->priv_data;
217 
218  av_freep(&s->decomp_buf);
219  s->decomp_size = 0;
220  av_freep(&s->uncomp_buf);
221  s->uncomp_size = 0;
222  inflateEnd(&s->zstream);
223 
224  return 0;
225 }
226 
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 
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 };
const char * s
Definition: avisynth_c.h:768
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static void copy(const float *p1, float *p2, const int length)
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: avcodec.h:1431
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
Definition: bytestream.h:143
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1727
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
uint8_t run
Definition: svq3.c:206
AVCodec.
Definition: avcodec.h:3408
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:42
uint8_t
#define av_cold
Definition: attributes.h:82
#define av_malloc(s)
static AVFrame * frame
const char data[16]
Definition: mxf.c:90
uint8_t * data
Definition: avcodec.h:1430
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord)
Definition: vf_neighbor.c:129
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition: avcodec.h:2734
unsigned bpp
Definition: mscc.c:34
#define av_log(a,...)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:91
static av_cold int decode_init(AVCodecContext *avctx)
Definition: mscc.c:176
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
const char * name
Name of the codec implementation.
Definition: avcodec.h:3415
AVCodec ff_mscc_decoder
Definition: mscc.c:227
unsigned int decomp_size
Definition: mscc.c:35
static av_always_inline void bytestream2_skip_p(PutByteContext *p, unsigned int size)
Definition: bytestream.h:176
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:301
z_stream zstream
Definition: mscc.c:39
int width
picture width / height.
Definition: avcodec.h:1690
unsigned int uncomp_size
Definition: mscc.c:37
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:65
AVCodec ff_srgc_decoder
Definition: mscc.c:239
Libavcodec external API header.
enum AVCodecID codec_id
Definition: avcodec.h:1528
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:249
main external API structure.
Definition: avcodec.h:1518
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1891
void * buf
Definition: avisynth_c.h:690
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:232
static int rle_uncompress(AVCodecContext *avctx, GetByteContext *gb, PutByteContext *pb, int bpp)
Definition: mscc.c:42
Y , 8bpp.
Definition: pixfmt.h:70
common internal api header.
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:356
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: mscc.c:118
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
void * priv_data
Definition: avcodec.h:1545
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:296
#define av_freep(p)
This structure stores compressed data.
Definition: avcodec.h:1407
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:959
uint8_t * decomp_buf
Definition: mscc.c:36
uint8_t * uncomp_buf
Definition: mscc.c:38
static av_cold int decode_close(AVCodecContext *avctx)
Definition: mscc.c:214