FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 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  * QT RLE Video Decoder by Mike Melanson (melanson@pcisys.net)
25  * For more information about the QT RLE format, visit:
26  * http://www.pcisys.net/~melanson/codecs/
27  *
28  * The QT RLE decoder has seven modes of operation:
29  * 1, 2, 4, 8, 16, 24, and 32 bits per pixel. For modes 1, 2, 4, and 8
30  * the decoder outputs PAL8 colorspace data. 16-bit data yields RGB555
31  * data. 24-bit data is RGB24 and 32-bit data is RGB32.
32  */
33 
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 == -1)
83  continue;
84 
85  if (rle_code < 0) {
86  /* decode the run length code */
87  rle_code = -rle_code;
88  /* get the next 2 bytes from the stream, treat them as groups
89  * of 8 pixels, and output them rle_code times */
90 
91  pi0 = bytestream2_get_byte(&s->g);
92  pi1 = bytestream2_get_byte(&s->g);
93  CHECK_PIXEL_PTR(rle_code * 2);
94 
95  while (rle_code--) {
96  rgb[pixel_ptr++] = pi0;
97  rgb[pixel_ptr++] = pi1;
98  }
99  } else {
100  /* copy the same pixel directly to output 2 times */
101  rle_code *= 2;
102  CHECK_PIXEL_PTR(rle_code);
103 
104  while (rle_code--)
105  rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
106  }
107  }
108 }
109 
110 static inline void qtrle_decode_2n4bpp(QtrleContext *s, int row_ptr,
111  int lines_to_change, int bpp)
112 {
113  int rle_code, i;
114  int pixel_ptr;
115  int row_inc = s->frame.linesize[0];
116  unsigned char pi[16]; /* 16 palette indices */
117  unsigned char *rgb = s->frame.data[0];
118  int pixel_limit = s->frame.linesize[0] * s->avctx->height;
119  int num_pixels = (bpp == 4) ? 8 : 16;
120 
121  while (lines_to_change--) {
122  pixel_ptr = row_ptr + (num_pixels * (bytestream2_get_byte(&s->g) - 1));
123  CHECK_PIXEL_PTR(0);
124 
125  while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
126  if (rle_code == 0) {
127  /* there's another skip code in the stream */
128  pixel_ptr += (num_pixels * (bytestream2_get_byte(&s->g) - 1));
129  CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
130  } else if (rle_code < 0) {
131  /* decode the run length code */
132  rle_code = -rle_code;
133  /* get the next 4 bytes from the stream, treat them as palette
134  * indexes, and output them rle_code times */
135  for (i = num_pixels-1; i >= 0; i--) {
136  pi[num_pixels-1-i] = (bytestream2_peek_byte(&s->g) >> ((i*bpp) & 0x07)) & ((1<<bpp)-1);
137  bytestream2_skip(&s->g, ((i & ((num_pixels>>2)-1)) == 0));
138  }
139  CHECK_PIXEL_PTR(rle_code * num_pixels);
140  while (rle_code--) {
141  for (i = 0; i < num_pixels; i++)
142  rgb[pixel_ptr++] = pi[i];
143  }
144  } else {
145  /* copy the same pixel directly to output 4 times */
146  rle_code *= 4;
147  CHECK_PIXEL_PTR(rle_code*(num_pixels>>2));
148  while (rle_code--) {
149  if(bpp == 4) {
150  int x = bytestream2_get_byte(&s->g);
151  rgb[pixel_ptr++] = (x >> 4) & 0x0f;
152  rgb[pixel_ptr++] = x & 0x0f;
153  } else {
154  int x = bytestream2_get_byte(&s->g);
155  rgb[pixel_ptr++] = (x >> 6) & 0x03;
156  rgb[pixel_ptr++] = (x >> 4) & 0x03;
157  rgb[pixel_ptr++] = (x >> 2) & 0x03;
158  rgb[pixel_ptr++] = x & 0x03;
159  }
160  }
161  }
162  }
163  row_ptr += row_inc;
164  }
165 }
166 
167 static void qtrle_decode_8bpp(QtrleContext *s, int row_ptr, int lines_to_change)
168 {
169  int rle_code;
170  int pixel_ptr;
171  int row_inc = s->frame.linesize[0];
172  unsigned char pi1, pi2, pi3, pi4; /* 4 palette indexes */
173  unsigned char *rgb = s->frame.data[0];
174  int pixel_limit = s->frame.linesize[0] * s->avctx->height;
175 
176  while (lines_to_change--) {
177  pixel_ptr = row_ptr + (4 * (bytestream2_get_byte(&s->g) - 1));
178  CHECK_PIXEL_PTR(0);
179 
180  while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
181  if (rle_code == 0) {
182  /* there's another skip code in the stream */
183  pixel_ptr += (4 * (bytestream2_get_byte(&s->g) - 1));
184  CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
185  } else if (rle_code < 0) {
186  /* decode the run length code */
187  rle_code = -rle_code;
188  /* get the next 4 bytes from the stream, treat them as palette
189  * indexes, and output them rle_code times */
190  pi1 = bytestream2_get_byte(&s->g);
191  pi2 = bytestream2_get_byte(&s->g);
192  pi3 = bytestream2_get_byte(&s->g);
193  pi4 = bytestream2_get_byte(&s->g);
194 
195  CHECK_PIXEL_PTR(rle_code * 4);
196 
197  while (rle_code--) {
198  rgb[pixel_ptr++] = pi1;
199  rgb[pixel_ptr++] = pi2;
200  rgb[pixel_ptr++] = pi3;
201  rgb[pixel_ptr++] = pi4;
202  }
203  } else {
204  /* copy the same pixel directly to output 4 times */
205  rle_code *= 4;
206  CHECK_PIXEL_PTR(rle_code);
207 
208  while (rle_code--) {
209  rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
210  }
211  }
212  }
213  row_ptr += row_inc;
214  }
215 }
216 
217 static void qtrle_decode_16bpp(QtrleContext *s, int row_ptr, int lines_to_change)
218 {
219  int rle_code;
220  int pixel_ptr;
221  int row_inc = s->frame.linesize[0];
222  unsigned short rgb16;
223  unsigned char *rgb = s->frame.data[0];
224  int pixel_limit = s->frame.linesize[0] * s->avctx->height;
225 
226  while (lines_to_change--) {
227  pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 2;
228  CHECK_PIXEL_PTR(0);
229 
230  while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
231  if (rle_code == 0) {
232  /* there's another skip code in the stream */
233  pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 2;
234  CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
235  } else if (rle_code < 0) {
236  /* decode the run length code */
237  rle_code = -rle_code;
238  rgb16 = bytestream2_get_be16(&s->g);
239 
240  CHECK_PIXEL_PTR(rle_code * 2);
241 
242  while (rle_code--) {
243  *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
244  pixel_ptr += 2;
245  }
246  } else {
247  CHECK_PIXEL_PTR(rle_code * 2);
248 
249  /* copy pixels directly to output */
250  while (rle_code--) {
251  rgb16 = bytestream2_get_be16(&s->g);
252  *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
253  pixel_ptr += 2;
254  }
255  }
256  }
257  row_ptr += row_inc;
258  }
259 }
260 
261 static void qtrle_decode_24bpp(QtrleContext *s, int row_ptr, int lines_to_change)
262 {
263  int rle_code;
264  int pixel_ptr;
265  int row_inc = s->frame.linesize[0];
266  unsigned char r, g, b;
267  unsigned char *rgb = s->frame.data[0];
268  int pixel_limit = s->frame.linesize[0] * s->avctx->height;
269 
270  while (lines_to_change--) {
271  pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 3;
272  CHECK_PIXEL_PTR(0);
273 
274  while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
275  if (rle_code == 0) {
276  /* there's another skip code in the stream */
277  pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 3;
278  CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
279  } else if (rle_code < 0) {
280  /* decode the run length code */
281  rle_code = -rle_code;
282  r = bytestream2_get_byte(&s->g);
283  g = bytestream2_get_byte(&s->g);
284  b = bytestream2_get_byte(&s->g);
285 
286  CHECK_PIXEL_PTR(rle_code * 3);
287 
288  while (rle_code--) {
289  rgb[pixel_ptr++] = r;
290  rgb[pixel_ptr++] = g;
291  rgb[pixel_ptr++] = b;
292  }
293  } else {
294  CHECK_PIXEL_PTR(rle_code * 3);
295 
296  /* copy pixels directly to output */
297  while (rle_code--) {
298  rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
299  rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
300  rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
301  }
302  }
303  }
304  row_ptr += row_inc;
305  }
306 }
307 
308 static void qtrle_decode_32bpp(QtrleContext *s, int row_ptr, int lines_to_change)
309 {
310  int rle_code;
311  int pixel_ptr;
312  int row_inc = s->frame.linesize[0];
313  unsigned int argb;
314  unsigned char *rgb = s->frame.data[0];
315  int pixel_limit = s->frame.linesize[0] * s->avctx->height;
316 
317  while (lines_to_change--) {
318  pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 4;
319  CHECK_PIXEL_PTR(0);
320 
321  while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
322  if (rle_code == 0) {
323  /* there's another skip code in the stream */
324  pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 4;
325  CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
326  } else if (rle_code < 0) {
327  /* decode the run length code */
328  rle_code = -rle_code;
329  argb = bytestream2_get_be32(&s->g);
330 
331  CHECK_PIXEL_PTR(rle_code * 4);
332 
333  while (rle_code--) {
334  AV_WN32A(rgb + pixel_ptr, argb);
335  pixel_ptr += 4;
336  }
337  } else {
338  CHECK_PIXEL_PTR(rle_code * 4);
339 
340  /* copy pixels directly to output */
341  while (rle_code--) {
342  argb = bytestream2_get_be32(&s->g);
343  AV_WN32A(rgb + pixel_ptr, argb);
344  pixel_ptr += 4;
345  }
346  }
347  }
348  row_ptr += row_inc;
349  }
350 }
351 
353 {
354  QtrleContext *s = avctx->priv_data;
355 
356  s->avctx = avctx;
357  switch (avctx->bits_per_coded_sample) {
358  case 1:
359  case 33:
360  avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
361  break;
362 
363  case 2:
364  case 4:
365  case 8:
366  case 34:
367  case 36:
368  case 40:
369  avctx->pix_fmt = AV_PIX_FMT_PAL8;
370  break;
371 
372  case 16:
373  avctx->pix_fmt = AV_PIX_FMT_RGB555;
374  break;
375 
376  case 24:
377  avctx->pix_fmt = AV_PIX_FMT_RGB24;
378  break;
379 
380  case 32:
381  avctx->pix_fmt = AV_PIX_FMT_RGB32;
382  break;
383 
384  default:
385  av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
386  avctx->bits_per_coded_sample);
387  return AVERROR_INVALIDDATA;
388  }
389 
391  s->frame.data[0] = NULL;
392 
393  return 0;
394 }
395 
397  void *data, int *got_frame,
398  AVPacket *avpkt)
399 {
400  QtrleContext *s = avctx->priv_data;
401  int header, start_line;
402  int height, row_ptr;
403  int has_palette = 0;
404 
405  bytestream2_init(&s->g, avpkt->data, avpkt->size);
406  s->frame.reference = 3;
409  if (avctx->reget_buffer(avctx, &s->frame)) {
410  av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
411  return -1;
412  }
413 
414  /* check if this frame is even supposed to change */
415  if (avpkt->size < 8)
416  goto done;
417 
418  /* start after the chunk size */
419  bytestream2_seek(&s->g, 4, SEEK_SET);
420 
421  /* fetch the header */
422  header = bytestream2_get_be16(&s->g);
423 
424  /* if a header is present, fetch additional decoding parameters */
425  if (header & 0x0008) {
426  if (avpkt->size < 14)
427  goto done;
428  start_line = bytestream2_get_be16(&s->g);
429  bytestream2_skip(&s->g, 2);
430  height = bytestream2_get_be16(&s->g);
431  bytestream2_skip(&s->g, 2);
432  if (height > s->avctx->height - start_line)
433  goto done;
434  } else {
435  start_line = 0;
436  height = s->avctx->height;
437  }
438  row_ptr = s->frame.linesize[0] * start_line;
439 
440  switch (avctx->bits_per_coded_sample) {
441  case 1:
442  case 33:
443  qtrle_decode_1bpp(s, row_ptr, height);
444  break;
445 
446  case 2:
447  case 34:
448  qtrle_decode_2n4bpp(s, row_ptr, height, 2);
449  has_palette = 1;
450  break;
451 
452  case 4:
453  case 36:
454  qtrle_decode_2n4bpp(s, row_ptr, height, 4);
455  has_palette = 1;
456  break;
457 
458  case 8:
459  case 40:
460  qtrle_decode_8bpp(s, row_ptr, height);
461  has_palette = 1;
462  break;
463 
464  case 16:
465  qtrle_decode_16bpp(s, row_ptr, height);
466  break;
467 
468  case 24:
469  qtrle_decode_24bpp(s, row_ptr, height);
470  break;
471 
472  case 32:
473  qtrle_decode_32bpp(s, row_ptr, height);
474  break;
475 
476  default:
477  av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
478  avctx->bits_per_coded_sample);
479  break;
480  }
481 
482  if(has_palette) {
484 
485  if (pal) {
486  s->frame.palette_has_changed = 1;
487  memcpy(s->pal, pal, AVPALETTE_SIZE);
488  }
489 
490  /* make the palette available on the way out */
491  memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE);
492  }
493 
494 done:
495  *got_frame = 1;
496  *(AVFrame*)data = s->frame;
497 
498  /* always report that the buffer was completely consumed */
499  return avpkt->size;
500 }
501 
503 {
504  QtrleContext *s = avctx->priv_data;
505 
506  if (s->frame.data[0])
507  avctx->release_buffer(avctx, &s->frame);
508 
509  return 0;
510 }
511 
513  .name = "qtrle",
514  .type = AVMEDIA_TYPE_VIDEO,
515  .id = AV_CODEC_ID_QTRLE,
516  .priv_data_size = sizeof(QtrleContext),
520  .capabilities = CODEC_CAP_DR1,
521  .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
522 };