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