/******************************************************************************
 *                                                                          
 * This software module was originally developed by 
 *
 * Robert Danielsen (Telenor / ACTS-MoMuSys). 	    	              	
 *
 * and edited by 
 *
 * Luis Ducla-Soares (IST / ACTS-MoMuSys).     	           	   	
 *
 * in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
 * This software module is an implementation of a part of one or more MPEG-4 
 * Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC 
 * 14496-2) standard. 
 *
 * ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free 
 * license to this software module or modifications thereof for use in hardware
 * or software products claiming conformance to the MPEG-4 Video (ISO/IEC 
 * 14496-2) standard. 
 *
 * Those intending to use this software module in hardware or software products
 * are advised that its use may infringe existing patents. The original 
 * developer of this software module and his/her company, the subsequent 
 * editors and their companies, and ISO/IEC have no liability for use of this 
 * software module or modifications thereof in an implementation. Copyright is 
 * not released for non MPEG-4 Video (ISO/IEC 14496-2) standard conforming 
 * products. 
 *
 * ACTS-MoMuSys partners retain full right to use the code for his/her own 
 * purpose, assign or donate the code to a third party and to inhibit third 
 * parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) standard
 * conforming products. This copyright notice must be included in all copies or
 * derivative works. 
 *
 * Copyright (c) 1997
 *
 *****************************************************************************/

/***********************************************************HeaderBegin*******
 *                                                                         
 * File:	mom_putbits.c
 *
 * Author:	Robert Danielsen
 * Created:	05.06.96
 *                                                                         
 * Description: Functions for writing bits to file. Based on functions from
 *		MPEG-2 software simulation group.
 *
 * Notes: 	Requires the file pointer to be externally declared, and
 *		initialization of the counters must be done before using the
 *		file accessing functions.
 *
 * Modified:	14-Jan-97 Luis Ducla-Soares: corrected bug in function NextStartCode().
 *              27-Mar-97 Luis Ducla-Soares: changed bitstuffing in CloseBits and 
 *                                           NextStartCode. Added NextResyncMarker().
 *              
 *
 ***********************************************************HeaderEnd*********/

/************************    INCLUDE FILES    ********************************/

#include <stdio.h>
#include "mom_putbits.h"
#include "vm_enc_defs.h"

extern File *bitstream[MAX_NUM_VOS][MAX_NUM_VOLS]; /* the required global var */

/* static data for pointers and counters */
static UChar outbfr[MAX_NUM_VOS][MAX_NUM_VOLS];
static Int outcnt[MAX_NUM_VOS][MAX_NUM_VOLS];
static Int bytecnt[MAX_NUM_VOS][MAX_NUM_VOLS];


/***********************************************************CommentBegin******
 *
 * -- InitBits -- Initializes counters
 *
 * Author :		
 *	Robert Danielsen
 *
 * Created :		
 *	05.06.96
 *
 * Purpose :		
 *	Initializes counters
 * 
 * Arguments in : 	
 * Int	index2
 *	Int	index1 - identifiers for what bitstream file pointer and bit counters
 *		are to be used.
 *
 * Arguments in/out :	
 *	none
 *
 * Arguments out :	
 *	none
 *
 * Return values :	
 *	none
 *
 * Side effects :	
 *	Initializes static variables local to this module
 *
 * Description :	
 *	Initialize buffer, call once before first putbits or alignbits.
 *	Based on function from MPEG-2 software simulation group.
 *
 * See also :
 *	
 *
 * Modified :		
 *	26.08.96 Noel O'Connor : Modified to cope with the fact that the encoder
 *	must be able to write to multiple bitstream files on disk. New input
 *	argument "index" added which specifies a unique bitstream file pointer
 * 	and unqiue bit counters.
 * 04.02.97 Noel O'Connor : mods for non unique VOL Ids (index1 & index 2)
 *
 ***********************************************************CommentEnd********/

Void
InitBits(Int index1,Int index2)
{
  outcnt[index1][index2] = 8;
  bytecnt[index1][index2] = 0;
}

/***********************************************************CommentBegin******
 *
 * -- PutBits -- Write bits to file
 *
 * Author :		
 *	Robert Danielsen
 *
 * Created :		
 *	05.06.96
 *
 * Purpose :		
 *	Write bits to file
 * 
 * Arguments in : 	
 *	int n :		number of bits to write
 *	int val :	bit values to write (the n least significant bits)
 *  int index1 : identifier for bitstream file pointer and bit counters
 * int index2 : identifier for bitstream file pointer and bit counters
 *
 * Arguments in/out :	
 *	none
 *
 * Arguments out :	
 *	none
 *
 * Return values :	
 *	none
 *
 * Side effects :	
 *	modifies static variables local to this module
 *
 * Description :	
 * 	write rightmost n (0<=n<=32) bits of val to outfile 
 *	Based on function from MPEG-2 software simulation group.
 *
 * See also :
 *	
 *
 * Modified :		
 *	26.08.96 Noel O'Connor : Modified to cope with the fact that the encoder
 *	must be able to write to multiple bitstream files on disk. New input
 *	argument "index" added which specifies a unique bitstream file pointer
 * 	and unqiue bit counters.
 * 04.02.97 Noel O'Connor: mods. for non unique VOL Ids (index1 & index 2)
 *
 ***********************************************************CommentEnd********/

Void
PutBits (Int n, Int val, Int index1, Int index2)
{
  Int i;
  U_Int mask;

  mask = 1 << (n-1);		/* selects first (leftmost) bit */

  for (i=0; i<n; i++)
    {
      outbfr[index1][index2] <<= 1;

      if (val & mask)
	outbfr[index1][index2]|= 1;

      mask >>= 1;		/* select next bit */
      outcnt[index1][index2]--;

      if (outcnt[index1][index2]==0)		/* 8 bit buffer full */
	{
	  putc(outbfr[index1][index2],bitstream[index1][index2]);
	  outcnt[index1][index2] = 8;
	  bytecnt[index1][index2]++;
	}
    }
}


/***********************************************************CommentBegin******
 *
 * -- CloseBits -- does bit stuffing with ones to next byte boundary
 *
 * Author :		
 *	Robert Danielsen
 *
 * Created :		
 *	07.06.96
 *
 * Purpose :		
 *	does bit stuffing with ones to next byte boundary
 * 
 * Arguments in : 	
 * int index1
 *	int index2 - unique identifiers for bitstream file pointer and counters
 *
 * Arguments in/out :	
 *	none
 *
 * Arguments out :	
 *	none
 *
 * Return values :	
 *	int :	number of ones stuffed in
 *
 * Side effects :	
 *	
 *
 * Description :
 *	Does bit stuffing with ones 
 *
 * See also :
 *	
 *
 * Modified :		
 *	26.08.96 Noel O'Connor : Modified to cope with the fact that the encoder
 *	must be able to cope with multiple bitstream files on disk. New input
 *	argument "index" added which specifies a unique bitstream file pointer
 * 	and unqiue bit counters
 * 04.02.97 Noel O'Connor: mods for non unique VOl Ids (index1 & index2)
 * 27.04.97 Luis Ducla-Soares: changed it to do bitstuffing at the end of
 *                             the bitstream (same as function NextStartCode());
 *                             this is needed for reversible decoding.
 *
 * 17.12.97 Luis Ducla-Soares: changed it back to the way it was.
 *
 ***********************************************************CommentEnd********/

Int
CloseBits (Int index1,Int index2)
{
  Int i;
  Int count, ret_value;
   

  if (outcnt[index1][index2]!=8)
    {
      count = outcnt[index1][index2];
      for (i = 0; i < count; i++)
	PutBits (1, 1, index1, index2);
      ret_value = outcnt[index1][index2];	/* outcnt is reset in call to
						   putbits () */
      return ret_value;
    }
  else
    return 0;
}


/***********************************************************CommentBegin******
 *
 * -- NextStartCode -- does bit stuffing for next sc as per VM 4.0
 *
 * Author :		
 *	Noel O'Connor
 *
 * Created :		
 *	09.10.96
 *
 * Purpose :		
 *	does bit stuffing for next sc as per VM 4.0 i.e. ("011...")
 * 
 * Arguments in : 
 *	int index1	
 *	int index2 - unique identifiers for bitstream file pointer and counters
 *
 * Arguments in/out :	
 *	none
 *
 * Arguments out :	
 *	none
 *
 * Return values :	
 *	int :	number of ones stuffed in
 *
 * Side effects :	
 *	
 *
 * Description :
 *
 * See also :
 *	
 *
 * Modified :
 *      14-Jan-97 Luis Ducla-Soares: function was stuffing one less bit than
 *                                   it should. Corrected it by swapping the
 *                                   following lines:
 *                                            count=outcnt[index]-1;
 *                                            PutBits(1,0,index);
 * 04.02.97 Noel O'Connor: mods for non unique VOl Ids (index1 & index2)
 * 27.04.97 Luis Ducla-Soares: modified function to do bitstuffing as per VM5.0
 *
 ***********************************************************CommentEnd********/
Int 
NextStartCode(Int index1, Int index2)
{

  Int count;
  Int	i;
  
  
  count = outcnt[index1][index2] - 1;
  i = 0;
  
  PutBits(1,0,index1,index2);
  
  while (i < count)
    {
      PutBits(1,1,index1,index2);
      i++;
    }
  
  
  return (count+1); 
}


/***********************************************************CommentBegin******
 *
 * -- NextResyncMarker -- does bit stuffing for next resync marker as per VM 5.0
 *
 * Author :		
 *	Luis Ducla-Soares (IST) - lds@lx.it.pt
 *
 * Created :		
 *	27.04.97
 *
 * Purpose :		
 *	does bit stuffing for next resync marker  as per VM 5.0 i.e. ("011...")
 * 
 *                                            "0"
 *                                           "01"
 *                                          "011"
 *                                         "0111"
 *                                        "01111"
 *                                       "011111"
 *                                      "0111111"
 *                                     "01111111"   (8-bit codeword)
 *
 * Arguments in : 
 *	int index1	
 *	int index2 - unique identifiers for bitstream file pointer and counters
 *
 * Arguments in/out :	
 *	none
 *
 * Arguments out :	
 *	none
 *
 * Return values :	
 *	int :	returns the number of bits to be stuffed.
 *
 * Side effects :	
 *	
 *
 * Description : this function does the same thing as  NextStartCode().
 *               Always stuffs 011.. before a resync marker even if the bitstream
 *               is byte aligned.
 *
 * See also :
 *	
 *
 * Modified :
 *
 *
 ***********************************************************CommentEnd********/
Int 
NextResyncMarker(Int index1, Int index2)
{

  Int count;
  Int	i;
  Int ret_value;
  
  
  ret_value = outcnt[index1][index2];
  
  count = outcnt[index1][index2] - 1;
  i = 0;
  
  PutBits(1,0,index1,index2);
  
  while (i < count)
    {
      PutBits(1,1,index1,index2);
      i++;
    }
  
  return ret_value;
  
}






