idcinvideo.c
Go to the documentation of this file.
1 /*
2  * id Quake II CIN 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 
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 
51 #include "avcodec.h"
52 
53 #define HUFFMAN_TABLE_SIZE 64 * 1024
54 #define HUF_TOKENS 256
55 #define PALETTE_COUNT 256
56 
57 typedef struct
58 {
59  int count;
60  unsigned char used;
61  int children[2];
62 } hnode;
63 
64 typedef struct IdcinContext {
65 
68 
69  const unsigned char *buf;
70  int size;
71 
73  int num_huff_nodes[256];
74 
75  uint32_t pal[256];
76 } IdcinContext;
77 
78 /*
79  * Find the lowest probability node in a Huffman table, and mark it as
80  * being assigned to a higher probability.
81  * @return the node index of the lowest unused node, or -1 if all nodes
82  * are used.
83  */
84 static int huff_smallest_node(hnode *hnodes, int num_hnodes) {
85  int i;
86  int best, best_node;
87 
88  best = 99999999;
89  best_node = -1;
90  for(i = 0; i < num_hnodes; i++) {
91  if(hnodes[i].used)
92  continue;
93  if(!hnodes[i].count)
94  continue;
95  if(hnodes[i].count < best) {
96  best = hnodes[i].count;
97  best_node = i;
98  }
99  }
100 
101  if(best_node == -1)
102  return -1;
103  hnodes[best_node].used = 1;
104  return best_node;
105 }
106 
107 /*
108  * Build the Huffman tree using the generated/loaded probabilities histogram.
109  *
110  * On completion:
111  * huff_nodes[prev][i < HUF_TOKENS] - are the nodes at the base of the tree.
112  * huff_nodes[prev][i >= HUF_TOKENS] - are used to construct the tree.
113  * num_huff_nodes[prev] - contains the index to the root node of the tree.
114  * That is: huff_nodes[prev][num_huff_nodes[prev]] is the root node.
115  */
116 static av_cold void huff_build_tree(IdcinContext *s, int prev) {
117  hnode *node, *hnodes;
118  int num_hnodes, i;
119 
120  num_hnodes = HUF_TOKENS;
121  hnodes = s->huff_nodes[prev];
122  for(i = 0; i < HUF_TOKENS * 2; i++)
123  hnodes[i].used = 0;
124 
125  while (1) {
126  node = &hnodes[num_hnodes]; /* next free node */
127 
128  /* pick two lowest counts */
129  node->children[0] = huff_smallest_node(hnodes, num_hnodes);
130  if(node->children[0] == -1)
131  break; /* reached the root node */
132 
133  node->children[1] = huff_smallest_node(hnodes, num_hnodes);
134  if(node->children[1] == -1)
135  break; /* reached the root node */
136 
137  /* combine nodes probability for new node */
138  node->count = hnodes[node->children[0]].count +
139  hnodes[node->children[1]].count;
140  num_hnodes++;
141  }
142 
143  s->num_huff_nodes[prev] = num_hnodes - 1;
144 }
145 
147 {
148  IdcinContext *s = avctx->priv_data;
149  int i, j, histogram_index = 0;
150  unsigned char *histograms;
151 
152  s->avctx = avctx;
153  avctx->pix_fmt = PIX_FMT_PAL8;
154 
155  /* make sure the Huffman tables make it */
157  av_log(s->avctx, AV_LOG_ERROR, " id CIN video: expected extradata size of %d\n", HUFFMAN_TABLE_SIZE);
158  return -1;
159  }
160 
161  /* build the 256 Huffman decode trees */
162  histograms = (unsigned char *)s->avctx->extradata;
163  for (i = 0; i < 256; i++) {
164  for(j = 0; j < HUF_TOKENS; j++)
165  s->huff_nodes[i][j].count = histograms[histogram_index++];
166  huff_build_tree(s, i);
167  }
168 
169  s->frame.data[0] = NULL;
170 
171  return 0;
172 }
173 
175 {
176  hnode *hnodes;
177  long x, y;
178  int prev;
179  unsigned char v = 0;
180  int bit_pos, node_num, dat_pos;
181 
182  prev = bit_pos = dat_pos = 0;
183  for (y = 0; y < (s->frame.linesize[0] * s->avctx->height);
184  y += s->frame.linesize[0]) {
185  for (x = y; x < y + s->avctx->width; x++) {
186  node_num = s->num_huff_nodes[prev];
187  hnodes = s->huff_nodes[prev];
188 
189  while(node_num >= HUF_TOKENS) {
190  if(!bit_pos) {
191  if(dat_pos >= s->size) {
192  av_log(s->avctx, AV_LOG_ERROR, "Huffman decode error.\n");
193  return;
194  }
195  bit_pos = 8;
196  v = s->buf[dat_pos++];
197  }
198 
199  node_num = hnodes[node_num].children[v & 0x01];
200  v = v >> 1;
201  bit_pos--;
202  }
203 
204  s->frame.data[0][x] = node_num;
205  prev = node_num;
206  }
207  }
208 }
209 
211  void *data, int *data_size,
212  AVPacket *avpkt)
213 {
214  const uint8_t *buf = avpkt->data;
215  int buf_size = avpkt->size;
216  IdcinContext *s = avctx->priv_data;
217  const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
218 
219  s->buf = buf;
220  s->size = buf_size;
221 
222  if (s->frame.data[0])
223  avctx->release_buffer(avctx, &s->frame);
224 
225  if (avctx->get_buffer(avctx, &s->frame)) {
226  av_log(avctx, AV_LOG_ERROR, " id CIN Video: get_buffer() failed\n");
227  return -1;
228  }
229 
231 
232  if (pal) {
233  s->frame.palette_has_changed = 1;
234  memcpy(s->pal, pal, AVPALETTE_SIZE);
235  }
236  /* make the palette available on the way out */
237  memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE);
238 
239  *data_size = sizeof(AVFrame);
240  *(AVFrame*)data = s->frame;
241 
242  /* report that the buffer was completely consumed */
243  return buf_size;
244 }
245 
247 {
248  IdcinContext *s = avctx->priv_data;
249 
250  if (s->frame.data[0])
251  avctx->release_buffer(avctx, &s->frame);
252 
253  return 0;
254 }
255 
257  .name = "idcinvideo",
258  .type = AVMEDIA_TYPE_VIDEO,
259  .id = CODEC_ID_IDCIN,
260  .priv_data_size = sizeof(IdcinContext),
264  .capabilities = CODEC_CAP_DR1,
265  .long_name = NULL_IF_CONFIG_SMALL("id Quake II CIN video"),
266 };
267 
static av_cold int idcin_decode_end(AVCodecContext *avctx)
Definition: idcinvideo.c:246
int(* get_buffer)(struct AVCodecContext *c, AVFrame *pic)
Called at the beginning of each frame to get a buffer for it.
Definition: avcodec.h:1726
enum PixelFormat pix_fmt
Pixel format, see PIX_FMT_xxx.
Definition: avcodec.h:1426
Audio Video Frame.
Definition: avcodec.h:985
void(* release_buffer)(struct AVCodecContext *c, AVFrame *pic)
Called to release buffers which were allocated with get_buffer.
Definition: avcodec.h:1737
AVFrame frame
Definition: idcinvideo.c:67
int size
Definition: avcodec.h:909
AVCodec.
Definition: avcodec.h:3189
int num_huff_nodes[256]
Definition: idcinvideo.c:73
#define v(n)
Definition: regs.h:34
static int decode(MimicContext *ctx, int quality, int num_coeffs, int is_iframe)
Definition: mimic.c:228
#define av_cold
Definition: attributes.h:71
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1387
AVCodec ff_idcin_decoder
Definition: idcinvideo.c:256
const char data[16]
Definition: mxf.c:60
uint8_t * data
Definition: avcodec.h:908
hnode huff_nodes[256][HUF_TOKENS *2]
Definition: idcinvideo.c:72
static int init(AVCodecParserContext *s)
Definition: h264_parser.c:336
struct IdcinContext IdcinContext
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:719
static int huff_smallest_node(hnode *hnodes, int num_hnodes)
Definition: idcinvideo.c:84
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:191
#define HUFFMAN_TABLE_SIZE
Definition: idcinvideo.c:53
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:140
const char * name
Name of the codec implementation.
Definition: avcodec.h:3196
static void idcin_decode_vlcs(IdcinContext *s)
Definition: idcinvideo.c:174
int width
picture width / height.
Definition: avcodec.h:1408
struct AVFrame AVFrame
Audio Video Frame.
int count
Definition: idcinvideo.c:59
static av_cold void huff_build_tree(IdcinContext *s, int prev)
Definition: idcinvideo.c:116
const unsigned char * buf
Definition: idcinvideo.c:69
uint8_t * av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int *size)
Get side information from packet.
Definition: avpacket.c:185
NULL
Definition: eval.c:50
AVCodecContext * avctx
Definition: idcinvideo.c:66
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:1329
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:327
static int idcin_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
Definition: idcinvideo.c:210
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:111
int children[2]
Definition: idcinvideo.c:61
int extradata_size
Definition: avcodec.h:1388
int palette_has_changed
Tell user application that palette has changed from previous frame.
Definition: avcodec.h:1188
#define HUF_TOKENS
Definition: idcinvideo.c:54
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: avcodec.h:997
#define AVPALETTE_SIZE
Definition: avcodec.h:3372
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:75
static av_cold int idcin_decode_init(AVCodecContext *avctx)
Definition: idcinvideo.c:146
void * priv_data
Definition: avcodec.h:1531
uint32_t pal[256]
Definition: idcinvideo.c:75
unsigned char used
Definition: idcinvideo.c:60
for(j=16;j >0;--j)