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 {
31  uint8_t *old_y_avg;
32 
33  uint8_t *new_y, *old_y;
34  uint8_t *new_u, *old_u;
35  uint8_t *new_v, *old_v;
36 
37  uint8_t *buf1, *buf2;
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,
359 };
AVCodec
AVCodec.
Definition: codec.h:202
skip_bits_long
static void skip_bits_long(GetBitContext *s, int n)
Skips the specified number of bits.
Definition: get_bits.h:292
FF_CODEC_CAP_INIT_THREADSAFE
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
Definition: internal.h:42
av_clip
#define av_clip
Definition: common.h:96
get_bits_left
static int get_bits_left(GetBitContext *gb)
Definition: get_bits.h:850
AVERROR
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
AV_CODEC_ID_ESCAPE130
@ AV_CODEC_ID_ESCAPE130
Definition: codec_id.h:220
cb
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:215
ff_escape130_decoder
const AVCodec ff_escape130_decoder
Definition: escape130.c:348
Escape130Context::old_v
uint8_t * old_v
Definition: escape130.c:35
get_bits_count
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:220
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:317
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:373
Escape130Context::buf1
uint8_t * buf1
Definition: escape130.c:37
data
const char data[16]
Definition: mxf.c:143
Escape130Context::new_v
uint8_t * new_v
Definition: escape130.c:35
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:338
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
init
static int init
Definition: av_tx.c:47
get_bits
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:380
GetBitContext
Definition: get_bits.h:62
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
init_get_bits8
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:678
decode
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
s
#define s(width, name)
Definition: cbs_vp9.c:257
get_bits.h
Escape130Context
Definition: escape130.c:30
chroma_adjust
static const int8_t chroma_adjust[2][8]
Definition: escape130.c:104
Escape130Context::buf2
uint8_t * buf2
Definition: escape130.c:37
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
escape130_decode_close
static av_cold int escape130_decode_close(AVCodecContext *avctx)
Definition: escape130.c:152
Escape130Context::linesize
int linesize[3]
Definition: escape130.c:38
Escape130Context::new_y
uint8_t * new_y
Definition: escape130.c:33
get_bits1
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:499
ff_dlog
#define ff_dlog(a,...)
Definition: tableprint_vlc.h:29
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1652
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:374
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
decode_skip_count
static int decode_skip_count(GetBitContext *gb)
Definition: escape130.c:163
attributes.h
offset_table
static const uint8_t offset_table[]
Definition: escape130.c:41
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
FF_CODEC_CAP_INIT_CLEANUP
#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:50
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:209
AVCodecContext::height
int height
Definition: avcodec.h:556
Escape130Context::old_u
uint8_t * old_u
Definition: escape130.c:34
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:593
avcodec.h
ret
ret
Definition: filter_design.txt:187
escape130_decode_init
static av_cold int escape130_decode_init(AVCodecContext *avctx)
Definition: escape130.c:116
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
sign_table
static const int8_t sign_table[64][4]
Definition: escape130.c:42
AVCodecContext
main external API structure.
Definition: avcodec.h:383
Escape130Context::new_u
uint8_t * new_u
Definition: escape130.c:34
Escape130Context::old_y_avg
uint8_t * old_y_avg
Definition: escape130.c:31
chroma_vals
static const uint8_t chroma_vals[]
Definition: escape130.c:109
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
mem.h
luma_adjust
static const int8_t luma_adjust[]
Definition: escape130.c:102
AVPacket
This structure stores compressed data.
Definition: packet.h:350
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:410
cr
static double cr(void *priv, double x, double y)
Definition: vf_geq.c:216
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:556
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:362
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
escape130_decode_frame
static int escape130_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: escape130.c:189
Escape130Context::old_y
uint8_t * old_y
Definition: escape130.c:33