Linux Game Programming for PC & Embedded Systems using SDL
Presented by
Fore June
Author of Windows Fan, Linux Fan

A simple video codec.

codecio.h
runhuf.h
encode.h
decode.h
dct_video.h
common.h
fbitios.h
avilib.h
vcodec.cpp
runhuf.cpp
encode.cpp
decode.cpp
dct_video.cpp
fbitios.cpp
Makefile
sample_video.avi ( not zipped )
avilib.o ( not zipped )



decode.cpp:
/*
  decode.cpp
  Contains functions to decode a bit stream to RGB data.
  See 'http://www.webkinesia.com/games/vcompress8.php'  
*/
#include "common.h"
#include "fbitios.h"
#include "runhuf.h"
#include "dct_video.h"
#include "rgb_ybr.h"
/*
  Read bit stream from inputs, Huffman-decode the input stream to obtain a
  sample block, then run-level decode it to get an 8x8 sample block, reverse-
  reorder and inverse-quantize it to get the desired DCT block.
  Output: 8x8 DCT sample block in Yi[].
*/
int get_dct_block ( bitFileIO *inputs, int Yi[] )
{
  short Yr[64], Y[64];
  run3D runs[64];
  static Dtables decode_tables;              //tables used in decoding process
  static set <RunHuff> htable;
  static short first = 1;
  if ( first ) {
    build_htable ( htable );
    build_huff_tree ( htable, decode_tables );
    first = 0;
  }

  if ( huff_decode( inputs, decode_tables, runs ) > 0 ) {
    run_decode ( runs, Yr );
    reverse_reorder ( Yr, Y );
    inverse_quantize_block ( Y );
    for ( int i = 0; i < 64; ++i )
      Yi[i] = (int) Y[i];
    return 1;
  } else 
    return -1;
}
/*
  Get DCT data from get_dct_block(); convert DCT coefficients to YCbcr and put the
  four 8x8 Y sample blocks, one 8x8 Cb sample block and one 8x8 Cr sample block into a
  struct of YCbCr_MACRO.
  Return: number of bytes read from file and put in YCbCr_MACRO struct.
*/
int get_ybrblocks( bitFileIO *inputs, YCbCr_MACRO *ycbcr_macro )
{
  short r, row, col, i, j, k, n, block, *py;
  short c;
   int   Y[64], X[64];           //for IDCT

  n = 0;
  //read data from file, perform IDCT and put them in four 8x8 Y sample blocks
  for ( block = 0; block < 4; block++ ) {
  if ( !get_dct_block ( inputs, Y ) )   //read in one DCT block
      return 0;
    idct ( Y, X );              	//perform IDCT, output in X
    k = 0;
    if ( block < 2 )
      py = ( short * ) &ycbcr_macro->Y + 8*block;               //points to beginning of block
    else
      py = (short *)&ycbcr_macro->Y + 128 + 8*(block-2);        //points to beginning of block
    for ( i = 0; i < 8; i++ ) {         //one sample-block
      if ( i > 0 ) py += 16;            //advance py by 16 ( length of one row of macroblock )
      for ( j = 0; j < 8; j++ ) {
        *(py+j) = X[k++];               //put sample value in macroblock
         n++;
      } //for j
    } //for i
  } //for block

  if ( !get_dct_block ( inputs, Y ) )	//read in one DCT block
    return 0;
  idct (Y, X );                         //perform IDCT, output in X
  k = 0;
  for ( i = 0; i < 8; ++i ) {
    for ( j = 0; j < 8; ++j ) {
      ycbcr_macro->Cb[k] = X[k];        //put Cb sample value in macro block
      k++;
      n++;
    }
  }
  //now do that for 8x8 Cr block
  if ( !get_dct_block ( inputs, Y ) ) 	//read in one DCT block
    return 0;
  idct (Y, X );                         //perform IDCT, output in X
  k = 0;
  for ( i = 0; i < 8; ++i ) {
    for ( j = 0; j < 8; ++j ) {
      ycbcr_macro->Cr[k] = X[k];        //put Cr sample value in macro block
      k++;
      n++;
    }
  }
  return n;                             //number of bytes read
}

/*
  Convert a YCbCr frame to RGB frame.
*/
int decode_ybrFrame (  bitFileIO *inputs, char *image, short width, short height )
{
  short r, row, col, i, j, k, block, *py;
  int n, numBytes = 0;
  RGB *p, macro16x16[256];
  YCbCr_MACRO ycbcr_macro;

  for ( row = 0; row < height; row += 16 ) {
    for ( col = 0; col < width; col += 16 ) {
      n = get_ybrblocks( inputs, &ycbcr_macro );
      if ( n <= 0 ) return n;
      ycbcr2macroblock( &ycbcr_macro, macro16x16 );	//converts to RGB
      p = ( RGB *) image  +  ( row * width + col );     //points to beginning of macroblock
      r = 0;
      for ( i = 0; i < 16; ++i ) {
        for ( j = 0; j < 16; ++j ) {
          *p++ =  macro16x16[r++];
        }
        p += ( width - 16 );          	//points to next row within macroblock
      }
      numBytes += 768;			// 768 = 16x16x3 
    } //for col
  }  //for row
  return numBytes;
}