FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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  switch (avctx->bits_per_coded_sample) {
56  case 8:
57  fill = bytestream2_get_byte(gb);
58  break;
59  case 16:
60  fill = bytestream2_get_le16(gb);
61  break;
62  case 24:
63  fill = bytestream2_get_le24(gb);
64  break;
65  case 32:
66  fill = bytestream2_get_le32(gb);
67  break;
68  }
69 
70  for (j = 0; j < run; j++) {
71  switch (avctx->bits_per_coded_sample) {
72  case 8:
73  bytestream2_put_byte(pb, fill);
74  break;
75  case 16:
76  bytestream2_put_le16(pb, fill);
77  break;
78  case 24:
79  bytestream2_put_le24(pb, fill);
80  break;
81  case 32:
82  bytestream2_put_le32(pb, fill);
83  break;
84  }
85  }
86  x += run;
87  } else {
88  unsigned copy = bytestream2_get_byte(gb);
89 
90  if (copy == 0) {
91  x = 0;
92  y++;
93  bytestream2_seek_p(pb, y * avctx->width * s->bpp, SEEK_SET);
94  } else if (copy == 1) {
95  return 0;
96  } else if (copy == 2) {
97 
98  x += bytestream2_get_byte(gb);
99  y += bytestream2_get_byte(gb);
100 
101  bytestream2_seek_p(pb, y * avctx->width * s->bpp + x * s->bpp, SEEK_SET);
102  } else {
103  for (j = 0; j < copy; j++) {
104  switch (avctx->bits_per_coded_sample) {
105  case 8:
106  bytestream2_put_byte(pb, bytestream2_get_byte(gb));
107  break;
108  case 16:
109  bytestream2_put_le16(pb, bytestream2_get_le16(gb));
110  break;
111  case 24:
112  bytestream2_put_le24(pb, bytestream2_get_le24(gb));
113  break;
114  case 32:
115  bytestream2_put_le32(pb, bytestream2_get_le32(gb));
116  break;
117  }
118  }
119 
120  if (s->bpp == 1 && (copy & 1))
121  bytestream2_skip(gb, 1);
122  x += copy;
123  }
124  }
125  }
126 
127  return AVERROR_INVALIDDATA;
128 }
129 
130 static int decode_frame(AVCodecContext *avctx,
131  void *data, int *got_frame,
132  AVPacket *avpkt)
133 {
134  MSCCContext *s = avctx->priv_data;
135  AVFrame *frame = data;
136  uint8_t *buf = avpkt->data;
137  int buf_size = avpkt->size;
138  GetByteContext gb;
139  PutByteContext pb;
140  int ret, j;
141 
142  if (avpkt->size < 3)
143  return buf_size;
144 
145  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
146  return ret;
147 
148  if (avctx->codec_id == AV_CODEC_ID_MSCC) {
149  avpkt->data[2] ^= avpkt->data[0];
150  buf += 2;
151  buf_size -= 2;
152  }
153 
154  if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
155  int size;
156  const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
157 
158  if (pal && size == AVPALETTE_SIZE) {
159  frame->palette_has_changed = 1;
160  for (j = 0; j < 256; j++)
161  s->pal[j] = 0xFF000000 | AV_RL32(pal + j * 4);
162  } else if (pal) {
163  av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
164  }
165  memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
166  }
167 
168  ret = inflateReset(&s->zstream);
169  if (ret != Z_OK) {
170  av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);
171  return AVERROR_UNKNOWN;
172  }
173  s->zstream.next_in = buf;
174  s->zstream.avail_in = buf_size;
175  s->zstream.next_out = s->decomp_buf;
176  s->zstream.avail_out = s->decomp_size;
177  ret = inflate(&s->zstream, Z_FINISH);
178  if (ret != Z_STREAM_END) {
179  av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret);
180  return AVERROR_UNKNOWN;
181  }
182 
183  bytestream2_init(&gb, s->decomp_buf, s->zstream.total_out);
185 
186  ret = rle_uncompress(avctx, &gb, &pb);
187  if (ret)
188  return ret;
189 
190  for (j = 0; j < avctx->height; j++) {
191  memcpy(frame->data[0] + (avctx->height - j - 1) * frame->linesize[0],
192  s->uncomp_buf + s->bpp * j * avctx->width, s->bpp * avctx->width);
193  }
194 
195  frame->key_frame = 1;
196  frame->pict_type = AV_PICTURE_TYPE_I;
197 
198  *got_frame = 1;
199 
200  return avpkt->size;
201 }
202 
204 {
205  MSCCContext *s = avctx->priv_data;
206  int stride, zret;
207 
208  switch (avctx->bits_per_coded_sample) {
209  case 8: avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
210  case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
211  case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24; break;
212  case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA; break;
213  default:
214  av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", avctx->bits_per_coded_sample);
215  return AVERROR_INVALIDDATA;
216  }
217 
218  s->bpp = avctx->bits_per_coded_sample >> 3;
219  stride = 4 * ((avctx->width * avctx->bits_per_coded_sample + 31) / 32);
220 
221  s->decomp_size = 2 * avctx->height * stride;
222  if (!(s->decomp_buf = av_malloc(s->decomp_size)))
223  return AVERROR(ENOMEM);
224 
225  s->uncomp_size = avctx->height * stride;
226  if (!(s->uncomp_buf = av_malloc(s->uncomp_size)))
227  return AVERROR(ENOMEM);
228 
229  s->zstream.zalloc = Z_NULL;
230  s->zstream.zfree = Z_NULL;
231  s->zstream.opaque = Z_NULL;
232  zret = inflateInit(&s->zstream);
233  if (zret != Z_OK) {
234  av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
235  return AVERROR_UNKNOWN;
236  }
237 
238  return 0;
239 }
240 
242 {
243  MSCCContext *s = avctx->priv_data;
244 
245  av_freep(&s->decomp_buf);
246  s->decomp_size = 0;
247  av_freep(&s->uncomp_buf);
248  s->uncomp_size = 0;
249  inflateEnd(&s->zstream);
250 
251  return 0;
252 }
253 
255  .name = "mscc",
256  .long_name = NULL_IF_CONFIG_SMALL("Mandsoft Screen Capture Codec"),
257  .type = AVMEDIA_TYPE_VIDEO,
258  .id = AV_CODEC_ID_MSCC,
259  .priv_data_size = sizeof(MSCCContext),
260  .init = decode_init,
261  .close = decode_close,
262  .decode = decode_frame,
263  .capabilities = AV_CODEC_CAP_DR1,
264  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
265 };
266 
268  .name = "srgc",
269  .long_name = NULL_IF_CONFIG_SMALL("Screen Recorder Gold Codec"),
270  .type = AVMEDIA_TYPE_VIDEO,
271  .id = AV_CODEC_ID_SRGC,
272  .priv_data_size = sizeof(MSCCContext),
273  .init = decode_init,
274  .close = decode_close,
275  .decode = decode_frame,
276  .capabilities = AV_CODEC_CAP_DR1,
277  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
278 };
#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)
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: avcodec.h:1445
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:1742
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:3423
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)
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
uint8_t * data
Definition: avcodec.h:1444
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord)
Definition: vf_neighbor.c:189
ptrdiff_t size
Definition: opengl_enc.c:101
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition: avcodec.h:2749
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
An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE bytes worth of palette...
Definition: avcodec.h:1157
#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:350
#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:95
static av_cold int decode_init(AVCodecContext *avctx)
Definition: mscc.c:203
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:3430
AVCodec ff_mscc_decoder
Definition: mscc.c:254
unsigned int decomp_size
Definition: mscc.c:35
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:1705
#define s(width, name)
Definition: cbs_vp9.c:257
unsigned int uncomp_size
Definition: mscc.c:37
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:267
Libavcodec external API header.
enum AVCodecID codec_id
Definition: avcodec.h:1542
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:1532
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1922
void * buf
Definition: avisynth_c.h:690
int palette_has_changed
Tell user application that palette has changed from previous frame.
Definition: frame.h:375
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:232
common internal api header.
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:367
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: mscc.c:130
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
void * priv_data
Definition: avcodec.h:1559
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:296
uint32_t pal[256]
Definition: mscc.c:41
#define av_freep(p)
#define stride
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:87
This structure stores compressed data.
Definition: avcodec.h:1421
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:967
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:241