dslinux/user/pixil/packages/dvdview/dvdview/src/system ptsvideo.cc ptsvideo.hh resync.cc resync.hh syncer.cc syncer.hh sysdec1.cc sysdec1.hh sysdemux.cc sysdemux.hh system1.hh videoauconv.cc videoauconv.hh

amadeus dslinux_amadeus at user.in-berlin.de
Tue Oct 3 13:26:01 CEST 2006


Update of /cvsroot/dslinux/dslinux/user/pixil/packages/dvdview/dvdview/src/system
In directory antilope:/tmp/cvs-serv11916/packages/dvdview/dvdview/src/system

Added Files:
	ptsvideo.cc ptsvideo.hh resync.cc resync.hh syncer.cc 
	syncer.hh sysdec1.cc sysdec1.hh sysdemux.cc sysdemux.hh 
	system1.hh videoauconv.cc videoauconv.hh 
Log Message:
adding pristine copy of pixil to HEAD so I can branch from it

--- NEW FILE: resync.hh ---
/********************************************************************************
  system/resync.hh

  purpose:
    Do automatic resynchronization on system layer stream errors.

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   30/Sep/1999 - Dirk Farin
     - first revision
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_SYSTEM_RESYNC_HH
#define DVDVIEW_SYSTEM_RESYNC_HH

#include "types.hh"
#include "system/system1.hh"


class SystemResyncer : public SysPacketSource
{
public:
  SystemResyncer();

  void SetSource(class SystemDecoder_MPEG1* src) { d_src=src; }

  SysPacket* GetNextPacket();	// Get next packet or return NULL if the end of the stream is reached.

private:
  class SystemDecoder_MPEG1* d_src;
};

#endif

--- NEW FILE: videoauconv.hh ---
/********************************************************************************
  system/videoauconv.hh
    Video-AccessUnit-Converter.

  purpose:
    Objects of this class split and combine packets so that the
    returned packets contain exactly one startcode-unit of video.

  notes:

  to do:
  1) PTS insertion when undefined ( step 2 in GetNextPacket() )

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   22/Oct/1999 - Dirk Farin
     - If stream does not start with 000001, data until first startcode is
       skipped.
   27/Dec/1998 - Dirk Farin
     - Bugfix: very first start code in file was not found if it
       had more leading 0-bytes than needed.
   22/Dec/1998 - Dirk Farin
     - Bugfix: the last byte of a input packet was inserted into
       the destination packet twice.
   19/Dec/1998 - Dirk Farin
     - first implementation, PTS insertion when undefined is not
       implemented yet.
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_SYSTEM_VIDEOAUCONV_HH
#define DVDVIEW_SYSTEM_VIDEOAUCONV_HH

#include "types.hh"
#include "utility/bytebuffer.hh"
#include "system/system1.hh"


class VideoAUConverter : public PacketSource
{
public:
  VideoAUConverter(PacketSource&);
  ~VideoAUConverter();

  // Get next packet or return NULL if the end of the stream is reached.
  SysPacket_Packet* GetNextPacket();

private:
  PacketSource& d_src;

  SysPacket_Packet* d_current;
  SysPacket_Packet* d_next;

  int    d_curr_pos;

  bool   d_HasPTS;
  PTS    d_pts;
  int    d_pts_picoffset;
  double d_framerate;

  ByteBufferParams d_bytebufparams;

  void   Reset();
};

#endif

--- NEW FILE: sysdec1.cc ---
/********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/


#include "system/sysdec1.hh"
#include "input/streamsrc.hh"
#include "input/errors.hh"
#include "error.hh"

#include <stdio.h>

#include <iostream.h>


const int c_ElementaryPacketSize = 63*1024;

int SystemDecoder_MPEG1::s_next_pck_nr = 0;


SystemDecoder_MPEG1::SystemDecoder_MPEG1()
  : d_strsrc(NULL),
    d_streamtype(Unknown),
    d_readahead_packet(NULL),
    d_synced(false),
    d_bytebufparams(3*1024,20)
{
}


SystemDecoder_MPEG1::~SystemDecoder_MPEG1()
{
  if (d_readahead_packet)
    {
      delete d_readahead_packet;
    }
}


void SystemDecoder_MPEG1::SetSource(StreamSource& strsrc)
{
  d_strsrc=&strsrc;
  HardReset();
}


void SystemDecoder_MPEG1::HardReset()
{
  SoftReset();


  // If streamtype is now known, guess it from the next startcode.

  if (d_streamtype == Unknown)
    {
      // Read first four bytes of stream to determine type of stream.
      // As we have read some bytes we have to read a complete startcode unit then.

      uint8 buf[4];
      int BytesRead = d_strsrc->FillBuffer(buf,4);

      /* New 17/May/99: Skip extra leading 0-bytes. */
      while (buf[0]==0 && buf[1]==0 && buf[2]==0)
	{
	  buf[0]=buf[1];
	  buf[1]=buf[2];
	  buf[2]=buf[3];
	  BytesRead--;
	  BytesRead += d_strsrc->FillBuffer(&buf[3],1);

	  // Leave loop if no complete startcode is possible any more.
	  if (BytesRead != 4)
	    break;
	}

      if (BytesRead!=4 || buf[0]!=0x00 || buf[1]!=0x00 || buf[2]!=0x01)
	{
	  d_streamtype = Illegal;
	}
      else if (buf[3]==0xBA)
	{
	  d_streamtype = System;
	  try
	    {
	      d_readahead_packet = ReadPack();
	    }
	  catch (Excpt_Error_UnexpectedEndOfStream&)
	    {
	      // Stream is far too short to be useable.
	      d_streamtype = Illegal;
	    }
	}
      else
	{
	  d_streamtype = Video;
	  d_readahead_packet = ReadElemPacket(true,buf[3]);
	}
    }
}


void SystemDecoder_MPEG1::SoftReset()
{
  if (d_readahead_packet)
    {
      delete d_readahead_packet;
      d_readahead_packet=NULL;
    }

  d_synced=false;
}


SysPacket* SystemDecoder_MPEG1::GetNextPacket()
{
  // While there are previously read packets pending in the queue, return these.

  if (d_readahead_packet)
    {
      SysPacket* pck = d_readahead_packet;
      d_readahead_packet = NULL;
      return pck;
    }

  // If end of input reached return nothing (as no more packets are in the queue).

  if (!d_strsrc->MoreDataPending() &&
      !d_synced) // This test because we have read 3 bytes already.
    return NULL;

  // Remember 'd_synced' flag and clear it.

  bool sync=d_synced;
  d_synced=false;

  // There is more data to be read. Generate more SysPackets if possible.

  if (d_streamtype==System)
    {
      // Find next startcode.

      uint8 buf[4];
      int BytesRead;
      if (!sync)
	{
	  BytesRead = d_strsrc->FillBuffer(buf,4);
	}
      else
	{
	  buf[0]=buf[1]=0; buf[2]=1;
	  BytesRead = d_strsrc->FillBuffer(&buf[3],1) + 3;
	}

      // Incomplete startcode.
      if (BytesRead!=4)
        {
	  if (BytesRead==0)
	    return NULL;	// End of stream reached, no more startcodes.
	  else
	    throw Excpt_Error_UnexpectedEndOfStream();
	}

      while (!(buf[0]==0 && buf[1]==0 && buf[2]==1)) // While startcode sync not found.
        {
	  // Shift buffer forward one byte.
	  buf[0]=buf[1]; buf[1]=buf[2]; buf[2]=buf[3];
	  if (d_strsrc->FillBuffer(&buf[3],1) != 1)
	    {
	      throw Excpt_Error_UnexpectedEndOfStream();
	    }
        }


      // According to the startcode read, get complete startcode-unit.

      if (buf[3]>=0xBD && buf[3]<=0xEF)
        {
	  //printf("%p\n",buf[3]);
          return ReadPacket(buf[3]);
        }
      else
        {
          switch (buf[3])
            {
            case 0xB9:
              {
                SysPacket* syspck = new SysPacket_Iso11172EndCode;
                syspck->pck_nr = s_next_pck_nr++;
                syspck->absolute_filepos = d_strsrc->AskCurrentPosition()-4;
                return syspck;
              }
              break;
            case 0xBA: return ReadPack(); break;
            case 0xBB: return ReadSystemHeader(); break;
            default:
	      {
		char errtxt[100];
		sprintf(errtxt,"Undefined system start code read (%p).",0x100|buf[3]);
		throw Excpt_Error_InvalidData(errtxt);
		break;
	      }
            }
        }
    }
  else
    {
      return ReadElemPacket(false);
    }

  Assert(0);
}


void SystemDecoder_MPEG1::Resync()
{
  if (d_streamtype==System)
    {
      int state=0;
      for (;;)
	{
	  unsigned char c;

	  // End of stream reached -> exit.
	  if (d_strsrc->FillBuffer(&c,1) != 1)
	    return;

	  /*                      -0-
                                  | |
                                  \ /
	    [0] --0--> (1) --0--> (2) --9--> (X)
              ^         |          |
              \        /          /
               ---?---------------
	   */

	  // simple state machine
	  if (state <= 1 && c==0)
	    state++;
	  else if (state==2 && c==0)
	    {
	    }
	  else if (state==2 && c==1)
	    {
	      d_synced=true;
	      return;
	    }
	  else
	    state=0;
	}
    }
}


SysPacket* SystemDecoder_MPEG1::ReadPack()
{
  uint8 buf[10];
  int BytesRead = d_strsrc->FillBuffer(buf,8);

  if (BytesRead!=8)
    {
      throw Excpt_Error_UnexpectedEndOfStream();
    }

  SysPacket_Pack* syspck = new SysPacket_Pack;
  syspck->absolute_filepos = d_strsrc->AskCurrentPosition()-4-8;
  syspck->pck_nr = s_next_pck_nr++;
  syspck->SCR     = (((uint64)(buf[0]&0x0E))<<29) |
                    (((uint64)(buf[1]&0xFF))<<22) |
                    (((uint64)(buf[2]&0xFE))<<14) |
                    (((uint64)(buf[3]&0xFF))<< 7) |
                    (((uint64)(buf[4]&0xFE))>> 1);
  syspck->MuxRate = (((uint32)(buf[5]&0x7F))<<15) |
                    (((uint32)(buf[6]&0xFF))<< 7) |
                    (((uint32)(buf[7]&0xFE))>> 1);

  return syspck;
}


SysPacket* SystemDecoder_MPEG1::ReadPacket(uint8 Channel)
{
  SysPacket_Packet* syspck = new SysPacket_Packet(d_bytebufparams);
  syspck->absolute_filepos = d_strsrc->AskCurrentPosition()-4;
  syspck->Channel=Channel;
  syspck->timing.HasPTS=false;
  syspck->timing.HasDTS=false;
  syspck->HasSTDBufferSpecs=false;

  // Read packet_length.

  uint8 buf[10];
  if (d_strsrc->FillBuffer(buf,2)!=2)
    {
      delete syspck;
      throw Excpt_Error_UnexpectedEndOfStream();
    }

  int packet_length = (((uint32)buf[0])<<8) | (((uint32)buf[1])<<0);

  if (Channel == 0xBF)
    {
      d_strsrc->SetCurrentPosition(d_strsrc->AskCurrentPosition()+packet_length);
      return syspck;
    }

  bool MPEG2_PES=false;

  if (Channel != 0xBE)   // FIX: 99/01/31     was: 0xBF
    {
      if (d_strsrc->FillBuffer(buf,1)!=1)
	{
	  delete syspck;
	  throw Excpt_Error_UnexpectedEndOfStream();
	}

      if ((buf[0]>>6)==0x02)
	{
	  // MPEG-2 PES packet

	  MPEG2_PES=true;

	  d_strsrc->SetCurrentPosition(d_strsrc->AskCurrentPosition()+1);
	  packet_length-=2;

	  d_strsrc->FillBuffer(buf,1);
	  d_strsrc->SetCurrentPosition(d_strsrc->AskCurrentPosition()+buf[0]);
	  packet_length-=buf[0]+1;
	}
      else
	{
	  // Read byte-padding.

	  for(;;)
	    {
	      if (buf[0] != 0xFF)
		break;
	      else
		packet_length--;

	      // read another byte

	      if (d_strsrc->FillBuffer(buf,1)!=1)
		{
		  delete syspck;
		  throw Excpt_Error_UnexpectedEndOfStream();
		}
	    }
	}


      if (!MPEG2_PES)
	{
	  // Read STDBufferSpecs.

	  if ((buf[0]&0xC0) == 0x40)
	    {
	      if (d_strsrc->FillBuffer(&buf[1],1)!=1)
		{
		  delete syspck;
		  throw Excpt_Error_UnexpectedEndOfStream();
		}

	      syspck->HasSTDBufferSpecs=true;
	      syspck->STDBufferScale = ((buf[0]&0x20)!=0);
	      syspck->STDBufferSize  = (((uint32)(buf[0]&0x1F))<<8) | ((uint32)(buf[1]));
	      packet_length -= 2;

	      if (d_strsrc->FillBuffer(buf,1)!=1)
		{
		  delete syspck;
		  throw Excpt_Error_UnexpectedEndOfStream();
		}
	    }
	  else
	    syspck->HasSTDBufferSpecs=false;


	  // Read PTS/DTS

	  if ((buf[0] & 0xE0) == 0x20)
	    {
	      bool ReadDTS = ((buf[0]&0xF0)==0x30);

	      syspck->timing.HasPTS=true;
	      syspck->timing.HasDTS=ReadDTS;

	      uint32 BytesToRead = (ReadDTS ? 10 : 5);
	      if (d_strsrc->FillBuffer(&buf[1],BytesToRead-1) != BytesToRead-1)
		{
		  delete syspck;
		  throw Excpt_Error_UnexpectedEndOfStream();
		}

	      syspck->timing.pts = (((PTS)(buf[0]&0x0E))<<29) |
		(((PTS)(buf[1]&0xFF))<<22) |
		(((PTS)(buf[2]&0xFE))<<14) |
		(((PTS)(buf[3]&0xFF))<< 7) |
		(((PTS)(buf[4]&0xFE))>> 1);

	      if (ReadDTS)
		{
		  syspck->timing.dts = (((DTS)(buf[5]&0x0E))<<29) |
		    (((DTS)(buf[6]&0xFF))<<22) |
		    (((DTS)(buf[7]&0xFE))<<14) |
		    (((DTS)(buf[8]&0xFF))<< 7) |
		    (((DTS)(buf[9]&0xFE))>> 1);
		}

	      packet_length -= BytesToRead;
	    }
	  else
	    {
	      if (buf[0])
		{
		  if (buf[0] != 0x0F)
		    {
		      delete syspck;
		      throw Excpt_Error_InvalidData("Invalid data read: packet header does not contain 00001111 where it should.");
		    }

		  packet_length--;
		}
	    }
	}
    }

  // Read packet data.

  if (packet_length<=0)
    {
      delete syspck;
      throw Excpt_Error_InvalidData("Invalid data read: packet data length <= 0.");
    }

  unsigned char* mem = syspck->data.GetPtrToAppendToBuffer(packet_length);
  uint32 nBytesRead = d_strsrc->FillBuffer(mem,packet_length);
  if (nBytesRead<packet_length)
    {
      delete syspck;
      throw Excpt_Error_UnexpectedEndOfStream();

      //syspck->data.TruncateBuffer(packet_length - nBytesRead);
    }


#if 0
  // throw away padding stream
  if (syspck->Channel == 0xBE)
    {
      return NULL;
    }
#endif

  syspck->pck_nr = s_next_pck_nr++;
  return syspck;
}


SysPacket* SystemDecoder_MPEG1::ReadElemPacket(bool AppendStartcode,uint8 startcode)
{
  /* As it's a video or audio stream, cut input into arbitrary pieces and
     return as SysPacket without PTS/DTS-times. */
  
  SysPacket_Packet* syspck = new SysPacket_Packet(d_bytebufparams);
  syspck->absolute_filepos = d_strsrc->AskCurrentPosition();
  syspck->timing.HasPTS = false;
  syspck->timing.HasDTS = false;
  syspck->HasSTDBufferSpecs = false;

       if (d_streamtype==Video) syspck->Channel = 0xE0;
  else if (d_streamtype==Audio) syspck->Channel = 0xC0;
  else { cerr << "Not implemented streamtype: " << d_streamtype << endl; NotImplemented }

  if (AppendStartcode)
    {
      syspck->absolute_filepos -= 4;
      uint8 buf[4]; buf[0]=buf[1]=0; buf[2]=1; buf[3]=startcode;
      syspck->data.AppendBytes(buf,4);
    }

  unsigned char* mem = syspck->data.GetPtrToAppendToBuffer(c_ElementaryPacketSize);
  int nBytesRead = d_strsrc->FillBuffer(mem,c_ElementaryPacketSize);
  if (nBytesRead<c_ElementaryPacketSize)
    { syspck->data.TruncateBuffer(c_ElementaryPacketSize - nBytesRead); }

  syspck->pck_nr = s_next_pck_nr++;
  return syspck;
}


SysPacket* SystemDecoder_MPEG1::ReadSystemHeader()
{
  // Read packet_length.

  uint8 buf[8];
  if (d_strsrc->FillBuffer(buf,8)!=8)
    {
      throw Excpt_Error_UnexpectedEndOfStream();
    }

  SysPacket_SystemHeader* syspck = new SysPacket_SystemHeader;

  uint32 packet_length = (((uint32)buf[0])<<8) | (((uint32)buf[1])<<0);

  syspck->absolute_filepos = d_strsrc->AskCurrentPosition()-4-8;
  syspck->RateBound = (((int)(buf[2]&0x7F))<<15) |
                      (((int)(buf[3]&0xFF))<< 7) |
                      (((int)(buf[4]&0xFE))>> 1);
  syspck->AudioBound = (buf[5]&0xFC)>>2;
  syspck->VideoBound = (buf[6]&0x1F);
  syspck->FixedBitRate         = ((buf[5]&0x02) != 0);
  syspck->ConstrainedBitstream = ((buf[5]&0x01) != 0);
  syspck->AudioLock  = ((buf[6]&0x80) != 0);
  syspck->VideoLock  = ((buf[6]&0x40) != 0);

  packet_length -= 6;

  while (packet_length>0)
    {
      if (packet_length<3)
        {
          delete syspck;
          throw Excpt_Error_InvalidData("Invalid data read: Junk at end of system header detected.");
        }

      if (d_strsrc->FillBuffer(buf,3)!=3)
        {
	  delete syspck;
	  throw Excpt_Error_UnexpectedEndOfStream();
	}

      if ((buf[0]&0x80) == 0)
        break;

      int scale;
      if ((buf[1]&0x20) != 0)
        scale=128;
      else
        scale=1024;

      uint32 size = (((uint32)(buf[1]&0x1F))<<8) | ((uint32)(buf[2]));

      if (buf[0]==0xB8)
        {
          // special StreadID 0xB8: BufferSize is set for all audio channels
          for (int i=0;i<32;i++) syspck->STDBufferSizeAudio[i] = size*scale;
        }
      else if (buf[0]==0xB9)
        {
          // special StreadID 0xB9: BufferSize is set for all video channels
          for (int i=0;i<16;i++) syspck->STDBufferSizeVideo[i] = size*scale;
        }
      else if (buf[0]<0xC0 || buf[0]>0xEF)
        {
	  /*
          delete syspck;
          throw Excpt_Error_InvalidData("Invalid data read: stream ID out of range.");
	  */
        }
      else
        {
          if (buf[0]<0xE0) syspck->STDBufferSizeAudio[buf[0]-0xC0] = size*scale;
          else             syspck->STDBufferSizeVideo[buf[0]-0xE0] = size*scale;
        }

      packet_length-=3;
    }

  syspck->pck_nr = s_next_pck_nr++;
  return syspck;
}


--- NEW FILE: videoauconv.cc ---
/********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/


/* TODO:
   - Warum werden vom d_next-Buffer 3 Bytes an d_curr angehaengt? Das dritte Byte
     wird doch niemals gelesen?
   - Was ist, wenn in d_next keine 3 Bytes drin sind, die an d_curr angehaengt werden
     koennten?
   - Einige Asserts() koennen bei fehlerhaften Eingabestreams ausloesen. In diesem
     Fall sollten Exceptions ausgeloest werden.
*/


#include "system/videoauconv.hh"
#include "error.hh"


VideoAUConverter::VideoAUConverter(PacketSource& src)
  : d_src(src),
    d_current(NULL),
    d_next(NULL),
    d_bytebufparams(3*1024,20)
{
  Reset();
}


VideoAUConverter::~VideoAUConverter()
{
  if (d_current) delete d_current;
  if (d_next)    delete d_next;
}


void VideoAUConverter::Reset()
{
  if (d_current) delete d_current;
  if (d_next)    delete d_next;
  d_current=NULL;
  d_next   =NULL;
  d_curr_pos=0;
}


#if 1
#include <iostream.h>
#include <iomanip.h>
void PrintDataHex(uint8* data,uint32 len)
{
  //cout << "POS: $" << hex << pck->absolute_filepos << dec << endl;

  for (uint32 i=0;i<len;i++)
    {
      if (i%16 == 0)
        cout << endl << hex << setw(8) << setfill('0') << i << ": ";
      
      cout << hex << setw(2) << setfill('0') << ((int)data[i]) << " ";
    }
  cout << dec << endl;
}

void PrintDataBin(uint8* data,uint32 len)
{
  //cout << "POS: $" << hex << pck->absolute_filepos << dec << endl;

  for (uint32 i=0;i<len;i++)
    {
      if (i%8 == 0)
        cout << endl << hex << setw(8) << setfill('0') << i << ": ";

      uint8 mask=0x80;
      for (int k=0;k<8;k++)
	cout << ((data[i]&(mask>>k)) ? '1' : '0');
      cout << ' ';
    }
  cout << dec << endl;
}
#endif


SysPacket_Packet* VideoAUConverter::GetNextPacket()
{
  // ****************** STEP 1: cut packet into new portions ********************/

  if (d_current==NULL)
    {
      d_current = d_src.GetNextPacket();
      if (d_current==NULL)
        return NULL;

      //cout << "VID 1\n";
      //PrintDataHex(d_current->data.AskContents(),d_current->data.AskLength());

      Assert(d_next==NULL);

      d_next = d_src.GetNextPacket();
      if (d_next)
        {
          //cout << "VID 2\n";
          //PrintDataHex(d_next->data.AskContents(),d_next->data.AskLength());

          // append first two bytes of second buffer to the end of the first one
          d_current->data.AppendBytes(d_next->data.AskContents(),3);
        }
    }


  uint8* currentbuf = d_current->data.AskContents();

  // TODO: throw exception instead (corrupted stread)
  //Assert(currentbuf[d_curr_pos]==0 && currentbuf[d_curr_pos+1]==0);

  SysPacket_Packet* newpck = new SysPacket_Packet(d_bytebufparams);
  newpck->pck_nr  = d_current->pck_nr;
  newpck->Channel = d_current->Channel;
  newpck->absolute_filepos = d_current->absolute_filepos;

  /* These fields are copied, but may be changed later. They are copied to
     store the values that were in effect when an access unit began. */

  newpck->timing = d_current->timing;


  // TODO: do we need these three lines?
  newpck->HasSTDBufferSpecs = d_current->HasSTDBufferSpecs;
  newpck->STDBufferScale    = d_current->STDBufferScale;
  newpck->STDBufferSize     = d_current->STDBufferSize;


  // Copy data until next startcode to new buffer.

  int state=0;
  uint32 pos=d_curr_pos+1;
  uint32 lastsearchpos = d_current->data.AskLength();
  if (d_next) lastsearchpos--;

  for (;;)
    {
      if (pos == lastsearchpos)
        {
          /* If end of current packet reached, copy rest of unused data in current-packet
             to new-packet and move next-packet into current-packet. The next-packet will
             be filled with a new packet if there is one. */
          if (d_next)
            {
              /* Copy from current position until end (excluding the last 2 extra bytes)
		 into the new buffer. */
              uint8* copystart = &currentbuf[d_curr_pos];
              uint32 copylen = d_current->data.AskLength()-1-d_curr_pos-2;
              /* Bugfix 22.Dec.98: This was the old (wrong?) version:
                 uint32 copylen = d_current->data.AskLength()-d_curr_pos-2;
              */
              newpck->data.AppendBytes(copystart,copylen);
              
              // Read in new packet.
              
              delete d_current;
              d_current=d_next;
              Assert(d_current);
              currentbuf = d_current->data.AskContents();
              d_next = d_src.GetNextPacket();
              if (d_next)
                { d_current->data.AppendBytes(d_next->data.AskContents(),3); }
              //cout << "VID 3\n";
              //PrintDataHex(d_next->data.AskContents(),d_next->data.AskLength());
              
              // Reset state machine and pointers.
              
              state=0;
              d_curr_pos=0;
              pos = 0;
              lastsearchpos = d_current->data.AskLength();
              if (d_next) lastsearchpos--;
            }
          else
            {
              // We are at the very end.

              Assert(d_next==NULL);

              uint8* copystart = &currentbuf[d_curr_pos];
              uint32 copylen = d_current->data.AskLength()-d_curr_pos;
              newpck->data.AppendBytes(copystart,copylen);

              delete d_current;
              d_current=NULL;
              goto step2;
            }
        }


      // State machine to find next occurrence of a startcode.

      uint8 c = currentbuf[pos];
      switch (state)
        {
        case 0:
        case 1:
          if (c==0) state++;
          else state=0;
          break;
        case 2: // before the 0x01
          if (c==1)
            {
	      goto leave_statemachine;
            }
          else if (c==0) { /*state=2 as it was before*/ }
          else state=0;
          break;
        }

      pos++;
    }

leave_statemachine:
  pos -= 2;

  newpck->data.AppendBytes( &currentbuf[d_curr_pos] , pos-d_curr_pos );
  d_curr_pos = pos;


step2:
  // ****************** STEP 2: adjust PTS values ********************


  // ****************** Throw away completely NULL-packet *****************
  // (This may be the case for the very first packet in the stream).

  /*
  Assert(newpck->data.AskContents()[0]==0);
  Assert(newpck->data.AskContents()[1]==0);
  */
  if (newpck->data.AskContents()[0] !=0 || newpck->data.AskContents()[1] != 0)
    {
      delete newpck;
      return GetNextPacket();
    }


  if (newpck->data.AskContents()[2]==0)
    {
      // check for all NULL-packet

      for (int i=0;i<newpck->data.AskLength();i++)
        { Assert(newpck->data.AskContents()[i]==0); }

      delete newpck;
      return GetNextPacket();
    }

#if 0
  if (newpck->data.AskContents()[0]==0 &&
      newpck->data.AskContents()[1]==0 &&
      newpck->data.AskContents()[2]==1 &&
      newpck->data.AskContents()[3]==0)
    {
      cout << "Picture Header: ";
      cout << "tRef: " << ((newpck->data.AskContents()[4] <<2) |
			   (newpck->data.AskContents()[5]>>6)) << " ";
      cout << "cType: " << ((newpck->data.AskContents()[5]>>3)&0x7) << " ";
      cout << "PTS: " << newpck->timing.pts << endl;
    }
#endif

  return newpck;
}


--- NEW FILE: syncer.cc ---

#include "system/syncer.hh"

#include <iostream.h>
#include <time.h>


void Syncer_Realtime::Reset()
{
  d_locked=false;
}


void Syncer_Realtime::WaitUntil(PTS pts)
{
  // cout << "syncer received PTS: " << pts << endl;

  /* --------------- This code is a quick hack and probably has a lot of overflow problems.
  */

  struct timeval tv;
  gettimeofday(&tv,NULL);

  if (d_locked)
    {
      long long usec2wait = (pts-d_lastpts)*1000*100/90/d_speed;
      long long usec_passed = (tv.tv_sec -d_lasttime.tv_sec )*1000000 +
	                      (tv.tv_usec-d_lasttime.tv_usec);
      if (usec_passed > usec2wait)
	return;

      usec2wait -= usec_passed;
      struct timespec ts;
      ts.tv_sec  = usec2wait/1000000;
      ts.tv_nsec = (usec2wait%1000000)*1000;
      nanosleep(&ts,NULL);
      return;
    }  

  d_lastpts = pts;
  d_lasttime = tv;
  d_locked = true;
}


--- NEW FILE: resync.cc ---
/********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#include "system/resync.hh"
#include "system/sysdec1.hh"
#include "input/errors.hh"
#include "error.hh"


SystemResyncer::SystemResyncer()
  : d_src(NULL)
{
}


SysPacket* SystemResyncer::GetNextPacket()
{
  Assert(d_src);

  int errcnt=0;

  for (;;)
    {
      try
	{
	  SysPacket* syspck = d_src->GetNextPacket();
	  return syspck;
	}
      catch(Excpt_Error_InvalidData& e)
	{
	  // Display error message only the first time as consecutive errors are
	  // most probably resynchronization errors.
	  if (errcnt==0)
	    MessageDisplay::Show(ErrSev_Warning,e.m_text);
	  errcnt++;

	  d_src->Resync();
	}
    }
}

--- NEW FILE: sysdec1.hh ---
/********************************************************************************
  system/sysdec1.hh

  purpose:
    Breaks a continuous input stream (delivered by a StreamSource
    object) into system packet. In case the stream consists of an
    elementary stream only, pseudo system packets are built with
    no PTS or DTS value set.

  notes:
   - Handling of corrupted input streams:
     Whenever invalid data is read in GetNextPacket(), an
     exception is thrown. If you want to continue decoding, you
     can catch these exceptions and call Resync(). This will
     probably find a position in the stream where decoding can
     be continued. Be prepared that although you called Resync(),
     the next GetNextPacket() call may fail again. It is guaranteed
     that continuing this way will not result in an endless loop.

  to do:
   - recognize audio stream type

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   22/Oct/1999 - Dirk Farin
     - MPEG-2 PES decoding (no header fields extracted yet)
   30/Sep/1999 - Dirk Farin
     - Added ForceStreamType().
   28/Sep/1999 - Dirk Farin
     - Resynchronization can be done after a stream error.
   17/May/1999 - Dirk Farin
     - System streams that start with extra 0-bytes are interpreted
       correctly now.
   31/Jan/1999 - Dirk Farin
     - Bugfix: Padding stream packets were not read correctly.
   19/Dec/1998 - Dirk Farin
     - New method introduced but not implemented:
       void RestartDecoderAtFileposition(uint64 filepos)
   18/Dec/1998 - Dirk Farin
     - Special Stream-IDs 0xB8 and 0xB9 in SequenceHeader are now
       supported.
     - Bugfix: SysPacket_Packet field HasDTS/HasPTS/HasSTDBufferSpecs
       were not set to false when there is no corresponding information.
   17/Dec/1998 - Dirk Farin
     - SysPacket_Iso11172EndCode packets are returned when a
       corresponding start code has been read.
   20/Nov/1998 - Dirk Farin
     - first implementation
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_SYSTEM_SYSDEC1_HH
#define DVDVIEW_SYSTEM_SYSDEC1_HH

#include "types.hh"
#include "utility/bytebuffer.hh"
#include "system/system1.hh"


class SystemDecoder_MPEG1 : public SysPacketSource
{
public:
   SystemDecoder_MPEG1();
  ~SystemDecoder_MPEG1();

  void SetSource(class StreamSource&); // Setting the source implies an implicit hard reset.

  void HardReset();		// Make full reset. Every internal variables are recalculated.
				// The hard reset implies an implicit soft reset.

  void SoftReset();		// Output buffers are cleared but stream specific variables are
				// not reset. A soft reset is needed if the current position in
				// the input stream is modified.

  enum StreamType { Illegal, Unknown, System, Audio, Video }; // The overall stream type.

  StreamType AskStreamType() const { return d_streamtype; }
  void ForceStreamType(StreamType t) { d_streamtype=t; } // You should call SoftReset() afterwards. Do not call
							 // HardReset() as this will try to guess the stream type again.

  SysPacket* GetNextPacket();	// Get next packet or return NULL if the end of the stream is reached.
				// May throw Excpt_Error_InvalidData or Excpt_Error_UnexpectedEndOfFile.
				// You may want to handle this by calling Resync() and trying again.

  void Resync();		// Try to resync to data stream after some parse error.

private:
  class StreamSource* d_strsrc;
  enum StreamType     d_streamtype;
  SysPacket*          d_readahead_packet;

  bool  d_synced;

  ByteBufferParams d_bytebufparams;

  SysPacket* ReadPack();
  SysPacket* ReadPacket(uint8 Channel);
  SysPacket* ReadSystemHeader();

  SysPacket* ReadElemPacket(bool AppendStartcode=false,uint8 startcode=0x00);

  static int s_next_pck_nr;
};

#endif

--- NEW FILE: ptsvideo.cc ---
/********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/


#include "system/ptsvideo.hh"
#include "error.hh"

// #include <iostream.h>


static int framerate2pts[] =
{
  0,
  3754,  // 23.976 fps
  3750,  // 24     fps
  3600,  // 25     fps
  3003,  // 29.97  fps
  3000,  // 30     fps
  1800,  // 50     fps
  1502,  // 59.94  fps
  1500   // 60     fps
};


PTSVideoCompleter::PTSVideoCompleter(PacketSource& src)
  : d_src(src),
    d_lastPTS(50000),
    d_fps(0),
    d_lastIdx(-9999),  // invalid val
    d_GOPlen(-9999)    // invalid val
{
  Reset();
}


PTSVideoCompleter::~PTSVideoCompleter()
{
}

SysPacket_Packet* PTSVideoCompleter::GetNextPacket()
{
  SysPacket_Packet* pck = d_src.GetNextPacket();

  if (pck==NULL)
    return NULL;

  uint8* currentbuf = pck->data.AskContents();

  Assert(currentbuf[0]==0x00);
  Assert(currentbuf[1]==0x00);
  Assert(currentbuf[2]==0x01);

  if (pck->timing.HasPTS)
    {
      d_lastPTS = pck->timing.pts;
      d_synchronized=true;
    }

  if (currentbuf[3]!=0x00)
    {
      // Extract fps-value out of sequence header.

      if (currentbuf[3]==0xB3)
	{
	  d_fps = framerate2pts[currentbuf[7] & 0xF];
	}

      // If GOP-start, move temporal references

      if (currentbuf[3]==0xB8)
	{
	  d_lastIdx = (d_lastIdx - d_GOPlen) -1;
	  d_GOPlen=0;
	}
  
      // Don't modify anything. PTS is only relevant in Picture-Header packets
    }
  else
    {
      int thisIdx = (((int)currentbuf[4])<<2) | (currentbuf[5]>>6);

      // If picture header already has a PTS, keep it.

      if (!pck->timing.HasPTS)
	{
	  pck->timing.HasPTS=true;
	  pck->timing.pts = d_lastPTS + (thisIdx-d_lastIdx)*d_fps;
	}
      else
	{
	  d_lastIdx = thisIdx;
	}

      // Watch GOP length.

      if (thisIdx > d_GOPlen)
	{
	  d_GOPlen = thisIdx;
	}
    }

  return pck;
}


--- NEW FILE: ptsvideo.hh ---
/********************************************************************************
  system/ptsvideo.hh
    Adds PTS values to picture headers without one.

  purpose:
    Make smooth synchronization possible.

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   03/Jul/2000 - Dirk Farin
     - first implementation
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_SYSTEM_PTSVIDEO_HH
#define DVDVIEW_SYSTEM_PTSVIDEO_HH

#include "types.hh"
#include "system/system1.hh"


class PTSVideoCompleter : public PacketSource
{
public:
  PTSVideoCompleter(PacketSource&);
  ~PTSVideoCompleter();

  void Reset() { d_synchronized=false; }

  // Get next packet or return NULL if the end of the stream is reached.
  SysPacket_Packet* GetNextPacket();

private:
  PacketSource& d_src;

  bool   d_synchronized;
  PTS    d_lastPTS;
  int    d_lastIdx;
  int    d_fps;           // number of PTS-ticks per frame

  int    d_GOPlen;
};

#endif

--- NEW FILE: system1.hh ---
/********************************************************************************
  system/system1.hh

  purpose:
    MPEG-1 system headers.

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   27/Sep/1999 - Dirk Farin
     - Extracted structure declarations into this file.
     - Moved 'absolute_filepos' member variable to SysPacket base class.
   19/Dec/1998 - Dirk Farin
     - Added member 'absolute_filepos' to SysPacket_Packet.
   17/Dec/1998 - Dirk Farin
     - Each SysPacket now has a pck_nr member.
   20/Nov/1998 - Dirk Farin
     - first implementation
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_SYSTEM_SYSTEM1_HH
#define DVDVIEW_SYSTEM_SYSTEM1_HH

#include "types.hh"
#include "utility/bytebuffer.hh"

typedef unsigned long long PTS;
typedef unsigned long long DTS;


struct SysPacket
{
  uint64 absolute_filepos;	// File position where this system packet started.

  int pck_nr; /* NOTE: This member is considered obsolet but is not
                 removed because is may help debugging. Think twice
                 before writing code that relies on this member.

                 Consecutive packet number. More packet with the same
                 packet number may be generated in later processing
                 stages but the SystemDecoder always generated a
                 strictly increasing sequence. */

  virtual ~SysPacket() { }
};


struct SystemTimingInformation
{
  bool   HasPTS;
  PTS    pts;
  
  bool   HasDTS;
  DTS    dts;
};


struct SysPacket_Packet : public SysPacket
{
  SysPacket_Packet(ByteBufferParams& p)
    : data(p) { }

  uint8  Channel;

  SystemTimingInformation timing;

  bool   HasSTDBufferSpecs;
  uint8  STDBufferScale;
  uint16 STDBufferSize;

  ByteBuffer data; /* The actual packet data. Note that this can be larger
                      than it is allowed by the standard, as the system
                      decoder is free to create pseudo system packets that
                      do not underlie any limitations. */
};


struct SysPacket_Pack : public SysPacket
{
  long long SCR;
  uint32    MuxRate;
};


struct SysPacket_SystemHeader : public SysPacket
{
  int   RateBound;
  int   AudioBound;
  int   VideoBound;
  bool  FixedBitRate;
  bool  ConstrainedBitstream;
  bool  AudioLock;
  bool  VideoLock;

  uint32 STDBufferSizeAudio[32];
  uint32 STDBufferSizeVideo[16];
};


struct SysPacket_Iso11172EndCode : public SysPacket
{
};



class SysPacketSource
{
public:
  virtual ~SysPacketSource() { }

  virtual SysPacket* GetNextPacket() = 0;	// Get next packet or return NULL if the end of the stream is reached.
};


class PacketSource
{
public:
  virtual ~PacketSource() { }

  virtual SysPacket_Packet* GetNextPacket() = 0; // Get next packet or return NULL if the end of the stream is reached.
};

#endif

--- NEW FILE: sysdemux.cc ---
/********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#include "system/sysdemux.hh"
#include "error.hh"


SystemDemux::SystemDemux(class SysPacketSource& src)
  : d_src(src)
{
  for (int i=c_FirstStream;i<=c_LastStream;i++)
    {
      d_enabled[i-c_FirstStream]=false;
    }
}


SystemDemux::~SystemDemux()
{
  Reset();
}


void SystemDemux::Reset()
{
  // Delete all packets that remained in the output queues.

  for (int i=c_FirstStream;i<=c_LastStream;i++)
    {
      while (!d_outputqueue[i-c_FirstStream].IsEmpty())
        {
          delete d_outputqueue[i-c_FirstStream].AskAndRemoveHead();
        }
    }
}


void SystemDemux::EnableChannel(int StreamID,bool enable)
{
  d_enabled[StreamID-c_FirstStream] = enable;

  if (!enable)
    {
      // Disabling channel. Delete all packet in its queue.

      while (!d_outputqueue[StreamID-c_FirstStream].IsEmpty())
        {
          delete d_outputqueue[StreamID-c_FirstStream].AskAndRemoveHead();
        }
    }
}


bool SystemDemux::ReadAPacket()
{
  SysPacket* syspck = d_src.GetNextPacket();
  if (syspck==NULL)
    return false;

  SysPacket_Packet* packet;
  if ((packet=dynamic_cast<SysPacket_Packet*>(syspck)) != NULL)
    {
      int queue = packet->Channel;

      if (queue<c_FirstStream || queue>c_LastStream)
        {
          //Error(ErrSev_Warning,"Packet found whose packet id is out of bounds. Ignoring it.");
          delete packet;
        }
      else
        {
	  if (d_enabled[queue-c_FirstStream])
	    { d_outputqueue[queue-c_FirstStream].Append(packet); }
	  else
	    { delete packet; }
        }
    }
  else
    {
      // Delete system packets.
      delete syspck;
    }

  return true;
}


SysPacket_Packet* SystemDemux::AskNextPacket(int streamid)
{
  int queueidx = streamid - c_FirstStream;

  Assert(d_enabled[queueidx]);


  // Read more packets until a packet of the requested type is received.

  while (d_outputqueue[queueidx].IsEmpty())
    {
      if (!ReadAPacket())
        return NULL;
    }

  return d_outputqueue[queueidx].AskHead();
}


SysPacket_Packet* SystemDemux::GetNextPacket(int streamid)
{
  SysPacket_Packet* pck = AskNextPacket(streamid);
  if (pck) { d_outputqueue[streamid - c_FirstStream].RemoveHead(); }
  return pck;
}

bool SystemDemux::PacketPending(int streamid) const
{
  int queueidx = streamid - c_FirstStream;

  Assert(d_enabled[queueidx]);

  return !(d_outputqueue[queueidx].IsEmpty());
}





SystemDemuxExtractor::SystemDemuxExtractor()
  : d_sysdemux(NULL),
    d_channel(-1)
{
}


SysPacket_Packet* SystemDemuxExtractor::GetNextPacket()
{
  Assert(d_sysdemux != NULL);
  Assert(d_channel>=0);

  return d_sysdemux->GetNextPacket(d_channel);
}

bool SystemDemuxExtractor::PacketPending() const
{
  Assert(d_sysdemux != NULL);
  Assert(d_channel>=0);

  return d_sysdemux->PacketPending(d_channel);
}



template class Queue<SysPacket_Packet*>;

#include "libvideogfx/containers/queue.cc"

--- NEW FILE: sysdemux.hh ---
/********************************************************************************
  system/sysdemux.hh

  purpose:

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   16/Apr/2000 - Dirk Farin
     - added method: PacketPending()
   30/Sep/1999 - Dirk Farin
     - new class: SystemDemuxExtractor
     - added Reset() to SystemDemux
   29/Sep/1999 - Dirk Farin
     - cleanup for integration into CVS
     - removed System-packet queue
     - channel queues may be selectively enabled/disabled
   17/Dec/1998 - Dirk Farin
     - first implementation
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_SYSTEM_SYSDEMUX_HH
#define DVDVIEW_SYSTEM_SYSDEMUX_HH

#include "types.hh"
#include "libvideogfx/containers/queue.hh"
#include "system/system1.hh"

#define StreamIDBase_Audio 0xC0
#define StreamIDBase_Video 0xE0


class SystemDemux
{
public:
  SystemDemux(SysPacketSource&);
  ~SystemDemux();

  void Reset(); // Clear all queues.

  // To be able to get packet of a channel, you have to enable this channel
  // before decoding.
  void EnableChannel(int StreamID,bool enable=true);

  // Get next packet or return NULL if the end of the stream is reached.
  SysPacket_Packet* AskNextPacket(int StreamID);
  SysPacket_Packet* GetNextPacket(int StreamID);
  bool PacketPending(int StreamID) const; /* True iff a packet is pending in the output queue.
					     A return value of "false" does NOT mean that
					     there will not be more packets of this channel
					     in the stream. */

private:

#define c_FirstStream 0xBD
#define c_LastStream  0xEF

  SysPacketSource& d_src;
  Queue<SysPacket_Packet*> d_outputqueue[c_LastStream-c_FirstStream+1];
  bool d_enabled[c_LastStream-c_FirstStream+1];

  bool ReadAPacket(); // Return false if no more packets available.
};



class SystemDemuxExtractor : public PacketSource
{
public:
  SystemDemuxExtractor();

  void SetSource(SystemDemux* src) { d_sysdemux=src; }
  void SetChannel(int ch) { d_channel=ch; }

  SysPacket_Packet* GetNextPacket();
  bool PacketPending() const;

private:
  SystemDemux* d_sysdemux;
  int          d_channel;
};

#endif

--- NEW FILE: syncer.hh ---
/********************************************************************************
  system/syncer.hh

  purpose:

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
    03/Sep/2000 - Dirk Farin
     - adjustable playback-speed
    08/Apr/2000 - Dirk Farin
     - first revision
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_SYSTEM_SYNCER_HH
#define DVDVIEW_SYSTEM_SYNCER_HH

#include "system/system1.hh"
#include <sys/time.h>
#include <unistd.h>


class Syncer
{
public:
  virtual ~Syncer() { }

  virtual void Reset() { }
  virtual void WaitUntil(PTS) = 0;
};


class Syncer_AsFastAsPossible : public Syncer
{
public:
  void WaitUntil(PTS) { /* Return immediately without waiting. */ }
};


class Syncer_Realtime : public Syncer
{
public:
  Syncer_Realtime() : d_speed(100) { Reset(); }

  void Reset();
  void WaitUntil(PTS);
  void SetSpeed(int percent) // 100% - real-time / >100% - faster / <100% - slower
  { assert(percent>0); d_speed=percent; } // 100% - real-time / >100% - faster / <100% - slower

private:
  bool d_locked;
  PTS  d_lastpts;
  struct timeval d_lasttime;
  int  d_speed;
};

#endif




More information about the dslinux-commit mailing list