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