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 = ¤tbuf[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 = ¤tbuf[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( ¤tbuf[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