qtrle.c
Go to the documentation of this file.
1 /*
2  * Quicktime Animation (RLE) Video Decoder
3  * Copyright (C) 2004 the ffmpeg project
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include "avcodec.h"
39 #include "bytestream.h"
40 
41 typedef struct QtrleContext {
44 
46  uint32_t pal[256];
47 } QtrleContext;
48 
49 #define CHECK_PIXEL_PTR(n) \
50  if ((pixel_ptr + n > pixel_limit) || (pixel_ptr + n < 0)) { \
51  av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr = %d, pixel_limit = %d\n", \
52  pixel_ptr + n, pixel_limit); \
53  return; \
54  } \
55 
56 static void qtrle_decode_1bpp(QtrleContext *s, int row_ptr, int lines_to_change)
57 {
58  int rle_code;
59  int pixel_ptr;
60  int row_inc = s->frame.linesize[0];
61  unsigned char pi0, pi1; /* 2 8-pixel values */
62  unsigned char *rgb = s->frame.data[0];
63  int pixel_limit = s->frame.linesize[0] * s->avctx->height;
64  int skip;
65 
66  row_ptr -= row_inc;
67  pixel_ptr = row_ptr;
68  lines_to_change++;
69  while (lines_to_change) {
70  skip = bytestream2_get_byte(&s->g);
71  rle_code = (signed char)bytestream2_get_byte(&s->g);
72  if (rle_code == 0)
73  break;
74  if(skip & 0x80) {
75  lines_to_change--;
76  row_ptr += row_inc;
77  pixel_ptr = row_ptr + 2 * (skip & 0x7f);
78  } else
79  pixel_ptr += 2 * skip;
80  CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
81 
82  if (rle_code < 0) {
83  /* decode the run length code */
84  rle_code = -rle_code;
85  /* get the next 2 bytes from the stream, treat them as groups
86  * of 8 pixels, and output them rle_code times */
87 
88  pi0 = bytestream2_get_byte(&s->g);
89  pi1 = bytestream2_get_byte(&s->g);
90  CHECK_PIXEL_PTR(rle_code * 2);
91 
92  while (rle_code--) {
93  rgb[pixel_ptr++] = pi0;
94  rgb[pixel_ptr++] = pi1;
95  }
96  } else {
97  /* copy the same pixel directly to output 2 times */
98  rle_code *= 2;
99  CHECK_PIXEL_PTR(rle_code);
100 
101  while (rle_code--)
102  rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
103  }
104  }
105 }
106 
107 static inline void qtrle_decode_2n4bpp(QtrleContext *s, int row_ptr,
108  int lines_to_change, int bpp)
109 {
110  int rle_code, i;
111  int pixel_ptr;
112  int row_inc = s->frame.linesize[0];
113  unsigned char pi[16]; /* 16 palette indices */
114  unsigned char *rgb = s->frame.data[0];
115  int pixel_limit = s->frame.linesize[0] * s->avctx->height;
116  int num_pixels = (bpp == 4) ? 8 : 16;
117 
118  while (lines_to_change--) {
119  pixel_ptr = row_ptr + (num_pixels * (bytestream2_get_byte(&s->g) - 1));
120  CHECK_PIXEL_PTR(0);
121 
122  while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
123  if (rle_code == 0) {
124  /* there's another skip code in the stream */
125  pixel_ptr += (num_pixels * (bytestream2_get_byte(&s->g) - 1));
126  CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
127  } else if (rle_code < 0) {
128  /* decode the run length code */
129  rle_code = -rle_code;
130  /* get the next 4 bytes from the stream, treat them as palette
131  * indexes, and output them rle_code times */
132  for (i = num_pixels-1; i >= 0; i--) {
133  pi[num_pixels-1-i] = (bytestream2_peek_byte(&s->g) >> ((i*bpp) & 0x07)) & ((1<<bpp)-1);
134  bytestream2_skip(&s->g, ((i & ((num_pixels>>2)-1)) == 0));
135  }
136  CHECK_PIXEL_PTR(rle_code * num_pixels);
137  while (rle_code--) {
138  for (i = 0; i < num_pixels; i++)
139  rgb[pixel_ptr++] = pi[i];
140  }
141  } else {
142  /* copy the same pixel directly to output 4 times */
143  rle_code *= 4;
144  CHECK_PIXEL_PTR(rle_code*(num_pixels>>2));
145  while (rle_code--) {
146  if(bpp == 4) {
147  int x = bytestream2_get_byte(&s->g);
148  rgb[pixel_ptr++] = (x >> 4) & 0x0f;
149  rgb[pixel_ptr++] = x & 0x0f;
150  } else {
151  int x = bytestream2_get_byte(&s->g);
152  rgb[pixel_ptr++] = (x >> 6) & 0x03;
153  rgb[pixel_ptr++] = (x >> 4) & 0x03;
154  rgb[pixel_ptr++] = (x >> 2) & 0x03;
155  rgb[pixel_ptr++] = x & 0x03;
156  }
157  }
158  }
159  }
160  row_ptr += row_inc;
161  }
162 }
163 
164 static void qtrle_decode_8bpp(QtrleContext *s, int row_ptr, int lines_to_change)
165 {
166  int rle_code;
167  int pixel_ptr;
168  int row_inc = s->frame.linesize[0];
169  unsigned char pi1, pi2, pi3, pi4; /* 4 palette indexes */
170  unsigned char *rgb = s->frame.data[0];
171  int pixel_limit = s->frame.linesize[0] * s->avctx->height;
172 
173  while (lines_to_change--) {
174  pixel_ptr = row_ptr + (4 * (bytestream2_get_byte(&s->g) - 1));
175  CHECK_PIXEL_PTR(0);
176 
177  while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
178  if (rle_code == 0) {
179  /* there's another skip code in the stream */
180  pixel_ptr += (4 * (bytestream2_get_byte(&s->g) - 1));
181  CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
182  } else if (rle_code < 0) {
183  /* decode the run length code */
184  rle_code = -rle_code;
185  /* get the next 4 bytes from the stream, treat them as palette
186  * indexes, and output them rle_code times */
187  pi1 = bytestream2_get_byte(&s->g);
188  pi2 = bytestream2_get_byte(&s->g);
189  pi3 = bytestream2_get_byte(&s->g);
190  pi4 = bytestream2_get_byte(&s->g);
191 
192  CHECK_PIXEL_PTR(rle_code * 4);
193 
194  while (rle_code--) {
195  rgb[pixel_ptr++] = pi1;
196  rgb[pixel_ptr++] = pi2;
197  rgb[pixel_ptr++] = pi3;
198  rgb[pixel_ptr++] = pi4;
199  }
200  } else {
201  /* copy the same pixel directly to output 4 times */
202  rle_code *= 4;
203  CHECK_PIXEL_PTR(rle_code);
204 
205  while (rle_code--) {
206  rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
207  }
208  }
209  }
210  row_ptr += row_inc;
211  }
212 }
213 
214 static void qtrle_decode_16bpp(QtrleContext *s, int row_ptr, int lines_to_change)
215 {
216  int rle_code;
217  int pixel_ptr;
218  int row_inc = s->frame.linesize[0];
219  unsigned short rgb16;
220  unsigned char *rgb = s->frame.data[0];
221  int pixel_limit = s->frame.linesize[0] * s->avctx->height;
222 
223  while (lines_to_change--) {
224  pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 2;
225  CHECK_PIXEL_PTR(0);
226 
227  while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
228  if (rle_code == 0) {
229  /* there's another skip code in the stream */
230  pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 2;
231  CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
232  } else if (rle_code < 0) {
233  /* decode the run length code */
234  rle_code = -rle_code;
235  rgb16 = bytestream2_get_be16(&s->g);
236 
237  CHECK_PIXEL_PTR(rle_code * 2);
238 
239  while (rle_code--) {
240  *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
241  pixel_ptr += 2;
242  }
243  } else {
244  CHECK_PIXEL_PTR(rle_code * 2);
245 
246  /* copy pixels directly to output */
247  while (rle_code--) {
248  rgb16 = bytestream2_get_be16(&s->g);
249  *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
250  pixel_ptr += 2;
251  }
252  }
253  }
254  row_ptr += row_inc;
255  }
256 }
257 
258 static void qtrle_decode_24bpp(QtrleContext *s, int row_ptr, int lines_to_change)
259 {
260  int rle_code;
261  int pixel_ptr;
262  int row_inc = s->frame.linesize[0];
263  unsigned char r, g, b;
264  unsigned char *rgb = s->frame.data[0];
265  int pixel_limit = s->frame.linesize[0] * s->avctx->height;
266 
267  while (lines_to_change--) {
268  pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 3;
269  CHECK_PIXEL_PTR(0);
270 
271  while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
272  if (rle_code == 0) {
273  /* there's another skip code in the stream */
274  pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 3;
275  CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
276  } else if (rle_code < 0) {
277  /* decode the run length code */
278  rle_code = -rle_code;
279  r = bytestream2_get_byte(&s->g);
280  g = bytestream2_get_byte(&s->g);
281  b = bytestream2_get_byte(&s->g);
282 
283  CHECK_PIXEL_PTR(rle_code * 3);
284 
285  while (rle_code--) {
286  rgb[pixel_ptr++] = r;
287  rgb[pixel_ptr++] = g;
288  rgb[pixel_ptr++] = b;
289  }
290  } else {
291  CHECK_PIXEL_PTR(rle_code * 3);
292 
293  /* copy pixels directly to output */
294  while (rle_code--) {
295  rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
296  rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
297  rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
298  }
299  }
300  }
301  row_ptr += row_inc;
302  }
303 }
304 
305 static void qtrle_decode_32bpp(QtrleContext *s, int row_ptr, int lines_to_change)
306 {
307  int rle_code;
308  int pixel_ptr;
309  int row_inc = s->frame.linesize[0];
310  unsigned int argb;
311  unsigned char *rgb = s->frame.data[0];
312  int pixel_limit = s->frame.linesize[0] * s->avctx->height;
313 
314  while (lines_to_change--) {
315  pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 4;
316  CHECK_PIXEL_PTR(0);
317 
318  while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
319  if (rle_code == 0) {
320  /* there's another skip code in the stream */
321  pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 4;
322  CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
323  } else if (rle_code < 0) {
324  /* decode the run length code */
325  rle_code = -rle_code;
326  argb = bytestream2_get_be32(&s->g);
327 
328  CHECK_PIXEL_PTR(rle_code * 4);
329 
330  while (rle_code--) {
331  AV_WN32A(rgb + pixel_ptr, argb);
332  pixel_ptr += 4;
333  }
334  } else {
335  CHECK_PIXEL_PTR(rle_code * 4);
336 
337  /* copy pixels directly to output */
338  while (rle_code--) {
339  argb = bytestream2_get_be32(&s->g);
340  AV_WN32A(rgb + pixel_ptr, argb);
341  pixel_ptr += 4;
342  }
343  }
344  }
345  row_ptr += row_inc;
346  }
347 }
348 
350 {
351  QtrleContext *s = avctx->priv_data;
352 
353  s->avctx = avctx;
354  switch (avctx->bits_per_coded_sample) {
355  case 1:
356  case 33:
357  avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
358  break;
359 
360  case 2:
361  case 4:
362  case 8:
363  case 34:
364  case 36:
365  case 40:
366  avctx->pix_fmt = AV_PIX_FMT_PAL8;
367  break;
368 
369  case 16:
370  avctx->pix_fmt = AV_PIX_FMT_RGB555;
371  break;
372 
373  case 24:
374  avctx->pix_fmt = AV_PIX_FMT_RGB24;
375  break;
376 
377  case 32:
378  avctx->pix_fmt = AV_PIX_FMT_RGB32;
379  break;
380 
381  default:
382  av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
383  avctx->bits_per_coded_sample);
384  return AVERROR_INVALIDDATA;
385  }
386 
387  s->frame.data[0] = NULL;
388 
389  return 0;
390 }
391 
393  void *data, int *got_frame,
394  AVPacket *avpkt)
395 {
396  QtrleContext *s = avctx->priv_data;
397  int header, start_line;
398  int height, row_ptr;
399  int has_palette = 0;
400 
401  bytestream2_init(&s->g, avpkt->data, avpkt->size);
402  s->frame.reference = 1;
405  if (avctx->reget_buffer(avctx, &s->frame)) {
406  av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
407  return -1;
408  }
409 
410  /* check if this frame is even supposed to change */
411  if (avpkt->size < 8)
412  goto done;
413 
414  /* start after the chunk size */
415  bytestream2_seek(&s->g, 4, SEEK_SET);
416 
417  /* fetch the header */
418  header = bytestream2_get_be16(&s->g);
419 
420  /* if a header is present, fetch additional decoding parameters */
421  if (header & 0x0008) {
422  if (avpkt->size < 14)
423  goto done;
424  start_line = bytestream2_get_be16(&s->g);
425  bytestream2_skip(&s->g, 2);
426  height = bytestream2_get_be16(&s->g);
427  bytestream2_skip(&s->g, 2);
428  } else {
429  start_line = 0;
430  height = s->avctx->height;
431  }
432  row_ptr = s->frame.linesize[0] * start_line;
433 
434  switch (avctx->bits_per_coded_sample) {
435  case 1:
436  case 33:
437  qtrle_decode_1bpp(s, row_ptr, height);
438  break;
439 
440  case 2:
441  case 34:
442  qtrle_decode_2n4bpp(s, row_ptr, height, 2);
443  has_palette = 1;
444  break;
445 
446  case 4:
447  case 36:
448  qtrle_decode_2n4bpp(s, row_ptr, height, 4);
449  has_palette = 1;
450  break;
451 
452  case 8:
453  case 40:
454  qtrle_decode_8bpp(s, row_ptr, height);
455  has_palette = 1;
456  break;
457 
458  case 16:
459  qtrle_decode_16bpp(s, row_ptr, height);
460  break;
461 
462  case 24:
463  qtrle_decode_24bpp(s, row_ptr, height);
464  break;
465 
466  case 32:
467  qtrle_decode_32bpp(s, row_ptr, height);
468  break;
469 
470  default:
471  av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
472  avctx->bits_per_coded_sample);
473  break;
474  }
475 
476  if(has_palette) {
478 
479  if (pal) {
480  s->frame.palette_has_changed = 1;
481  memcpy(s->pal, pal, AVPALETTE_SIZE);
482  }
483 
484  /* make the palette available on the way out */
485  memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE);
486  }
487 
488 done:
489  *got_frame = 1;
490  *(AVFrame*)data = s->frame;
491 
492  /* always report that the buffer was completely consumed */
493  return avpkt->size;
494 }
495 
497 {
498  QtrleContext *s = avctx->priv_data;
499 
500  if (s->frame.data[0])
501  avctx->release_buffer(avctx, &s->frame);
502 
503  return 0;
504 }
505 
507  .name = "qtrle",
508  .type = AVMEDIA_TYPE_VIDEO,
509  .id = AV_CODEC_ID_QTRLE,
510  .priv_data_size = sizeof(QtrleContext),
514  .capabilities = CODEC_CAP_DR1,
515  .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
516 };
AVFrame frame
Definition: qtrle.c:43
static void qtrle_decode_2n4bpp(QtrleContext *s, int row_ptr, int lines_to_change, int bpp)
Definition: qtrle.c:107
This structure describes decoded (raw) audio or video data.
Definition: avcodec.h:989
GetByteContext g
Definition: qtrle.c:45
int buffer_hints
codec suggestion on buffer type if != 0
Definition: avcodec.h:1253
void(* release_buffer)(struct AVCodecContext *c, AVFrame *pic)
Called to release buffers which were allocated with get_buffer.
Definition: avcodec.h:2259
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:67
int size
Definition: avcodec.h:916
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1533
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:130
AVCodec.
Definition: avcodec.h:2960
#define AV_WN32A(p, v)
Definition: intreadwrite.h:458
int(* reget_buffer)(struct AVCodecContext *c, AVFrame *pic)
Called at the beginning of a frame to get cr buffer for it.
Definition: avcodec.h:2273
static int decode(MimicContext *ctx, int quality, int num_coeffs, int is_iframe)
Definition: mimic.c:228
uint8_t
static void qtrle_decode_24bpp(QtrleContext *s, int row_ptr, int lines_to_change)
Definition: qtrle.c:258
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:76
#define b
Definition: input.c:52
const char data[16]
Definition: mxf.c:66
AVCodecContext * avctx
Definition: qtrle.c:42
uint8_t * data
Definition: avcodec.h:915
static av_cold int qtrle_decode_init(AVCodecContext *avctx)
Definition: qtrle.c:349
static void qtrle_decode_1bpp(QtrleContext *s, int row_ptr, int lines_to_change)
Definition: qtrle.c:56
struct QtrleContext QtrleContext
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition: avcodec.h:2704
static int init(AVCodecParserContext *s)
Definition: h264_parser.c:335
#define r
Definition: input.c:51
int reference
is this picture used as reference The values for this are the same as the MpegEncContext.picture_structure variable, that is 1->top field, 2->bottom field, 3->frame/both fields.
Definition: avcodec.h:1132
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. ...
Definition: internal.h:88
g
Definition: yuv2rgb.c:540
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:146
const char * name
Name of the codec implementation.
Definition: avcodec.h:2967
static void qtrle_decode_8bpp(QtrleContext *s, int row_ptr, int lines_to_change)
Definition: qtrle.c:164
uint32_t pal[256]
Definition: qtrle.c:46
#define CHECK_PIXEL_PTR(n)
Definition: qtrle.c:49
NULL
Definition: eval.c:52
external API header
int linesize[AV_NUM_DATA_POINTERS]
Size, in bytes, of the data for each picture/channel plane.
Definition: avcodec.h:1008
main external API structure.
Definition: avcodec.h:1339
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:326
int palette_has_changed
Tell user application that palette has changed from previous frame.
Definition: avcodec.h:1246
static void qtrle_decode_32bpp(QtrleContext *s, int row_ptr, int lines_to_change)
Definition: qtrle.c:305
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: avcodec.h:997
int height
Definition: gxfenc.c:72
Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb...
Definition: pixfmt.h:74
static int qtrle_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: qtrle.c:392
void * priv_data
Definition: avcodec.h:1382
AVCodec ff_qtrle_decoder
Definition: qtrle.c:506
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:193
uint8_t * av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int *size)
Get side information from packet.
Definition: avpacket.c:190
static void qtrle_decode_16bpp(QtrleContext *s, int row_ptr, int lines_to_change)
Definition: qtrle.c:214
static av_cold int qtrle_decode_end(AVCodecContext *avctx)
Definition: qtrle.c:496
This structure stores compressed data.
Definition: avcodec.h:898