FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tiertexseqv.c
Go to the documentation of this file.
1 /*
2  * Tiertex Limited SEQ Video Decoder
3  * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
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  * Tiertex Limited SEQ video decoder
25  */
26 
27 #include "avcodec.h"
28 #define BITSTREAM_READER_LE
29 #include "get_bits.h"
30 
31 
32 typedef struct SeqVideoContext {
36 
37 
38 static const unsigned char *seq_unpack_rle_block(const unsigned char *src,
39  const unsigned char *src_end,
40  unsigned char *dst, int dst_size)
41 {
42  int i, len, sz;
43  GetBitContext gb;
44  int code_table[64];
45 
46  /* get the rle codes */
47  init_get_bits(&gb, src, (src_end - src) * 8);
48  for (i = 0, sz = 0; i < 64 && sz < dst_size; i++) {
49  if (get_bits_left(&gb) < 4)
50  return NULL;
51  code_table[i] = get_sbits(&gb, 4);
52  sz += FFABS(code_table[i]);
53  }
54  src += (get_bits_count(&gb) + 7) / 8;
55 
56  /* do the rle unpacking */
57  for (i = 0; i < 64 && dst_size > 0; i++) {
58  len = code_table[i];
59  if (len < 0) {
60  len = -len;
61  if (src_end - src < 1)
62  return NULL;
63  memset(dst, *src++, FFMIN(len, dst_size));
64  } else {
65  if (src_end - src < len)
66  return NULL;
67  memcpy(dst, src, FFMIN(len, dst_size));
68  src += len;
69  }
70  dst += len;
71  dst_size -= len;
72  }
73  return src;
74 }
75 
76 static const unsigned char *seq_decode_op1(SeqVideoContext *seq,
77  const unsigned char *src,
78  const unsigned char *src_end,
79  unsigned char *dst)
80 {
81  const unsigned char *color_table;
82  int b, i, len, bits;
83  GetBitContext gb;
84  unsigned char block[8 * 8];
85 
86  if (src_end - src < 1)
87  return NULL;
88  len = *src++;
89  if (len & 0x80) {
90  switch (len & 3) {
91  case 1:
92  src = seq_unpack_rle_block(src, src_end, block, sizeof(block));
93  for (b = 0; b < 8; b++) {
94  memcpy(dst, &block[b * 8], 8);
95  dst += seq->frame.linesize[0];
96  }
97  break;
98  case 2:
99  src = seq_unpack_rle_block(src, src_end, block, sizeof(block));
100  for (i = 0; i < 8; i++) {
101  for (b = 0; b < 8; b++)
102  dst[b * seq->frame.linesize[0]] = block[i * 8 + b];
103  ++dst;
104  }
105  break;
106  }
107  } else {
108  if (len <= 0)
109  return NULL;
110  bits = ff_log2_tab[len - 1] + 1;
111  if (src_end - src < len + 8 * bits)
112  return NULL;
113  color_table = src;
114  src += len;
115  init_get_bits(&gb, src, bits * 8 * 8); src += bits * 8;
116  for (b = 0; b < 8; b++) {
117  for (i = 0; i < 8; i++)
118  dst[i] = color_table[get_bits(&gb, bits)];
119  dst += seq->frame.linesize[0];
120  }
121  }
122 
123  return src;
124 }
125 
126 static const unsigned char *seq_decode_op2(SeqVideoContext *seq,
127  const unsigned char *src,
128  const unsigned char *src_end,
129  unsigned char *dst)
130 {
131  int i;
132 
133  if (src_end - src < 8 * 8)
134  return NULL;
135 
136  for (i = 0; i < 8; i++) {
137  memcpy(dst, src, 8);
138  src += 8;
139  dst += seq->frame.linesize[0];
140  }
141 
142  return src;
143 }
144 
145 static const unsigned char *seq_decode_op3(SeqVideoContext *seq,
146  const unsigned char *src,
147  const unsigned char *src_end,
148  unsigned char *dst)
149 {
150  int pos, offset;
151 
152  do {
153  if (src_end - src < 2)
154  return NULL;
155  pos = *src++;
156  offset = ((pos >> 3) & 7) * seq->frame.linesize[0] + (pos & 7);
157  dst[offset] = *src++;
158  } while (!(pos & 0x80));
159 
160  return src;
161 }
162 
163 static int seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int data_size)
164 {
165  const unsigned char *data_end = data + data_size;
166  GetBitContext gb;
167  int flags, i, j, x, y, op;
168  unsigned char c[3];
169  unsigned char *dst;
170  uint32_t *palette;
171 
172  flags = *data++;
173 
174  if (flags & 1) {
175  palette = (uint32_t *)seq->frame.data[1];
176  if (data_end - data < 256 * 3)
177  return AVERROR_INVALIDDATA;
178  for (i = 0; i < 256; i++) {
179  for (j = 0; j < 3; j++, data++)
180  c[j] = (*data << 2) | (*data >> 4);
181  palette[i] = 0xFFU << 24 | AV_RB24(c);
182  }
183  seq->frame.palette_has_changed = 1;
184  }
185 
186  if (flags & 2) {
187  if (data_end - data < 128)
188  return AVERROR_INVALIDDATA;
189  init_get_bits(&gb, data, 128 * 8); data += 128;
190  for (y = 0; y < 128; y += 8)
191  for (x = 0; x < 256; x += 8) {
192  dst = &seq->frame.data[0][y * seq->frame.linesize[0] + x];
193  op = get_bits(&gb, 2);
194  switch (op) {
195  case 1:
196  data = seq_decode_op1(seq, data, data_end, dst);
197  break;
198  case 2:
199  data = seq_decode_op2(seq, data, data_end, dst);
200  break;
201  case 3:
202  data = seq_decode_op3(seq, data, data_end, dst);
203  break;
204  }
205  if (!data)
206  return AVERROR_INVALIDDATA;
207  }
208  }
209  return 0;
210 }
211 
213 {
214  SeqVideoContext *seq = avctx->priv_data;
215 
216  seq->avctx = avctx;
217  avctx->pix_fmt = AV_PIX_FMT_PAL8;
218 
220  seq->frame.data[0] = NULL;
221 
222  return 0;
223 }
224 
226  void *data, int *got_frame,
227  AVPacket *avpkt)
228 {
229  const uint8_t *buf = avpkt->data;
230  int buf_size = avpkt->size;
231 
232  SeqVideoContext *seq = avctx->priv_data;
233 
234  seq->frame.reference = 3;
236  if (avctx->reget_buffer(avctx, &seq->frame)) {
237  av_log(seq->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
238  return -1;
239  }
240 
241  if (seqvideo_decode(seq, buf, buf_size))
242  return AVERROR_INVALIDDATA;
243 
244  *got_frame = 1;
245  *(AVFrame *)data = seq->frame;
246 
247  return buf_size;
248 }
249 
251 {
252  SeqVideoContext *seq = avctx->priv_data;
253 
254  if (seq->frame.data[0])
255  avctx->release_buffer(avctx, &seq->frame);
256 
257  return 0;
258 }
259 
261  .name = "tiertexseqvideo",
262  .type = AVMEDIA_TYPE_VIDEO,
264  .priv_data_size = sizeof(SeqVideoContext),
268  .capabilities = CODEC_CAP_DR1,
269  .long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"),
270 };