/*****************************************************************************
 *
 * This software module was originally developed by
 *
 *   Gunnar Nitsche (Bosch / ACTS-MoMuSyS)
 *
 * and edited by
 * 
 *   Robert Danielsen (Telenor / ACTS-MoMuSyS)
 *   Paulo Nunes (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) 1996
 *
 *****************************************************************************/

/***********************************************************HeaderBegin*******
 *                                                                         
 * File:	mom_bitstream_i.c
 *
 * Author:	Gunnar Nitsche
 * Created:	6-Feb-96
 *                                                                         
 * Description: 
 *
 * Notes: 	
 *
 * Modified:	21.04.96 Robert Danielsen: Reformatted. New headers.
 *
 ***********************************************************HeaderEnd*********/

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

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

/***********************************************************CommentBegin******
 *
 * -- BitstreamInit -- Returns an bitstream in the form of an Image pointer
 *
 * Author :		
 *	Gunnar Nitsche
 *
 * Created :		
 *	6-Feb-96
 *
 * Purpose :		
 *	Returns an empty bitstream in the form of an Image pointer.
 * 
 * Arguments in : 	
 *	none
 *
 * Arguments in/out :	
 *	none
 *
 * Arguments out :	
 *	none
 *
 * Return values :	
 *	The empty Image/Bitstream pointer.
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	Image *bitstream = BitstreamInit();
 *
 * See also :
 *	BitstreamFree()
 *
 * Modified :		
 *	
 *
 ***********************************************************CommentEnd********/
 
Image *
BitstreamInit()
{
  Image *bitstream;

  /* avoids problems with allocating zero size */

  bitstream = AllocImage(BITSTREAM_ALLOC_SIZE, 1, SHORT_TYPE);

  /* however, allocated size is not equal to x to avoid too many reallocations */
  /* there is no access function to store x, this is another reason that
     macros would make more sense than functions for this purpose */

  bitstream->x = 0;
  return bitstream;
}



/***********************************************************CommentBegin******
 *
 * -- BitstreamFree -- Frees previously allocated memory for a bitstream. 
 *
 * Author :		
 *	Gunnar Nitsche
 *
 * Created :		
 *	6-Feb-96
 *
 * Purpose :		
 *	Frees previously allocated memory for a bitstream. 
 * 
 * Arguments in : 	
 *	Image *bitstream
 *
 * Arguments in/out :	
 *	none
 *
 * Arguments out :	
 *	none
 *
 * Return values :	
 *	none
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	BitstreamInit()
 *
 * Modified :		
 *	
 *
 ***********************************************************CommentEnd********/

Void
BitstreamFree(Image *bitstream)
{
  FreeImage(bitstream);
}


/***********************************************************CommentBegin******
 *
 * -- BitstreamPutBit -- Appends one bit to the bitstream.
 *
 * Author :		
 *	Gunnar Nitsche
 *
 * Created :		
 *	6-Feb-96 
 *
 * Purpose :		
 *	Appends one bit to the bitstream.
 * 
 * Arguments in : 	
 *	Image *bitstream
 *	SInt bit
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	
 *
 * Return values :	
 *	none
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	The variable bitstream must be previously initialised
 *	The variable bit is equal to 1 or 0.
 *
 * See also :
 *	BitstreamInit(), BitstreamFree()
 *
 * Modified :		
 *	
 *
 ***********************************************************CommentEnd********/

Void
BitstreamPutBit(Image *bitstream, SInt bit)
{
  UInt size_x;

  size_x = GetImageSizeX(bitstream);
  if (size_x > 0 && size_x % BITSTREAM_ALLOC_SIZE == 0)
    {
      ReallocImage(bitstream, size_x+BITSTREAM_ALLOC_SIZE, 1);
      bitstream->x = size_x;
    }

  /* it was a good idea to use long instead of short for the sizes */

  bitstream->f[bitstream->x++] = bit;
}




/***********************************************************CommentBegin******
 *
 * -- BitstreamPutBits -- Appends a stream of bits to the bitstream.
 *
 * Author :		
 *	Gunnar Nitsche
 *
 * Created :		
 *	6-Feb-96 
 *
 * Purpose :		
 *	Appends a stream of bits to the bitstream.
 * 
 * Arguments in : 	
 *	Image *bitstream
 *	UInt bits
 *	UInt nbits
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	
 *
 * Return values :	
 *	none
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	The variable bitstream must be previously initialised
 *  	Appends the low order nbits (up to 32) of bits (MSB 
 *	first) to the bitstream
 *
 * See also :
 *	BitstreamInit(), BitstreamFree(), BitstreamPutBit()
 *
 * Modified :
 *	07.06.96 Robert Danielsen:
 *		Added the 'if (nbits > 0)' part to allow writing of 0 bits.
 *	09.03.98 Paulo Nunes: Cleaning.
 *	
 *
 ***********************************************************CommentEnd********/

Void
BitstreamPutBits(Image *bitstream, UInt bits, UInt nbits)
{
  UInt mask;

  /* it should be 1 <= nbits <= 32 */

  if (nbits > 0)
    {
      for (mask = 1L << (nbits-1); mask; mask >>= 1)
	BitstreamPutBit(bitstream, (SInt)((bits & mask) == mask));
    }
}



/***********************************************************CommentBegin******
 *
 * -- BitstreamAppend -- Appends one bitstream to another bitstream.
 *
 * Author :		
 *	Gunnar Nitsche
 *
 * Created :		
 *	6-Feb-96
 *
 * Purpose :		
 *	Appends one bitstream to another bitstream.
 * 
 * Arguments in : 	
 *	Image *bitstream1
 *	Image *bitstream2
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	
 *
 * Return values :	
 *	none
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	Appends bitstream1 to bitstream2
 *
 * See also :
 *	BitstreamInit(), BitstreamFree(), BitstreamPutBit()
 *
 * Modified :		
 *	
 *
 ***********************************************************CommentEnd********/
 
Void
BitstreamAppend(Image *bitstream1, Image *bitstream2)
{
  UInt size_x;
  SInt *p = (SInt *)GetImageData(bitstream1);

  for (size_x = GetImageSizeX(bitstream1); size_x > 0; size_x--)
    BitstreamPutBit(bitstream2, *p++);
}



/***********************************************************CommentBegin******
 *
 * -- BitstreamPrint -- Prints a bitstream to stdout
 *
 * Author :		
 *	Gunnar Nitsche
 *
 * Created :		
 *	6-Feb-96
 *
 * Purpose :		
 *	Prints a bitstream to stdout
 * 
 * Arguments in : 	
 *	Image *bitstream
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	BitstreamInit(), BitstreamFree(), BitstreamPutBit()
 *
 * Modified :		
 *	
 *
 ***********************************************************CommentEnd********/
 
Void
BitstreamPrint(Image *bitstream)
{
  UInt size_x = GetImageSizeX(bitstream);
  SInt *p = (SInt *)GetImageData(bitstream);

  printf("size = %d, data = ", (int)size_x);
  for (; size_x > 0; size_x--)
    printf("%1d", *p++);
  printf("\n");
}

/***********************************************************CommentBegin******
 *
 * -- BitstreamPut -- Writes a bitstream to disk
 *
 * Author :		
 *	Gunnar Nitsche
 *
 * Created :		
 *	6-Feb-96
 *
 * Purpose :		
 *	Writes a bitstream to disk
 * 
 * Arguments in : 	
 *	Image *bitstream
 *	Int index1
 *	Int index2 - unique identifiers for bitstream to write to (normally VOL id)
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	Writes bitstream to a disk file. The file must have been opened
 *	previous to writing by an open statement in the calling file..
 *
 * See also :
 *	BitstreamInit(), BitstreamFree(), BitstreamPutBit(), and
 *	fopen() and fclose() in a higher level file.
 *
 * Modified :		
 *	26.08.96 Noel O'Connor: modification to allow for fact that encoder now
 *	has to be able to write to multiple bitstream files on disk. New argument
 *	"index" which is a unique identifier for bitstream file pointer and 
 *	counters.
 * 04.02.97 Noel O'Connor: mods for non unique VOl Ids (index1 & index2)
 *
 ***********************************************************CommentEnd********/
 
UInt
BitstreamPut (Image *b_stream, Int index1, Int index2)
{
  UInt i;
  SInt *stream = (SInt *)GetImageData (b_stream);
  UInt size_stream = GetImageSizeX (b_stream);

  for (i = 0; i < size_stream; i++)
    PutBits (1, *(stream++), index1,index2);

  return(size_stream);
}
