qpeg.c
Go to the documentation of this file.
1 /*
2  * QPEG codec
3  * Copyright (c) 2004 Konstantin Shishkov
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 /**
23  * @file
24  * QPEG codec.
25  */
26 
27 #include "avcodec.h"
28 #include "bytestream.h"
29 #include "internal.h"
30 
31 typedef struct QpegContext{
34  uint32_t pal[256];
36 } QpegContext;
37 
39  int stride, int width, int height)
40 {
41  int i;
42  int code;
43  int c0, c1;
44  int run, copy;
45  int filled = 0;
46  int rows_to_go;
47 
48  rows_to_go = height;
49  height--;
50  dst = dst + height * stride;
51 
52  while ((bytestream2_get_bytes_left(&qctx->buffer) > 0) && (rows_to_go > 0)) {
53  code = bytestream2_get_byte(&qctx->buffer);
54  run = copy = 0;
55  if(code == 0xFC) /* end-of-picture code */
56  break;
57  if(code >= 0xF8) { /* very long run */
58  c0 = bytestream2_get_byte(&qctx->buffer);
59  c1 = bytestream2_get_byte(&qctx->buffer);
60  run = ((code & 0x7) << 16) + (c0 << 8) + c1 + 2;
61  } else if (code >= 0xF0) { /* long run */
62  c0 = bytestream2_get_byte(&qctx->buffer);
63  run = ((code & 0xF) << 8) + c0 + 2;
64  } else if (code >= 0xE0) { /* short run */
65  run = (code & 0x1F) + 2;
66  } else if (code >= 0xC0) { /* very long copy */
67  c0 = bytestream2_get_byte(&qctx->buffer);
68  c1 = bytestream2_get_byte(&qctx->buffer);
69  copy = ((code & 0x3F) << 16) + (c0 << 8) + c1 + 1;
70  } else if (code >= 0x80) { /* long copy */
71  c0 = bytestream2_get_byte(&qctx->buffer);
72  copy = ((code & 0x7F) << 8) + c0 + 1;
73  } else { /* short copy */
74  copy = code + 1;
75  }
76 
77  /* perform actual run or copy */
78  if(run) {
79  int p;
80 
81  p = bytestream2_get_byte(&qctx->buffer);
82  for(i = 0; i < run; i++) {
83  dst[filled++] = p;
84  if (filled >= width) {
85  filled = 0;
86  dst -= stride;
87  rows_to_go--;
88  if(rows_to_go <= 0)
89  break;
90  }
91  }
92  } else {
93  for(i = 0; i < copy; i++) {
94  dst[filled++] = bytestream2_get_byte(&qctx->buffer);
95  if (filled >= width) {
96  filled = 0;
97  dst -= stride;
98  rows_to_go--;
99  if(rows_to_go <= 0)
100  break;
101  }
102  }
103  }
104  }
105 }
106 
107 static const int qpeg_table_h[16] =
108  { 0x00, 0x20, 0x20, 0x20, 0x18, 0x10, 0x10, 0x20, 0x10, 0x08, 0x18, 0x08, 0x08, 0x18, 0x10, 0x04};
109 static const int qpeg_table_w[16] =
110  { 0x00, 0x20, 0x18, 0x08, 0x18, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x20, 0x08, 0x10, 0x18, 0x04};
111 
112 /* Decodes delta frames */
114  int stride, int width, int height,
115  int delta, const uint8_t *ctable,
116  uint8_t *refdata)
117 {
118  int i, j;
119  int code;
120  int filled = 0;
121  int orig_height;
122 
123  if(!refdata)
124  refdata= dst;
125 
126  /* copy prev frame */
127  for(i = 0; i < height; i++)
128  memcpy(dst + (i * stride), refdata + (i * stride), width);
129 
130  orig_height = height;
131  height--;
132  dst = dst + height * stride;
133 
134  while ((bytestream2_get_bytes_left(&qctx->buffer) > 0) && (height >= 0)) {
135  code = bytestream2_get_byte(&qctx->buffer);
136 
137  if(delta) {
138  /* motion compensation */
139  while(bytestream2_get_bytes_left(&qctx->buffer) > 0 && (code & 0xF0) == 0xF0) {
140  if(delta == 1) {
141  int me_idx;
142  int me_w, me_h, me_x, me_y;
143  uint8_t *me_plane;
144  int corr, val;
145 
146  /* get block size by index */
147  me_idx = code & 0xF;
148  me_w = qpeg_table_w[me_idx];
149  me_h = qpeg_table_h[me_idx];
150 
151  /* extract motion vector */
152  corr = bytestream2_get_byte(&qctx->buffer);
153 
154  val = corr >> 4;
155  if(val > 7)
156  val -= 16;
157  me_x = val;
158 
159  val = corr & 0xF;
160  if(val > 7)
161  val -= 16;
162  me_y = val;
163 
164  /* check motion vector */
165  if ((me_x + filled < 0) || (me_x + me_w + filled > width) ||
166  (height - me_y - me_h < 0) || (height - me_y > orig_height) ||
167  (filled + me_w > width) || (height - me_h < 0))
168  av_log(NULL, AV_LOG_ERROR, "Bogus motion vector (%i,%i), block size %ix%i at %i,%i\n",
169  me_x, me_y, me_w, me_h, filled, height);
170  else {
171  /* do motion compensation */
172  me_plane = refdata + (filled + me_x) + (height - me_y) * stride;
173  for(j = 0; j < me_h; j++) {
174  for(i = 0; i < me_w; i++)
175  dst[filled + i - (j * stride)] = me_plane[i - (j * stride)];
176  }
177  }
178  }
179  code = bytestream2_get_byte(&qctx->buffer);
180  }
181  }
182 
183  if(code == 0xE0) /* end-of-picture code */
184  break;
185  if(code > 0xE0) { /* run code: 0xE1..0xFF */
186  int p;
187 
188  code &= 0x1F;
189  p = bytestream2_get_byte(&qctx->buffer);
190  for(i = 0; i <= code; i++) {
191  dst[filled++] = p;
192  if(filled >= width) {
193  filled = 0;
194  dst -= stride;
195  height--;
196  if(height < 0)
197  break;
198  }
199  }
200  } else if(code >= 0xC0) { /* copy code: 0xC0..0xDF */
201  code &= 0x1F;
202 
203  if(code + 1 > bytestream2_get_bytes_left(&qctx->buffer))
204  break;
205 
206  for(i = 0; i <= code; i++) {
207  dst[filled++] = bytestream2_get_byte(&qctx->buffer);
208  if(filled >= width) {
209  filled = 0;
210  dst -= stride;
211  height--;
212  if(height < 0)
213  break;
214  }
215  }
216  } else if(code >= 0x80) { /* skip code: 0x80..0xBF */
217  int skip;
218 
219  code &= 0x3F;
220  /* codes 0x80 and 0x81 are actually escape codes,
221  skip value minus constant is in the next byte */
222  if(!code)
223  skip = bytestream2_get_byte(&qctx->buffer) + 64;
224  else if(code == 1)
225  skip = bytestream2_get_byte(&qctx->buffer) + 320;
226  else
227  skip = code;
228  filled += skip;
229  while( filled >= width) {
230  filled -= width;
231  dst -= stride;
232  height--;
233  if(height < 0)
234  break;
235  }
236  } else {
237  /* zero code treated as one-pixel skip */
238  if(code) {
239  dst[filled++] = ctable[code & 0x7F];
240  }
241  else
242  filled++;
243  if(filled >= width) {
244  filled = 0;
245  dst -= stride;
246  height--;
247  }
248  }
249  }
250 }
251 
253  void *data, int *got_frame,
254  AVPacket *avpkt)
255 {
256  uint8_t ctable[128];
257  QpegContext * const a = avctx->priv_data;
258  AVFrame * p = &a->pic;
259  AVFrame * ref= &a->ref;
260  uint8_t* outdata;
261  int delta, ret;
263 
264  if (avpkt->size < 0x86) {
265  av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
266  return AVERROR_INVALIDDATA;
267  }
268 
269  bytestream2_init(&a->buffer, avpkt->data, avpkt->size);
270 
271  av_frame_unref(ref);
272  av_frame_move_ref(ref, p);
273 
274  if ((ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF)) < 0)
275  return ret;
276  outdata = a->pic.data[0];
277  bytestream2_skip(&a->buffer, 4);
278  bytestream2_get_buffer(&a->buffer, ctable, 128);
279  bytestream2_skip(&a->buffer, 1);
280 
281  delta = bytestream2_get_byte(&a->buffer);
282  if(delta == 0x10) {
283  qpeg_decode_intra(a, outdata, a->pic.linesize[0], avctx->width, avctx->height);
284  } else {
285  qpeg_decode_inter(a, outdata, a->pic.linesize[0], avctx->width, avctx->height, delta, ctable, a->ref.data[0]);
286  }
287 
288  /* make the palette available on the way out */
289  if (pal) {
290  a->pic.palette_has_changed = 1;
291  memcpy(a->pal, pal, AVPALETTE_SIZE);
292  }
293  memcpy(a->pic.data[1], a->pal, AVPALETTE_SIZE);
294 
295  if ((ret = av_frame_ref(data, &a->pic)) < 0)
296  return ret;
297 
298  *got_frame = 1;
299 
300  return avpkt->size;
301 }
302 
304  QpegContext * const a = avctx->priv_data;
305  int i, pal_size;
306  const uint8_t *pal_src;
307 
308  pal_size = FFMIN(1024U, avctx->extradata_size);
309  pal_src = avctx->extradata + avctx->extradata_size - pal_size;
310 
311  for (i=0; i<pal_size/4; i++)
312  a->pal[i] = 0xFFU<<24 | AV_RL32(pal_src+4*i);
313 }
314 
316  QpegContext * const a = avctx->priv_data;
317 
320  a->avctx = avctx;
321  avctx->pix_fmt= AV_PIX_FMT_PAL8;
322 
323  decode_flush(avctx);
324 
326 
327  return 0;
328 }
329 
331  QpegContext * const a = avctx->priv_data;
332  AVFrame * const p = &a->pic;
333  AVFrame * const ref= &a->ref;
334 
335  av_frame_unref(p);
336  av_frame_unref(ref);
337 
338  return 0;
339 }
340 
342  .name = "qpeg",
343  .type = AVMEDIA_TYPE_VIDEO,
344  .id = AV_CODEC_ID_QPEG,
345  .priv_data_size = sizeof(QpegContext),
346  .init = decode_init,
347  .close = decode_end,
348  .decode = decode_frame,
349  .flush = decode_flush,
350  .capabilities = CODEC_CAP_DR1,
351  .long_name = NULL_IF_CONFIG_SMALL("Q-team QPEG"),
352 };
#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:76
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:130
uint32_t pal[256]
Definition: qpeg.c:34
uint8_t run
Definition: svq3.c:136
int stride
Definition: mace.c:144
uint8_t
#define av_cold
Definition: attributes.h:78
float delta
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:79
#define AVPALETTE_SIZE
Definition: pixfmt.h:33
AVFrame ref
Definition: qpeg.c:33
AVFrame pic
Definition: qpeg.c:33
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everythnig contained in src to dst and reset src.
Definition: frame.c:352
uint8_t * data
static void copy(LZOContext *c, int cnt)
Copies bytes from input to output buffer with checking.
Definition: lzo.c:79
static void qpeg_decode_intra(QpegContext *qctx, uint8_t *dst, int stride, int width, int height)
Definition: qpeg.c:38
static void qpeg_decode_inter(QpegContext *qctx, uint8_t *dst, int stride, int width, int height, int delta, const uint8_t *ctable, uint8_t *refdata)
Definition: qpeg.c:113
#define U(x)
static av_cold int decode_init(AVCodecContext *avctx)
Definition: qpeg.c:315
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:159
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Spectrum Plot time data
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:258
struct QpegContext QpegContext
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:149
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
external API header
static void decode_flush(AVCodecContext *avctx)
Definition: qpeg.c:303
#define FFMIN(a, b)
Definition: common.h:58
ret
Definition: avfilter.c:821
int width
picture width / height.
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: qpeg.c:252
#define AV_RL32
AVCodec ff_qpeg_decoder
Definition: qpeg.c:341
static void flush(AVCodecContext *avctx)
static const int qpeg_table_w[16]
Definition: qpeg.c:109
NULL
Definition: eval.c:55
or the Software in violation of any applicable export control laws in any jurisdiction Except as provided by mandatorily applicable UPF has no obligation to provide you with source code to the Software In the event Software contains any source code
static int width
Definition: tests/utils.c:158
static const int qpeg_table_h[16]
Definition: qpeg.c:107
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
main external API structure.
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
BYTE int const BYTE int int int height
Definition: avisynth_c.h:713
void avcodec_get_frame_defaults(AVFrame *frame)
Set the fields of the given AVFrame to default values.
synthesis window for stochastic i
int palette_has_changed
Tell user application that palette has changed from previous frame.
Definition: frame.h:280
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:330
GetByteContext buffer
Definition: qpeg.c:35
int av_frame_ref(AVFrame *dst, AVFrame *src)
Setup a new reference to the data described by an given frame.
Definition: frame.c:228
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
common internal api header.
AVCodecContext * avctx
Definition: qpeg.c:32
static av_cold int decode_end(AVCodecContext *avctx)
Definition: qpeg.c:330
else dst[i][x+y *dst_stride[i]]
Definition: vf_mcdeint.c:160
uint8_t * av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int *size)
Get side information from packet.
Definition: avpacket.c:289
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
This structure stores compressed data.
#define AV_GET_BUFFER_FLAG_REF
The decoder will keep a reference to the frame and may reuse it later.
#define c1
Definition: idct_sh4.c:26