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 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  * id Quake II Cin Video Decoder by Dr. Tim Ferguson
25  * For more information about the id CIN format, visit:
26  * http://www.csse.monash.edu.au/~timf/
27  *
28  * This video decoder outputs PAL8 colorspace data. Interacting with this
29  * decoder is a little involved. During initialization, the demuxer must
30  * transmit the 65536-byte Huffman table(s) to the decoder via extradata.
31  * Then, whenever a palette change is encountered while demuxing the file,
32  * the demuxer must use the same extradata space to transmit an
33  * AVPaletteControl structure.
34  *
35  * id CIN video is purely Huffman-coded, intraframe-only codec. It achieves
36  * a little more compression by exploiting the fact that adjacent pixels
37  * tend to be similar.
38  *
39  * Note that this decoder could use libavcodec's optimized VLC facilities
40  * rather than naive, tree-based Huffman decoding. However, there are 256
41  * Huffman tables. Plus, the VLC bit coding order is right -> left instead
42  * or left -> right, so all of the bits would have to be reversed. Further,
43  * the original Quake II implementation likely used a similar naive
44  * decoding algorithm and it worked fine on much lower spec machines.
45  */
46 
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 
69 
70  const unsigned char *buf;
71  int size;
72 
74  int num_huff_nodes[256];
75 
76  uint32_t pal[256];
77 } IdcinContext;
78 
79 /**
80  * Find the lowest probability node in a Huffman table, and mark it as
81  * being assigned to a higher probability.
82  * @return the node index of the lowest unused node, or -1 if all nodes
83  * are used.
84  */
85 static int huff_smallest_node(hnode *hnodes, int num_hnodes) {
86  int i;
87  int best, best_node;
88 
89  best = 99999999;
90  best_node = -1;
91  for(i = 0; i < num_hnodes; i++) {
92  if(hnodes[i].used)
93  continue;
94  if(!hnodes[i].count)
95  continue;
96  if(hnodes[i].count < best) {
97  best = hnodes[i].count;
98  best_node = i;
99  }
100  }
101 
102  if(best_node == -1)
103  return -1;
104  hnodes[best_node].used = 1;
105  return best_node;
106 }
107 
108 /*
109  * Build the Huffman tree using the generated/loaded probabilities histogram.
110  *
111  * On completion:
112  * huff_nodes[prev][i < HUF_TOKENS] - are the nodes at the base of the tree.
113  * huff_nodes[prev][i >= HUF_TOKENS] - are used to construct the tree.
114  * num_huff_nodes[prev] - contains the index to the root node of the tree.
115  * That is: huff_nodes[prev][num_huff_nodes[prev]] is the root node.
116  */
117 static av_cold void huff_build_tree(IdcinContext *s, int prev) {
118  hnode *node, *hnodes;
119  int num_hnodes, i;
120 
121  num_hnodes = HUF_TOKENS;
122  hnodes = s->huff_nodes[prev];
123  for(i = 0; i < HUF_TOKENS * 2; i++)
124  hnodes[i].used = 0;
125 
126  while (1) {
127  node = &hnodes[num_hnodes]; /* next free node */
128 
129  /* pick two lowest counts */
130  node->children[0] = huff_smallest_node(hnodes, num_hnodes);
131  if(node->children[0] == -1)
132  break; /* reached the root node */
133 
134  node->children[1] = huff_smallest_node(hnodes, num_hnodes);
135  if(node->children[1] == -1)
136  break; /* reached the root node */
137 
138  /* combine nodes probability for new node */
139  node->count = hnodes[node->children[0]].count +
140  hnodes[node->children[1]].count;
141  num_hnodes++;
142  }
143 
144  s->num_huff_nodes[prev] = num_hnodes - 1;
145 }
146 
148 {
149  IdcinContext *s = avctx->priv_data;
150  int i, j, histogram_index = 0;
151  unsigned char *histograms;
152 
153  s->avctx = avctx;
154  avctx->pix_fmt = AV_PIX_FMT_PAL8;
155 
156  /* make sure the Huffman tables make it */
158  av_log(s->avctx, AV_LOG_ERROR, " id CIN video: expected extradata size of %d\n", HUFFMAN_TABLE_SIZE);
159  return -1;
160  }
161 
162  /* build the 256 Huffman decode trees */
163  histograms = (unsigned char *)s->avctx->extradata;
164  for (i = 0; i < 256; i++) {
165  for(j = 0; j < HUF_TOKENS; j++)
166  s->huff_nodes[i][j].count = histograms[histogram_index++];
167  huff_build_tree(s, i);
168  }
169 
170  return 0;
171 }
172 
174 {
175  hnode *hnodes;
176  long x, y;
177  int prev;
178  unsigned char v = 0;
179  int bit_pos, node_num, dat_pos;
180 
181  prev = bit_pos = dat_pos = 0;
182  for (y = 0; y < (frame->linesize[0] * s->avctx->height);
183  y += frame->linesize[0]) {
184  for (x = y; x < y + s->avctx->width; x++) {
185  node_num = s->num_huff_nodes[prev];
186  hnodes = s->huff_nodes[prev];
187 
188  while(node_num >= HUF_TOKENS) {
189  if(!bit_pos) {
190  if(dat_pos >= s->size) {
191  av_log(s->avctx, AV_LOG_ERROR, "Huffman decode error.\n");
192  return -1;
193  }
194  bit_pos = 8;
195  v = s->buf[dat_pos++];
196  }
197 
198  node_num = hnodes[node_num].children[v & 0x01];
199  v = v >> 1;
200  bit_pos--;
201  }
202 
203  frame->data[0][x] = node_num;
204  prev = node_num;
205  }
206  }
207 
208  return 0;
209 }
210 
212  void *data, int *got_frame,
213  AVPacket *avpkt)
214 {
215  const uint8_t *buf = avpkt->data;
216  int buf_size = avpkt->size;
217  IdcinContext *s = avctx->priv_data;
219  AVFrame *frame = data;
220  int ret;
221 
222  s->buf = buf;
223  s->size = buf_size;
224 
225  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
226  return ret;
227 
228  if (idcin_decode_vlcs(s, frame))
229  return AVERROR_INVALIDDATA;
230 
231  if (pal) {
232  frame->palette_has_changed = 1;
233  memcpy(s->pal, pal, AVPALETTE_SIZE);
234  }
235  /* make the palette available on the way out */
236  memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
237 
238  *got_frame = 1;
239 
240  /* report that the buffer was completely consumed */
241  return buf_size;
242 }
243 
245  .name = "idcinvideo",
246  .type = AVMEDIA_TYPE_VIDEO,
247  .id = AV_CODEC_ID_IDCIN,
248  .priv_data_size = sizeof(IdcinContext),
251  .capabilities = CODEC_CAP_DR1,
252  .long_name = NULL_IF_CONFIG_SMALL("id Quake II CIN video"),
253 };
float v
const char * s
Definition: avisynth_c.h:668
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
static int idcin_decode_vlcs(IdcinContext *s, AVFrame *frame)
Definition: idcinvideo.c:173
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
int num_huff_nodes[256]
Definition: idcinvideo.c:74
uint8_t
#define av_cold
Definition: attributes.h:78
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:79
#define AVPALETTE_SIZE
Definition: pixfmt.h:33
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
AVCodec ff_idcin_decoder
Definition: idcinvideo.c:244
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
uint8_t * data
hnode huff_nodes[256][HUF_TOKENS *2]
Definition: idcinvideo.c:73
struct IdcinContext IdcinContext
frame
Definition: stft.m:14
Discrete Time axis x
static int huff_smallest_node(hnode *hnodes, int num_hnodes)
Find the lowest probability node in a Huffman table, and mark it as being assigned to a higher probab...
Definition: idcinvideo.c:85
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Spectrum Plot time data
#define HUFFMAN_TABLE_SIZE
Definition: idcinvideo.c:55
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
FFmpeg Automated Testing Environment ************************************Table of Contents *****************FFmpeg Automated Testing Environment Introduction Using FATE from your FFmpeg source directory Submitting the results to the FFmpeg result aggregation server FATE makefile targets and variables Makefile targets Makefile variables Examples Introduction **************FATE is an extended regression suite on the client side and a means for results aggregation and presentation on the server side The first part of this document explains how you can use FATE from your FFmpeg source directory to test your ffmpeg binary The second part describes how you can run FATE to submit the results to FFmpeg s FATE server In any way you can have a look at the publicly viewable FATE results by visiting this as it can be seen if some test on some platform broke with their recent contribution This usually happens on the platforms the developers could not test on The second part of this document describes how you can run FATE to submit your results to FFmpeg s FATE server If you want to submit your results be sure to check that your combination of OS and compiler is not already listed on the above mentioned website In the third part you can find a comprehensive listing of FATE makefile targets and variables Using FATE from your FFmpeg source directory **********************************************If you want to run FATE on your machine you need to have the samples in place You can get the samples via the build target fate rsync Use this command from the top level source this will cause FATE to fail NOTE To use a custom wrapper to run the pass target exec to configure or set the TARGET_EXEC Make variable Submitting the results to the FFmpeg result aggregation server ****************************************************************To submit your results to the server you should run fate through the shell script tests fate sh from the FFmpeg sources This script needs to be invoked with a configuration file as its first argument tests fate sh path to fate_config A configuration file template with comments describing the individual configuration variables can be found at doc fate_config sh template Create a configuration that suits your based on the configuration template The slot configuration variable can be any string that is not yet used
Definition: fate.txt:34
external API header
common internal API header
ret
Definition: avfilter.c:821
int width
picture width / height.
int count
Definition: idcinvideo.c:61
static av_cold void huff_build_tree(IdcinContext *s, int prev)
Definition: idcinvideo.c:117
const unsigned char * buf
Definition: idcinvideo.c:70
NULL
Definition: eval.c:55
AVCodecContext * avctx
Definition: idcinvideo.c:68
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
main external API structure.
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
int children[2]
Definition: idcinvideo.c:63
synthesis window for stochastic i
int palette_has_changed
Tell user application that palette has changed from previous frame.
Definition: frame.h:280
#define HUF_TOKENS
Definition: idcinvideo.c:56
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
common internal api header.
static av_cold int idcin_decode_init(AVCodecContext *avctx)
Definition: idcinvideo.c:147
function y
Definition: D.m:1
static int idcin_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: idcinvideo.c:211
uint32_t pal[256]
Definition: idcinvideo.c:76
unsigned char used
Definition: idcinvideo.c:62
void INT64 INT64 count
Definition: avisynth_c.h:594
uint8_t * av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int *size)
Get side information from packet.
Definition: avpacket.c:289
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
This structure stores compressed data.
for(j=16;j >0;--j)