FFmpeg  4.4
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 };
Macro definitions for various function/variable attributes.
#define av_cold
Definition: attributes.h:88
uint8_t
Libavcodec external API header.
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
#define s(width, name)
Definition: cbs_vp9.c:257
#define FFSWAP(type, a, b)
Definition: common.h:108
#define av_clip
Definition: common.h:122
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1893
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
static int escape130_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: escape130.c:189
static const int8_t sign_table[64][4]
Definition: escape130.c:42
static const int8_t chroma_adjust[2][8]
Definition: escape130.c:104
AVCodec ff_escape130_decoder
Definition: escape130.c:348
static const uint8_t offset_table[]
Definition: escape130.c:41
static const uint8_t chroma_vals[]
Definition: escape130.c:109
static int decode_skip_count(GetBitContext *gb)
Definition: escape130.c:163
static av_cold int escape130_decode_init(AVCodecContext *avctx)
Definition: escape130.c:116
static const int8_t luma_adjust[]
Definition: escape130.c:102
static av_cold int escape130_decode_close(AVCodecContext *avctx)
Definition: escape130.c:152
double value
Definition: eval.c:98
bitstream reader API header.
static int get_bits_left(GetBitContext *gb)
Definition: get_bits.h:849
static void skip_bits_long(GetBitContext *s, int n)
Skips the specified number of bits.
Definition: get_bits.h:291
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:498
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:677
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:219
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:379
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
@ AV_CODEC_ID_ESCAPE130
Definition: codec_id.h:219
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
uint16_t * dstV
Definition: input.c:403
int i
Definition: input.c:407
#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:49
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
Memory handling functions.
const char data[16]
Definition: mxf.c:142
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
main external API structure.
Definition: avcodec.h:536
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:746
int width
picture width / height.
Definition: avcodec.h:709
void * priv_data
Definition: avcodec.h:563
AVCodec.
Definition: codec.h:197
const char * name
Name of the codec implementation.
Definition: codec.h:204
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:332
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:349
This structure stores compressed data.
Definition: packet.h:346
int size
Definition: packet.h:370
uint8_t * data
Definition: packet.h:369
uint8_t * old_u
Definition: escape130.c:34
uint8_t * new_u
Definition: escape130.c:34
uint8_t * new_y
Definition: escape130.c:33
uint8_t * buf1
Definition: escape130.c:37
uint8_t * old_y_avg
Definition: escape130.c:31
uint8_t * old_y
Definition: escape130.c:33
uint8_t * old_v
Definition: escape130.c:35
uint8_t * new_v
Definition: escape130.c:35
int linesize[3]
Definition: escape130.c:38
uint8_t * buf2
Definition: escape130.c:37
#define ff_dlog(a,...)
#define av_freep(p)
#define av_malloc(s)
#define av_log(a,...)
static double cr(void *priv, double x, double y)
Definition: vf_geq.c:216
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:215