• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/idcinvideo.c

Go to the documentation of this file.
00001 /*
00002  * id Quake II CIN Video Decoder
00003  * Copyright (C) 2003 the ffmpeg project
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <string.h>
00050 
00051 #include "avcodec.h"
00052 
00053 #define HUFFMAN_TABLE_SIZE 64 * 1024
00054 #define HUF_TOKENS 256
00055 #define PALETTE_COUNT 256
00056 
00057 typedef struct
00058 {
00059   int count;
00060   unsigned char used;
00061   int children[2];
00062 } hnode;
00063 
00064 typedef struct IdcinContext {
00065 
00066     AVCodecContext *avctx;
00067     AVFrame frame;
00068 
00069     const unsigned char *buf;
00070     int size;
00071 
00072     hnode huff_nodes[256][HUF_TOKENS*2];
00073     int num_huff_nodes[256];
00074 
00075 } IdcinContext;
00076 
00077 /*
00078  * Find the lowest probability node in a Huffman table, and mark it as
00079  * being assigned to a higher probability.
00080  * Returns the node index of the lowest unused node, or -1 if all nodes
00081  * are used.
00082  */
00083 static int huff_smallest_node(hnode *hnodes, int num_hnodes) {
00084     int i;
00085     int best, best_node;
00086 
00087     best = 99999999;
00088     best_node = -1;
00089     for(i = 0; i < num_hnodes; i++) {
00090         if(hnodes[i].used)
00091             continue;
00092         if(!hnodes[i].count)
00093             continue;
00094         if(hnodes[i].count < best) {
00095             best = hnodes[i].count;
00096             best_node = i;
00097         }
00098     }
00099 
00100     if(best_node == -1)
00101         return -1;
00102     hnodes[best_node].used = 1;
00103     return best_node;
00104 }
00105 
00106 /*
00107  * Build the Huffman tree using the generated/loaded probabilities histogram.
00108  *
00109  * On completion:
00110  *  huff_nodes[prev][i < HUF_TOKENS] - are the nodes at the base of the tree.
00111  *  huff_nodes[prev][i >= HUF_TOKENS] - are used to construct the tree.
00112  *  num_huff_nodes[prev] - contains the index to the root node of the tree.
00113  *    That is: huff_nodes[prev][num_huff_nodes[prev]] is the root node.
00114  */
00115 static av_cold void huff_build_tree(IdcinContext *s, int prev) {
00116     hnode *node, *hnodes;
00117      int num_hnodes, i;
00118 
00119     num_hnodes = HUF_TOKENS;
00120     hnodes = s->huff_nodes[prev];
00121     for(i = 0; i < HUF_TOKENS * 2; i++)
00122         hnodes[i].used = 0;
00123 
00124     while (1) {
00125         node = &hnodes[num_hnodes];             /* next free node */
00126 
00127         /* pick two lowest counts */
00128         node->children[0] = huff_smallest_node(hnodes, num_hnodes);
00129         if(node->children[0] == -1)
00130             break;      /* reached the root node */
00131 
00132         node->children[1] = huff_smallest_node(hnodes, num_hnodes);
00133         if(node->children[1] == -1)
00134             break;      /* reached the root node */
00135 
00136         /* combine nodes probability for new node */
00137         node->count = hnodes[node->children[0]].count +
00138         hnodes[node->children[1]].count;
00139         num_hnodes++;
00140     }
00141 
00142     s->num_huff_nodes[prev] = num_hnodes - 1;
00143 }
00144 
00145 static av_cold int idcin_decode_init(AVCodecContext *avctx)
00146 {
00147     IdcinContext *s = avctx->priv_data;
00148     int i, j, histogram_index = 0;
00149     unsigned char *histograms;
00150 
00151     s->avctx = avctx;
00152     avctx->pix_fmt = PIX_FMT_PAL8;
00153 
00154     /* make sure the Huffman tables make it */
00155     if (s->avctx->extradata_size != HUFFMAN_TABLE_SIZE) {
00156         av_log(s->avctx, AV_LOG_ERROR, "  id CIN video: expected extradata size of %d\n", HUFFMAN_TABLE_SIZE);
00157         return -1;
00158     }
00159 
00160     /* build the 256 Huffman decode trees */
00161     histograms = (unsigned char *)s->avctx->extradata;
00162     for (i = 0; i < 256; i++) {
00163         for(j = 0; j < HUF_TOKENS; j++)
00164             s->huff_nodes[i][j].count = histograms[histogram_index++];
00165         huff_build_tree(s, i);
00166     }
00167 
00168     s->frame.data[0] = NULL;
00169 
00170     return 0;
00171 }
00172 
00173 static void idcin_decode_vlcs(IdcinContext *s)
00174 {
00175     hnode *hnodes;
00176     long x, y;
00177     int prev;
00178     unsigned char v = 0;
00179     int bit_pos, node_num, dat_pos;
00180 
00181     prev = bit_pos = dat_pos = 0;
00182     for (y = 0; y < (s->frame.linesize[0] * s->avctx->height);
00183         y += s->frame.linesize[0]) {
00184         for (x = y; x < y + s->avctx->width; x++) {
00185             node_num = s->num_huff_nodes[prev];
00186             hnodes = s->huff_nodes[prev];
00187 
00188             while(node_num >= HUF_TOKENS) {
00189                 if(!bit_pos) {
00190                     if(dat_pos >= s->size) {
00191                         av_log(s->avctx, AV_LOG_ERROR, "Huffman decode error.\n");
00192                         return;
00193                     }
00194                     bit_pos = 8;
00195                     v = s->buf[dat_pos++];
00196                 }
00197 
00198                 node_num = hnodes[node_num].children[v & 0x01];
00199                 v = v >> 1;
00200                 bit_pos--;
00201             }
00202 
00203             s->frame.data[0][x] = node_num;
00204             prev = node_num;
00205         }
00206     }
00207 }
00208 
00209 static int idcin_decode_frame(AVCodecContext *avctx,
00210                               void *data, int *data_size,
00211                               AVPacket *avpkt)
00212 {
00213     const uint8_t *buf = avpkt->data;
00214     int buf_size = avpkt->size;
00215     IdcinContext *s = avctx->priv_data;
00216     AVPaletteControl *palette_control = avctx->palctrl;
00217 
00218     s->buf = buf;
00219     s->size = buf_size;
00220 
00221     if (s->frame.data[0])
00222         avctx->release_buffer(avctx, &s->frame);
00223 
00224     if (avctx->get_buffer(avctx, &s->frame)) {
00225         av_log(avctx, AV_LOG_ERROR, "  id CIN Video: get_buffer() failed\n");
00226         return -1;
00227     }
00228 
00229     idcin_decode_vlcs(s);
00230 
00231     /* make the palette available on the way out */
00232     memcpy(s->frame.data[1], palette_control->palette, PALETTE_COUNT * 4);
00233     /* If palette changed inform application*/
00234     if (palette_control->palette_changed) {
00235         palette_control->palette_changed = 0;
00236         s->frame.palette_has_changed = 1;
00237     }
00238 
00239     *data_size = sizeof(AVFrame);
00240     *(AVFrame*)data = s->frame;
00241 
00242     /* report that the buffer was completely consumed */
00243     return buf_size;
00244 }
00245 
00246 static av_cold int idcin_decode_end(AVCodecContext *avctx)
00247 {
00248     IdcinContext *s = avctx->priv_data;
00249 
00250     if (s->frame.data[0])
00251         avctx->release_buffer(avctx, &s->frame);
00252 
00253     return 0;
00254 }
00255 
00256 AVCodec idcin_decoder = {
00257     "idcinvideo",
00258     AVMEDIA_TYPE_VIDEO,
00259     CODEC_ID_IDCIN,
00260     sizeof(IdcinContext),
00261     idcin_decode_init,
00262     NULL,
00263     idcin_decode_end,
00264     idcin_decode_frame,
00265     CODEC_CAP_DR1,
00266     .long_name = NULL_IF_CONFIG_SMALL("id Quake II CIN video"),
00267 };
00268 

Generated on Fri Sep 16 2011 17:17:37 for FFmpeg by  doxygen 1.7.1