/*
 *  This file handles filling of the buffer and contains some additional utility routines.
 */

#include "video.h"
#include "proto.h"
#include "util.h"

/* Declarations of global variables used. */

int bitOffset;
int bufLength;
unsigned int *bitBuffer;


/*
 *--------------------------------------------------------------
 *
 * correct_underflow --
 *
 *	Called when buffer does not have sufficient data to 
 *      satisfy request for bits.
 *      Calls get_more_data, an application specific routine
 *      required to fill the buffer with more data.
 *
 * Results:
 *      None really.
 *  
 * Side effects:
 *	buf_length and buffer fields in curVidStream structure
 *      may be changed.
 *
 *--------------------------------------------------------------
 */

void correct_underflow(void)
{
  int status;

  status = get_more_data(curVidStream->buf_start, curVidStream->max_buf_length, &bufLength, &bitBuffer);

  if (status  < 0) {
    if (!quietFlag) {
      fprintf (stderr, "\n");
      perror("Unexpected read error.");
    }
    exit(1);
  }
  else if ((status == 0) && (bufLength < 1)) {
    if (!quietFlag) {
      fprintf(stderr, "\nImproper or missing sequence end code.\n");
    }
#ifdef ANALYSIS
    PrintAllStats();
#endif
    if (!quietFlag) {
      PrintTimeInfo();
    }

    if (loopFlag) longjmp(env, 1);
    DestroyVidStream(curVidStream);
    exit(0);
  }

}


/*
 *--------------------------------------------------------------
 *
 * get_ext_data --
 *
 *	Assumes that bit stream is at begining of extension
 *      data. Parses off extension data into dynamically 
 *      allocated space until start code is hit. 
 *
 * Results:
 *	Pointer to dynamically allocated memory containing
 *      extension data.
 *
 * Side effects:
 *	Bit stream irreversibly parsed.
 *
 * Niceness -10000 !!!!
 *
 *--------------------------------------------------------------
 */

char *get_ext_data (void)
{
  int size, marker;
  char *dataPtr;
  unsigned int data;

  /* Set initial ext data buffer size. */

  size = EXT_BUF_SIZE;

  /* Allocate ext data buffer. */

  dataPtr = (char *) malloc(size);

  /* Initialize marker to keep place in ext data buffer. */

  marker = 0;

  /* While next data is not start code... */
  while ((show_bitsn(24,data)) != 0x000001) {				/* data re-usage could be applied ! */

    /* Put ext data into ext data buffer. Advance marker. */

    get_bits8( dataPtr[marker] );
    marker++;

    /* If end of ext data buffer reached, resize data buffer. */

    if (marker == size) {
      size += EXT_BUF_SIZE;
      dataPtr = (char *) realloc(dataPtr, size);
    }
  }

  /* Realloc data buffer to free any extra space. */

  dataPtr = (char *) realloc(dataPtr, marker);

  /* Return pointer to ext data buffer. */

  return dataPtr;
}


/*
 *--------------------------------------------------------------
 *
 * get_extra_bit_info --
 *
 *	Parses off extra bit info stream into dynamically 
 *      allocated memory. Extra bit info is indicated by
 *      a flag bit set to 1, followed by 8 bits of data.
 *      This continues until the flag bit is zero. Assumes
 *      that bit stream set to first flag bit in extra
 *      bit info stream.
 *
 * Results:
 *	Pointer to dynamically allocated memory with extra
 *      bit info in it. Flag bits are NOT included.
 *
 * Side effects:
 *	Bit stream irreversibly parsed.
 *
 *--------------------------------------------------------------
 */

char *get_extra_bit_info (void)
{
  int size, marker;
  char *dataPtr;
  unsigned int data;

  /* Get first flag bit; if flag is false, return NULL pointer (i.e. no extra bit info). */

  if (!(get_bits1(data))) return NULL;

  /* Initialize size of extra bit info buffer and allocate. */

  size = EXT_BUF_SIZE;
  dataPtr = (char *) malloc(size);

  /* Reset marker to hold place in buffer. */

  marker = 0;

  /* While flag bit is true. */

  while (data) {

    /* Place in extra bit info buffer. */

    get_bits8( dataPtr[marker] );
    marker++;

    /* If buffer is full, reallocate. */

    if (marker == size) {
      size += EXT_BUF_SIZE;
      dataPtr = (char *) realloc(dataPtr, size);
    }

    /* Get next flag bit. */
    get_bits1(data);
  }

  /* Reallocate buffer to free extra space. */

  dataPtr = (char *) realloc(dataPtr, marker);

  /* Return pointer to extra bit info buffer. */

  return dataPtr;
}
