FFmpeg  4.3.7
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 
41  uint32_t pal[256];
42 } MSCCContext;
43 
45 {
46  MSCCContext *s = avctx->priv_data;
47  unsigned x = 0, y = 0;
48 
49  while (bytestream2_get_bytes_left(gb) > 0) {
50  uint32_t fill;
51  int j;
52  unsigned run = bytestream2_get_byte(gb);
53 
54  if (run) {
55  if (bytestream2_get_bytes_left_p(pb) < run * s->bpp)
56  return AVERROR_INVALIDDATA;
57 
58  switch (avctx->bits_per_coded_sample) {
59  case 8:
60  fill = bytestream2_get_byte(gb);
61  break;
62  case 16:
63  fill = bytestream2_get_le16(gb);
64  break;
65  case 24:
66  fill = bytestream2_get_le24(gb);
67  break;
68  case 32:
69  fill = bytestream2_get_le32(gb);
70  break;
71  }
72 
73  for (j = 0; j < run; j++) {
74  switch (avctx->bits_per_coded_sample) {
75  case 8:
76  bytestream2_put_byte(pb, fill);
77  break;
78  case 16:
79  bytestream2_put_le16(pb, fill);
80  break;
81  case 24:
82  bytestream2_put_le24(pb, fill);
83  break;
84  case 32:
85  bytestream2_put_le32(pb, fill);
86  break;
87  }
88  }
89  x += run;
90  } else {
91  unsigned copy = bytestream2_get_byte(gb);
92 
93  if (copy == 0) {
94  x = 0;
95  y++;
96  bytestream2_seek_p(pb, y * avctx->width * s->bpp, SEEK_SET);
97  } else if (copy == 1) {
98  return 0;
99  } else if (copy == 2) {
100 
101  x += bytestream2_get_byte(gb);
102  y += bytestream2_get_byte(gb);
103 
104  bytestream2_seek_p(pb, y * avctx->width * s->bpp + x * s->bpp, SEEK_SET);
105  } else {
106  if (bytestream2_get_bytes_left_p(pb) < copy * s->bpp)
107  return AVERROR_INVALIDDATA;
108 
109  for (j = 0; j < copy; j++) {
110  switch (avctx->bits_per_coded_sample) {
111  case 8:
112  bytestream2_put_byte(pb, bytestream2_get_byte(gb));
113  break;
114  case 16:
115  bytestream2_put_le16(pb, bytestream2_get_le16(gb));
116  break;
117  case 24:
118  bytestream2_put_le24(pb, bytestream2_get_le24(gb));
119  break;
120  case 32:
121  bytestream2_put_le32(pb, bytestream2_get_le32(gb));
122  break;
123  }
124  }
125 
126  if (s->bpp == 1 && (copy & 1))
127  bytestream2_skip(gb, 1);
128  x += copy;
129  }
130  }
131  }
132 
133  return AVERROR_INVALIDDATA;
134 }
135 
136 static int decode_frame(AVCodecContext *avctx,
137  void *data, int *got_frame,
138  AVPacket *avpkt)
139 {
140  MSCCContext *s = avctx->priv_data;
141  AVFrame *frame = data;
142  uint8_t *buf = avpkt->data;
143  int buf_size = avpkt->size;
144  GetByteContext gb;
145  PutByteContext pb;
146  int ret, j;
147 
148  if (avpkt->size < 3)
149  return buf_size;
150 
151  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
152  return ret;
153 
154  if (avctx->codec_id == AV_CODEC_ID_MSCC) {
155  avpkt->data[2] ^= avpkt->data[0];
156  buf += 2;
157  buf_size -= 2;
158  }
159 
160  if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
161  int size;
162  const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
163 
164  if (pal && size == AVPALETTE_SIZE) {
165  frame->palette_has_changed = 1;
166  for (j = 0; j < 256; j++)
167  s->pal[j] = 0xFF000000 | AV_RL32(pal + j * 4);
168  } else if (pal) {
169  av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
170  }
171  memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
172  }
173 
174  ret = inflateReset(&s->zstream);
175  if (ret != Z_OK) {
176  av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);
177  return AVERROR_UNKNOWN;
178  }
179  s->zstream.next_in = buf;
180  s->zstream.avail_in = buf_size;
181  s->zstream.next_out = s->decomp_buf;
182  s->zstream.avail_out = s->decomp_size;
183  ret = inflate(&s->zstream, Z_FINISH);
184  if (ret != Z_STREAM_END) {
185  av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret);
186  return AVERROR_UNKNOWN;
187  }
188 
189  bytestream2_init(&gb, s->decomp_buf, s->zstream.total_out);
191 
192  ret = rle_uncompress(avctx, &gb, &pb);
193  if (ret)
194  return ret;
195 
196  for (j = 0; j < avctx->height; j++) {
197  memcpy(frame->data[0] + (avctx->height - j - 1) * frame->linesize[0],
198  s->uncomp_buf + s->bpp * j * avctx->width, s->bpp * avctx->width);
199  }
200 
201  frame->key_frame = 1;
202  frame->pict_type = AV_PICTURE_TYPE_I;
203 
204  *got_frame = 1;
205 
206  return avpkt->size;
207 }
208 
210 {
211  MSCCContext *s = avctx->priv_data;
212  int stride, zret;
213 
214  switch (avctx->bits_per_coded_sample) {
215  case 8: avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
216  case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
217  case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24; break;
218  case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA; break;
219  default:
220  av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", avctx->bits_per_coded_sample);
221  return AVERROR_INVALIDDATA;
222  }
223 
224  s->bpp = avctx->bits_per_coded_sample >> 3;
225  stride = 4 * ((avctx->width * avctx->bits_per_coded_sample + 31) / 32);
226 
227  s->decomp_size = 2 * avctx->height * stride;
228  if (!(s->decomp_buf = av_malloc(s->decomp_size)))
229  return AVERROR(ENOMEM);
230 
231  s->uncomp_size = avctx->height * stride;
232  if (!(s->uncomp_buf = av_malloc(s->uncomp_size)))
233  return AVERROR(ENOMEM);
234 
235  s->zstream.zalloc = Z_NULL;
236  s->zstream.zfree = Z_NULL;
237  s->zstream.opaque = Z_NULL;
238  zret = inflateInit(&s->zstream);
239  if (zret != Z_OK) {
240  av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
241  return AVERROR_UNKNOWN;
242  }
243 
244  return 0;
245 }
246 
248 {
249  MSCCContext *s = avctx->priv_data;
250 
251  av_freep(&s->decomp_buf);
252  s->decomp_size = 0;
253  av_freep(&s->uncomp_buf);
254  s->uncomp_size = 0;
255  inflateEnd(&s->zstream);
256 
257  return 0;
258 }
259 
261  .name = "mscc",
262  .long_name = NULL_IF_CONFIG_SMALL("Mandsoft Screen Capture Codec"),
263  .type = AVMEDIA_TYPE_VIDEO,
264  .id = AV_CODEC_ID_MSCC,
265  .priv_data_size = sizeof(MSCCContext),
266  .init = decode_init,
267  .close = decode_close,
268  .decode = decode_frame,
269  .capabilities = AV_CODEC_CAP_DR1,
270  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
271 };
272 
274  .name = "srgc",
275  .long_name = NULL_IF_CONFIG_SMALL("Screen Recorder Gold Codec"),
276  .type = AVMEDIA_TYPE_VIDEO,
277  .id = AV_CODEC_ID_SRGC,
278  .priv_data_size = sizeof(MSCCContext),
279  .init = decode_init,
280  .close = decode_close,
281  .decode = decode_frame,
282  .capabilities = AV_CODEC_CAP_DR1,
283  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
284 };
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: internal.h:48
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static void copy(const float *p1, float *p2, const int length)
int size
This structure describes decoded (raw) audio or video data.
Definition: frame.h:300
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: packet.h:356
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:736
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:209
int stride
Definition: mace.c:144
AVCodec.
Definition: codec.h:190
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
uint8_t
#define av_cold
Definition: attributes.h:88
#define av_malloc(s)
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
static int rle_uncompress(AVCodecContext *avctx, GetByteContext *gb, PutByteContext *pb)
Definition: mscc.c:44
static AVFrame * frame
const char data[16]
Definition: mxf.c:91
uint8_t * data
Definition: packet.h:355
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition: avcodec.h:1750
unsigned bpp
Definition: mscc.c:34
#define av_log(a,...)
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE bytes worth of palette...
Definition: packet.h:46
static av_always_inline int bytestream2_get_bytes_left_p(PutByteContext *p)
Definition: bytestream.h:159
#define AVERROR(e)
Definition: error.h:43
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:164
uint8_t * av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, int *size)
Get side information from packet.
Definition: avpacket.c:353
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:188
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
static av_cold int decode_init(AVCodecContext *avctx)
Definition: mscc.c:209
const char * name
Name of the codec implementation.
Definition: codec.h:197
AVCodec ff_mscc_decoder
Definition: mscc.c:260
unsigned int decomp_size
Definition: mscc.c:35
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:383
z_stream zstream
Definition: mscc.c:39
int width
picture width / height.
Definition: avcodec.h:699
#define s(width, name)
Definition: cbs_vp9.c:257
unsigned int uncomp_size
Definition: mscc.c:37
#define AV_RL32
Definition: intreadwrite.h:146
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
static av_always_inline int bytestream2_seek_p(PutByteContext *p, int offset, int whence)
Definition: bytestream.h:232
AVCodec ff_srgc_decoder
Definition: mscc.c:273
Libavcodec external API header.
enum AVCodecID codec_id
Definition: avcodec.h:536
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:331
main external API structure.
Definition: avcodec.h:526
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1854
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
Definition: vf_neighbor.c:198
int palette_has_changed
Tell user application that palette has changed from previous frame.
Definition: frame.h:457
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:314
common internal api header.
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:385
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: mscc.c:136
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
void * priv_data
Definition: avcodec.h:553
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:378
uint32_t pal[256]
Definition: mscc.c:41
#define av_freep(p)
This structure stores compressed data.
Definition: packet.h:332
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:50
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:247