rpza.c
Go to the documentation of this file.
1 /*
2  * Quicktime Video (RPZA) Video Decoder
3  * Copyright (C) 2003 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 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 #include "libavutil/common.h"
42 #include "libavutil/internal.h"
43 #include "libavutil/intreadwrite.h"
44 #include "libavutil/common.h"
45 #include "avcodec.h"
46 
47 typedef struct RpzaContext {
48 
51 
52  const unsigned char *buf;
53  int size;
54 
55 } RpzaContext;
56 
57 #define ADVANCE_BLOCK() \
58 { \
59  pixel_ptr += 4; \
60  if (pixel_ptr >= width) \
61  { \
62  pixel_ptr = 0; \
63  row_ptr += stride * 4; \
64  } \
65  total_blocks--; \
66  if (total_blocks < 0) \
67  { \
68  av_log(s->avctx, AV_LOG_ERROR, "warning: block counter just went negative (this should not happen)\n"); \
69  return; \
70  } \
71 }
72 
74 {
75  int width = s->avctx->width;
76  int stride = s->frame.linesize[0] / 2;
77  int row_inc = stride - 4;
78  int stream_ptr = 0;
79  int chunk_size;
80  unsigned char opcode;
81  int n_blocks;
82  unsigned short colorA = 0, colorB;
83  unsigned short color4[4];
84  unsigned char index, idx;
85  unsigned short ta, tb;
86  unsigned short *pixels = (unsigned short *)s->frame.data[0];
87 
88  int row_ptr = 0;
89  int pixel_ptr = 0;
90  int block_ptr;
91  int pixel_x, pixel_y;
92  int total_blocks;
93 
94  /* First byte is always 0xe1. Warn if it's different */
95  if (s->buf[stream_ptr] != 0xe1)
96  av_log(s->avctx, AV_LOG_ERROR, "First chunk byte is 0x%02x instead of 0xe1\n",
97  s->buf[stream_ptr]);
98 
99  /* Get chunk size, ingnoring first byte */
100  chunk_size = AV_RB32(&s->buf[stream_ptr]) & 0x00FFFFFF;
101  stream_ptr += 4;
102 
103  /* If length mismatch use size from MOV file and try to decode anyway */
104  if (chunk_size != s->size)
105  av_log(s->avctx, AV_LOG_ERROR, "MOV chunk size != encoded chunk size; using MOV chunk size\n");
106 
107  chunk_size = s->size;
108 
109  /* Number of 4x4 blocks in frame. */
110  total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4);
111 
112  /* Process chunk data */
113  while (stream_ptr < chunk_size) {
114  opcode = s->buf[stream_ptr++]; /* Get opcode */
115 
116  n_blocks = (opcode & 0x1f) + 1; /* Extract block counter from opcode */
117 
118  /* If opcode MSbit is 0, we need more data to decide what to do */
119  if ((opcode & 0x80) == 0) {
120  colorA = (opcode << 8) | (s->buf[stream_ptr++]);
121  opcode = 0;
122  if ((s->buf[stream_ptr] & 0x80) != 0) {
123  /* Must behave as opcode 110xxxxx, using colorA computed
124  * above. Use fake opcode 0x20 to enter switch block at
125  * the right place */
126  opcode = 0x20;
127  n_blocks = 1;
128  }
129  }
130 
131  n_blocks = FFMIN(n_blocks, total_blocks);
132 
133  switch (opcode & 0xe0) {
134 
135  /* Skip blocks */
136  case 0x80:
137  while (n_blocks--) {
138  ADVANCE_BLOCK();
139  }
140  break;
141 
142  /* Fill blocks with one color */
143  case 0xa0:
144  colorA = AV_RB16 (&s->buf[stream_ptr]);
145  stream_ptr += 2;
146  while (n_blocks--) {
147  block_ptr = row_ptr + pixel_ptr;
148  for (pixel_y = 0; pixel_y < 4; pixel_y++) {
149  for (pixel_x = 0; pixel_x < 4; pixel_x++){
150  pixels[block_ptr] = colorA;
151  block_ptr++;
152  }
153  block_ptr += row_inc;
154  }
155  ADVANCE_BLOCK();
156  }
157  break;
158 
159  /* Fill blocks with 4 colors */
160  case 0xc0:
161  colorA = AV_RB16 (&s->buf[stream_ptr]);
162  stream_ptr += 2;
163  case 0x20:
164  colorB = AV_RB16 (&s->buf[stream_ptr]);
165  stream_ptr += 2;
166 
167  /* sort out the colors */
168  color4[0] = colorB;
169  color4[1] = 0;
170  color4[2] = 0;
171  color4[3] = colorA;
172 
173  /* red components */
174  ta = (colorA >> 10) & 0x1F;
175  tb = (colorB >> 10) & 0x1F;
176  color4[1] |= ((11 * ta + 21 * tb) >> 5) << 10;
177  color4[2] |= ((21 * ta + 11 * tb) >> 5) << 10;
178 
179  /* green components */
180  ta = (colorA >> 5) & 0x1F;
181  tb = (colorB >> 5) & 0x1F;
182  color4[1] |= ((11 * ta + 21 * tb) >> 5) << 5;
183  color4[2] |= ((21 * ta + 11 * tb) >> 5) << 5;
184 
185  /* blue components */
186  ta = colorA & 0x1F;
187  tb = colorB & 0x1F;
188  color4[1] |= ((11 * ta + 21 * tb) >> 5);
189  color4[2] |= ((21 * ta + 11 * tb) >> 5);
190 
191  if (s->size - stream_ptr < n_blocks * 4)
192  return;
193  while (n_blocks--) {
194  block_ptr = row_ptr + pixel_ptr;
195  for (pixel_y = 0; pixel_y < 4; pixel_y++) {
196  index = s->buf[stream_ptr++];
197  for (pixel_x = 0; pixel_x < 4; pixel_x++){
198  idx = (index >> (2 * (3 - pixel_x))) & 0x03;
199  pixels[block_ptr] = color4[idx];
200  block_ptr++;
201  }
202  block_ptr += row_inc;
203  }
204  ADVANCE_BLOCK();
205  }
206  break;
207 
208  /* Fill block with 16 colors */
209  case 0x00:
210  if (s->size - stream_ptr < 30)
211  return;
212  block_ptr = row_ptr + pixel_ptr;
213  for (pixel_y = 0; pixel_y < 4; pixel_y++) {
214  for (pixel_x = 0; pixel_x < 4; pixel_x++){
215  /* We already have color of upper left pixel */
216  if ((pixel_y != 0) || (pixel_x !=0)) {
217  colorA = AV_RB16 (&s->buf[stream_ptr]);
218  stream_ptr += 2;
219  }
220  pixels[block_ptr] = colorA;
221  block_ptr++;
222  }
223  block_ptr += row_inc;
224  }
225  ADVANCE_BLOCK();
226  break;
227 
228  /* Unknown opcode */
229  default:
230  av_log(s->avctx, AV_LOG_ERROR, "Unknown opcode %d in rpza chunk."
231  " Skip remaining %d bytes of chunk data.\n", opcode,
232  chunk_size - stream_ptr);
233  return;
234  } /* Opcode switch */
235  }
236 }
237 
239 {
240  RpzaContext *s = avctx->priv_data;
241 
242  s->avctx = avctx;
243  avctx->pix_fmt = AV_PIX_FMT_RGB555;
244 
245  s->frame.data[0] = NULL;
246 
247  return 0;
248 }
249 
251  void *data, int *got_frame,
252  AVPacket *avpkt)
253 {
254  const uint8_t *buf = avpkt->data;
255  int buf_size = avpkt->size;
256  RpzaContext *s = avctx->priv_data;
257 
258  s->buf = buf;
259  s->size = buf_size;
260 
261  s->frame.reference = 1;
263  if (avctx->reget_buffer(avctx, &s->frame)) {
264  av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
265  return -1;
266  }
267 
269 
270  *got_frame = 1;
271  *(AVFrame*)data = s->frame;
272 
273  /* always report that the buffer was completely consumed */
274  return buf_size;
275 }
276 
278 {
279  RpzaContext *s = avctx->priv_data;
280 
281  if (s->frame.data[0])
282  avctx->release_buffer(avctx, &s->frame);
283 
284  return 0;
285 }
286 
288  .name = "rpza",
289  .type = AVMEDIA_TYPE_VIDEO,
290  .id = AV_CODEC_ID_RPZA,
291  .priv_data_size = sizeof(RpzaContext),
295  .capabilities = CODEC_CAP_DR1,
296  .long_name = NULL_IF_CONFIG_SMALL("QuickTime video (RPZA)"),
297 };
static int rpza_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: rpza.c:250
This structure describes decoded (raw) audio or video data.
Definition: avcodec.h:989
struct RpzaContext RpzaContext
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
int size
Definition: avcodec.h:916
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1533
int stride
Definition: mace.c:144
AVCodec.
Definition: avcodec.h:2960
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
static void rpza_decode_stream(RpzaContext *s)
Definition: rpza.c:73
uint8_t
#define AV_RB32
Definition: intreadwrite.h:130
AVCodec ff_rpza_decoder
Definition: rpza.c:287
const char data[16]
Definition: mxf.c:66
uint8_t * data
Definition: avcodec.h:915
static int init(AVCodecParserContext *s)
Definition: h264_parser.c:335
static av_cold int rpza_decode_end(AVCodecContext *avctx)
Definition: rpza.c:277
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
#define AV_RB16
Definition: intreadwrite.h:53
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:88
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
common internal API header
int width
picture width / height.
Definition: avcodec.h:1508
static av_cold int rpza_decode_init(AVCodecContext *avctx)
Definition: rpza.c:238
NULL
Definition: eval.c:52
static int width
Definition: utils.c:156
int size
Definition: rpza.c:53
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 index
Definition: gxfenc.c:72
const unsigned char * buf
Definition: rpza.c:52
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: avcodec.h:997
common internal and external API header
AVCodecContext * avctx
Definition: rpza.c:49
void * priv_data
Definition: avcodec.h:1382
#define ADVANCE_BLOCK()
Definition: rpza.c:57
AVFrame frame
Definition: rpza.c:50
This structure stores compressed data.
Definition: avcodec.h:898
if(!(ptr_align%ac->ptr_align)&&samples_align >=aligned_len)