/*
 * Copyright 1993 by the University of Pennsylvania
 *
 * Permission to use, copy, and distribute for non-commercial purposes,
 * is hereby granted without fee, providing that the above copyright
 * notice appear in all copies and that both the copyright notice and this
 * permission notice appear in supporting documentation.
 *
 * The software may be modified for your own purposes, but modified versions
 * may not be distributed.
 *
 * This software is provided "as is" without any expressed or implied warranty.
 */

typedef unsigned short word;
typedef struct {
  unsigned int data;
  int length;
} CODE;
void align();
void put_bits();
static int frames = 0;
extern int curr_pri;
extern int mb_bits;

void
  put_sequence_start_code(wd,ht)
int wd, ht;
{
  CODE seq_code;
  mb_bits = 0;
  curr_pri = 0;
  /* Start Code */
  seq_code.data = 0x000001b3; seq_code.length = 32; put_bits(seq_code);
  /* Frame dimensions, aspect ratio, rate*/
  seq_code.data = wd; seq_code.length = 12; put_bits(seq_code);
  seq_code.data = ht; seq_code.length = 12; put_bits(seq_code);
  seq_code.data = 1; seq_code.length = 4; put_bits(seq_code);
  seq_code.data = 2; seq_code.length = 4; put_bits(seq_code);
  /* Codes for constrained VBR coding */
  seq_code.data = 0xffff; seq_code.length = 16; put_bits(seq_code);
  seq_code.data = 0x3; seq_code.length = 2; put_bits(seq_code);
  seq_code.data = 0x1; seq_code.length = 1; put_bits(seq_code);
  seq_code.data = 0x14; seq_code.length = 10; put_bits(seq_code);
  seq_code.data = 0x1; seq_code.length = 1; put_bits(seq_code);
  /* Load quantizer matrix options disabled*/
  seq_code.data = 0x0; seq_code.length = 1; put_bits(seq_code);
  seq_code.data = 0x0; seq_code.length = 1; put_bits(seq_code);
}

void
  put_sequence_end_code()
{
  CODE seq_code;
  mb_bits = 0;
  curr_pri = 0;
  align();
  seq_code.data = 0x000001b7; seq_code.length = 32; put_bits(seq_code);
}

void
  put_group_code()
{
  CODE gcode;

  static int min = 0;
  static int sec = 0;
  mb_bits = 0;
  curr_pri = 0;
  align();

  /* Group Start Code */
  gcode.data = 0x000001b8; gcode.length = 32; put_bits(gcode); 

  gcode.data = 0x0; gcode.length = 1; put_bits(gcode);   /* SMPTE Code */
  gcode.data = 0x0; gcode.length = 5;  put_bits(gcode);
  gcode.data = min; gcode.length = 6;  put_bits(gcode);
  gcode.data = 0x1; gcode.length = 1; put_bits(gcode);
  gcode.data = sec; gcode.length = 6;  put_bits(gcode);
  gcode.data = frames; gcode.length = 6;  put_bits(gcode);
  sec = frames/24; min = sec/60; frames = frames % 24;
  gcode.data = 0x1; gcode.length = 1; put_bits(gcode);
  gcode.data = 0x0; gcode.length = 1; put_bits(gcode);
}

void
  put_picture_code(p)
int p; /* Frame type indicator ( 0:I, 1:P, 3:B ) */
{
  static int frame_num = 0;
  CODE pcode;
  mb_bits = 0;
  curr_pri = 0;
  align();
  /* Picture Start Code */
  pcode.data = 0x00000100; pcode.length = 32; put_bits(pcode);

  if (p == 0)
    frame_num = 0;
  pcode.data = frame_num; pcode.length = 10; /* Temporal Reference code */
  put_bits(pcode); 

  /* Picture coding type */
  switch (p) { 
    case 0: pcode.data = 1;break; /* I */
    case 1: pcode.data = 2;break; /* P */
    case 3: pcode.data = 3;break; /* B */
  }
  pcode.length = 3    ; put_bits(pcode); 
  pcode.data   = 3000 ; pcode.length = 16;  put_bits(pcode); 
  /* Full pixel forward motion vectors in [-16,16] */
  if (p != 0) {  /* when P or B */
    pcode.data = 1; pcode.length = 1;  put_bits(pcode); 
    pcode.data = 1; pcode.length = 3;  put_bits(pcode);
  }
  /* Full pixel backward motion vectors in [-16,16] */
  if (p == 3) {  /* B mode only */
    pcode.data = 1; pcode.length = 1;  put_bits(pcode); 
    pcode.data = 1; pcode.length = 3;  put_bits(pcode);
  }
  pcode.data = 0; pcode.length = 1;  put_bits(pcode);
  frame_num++; frames++;
}

void
  put_slice_code(slice_num,q)
int slice_num,q;
{
  CODE slice_code;
  mb_bits = 0;
  curr_pri = 0;
  align();

  slice_code.data = 0x00000100 + slice_num; slice_code.length = 32;
  put_bits(slice_code);

  slice_code.data = q; slice_code.length = 5; put_bits(slice_code);
  slice_code.data = 0; slice_code.length = 1; put_bits(slice_code);
}


