FFmpeg
escape130.c
Go to the documentation of this file.
1 /*
2  * Escape 130 video decoder
3  * Copyright (C) 2008 Eli Friedman (eli.friedman <at> gmail.com)
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/attributes.h"
23 #include "libavutil/mem.h"
24 
25 #define BITSTREAM_READER_LE
26 #include "avcodec.h"
27 #include "get_bits.h"
28 #include "internal.h"
29 
30 typedef struct Escape130Context {
32 
36 
38  int linesize[3];
40 
41 static const uint8_t offset_table[] = { 2, 4, 10, 20 };
42 static const int8_t sign_table[64][4] = {
43  { 0, 0, 0, 0 },
44  { -1, 1, 0, 0 },
45  { 1, -1, 0, 0 },
46  { -1, 0, 1, 0 },
47  { -1, 1, 1, 0 },
48  { 0, -1, 1, 0 },
49  { 1, -1, 1, 0 },
50  { -1, -1, 1, 0 },
51  { 1, 0, -1, 0 },
52  { 0, 1, -1, 0 },
53  { 1, 1, -1, 0 },
54  { -1, 1, -1, 0 },
55  { 1, -1, -1, 0 },
56  { -1, 0, 0, 1 },
57  { -1, 1, 0, 1 },
58  { 0, -1, 0, 1 },
59 
60  { 0, 0, 0, 0 },
61  { 1, -1, 0, 1 },
62  { -1, -1, 0, 1 },
63  { -1, 0, 1, 1 },
64  { -1, 1, 1, 1 },
65  { 0, -1, 1, 1 },
66  { 1, -1, 1, 1 },
67  { -1, -1, 1, 1 },
68  { 0, 0, -1, 1 },
69  { 1, 0, -1, 1 },
70  { -1, 0, -1, 1 },
71  { 0, 1, -1, 1 },
72  { 1, 1, -1, 1 },
73  { -1, 1, -1, 1 },
74  { 0, -1, -1, 1 },
75  { 1, -1, -1, 1 },
76 
77  { 0, 0, 0, 0 },
78  { -1, -1, -1, 1 },
79  { 1, 0, 0, -1 },
80  { 0, 1, 0, -1 },
81  { 1, 1, 0, -1 },
82  { -1, 1, 0, -1 },
83  { 1, -1, 0, -1 },
84  { 0, 0, 1, -1 },
85  { 1, 0, 1, -1 },
86  { -1, 0, 1, -1 },
87  { 0, 1, 1, -1 },
88  { 1, 1, 1, -1 },
89  { -1, 1, 1, -1 },
90  { 0, -1, 1, -1 },
91  { 1, -1, 1, -1 },
92  { -1, -1, 1, -1 },
93 
94  { 0, 0, 0, 0 },
95  { 1, 0, -1, -1 },
96  { 0, 1, -1, -1 },
97  { 1, 1, -1, -1 },
98  { -1, 1, -1, -1 },
99  { 1, -1, -1, -1 }
100 };
101 
102 static const int8_t luma_adjust[] = { -4, -3, -2, -1, 1, 2, 3, 4 };
103 
104 static const int8_t chroma_adjust[2][8] = {
105  { 1, 1, 0, -1, -1, -1, 0, 1 },
106  { 0, 1, 1, 1, 0, -1, -1, -1 }
107 };
108 
109 static const uint8_t chroma_vals[] = {
110  20, 28, 36, 44, 52, 60, 68, 76,
111  84, 92, 100, 106, 112, 116, 120, 124,
112  128, 132, 136, 140, 144, 150, 156, 164,
113  172, 180, 188, 196, 204, 212, 220, 228
114 };
115 
117 {
118  Escape130Context *s = avctx->priv_data;
119  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
120 
121  if ((avctx->width & 1) || (avctx->height & 1)) {
122  av_log(avctx, AV_LOG_ERROR,
123  "Dimensions should be a multiple of two.\n");
124  return AVERROR_INVALIDDATA;
125  }
126 
127  s->old_y_avg = av_malloc(avctx->width * avctx->height / 4);
128  s->buf1 = av_malloc(avctx->width * avctx->height * 3 / 2);
129  s->buf2 = av_malloc(avctx->width * avctx->height * 3 / 2);
130  if (!s->old_y_avg || !s->buf1 || !s->buf2) {
131  av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
132  return AVERROR(ENOMEM);
133  }
134 
135  s->linesize[0] = avctx->width;
136  s->linesize[1] =
137  s->linesize[2] = avctx->width / 2;
138 
139  s->new_y = s->buf1;
140  s->new_u = s->new_y + avctx->width * avctx->height;
141  s->new_v = s->new_u + avctx->width * avctx->height / 4;
142  s->old_y = s->buf2;
143  s->old_u = s->old_y + avctx->width * avctx->height;
144  s->old_v = s->old_u + avctx->width * avctx->height / 4;
145  memset(s->old_y, 0, avctx->width * avctx->height);
146  memset(s->old_u, 0x10, avctx->width * avctx->height / 4);
147  memset(s->old_v, 0x10, avctx->width * avctx->height / 4);
148 
149  return 0;
150 }
151 
153 {
154  Escape130Context *s = avctx->priv_data;
155 
156  av_freep(&s->old_y_avg);
157  av_freep(&s->buf1);
158  av_freep(&s->buf2);
159 
160  return 0;
161 }
162 
164 {
165  int value;
166 
167  if (get_bits_left(gb) < 1+3)
168  return -1;
169 
170  value = get_bits1(gb);
171  if (value)
172  return 0;
173 
174  value = get_bits(gb, 3);
175  if (value)
176  return value;
177 
178  value = get_bits(gb, 8);
179  if (value)
180  return value + 7;
181 
182  value = get_bits(gb, 15);
183  if (value)
184  return value + 262;
185 
186  return -1;
187 }
188 
189 static int escape130_decode_frame(AVCodecContext *avctx, void *data,
190  int *got_frame, AVPacket *avpkt)
191 {
192  int buf_size = avpkt->size;
193  Escape130Context *s = avctx->priv_data;
194  AVFrame *pic = data;
195  GetBitContext gb;
196  int ret;
197 
198  uint8_t *old_y, *old_cb, *old_cr,
199  *new_y, *new_cb, *new_cr;
200  uint8_t *dstY, *dstU, *dstV;
201  unsigned old_y_stride, old_cb_stride, old_cr_stride,
202  new_y_stride, new_cb_stride, new_cr_stride;
203  unsigned total_blocks = avctx->width * avctx->height / 4,
204  block_index, block_x = 0;
205  unsigned y[4] = { 0 }, cb = 0x10, cr = 0x10;
206  int skip = -1, y_avg = 0, i, j;
207  uint8_t *ya = s->old_y_avg;
208 
209  // first 16 bytes are header; no useful information in here
210  if (buf_size <= 16) {
211  av_log(avctx, AV_LOG_ERROR, "Insufficient frame data\n");
212  return AVERROR_INVALIDDATA;
213  }
214 
215  if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
216  return ret;
217 
218  if ((ret = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)
219  return ret;
220  skip_bits_long(&gb, 16 * 8);
221 
222  new_y = s->new_y;
223  new_cb = s->new_u;
224  new_cr = s->new_v;
225  new_y_stride = s->linesize[0];
226  new_cb_stride = s->linesize[1];
227  new_cr_stride = s->linesize[2];
228  old_y = s->old_y;
229  old_cb = s->old_u;
230  old_cr = s->old_v;
231  old_y_stride = s->linesize[0];
232  old_cb_stride = s->linesize[1];
233  old_cr_stride = s->linesize[2];
234 
235  for (block_index = 0; block_index < total_blocks; block_index++) {
236  // Note that this call will make us skip the rest of the blocks
237  // if the frame ends prematurely.
238  if (skip == -1)
239  skip = decode_skip_count(&gb);
240  if (skip == -1) {
241  av_log(avctx, AV_LOG_ERROR, "Error decoding skip value\n");
242  return AVERROR_INVALIDDATA;
243  }
244 
245  if (skip) {
246  y[0] = old_y[0];
247  y[1] = old_y[1];
248  y[2] = old_y[old_y_stride];
249  y[3] = old_y[old_y_stride + 1];
250  y_avg = ya[0];
251  cb = old_cb[0];
252  cr = old_cr[0];
253  } else {
254  if (get_bits1(&gb)) {
255  unsigned sign_selector = get_bits(&gb, 6);
256  unsigned difference_selector = get_bits(&gb, 2);
257  y_avg = 2 * get_bits(&gb, 5);
258  for (i = 0; i < 4; i++) {
259  y[i] = av_clip(y_avg + offset_table[difference_selector] *
260  sign_table[sign_selector][i], 0, 63);
261  }
262  } else if (get_bits1(&gb)) {
263  if (get_bits1(&gb)) {
264  y_avg = get_bits(&gb, 6);
265  } else {
266  unsigned adjust_index = get_bits(&gb, 3);
267  y_avg = (y_avg + luma_adjust[adjust_index]) & 63;
268  }
269  for (i = 0; i < 4; i++)
270  y[i] = y_avg;
271  }
272 
273  if (get_bits1(&gb)) {
274  if (get_bits1(&gb)) {
275  cb = get_bits(&gb, 5);
276  cr = get_bits(&gb, 5);
277  } else {
278  unsigned adjust_index = get_bits(&gb, 3);
279  cb = (cb + chroma_adjust[0][adjust_index]) & 31;
280  cr = (cr + chroma_adjust[1][adjust_index]) & 31;
281  }
282  }
283  }
284  *ya++ = y_avg;
285 
286  new_y[0] = y[0];
287  new_y[1] = y[1];
288  new_y[new_y_stride] = y[2];
289  new_y[new_y_stride + 1] = y[3];
290  *new_cb = cb;
291  *new_cr = cr;
292 
293  old_y += 2;
294  old_cb++;
295  old_cr++;
296  new_y += 2;
297  new_cb++;
298  new_cr++;
299  block_x++;
300  if (block_x * 2 == avctx->width) {
301  block_x = 0;
302  old_y += old_y_stride * 2 - avctx->width;
303  old_cb += old_cb_stride - avctx->width / 2;
304  old_cr += old_cr_stride - avctx->width / 2;
305  new_y += new_y_stride * 2 - avctx->width;
306  new_cb += new_cb_stride - avctx->width / 2;
307  new_cr += new_cr_stride - avctx->width / 2;
308  }
309 
310  skip--;
311  }
312 
313  new_y = s->new_y;
314  new_cb = s->new_u;
315  new_cr = s->new_v;
316  dstY = pic->data[0];
317  dstU = pic->data[1];
318  dstV = pic->data[2];
319  for (j = 0; j < avctx->height; j++) {
320  for (i = 0; i < avctx->width; i++)
321  dstY[i] = new_y[i] << 2;
322  dstY += pic->linesize[0];
323  new_y += new_y_stride;
324  }
325  for (j = 0; j < avctx->height / 2; j++) {
326  for (i = 0; i < avctx->width / 2; i++) {
327  dstU[i] = chroma_vals[new_cb[i]];
328  dstV[i] = chroma_vals[new_cr[i]];
329  }
330  dstU += pic->linesize[1];
331  dstV += pic->linesize[2];
332  new_cb += new_cb_stride;
333  new_cr += new_cr_stride;
334  }
335 
336  ff_dlog(avctx, "Frame data: provided %d bytes, used %d bytes\n",
337  buf_size, get_bits_count(&gb) >> 3);
338 
339  FFSWAP(uint8_t*, s->old_y, s->new_y);
340  FFSWAP(uint8_t*, s->old_u, s->new_u);
341  FFSWAP(uint8_t*, s->old_v, s->new_v);
342 
343  *got_frame = 1;
344 
345  return buf_size;
346 }
347 
349  .name = "escape130",
350  .long_name = NULL_IF_CONFIG_SMALL("Escape 130"),
351  .type = AVMEDIA_TYPE_VIDEO,
352  .id = AV_CODEC_ID_ESCAPE130,
353  .priv_data_size = sizeof(Escape130Context),
355  .close = escape130_decode_close,
357  .capabilities = AV_CODEC_CAP_DR1,
358  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
359 };
#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
static const uint8_t chroma_vals[]
Definition: escape130.c:109
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:308
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:379
Memory handling functions.
static void skip_bits_long(GetBitContext *s, int n)
Skips the specified number of bits.
Definition: get_bits.h:291
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: packet.h:364
uint8_t * old_v
Definition: escape130.c:35
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:736
AVCodec.
Definition: codec.h:190
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
Macro definitions for various function/variable attributes.
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:215
static av_cold int escape130_decode_close(AVCodecContext *avctx)
Definition: escape130.c:152
uint8_t
#define av_cold
Definition: attributes.h:88
#define av_malloc(s)
uint8_t * old_u
Definition: escape130.c:34
uint8_t * new_v
Definition: escape130.c:35
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:108
uint8_t * new_y
Definition: escape130.c:33
uint8_t * data
Definition: packet.h:363
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:219
#define ff_dlog(a,...)
bitstream reader API header.
static const int8_t chroma_adjust[2][8]
Definition: escape130.c:104
#define av_log(a,...)
static const int8_t sign_table[64][4]
Definition: escape130.c:42
static int escape130_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: escape130.c:189
static int get_bits_left(GetBitContext *gb)
Definition: get_bits.h:849
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:153
const char * name
Name of the codec implementation.
Definition: codec.h:197
int width
picture width / height.
Definition: avcodec.h:699
uint8_t * buf1
Definition: escape130.c:37
#define s(width, name)
Definition: cbs_vp9.c:257
static int decode_skip_count(GetBitContext *gb)
Definition: escape130.c:163
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:339
static const int8_t luma_adjust[]
Definition: escape130.c:102
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:677
main external API structure.
Definition: avcodec.h:526
AVCodec ff_escape130_decoder
Definition: escape130.c:348
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1872
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:498
uint8_t * old_y
Definition: escape130.c:33
uint8_t * buf2
Definition: escape130.c:37
uint16_t * dstV
Definition: input.c:403
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:322
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
common internal api header.
void * priv_data
Definition: avcodec.h:553
static const uint8_t offset_table[]
Definition: escape130.c:41
static av_cold int escape130_decode_init(AVCodecContext *avctx)
Definition: escape130.c:116
int linesize[3]
Definition: escape130.c:38
#define av_freep(p)
uint8_t * old_y_avg
Definition: escape130.c:31
#define FFSWAP(type, a, b)
Definition: common.h:99
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
static double cr(void *priv, double x, double y)
Definition: vf_geq.c:216
This structure stores compressed data.
Definition: packet.h:340
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:50
int i
Definition: input.c:407
uint8_t * new_u
Definition: escape130.c:34