00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <string.h>
00049 #include <unistd.h>
00050
00051 #include "common.h"
00052 #include "avcodec.h"
00053 #include "dsputil.h"
00054
00055 #define HUFFMAN_TABLE_SIZE 64 * 1024
00056 #define HUF_TOKENS 256
00057 #define PALETTE_COUNT 256
00058
00059 typedef struct
00060 {
00061 int count;
00062 unsigned char used;
00063 int children[2];
00064 } hnode_t;
00065
00066 typedef struct IdcinContext {
00067
00068 AVCodecContext *avctx;
00069 DSPContext dsp;
00070 AVFrame frame;
00071
00072 unsigned char *buf;
00073 int size;
00074
00075 hnode_t huff_nodes[256][HUF_TOKENS*2];
00076 int num_huff_nodes[256];
00077
00078 } IdcinContext;
00079
00080
00081
00082
00083
00084
00085
00086 static int huff_smallest_node(hnode_t *hnodes, int num_hnodes) {
00087 int i;
00088 int best, best_node;
00089
00090 best = 99999999;
00091 best_node = -1;
00092 for(i = 0; i < num_hnodes; i++) {
00093 if(hnodes[i].used)
00094 continue;
00095 if(!hnodes[i].count)
00096 continue;
00097 if(hnodes[i].count < best) {
00098 best = hnodes[i].count;
00099 best_node = i;
00100 }
00101 }
00102
00103 if(best_node == -1)
00104 return -1;
00105 hnodes[best_node].used = 1;
00106 return best_node;
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 static void huff_build_tree(IdcinContext *s, int prev) {
00119 hnode_t *node, *hnodes;
00120 int num_hnodes, i;
00121
00122 num_hnodes = HUF_TOKENS;
00123 hnodes = s->huff_nodes[prev];
00124 for(i = 0; i < HUF_TOKENS * 2; i++)
00125 hnodes[i].used = 0;
00126
00127 while (1) {
00128 node = &hnodes[num_hnodes];
00129
00130
00131 node->children[0] = huff_smallest_node(hnodes, num_hnodes);
00132 if(node->children[0] == -1)
00133 break;
00134
00135 node->children[1] = huff_smallest_node(hnodes, num_hnodes);
00136 if(node->children[1] == -1)
00137 break;
00138
00139
00140 node->count = hnodes[node->children[0]].count +
00141 hnodes[node->children[1]].count;
00142 num_hnodes++;
00143 }
00144
00145 s->num_huff_nodes[prev] = num_hnodes - 1;
00146 }
00147
00148 static int idcin_decode_init(AVCodecContext *avctx)
00149 {
00150 IdcinContext *s = (IdcinContext *)avctx->priv_data;
00151 int i, j, histogram_index = 0;
00152 unsigned char *histograms;
00153
00154 s->avctx = avctx;
00155 avctx->pix_fmt = PIX_FMT_PAL8;
00156 avctx->has_b_frames = 0;
00157 dsputil_init(&s->dsp, avctx);
00158
00159
00160 if (s->avctx->extradata_size != HUFFMAN_TABLE_SIZE) {
00161 av_log(s->avctx, AV_LOG_ERROR, " Id CIN video: expected extradata size of %d\n", HUFFMAN_TABLE_SIZE);
00162 return -1;
00163 }
00164
00165
00166 histograms = (unsigned char *)s->avctx->extradata;
00167 for (i = 0; i < 256; i++) {
00168 for(j = 0; j < HUF_TOKENS; j++)
00169 s->huff_nodes[i][j].count = histograms[histogram_index++];
00170 huff_build_tree(s, i);
00171 }
00172
00173 s->frame.data[0] = NULL;
00174
00175 return 0;
00176 }
00177
00178 static void idcin_decode_vlcs(IdcinContext *s)
00179 {
00180 hnode_t *hnodes;
00181 long x, y;
00182 int prev;
00183 unsigned char v = 0;
00184 int bit_pos, node_num, dat_pos;
00185
00186 prev = bit_pos = dat_pos = 0;
00187 for (y = 0; y < (s->frame.linesize[0] * s->avctx->height);
00188 y += s->frame.linesize[0]) {
00189 for (x = y; x < y + s->avctx->width; x++) {
00190 node_num = s->num_huff_nodes[prev];
00191 hnodes = s->huff_nodes[prev];
00192
00193 while(node_num >= HUF_TOKENS) {
00194 if(!bit_pos) {
00195 if(dat_pos >= s->size) {
00196 av_log(s->avctx, AV_LOG_ERROR, "Huffman decode error.\n");
00197 return;
00198 }
00199 bit_pos = 8;
00200 v = s->buf[dat_pos++];
00201 }
00202
00203 node_num = hnodes[node_num].children[v & 0x01];
00204 v = v >> 1;
00205 bit_pos--;
00206 }
00207
00208 s->frame.data[0][x] = node_num;
00209 prev = node_num;
00210 }
00211 }
00212 }
00213
00214 static int idcin_decode_frame(AVCodecContext *avctx,
00215 void *data, int *data_size,
00216 uint8_t *buf, int buf_size)
00217 {
00218 IdcinContext *s = (IdcinContext *)avctx->priv_data;
00219 AVPaletteControl *palette_control = avctx->palctrl;
00220
00221 s->buf = buf;
00222 s->size = buf_size;
00223
00224 if (s->frame.data[0])
00225 avctx->release_buffer(avctx, &s->frame);
00226
00227 if (avctx->get_buffer(avctx, &s->frame)) {
00228 av_log(avctx, AV_LOG_ERROR, " Id CIN Video: get_buffer() failed\n");
00229 return -1;
00230 }
00231
00232 idcin_decode_vlcs(s);
00233
00234
00235 memcpy(s->frame.data[1], palette_control->palette, PALETTE_COUNT * 4);
00236
00237 if (palette_control->palette_changed) {
00238 palette_control->palette_changed = 0;
00239 s->frame.palette_has_changed = 1;
00240 }
00241
00242 *data_size = sizeof(AVFrame);
00243 *(AVFrame*)data = s->frame;
00244
00245
00246 return buf_size;
00247 }
00248
00249 static int idcin_decode_end(AVCodecContext *avctx)
00250 {
00251 IdcinContext *s = (IdcinContext *)avctx->priv_data;
00252
00253 if (s->frame.data[0])
00254 avctx->release_buffer(avctx, &s->frame);
00255
00256 return 0;
00257 }
00258
00259 AVCodec idcin_decoder = {
00260 "idcinvideo",
00261 CODEC_TYPE_VIDEO,
00262 CODEC_ID_IDCIN,
00263 sizeof(IdcinContext),
00264 idcin_decode_init,
00265 NULL,
00266 idcin_decode_end,
00267 idcin_decode_frame,
00268 CODEC_CAP_DR1,
00269 };
00270