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 )



encode.cpp:
/*
  encode.cpp
  Contains functions to encode one frame and save bit stream in a file.
  See 'http://www.webkinesia.com/games/vcompress8.php'
*/
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "rgb_ybr.h"
#include "dct_video.h"
#include "runhuf.h"
#include <set>

//save a  DCT block in an array
void save_dct_block ( int *Y, short *dctc )
{
  for ( int i = 0; i < 64; ++i )
    dctc[i] = ( short ) Y[i];		//convert to short  ( 2 bytes );
}

//make DCT coeffs for one  macroblock.
void get_dctcoefs( YCbCr_MACRO *ycbcr_macro, short dctcoefs[][64] )
{
  short block, i, j, k, *py;
  int X[64], Y[64];			//for DCT transform
  short bn = 0;
 
  //save DCT coefs in array dctcoefs[] for four 8x8 Y sample blocks
  for ( block = 0; block < 4; block++ ) {
    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
    k = 0;
    for ( i = 0; i < 8; i++ ) {		//one sample-block
      if ( i > 0 ) py += 16;		//advance py by 16 ( length of one row )
      for ( j = 0; j < 8; j++ ) {
	X[k++] = (int) *( py + j );
      }
    }
    dct ( X, Y );			//perform DCT for the sample block
    save_dct_block (Y, dctcoefs[bn++]);	//save DCT coefs for Y block
  }
  
  //save one 8x8 Cb block
  k = 0;
  for ( i = 0; i < 8; ++i ) {
    for ( j = 0; j < 8; ++j ) {
      X[k] = (int) ycbcr_macro->Cb[k];
      k++;
    }
  }
  dct ( X, Y );				//perform DCT for the sample block
  save_dct_block ( Y, dctcoefs[bn++] );	//save DCT coefs for Cb block in dctcoefs[]

  //save one 8x8 Cr block
  k = 0; 
  for ( i = 0; i < 8; ++i ) {
    for ( j = 0; j < 8; ++j ) {
      X[k] = (int) ycbcr_macro->Cr[k];
      k++;
    }
  } 
  dct ( X, Y );				//perform DCT for the sample block
  save_dct_block ( Y, dctcoefs[bn] );	//save DCT coefs for Cr block in dctcoefs[]
}

/*
  Encode one image frame pointed by image using Huffman table htable.
  Bit stream outputs are saved in a file pointed by outputs.
  iwidth, iheight are width and height of image.
*/
void encode_one_frame ( char *image, short iwidth, short iheight, bitFileIO *outputs, set <RunHuff> &htable )
{
  short row, col, i, j, r;
  YCbCr_MACRO ycbcr_macro;      	//macroblock for YCbCr samples
  short dctcoefs[8][64];		//DCT coefficients for 8 sample blocks
  RGB macro16x16[256];          	//16x16 pixel macroblock; assume 24-bit for each RGB pixel
  short *Y, Yr[64], bn;
  run3D runs[64];
  RGB *p;				//pointer to an RGB pixel


  for ( row = 0; row < iheight; row += 16 ) {		//scan all rows of image
    for ( col = 0; col < iwidth; col += 16 ) {		//scan all columns of image
      p = ( RGB *) image  +  ( row * iwidth + col );	//points to beginning of macroblock
      r = 0;						//note pointer arithmetic
      for ( i = 0; i < 16; ++i ) {
	for ( j = 0; j < 16; ++j ) {
	  macro16x16[r++] = (RGB) *p++;
	}
	p += ( iwidth - 16 );		//points to next row within macroblock ( pointer arithmetic )
      }
      macroblock2ycbcr ( macro16x16,  &ycbcr_macro );	//convert from RGB to YCbCr
      get_dctcoefs( &ycbcr_macro, dctcoefs );		//get 6 dct coefs blocks from 1 YCbCr macroblock
      for ( bn = 0; bn < 6; ++bn ) {
	Y = dctcoefs[bn];
	quantize_block ( Y );		//quantize one dct sample block
    	reorder ( Y, Yr );		//reorder the quantized sample block
    	run_block ( Yr, runs );		//encode reordered DCT coefs using 3D run-level code
	/*
	  Encode the 3D runs with precalculated Huffman codes using the provided
	  Huffman table htable. Save the encoded bit stream in file pointed by
	  outputs.
	*/
    	huff_encode ( htable, runs, outputs );      //encode and save
      } //for bn
    } //for col
  } //for row
}