/* systems.c, systems-specific routines                                 */



/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */



/*

 * Disclaimer of Warranty

 *

 * These software programs are available to the user without any license fee or

 * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims

 * any and all warranties, whether express, implied, or statuary, including any

 * implied warranties or merchantability or of fitness for a particular

 * purpose.  In no event shall the copyright-holder be liable for any

 * incidental, punitive, or consequential damages of any kind whatsoever

 * arising from the use of these programs.

 *

 * This disclaimer of warranty extends to the user of these programs and user's

 * customers, employees, agents, transferees, successors, and assigns.

 *

 * The MPEG Software Simulation Group does not represent or warrant that the

 * programs furnished hereunder are free of infringement of any third-party

 * patents.

 *

 * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,

 * are subject to royalty fees to patent holders.  Many of these patents are

 * general enough such that they are unavoidable regardless of implementation

 * design.

 *

 */



#include <stdio.h>

#include <stdlib.h>



#include "config.h"

#include "global.h"



/* initialize buffer, call once before first getbits or showbits */



/* parse system layer, ignore everything we don't need */

void Next_Packet()

{

  unsigned int code;

  int l;



  for(;;)

  {

    code = Get_Long();



    /* remove system layer byte stuffing */

    while ((code & 0xffffff00) != 0x100)

      code = (code<<8) | Get_Byte();



    switch(code)

    {

    case PACK_START_CODE: /* pack header */

      /* skip pack header (system_clock_reference and mux_rate) */

      ld->Rdptr += 8;

      break;

    case VIDEO_ELEMENTARY_STREAM:   

      code = Get_Word();             /* packet_length */

      ld->Rdmax = ld->Rdptr + code;



      code = Get_Byte();



      if((code>>6)==0x02)

      {

        ld->Rdptr++;

        code=Get_Byte();  /* parse PES_header_data_length */

        ld->Rdptr+=code;    /* advance pointer by PES_header_data_length */

        printf("MPEG-2 PES packet\n");

        return;

      }

      else if(code==0xff)

      {

        /* parse MPEG-1 packet header */

        while((code=Get_Byte())== 0xFF);

      }

       

      /* stuffing bytes */

      if(code>=0x40)

      {

        if(code>=0x80)

        {

          fprintf(stderr,"Error in packet header\n");

          exit(1);

        }

        /* skip STD_buffer_scale */

        ld->Rdptr++;

        code = Get_Byte();

      }



      if(code>=0x30)

      {

        if(code>=0x40)

        {

          fprintf(stderr,"Error in packet header\n");

          exit(1);

        }

        /* skip presentation and decoding time stamps */

        ld->Rdptr += 9;

      }

      else if(code>=0x20)

      {

        /* skip presentation time stamps */

        ld->Rdptr += 4;

      }

      else if(code!=0x0f)

      {

        fprintf(stderr,"Error in packet header\n");

        exit(1);

      }

      return;

    case ISO_END_CODE: /* end */

      /* simulate a buffer full of sequence end codes */

      l = 0;

      while (l<2048)

      {

        ld->Rdbfr[l++] = SEQUENCE_END_CODE>>24;

        ld->Rdbfr[l++] = SEQUENCE_END_CODE>>16;

        ld->Rdbfr[l++] = SEQUENCE_END_CODE>>8;

        ld->Rdbfr[l++] = SEQUENCE_END_CODE&0xff;

      }

      ld->Rdptr = ld->Rdbfr;

      ld->Rdmax = ld->Rdbfr + 2048;

      return;

    default:

      if(code>=SYSTEM_START_CODE)

      {

        /* skip system headers and non-video packets*/

        code = Get_Word();

        ld->Rdptr += code;

      }

      else

      {

        fprintf(stderr,"Unexpected startcode %08x in system layer\n",code);

        exit(1);

      }

      break;

    }

  }

}







void Flush_Buffer32()

{

  int Incnt;



  ld->Bfr = 0;



  Incnt = ld->Incnt;

  Incnt -= 32;



  if (System_Stream_Flag && (ld->Rdptr >= ld->Rdmax-4))

  {

    while (Incnt <= 24)

    {

      if (ld->Rdptr >= ld->Rdmax)

        Next_Packet();

      ld->Bfr |= Get_Byte() << (24 - Incnt);

      Incnt += 8;

    }

  }

  else

  {

    while (Incnt <= 24)

    {

      if (ld->Rdptr >= ld->Rdbfr+2048)

        Fill_Buffer();

      ld->Bfr |= *ld->Rdptr++ << (24 - Incnt);

      Incnt += 8;

    }

  }

  ld->Incnt = Incnt;



#ifdef VERIFY 

  ld->Bitcnt += 32;

#endif /* VERIFY */

}





unsigned int Get_Bits32()

{

  unsigned int l;



  l = Show_Bits(32);

  Flush_Buffer32();



  return l;

}





int Get_Long()

{

  int i;



  i = Get_Word();

  return (i<<16) | Get_Word();

}





