/* $Id: context.c,v 1.2 1998/03/16 20:36:00 hatrack Exp $ */

/****************************************************************************/
/*   MPEG4 Visual Texture Coding (VTC) Mode Software                        */
/*                                                                          */
/*   This software was developed by                                         */
/*   Sarnoff Coporation                   and    Texas Instruments          */
/*   Iraj Sodagar   (iraj@sarnoff.com)           Jie Liang (liang@ti.com)   */
/*   Hung-Ju Lee    (hjlee@sarnoff.com)                                     */
/*   Paul Hatrack   (hatrack@sarnoff.com)                                   */
/*   Shipeng Li     (shipeng@sarnoff.com)                                   */
/*   Bing-Bing Chai (bchai@sarnoff.com)                                     */
/*                                                                          */
/* In the course of development of the MPEG-4 standard. This software       */
/* module is an implementation of a part of one or more MPEG-4 tools as     */
/* specified by the MPEG-4 standard.                                        */
/*                                                                          */
/* The copyright of this software belongs to ISO/IEC. ISO/IEC gives use     */
/* of the MPEG-4 standard free license to use this  software module or      */
/* modifications thereof for hardware or software products claiming         */
/* conformance to the MPEG-4 standard.                                      */
/*                                                                          */
/* Those intending to use this software module in hardware or software      */
/* products are advised that use may infringe existing  patents. The        */
/* original developers of this software module and their companies, the     */
/* subsequent editors and their companies, and ISO/IEC have no liability    */
/* and ISO/IEC have no liability for use of this software module or         */
/* modification thereof in an implementation.                               */
/*                                                                          */
/* Permission is granted to MPEG memebers to use, copy, modify,             */
/* and distribute the software modules ( or portions thereof )              */
/* for standardization activity within ISO/IEC JTC1/SC29/WG11.              */
/*                                                                          */
/* Copyright (C) 1998  Sarnoff Coporation and Texas Instruments             */ 
/****************************************************************************/

/************************************************************/
/*     Sarnoff Very Low Bit Rate Still Image Coder          */
/*     Copyright 1995, 1996, 1997, 1998 Sarnoff Corporation */
/************************************************************/


#include "dataStruct.h"
#include "globals.h"
#include "ac.h"
#include "errorHandler.h"
#include "context.h"

static Char *errorStr_alloc="Cannot allocate memory in %s";


static Void initContext(ac_context *acc, Int nsym, Char *str, Int maxContexts,
			Int inc)
{
  Int i;
  UShort *ifreq;

  if (mzte_codec.acm_order==AC_MODEL_ZEROTH)
    return;

  acc->nsym = (UShort)nsym;

  /* get number of contexts */
  acc->numContexts = (UShort)MIN(nsym, maxContexts);

  /* allocate memory for model structures */
  if ((acc->contextModelList =
       (ac_model *)calloc(acc->numContexts, sizeof(ac_model)))==NULL)
    errorHandler(errorStr_alloc,str);
  
  /* initialize models */
  /* allocate memory for initial frequency */
  if ((ifreq=(UShort *)calloc(acc->nsym,sizeof(UShort)))==NULL)
    errorHandler(errorStr_alloc,str);
  for (i=0; i<(Int)acc->numContexts; ++i)
  {
    Int j, r, l, u;

    /* initialize freq count */
    r = acc->nsym/acc->numContexts + (acc->nsym%acc->numContexts!=0);
    l = MIN((Int)acc->nsym, i*r);
    u = MIN((Int)acc->nsym, l+r);
    if (mzte_codec.acm_order==AC_MODEL_FIRST)
    {
      for (j=0; j < l; ++j)
	ifreq[j] = 1;
      for (; j < u; ++j)
	ifreq[j] = inc;
      for (; j < (Int)acc->nsym; ++j)
	ifreq[j] = 1;
    }
    else
    {
      for (j=0; j < l; ++j)
	ifreq[j] = 0;
      for (; j < u; ++j)
	ifreq[j] = inc;
      for (; j < (Int)acc->nsym; ++j)
	ifreq[j] = 0;
    }

    (acc->contextModelList+i)->Max_frequency=16383;

    ac_model_init(acc->contextModelList+i, acc->nsym, ifreq, 1, 
		  (mzte_codec.acm_order==AC_MODEL_FIRST) ? 1 : inc);
  }
  free(ifreq);

  /* Set current context to some initial value */
  acc->curContext = (UShort)0;
}


static Void freeContext(ac_context *acc)
{  
  Int i;

  if (mzte_codec.acm_order==AC_MODEL_ZEROTH)
    return;

  /* Set current context to some initial value */
  acc->curContext = (UShort)0;
  
  /* free up models */
  for (i=0; i<(Int)acc->numContexts; ++i)
    ac_model_done(acc->contextModelList+i);

  /* de-allocate memory for model structures */
  free(acc->contextModelList);

  acc->numContexts = acc->nsym = (UShort)0;
}

static Void updateContext(ac_context *acc, Int sym)
{
  if (mzte_codec.acm_order==AC_MODEL_ZEROTH)
    return;

  acc->curContext = (sym*(Int)acc->numContexts) / (Int)acc->nsym;
}

static ac_model *contextToModel(ac_context *acc)
{
  return (mzte_codec.acm_order==AC_MODEL_ZEROTH)
    ? NULL 
    : (acc->contextModelList + acc->curContext);
}

/*------------------------------------------------------------*/

/*
  Type Context Handling Functions
*/
#define MAX_CONTEXTS_TYPE 4
#define INC_TYPE 15

Void initContext_Type(ac_context *acc, Int nsym)
{
  initContext(acc, nsym, "Type", MAX_CONTEXTS_TYPE, INC_TYPE);
}

Void freeContext_Type(ac_context *acc)
{
  freeContext(acc);
}

Void updateContext_Type(ac_context *acc, Int sym)
{
  updateContext(acc, sym);
}

ac_model *contextToModel_Type(ac_context *acc)
{
  return contextToModel(acc);
}

#ifdef _IMPLIED_SKIP_IZ_ 

/*
  Skip Type Context Handling Functions
*/
#define MAX_CONTEXTS_SKIP_TYPE 2
#define INC_SKIP_TYPE 15

Void initContext_SkipType(ac_context *acc, Int nsym)
{
  initContext(acc, nsym, "Skip Type", MAX_CONTEXTS_SKIP_TYPE, INC_SKIP_TYPE);
}

Void freeContext_SkipType(ac_context *acc)
{
  freeContext(acc);
}

Void updateContext_SkipType(ac_context *acc, Int sym)
{
  updateContext(acc, sym);
}

ac_model *contextToModel_SkipType(ac_context *acc)
{
  return contextToModel(acc);
}

#endif /*_IMPLIED_SKIP_IZ_*/ 

/*
  Root Band (No Zeros Allowed) Context Handling Functions
*/
#define MAX_CONTEXTS_ROOT 10
#define INC_ROOT 15

Void initContext_Root(ac_context *acc, Int nsym)
{
  initContext(acc, nsym, "Root", MAX_CONTEXTS_ROOT, INC_ROOT);
}

Void freeContext_Root(ac_context *acc)
{
  freeContext(acc);
}

Void updateContext_Root(ac_context *acc, Int sym)
{
  updateContext(acc, sym);
}

ac_model *contextToModel_Root(ac_context *acc)
{
  return contextToModel(acc);
}

/*
  VZ (Leaf Bands - Zeros Allowed) Context Handling Functions
*/
#define MAX_CONTEXTS_VZ 10
#define INC_VZ 15

Void initContext_VZ(ac_context *acc, Int nsym)
{
  initContext(acc, nsym, "VZ", MAX_CONTEXTS_VZ, INC_VZ);
}

Void freeContext_VZ(ac_context *acc)
{
  freeContext(acc);
}

Void updateContext_VZ(ac_context *acc, Int sym)
{
  updateContext(acc, sym);
}

ac_model *contextToModel_VZ(ac_context *acc)
{
  return contextToModel(acc);
}


/*
  VNZ (Non-Root Intermediate Bands - No Zeros Allowed) Context Handling 
  Functions
*/
#define MAX_CONTEXTS_VNZ 4
#define INC_VNZ 15

Void initContext_VNZ(ac_context *acc, Int nsym)
{
  initContext(acc, nsym, "VNZ", MAX_CONTEXTS_VNZ, INC_VNZ);
}

Void freeContext_VNZ(ac_context *acc)
{
  freeContext(acc);
}


Void updateContext_VNZ(ac_context *acc, Int sym)
{
  updateContext(acc, sym);
}

ac_model *contextToModel_VNZ(ac_context *acc)
{
  return contextToModel(acc);
}

/*
  Residual Context Handling Functions
*/
#define MAX_CONTEXTS_RES 4
#define INC_RES 15

Void initContext_Res(ac_context *acc, Int nsym)
{
  initContext(acc, nsym, "Res", MAX_CONTEXTS_RES, INC_RES);
}

Void freeContext_Res(ac_context *acc)
{
  freeContext(acc);
}


Void updateContext_Res(ac_context *acc, Int sym)
{
  updateContext(acc, sym);
}

ac_model *contextToModel_Res(ac_context *acc)
{
  return contextToModel(acc);
}

/*
  Sign Context Handling Functions
*/
#define MAX_CONTEXTS_SIGN 4
#define INC_SIGN 15

Void initContext_Sign(ac_context *acc, Int nsym)
{
  initContext(acc, nsym, "Sign", MAX_CONTEXTS_SIGN, INC_SIGN);
}

Void freeContext_Sign(ac_context *acc)
{
  freeContext(acc);
}

Void updateContext_Sign(ac_context *acc, Int sym)
{
  updateContext(acc, sym);
}

ac_model *contextToModel_Sign(ac_context *acc)
{
  return contextToModel(acc);
}
