[PATCH] Rewrite of mpeg/ps2ts.cpp version 2 -- vls-cvs-ps2ts-2.patch
Andrew de Quincey <[email protected]> Tue, 12 Aug 2003 10:35:26 +0100
| Newsgroups | gmane.comp.video.videolan.vls.devel |
|---|---|
| Message-ID | <[email protected]> |
Whoops! forgot part of the patch. This one is the same as version 1, except: tsstreamer.cpp now doesn't call WaitSendDate() the very first time. With the files I'm streaming, this was causing hangs 'cos the first time round, m_iLastTime is 0... so vls ends up sleeping for 57348557347843 seconds.
vls-cvs-ps2ts-2.patch
(text/x-diff, 40.3 KB)
--- vls.orig/src/modules/ps2ts/ps2ts.cpp 2003-08-11 11:15:48.000000000 +0100
+++ vls/src/modules/ps2ts/ps2ts.cpp 2003-08-11 15:11:26.000000000 +0100
@@ -105,7 +105,8 @@
C_MpegConverter(pModule, cConfig),
m_cConverter(cConfig.m_pReader,
cConfig.m_pTsProvider, 2,
- cConfig.m_pBroadcast->GetOption("mpegversion").ToInt())
+ cConfig.m_pBroadcast->GetOption("mpegversion").ToInt(),
+ cConfig.m_pBroadcast->GetOption("loop").ToInt())
{
m_bPreParse = (cConfig.m_pBroadcast->GetOption("preparse") == "1");
@@ -133,14 +134,13 @@
C_MpegConverter::InitWork();
m_cConverter.Synch();
-
if(m_bPreParse)
{
for(unsigned int i = 0; i < m_pReader->Size() / 188 / 256; i++)
{
// preparsing to make the PAT and the PMT
- C_TsPacket* pPacket = m_cConverter.GetPacket();
- ASSERT(pPacket);
+ C_TsPacket* pPacket = m_cConverter.GetPacket(true);
+ if (!pPacket) break;
m_pTsProvider->ReleasePacket(pPacket);
}
@@ -166,8 +166,9 @@
switch(m_cConverter.GetStatus())
{
case 0:
- if(!pPacket)
+ if(!pPacket) {
iRc = MPEG_STREAMERROR;
+ }
break;
case -99:
iRc = MPEG_ENDOFSTREAM;
--- vls.orig/src/modules/filereader/filereader.h 2003-08-11 11:15:48.000000000 +0100
+++ vls/src/modules/filereader/filereader.h 2003-08-11 13:00:04.000000000 +0100
@@ -49,6 +49,7 @@
virtual s64 Seek(s64 iOffset, s64 bStartPos);
virtual s64 Size();
virtual s64 GetPos();
+ virtual void ResetEndOfStream();
protected:
C_File m_cFile;
--- vls.orig/src/modules/filereader/filereader.cpp 2003-08-11 11:15:48.000000000 +0100
+++ vls/src/modules/filereader/filereader.cpp 2003-08-11 16:49:10.000000000 +0100
@@ -80,7 +80,6 @@
m_cFile(pBroadcast->GetOption("filename"))
{
m_iLoop = pBroadcast->GetOption("loop").ToInt();
- if(m_iLoop) m_iLoop--;
if(pBroadcast->GetOption("end") == "1")
m_bEnd = true;
@@ -123,13 +122,13 @@
try
{
s64 iRc = m_cFile.Read(pBuff, iSize);
- // Loop on stream and set the discontinuity flag
- if((iRc == FILE_EOF) && m_iLoop--)
- {
- m_cFile.Seek((s64)0, FILE_SEEK_BEGIN);
- m_bDiscontinuity = true;
- iRc = m_cFile.Read(pBuff, iSize);
+
+ // check for end of stream
+ if ((iRc == FILE_EOF) || (iRc != iSize)) {
+ m_bEndOfStream = true;
+ iRc = 0;
}
+
return iRc;
}
catch(E_File e)
@@ -138,6 +137,15 @@
}
}
+//------------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------------
+void C_FileMpegReader::ResetEndOfStream()
+{
+ m_cFile.Seek((s64)0, FILE_SEEK_BEGIN);
+ m_bDiscontinuity = true;
+ m_bEndOfStream = false;
+}
//------------------------------------------------------------------------------
//
--- vls.orig/src/mpeg/reader.h 2003-08-11 11:15:48.000000000 +0100
+++ vls/src/mpeg/reader.h 2003-08-11 13:44:45.000000000 +0100
@@ -71,6 +71,11 @@
void ResetDiscontinuity()
{ m_bDiscontinuity = false; };
+ virtual bool EndOfStream()
+ { return m_bEndOfStream; };
+ virtual void ResetEndOfStream()
+ { /* By default, this is not supported */ };
+
protected:
C_Module* m_pModule;
@@ -80,6 +85,8 @@
bool m_bDiscontinuity;
+ bool m_bEndOfStream;
+
handle m_hLog;
};
--- vls.orig/src/mpeg/reader.cpp 2003-08-11 11:15:48.000000000 +0100
+++ vls/src/mpeg/reader.cpp 2003-08-11 16:48:55.000000000 +0100
@@ -63,6 +63,7 @@
m_hLog = pModule->GetLogger();
m_bDiscontinuity = false;
+ m_bEndOfStream = false;
}
--- vls.orig/src/mpeg/ps2ts.cpp 2003-03-14 10:32:49.000000000 +0000
+++ vls/src/mpeg/ps2ts.cpp 2003-08-11 16:41:57.000000000 +0100
@@ -6,6 +6,7 @@
*
* Authors: Benoit Steiner <[email protected]>
* Arnaud de Bossoreille de Ribou <[email protected]>
+* Andrew de Quincey <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -50,7 +51,8 @@
template <class Reader, class TsProvider>
C_Ps2Ts<Reader, TsProvider>::C_Ps2Ts(Reader* pReader, TsProvider* pTsProvider,
unsigned int iMaxBufferedTs,
- unsigned int iMpegVersion) :
+ unsigned int iMpegVersion,
+ bool bLooping) :
m_cPgrmDescriptor(iMpegVersion),
m_cPat(0, 0, 0), m_cPmt(0, 0, 0, 0, 0x50),
m_cPendingTS(NO)
@@ -65,20 +67,23 @@
m_iMaxBufferedTs = iMaxBufferedTs;
m_iDataType = UNKNOWN_DATA;
+ m_iPrivateId = 0;
m_iStatus = NO_ERR;
- m_pDelayedPacket = NULL;
m_bDiscontinuity = false;
- ZERO(m_pCurrentData);
-
- m_bSendPSI = m_bGenPat = m_bGenPmt = m_bResetPSI = true;
+ m_bSendPSI = m_bGenPat = m_bGenPmt = true;
m_iTSCounter = 0;
- m_iPrevSCR = 0;
+ m_bNeedToSendPCR = true;
+ m_iNextPCR = 0;
+ m_iPrevPCR = 0;
+ m_bLooping = bLooping;
+ m_bInMiddleOfPES = false;
+ m_bJustSynched = false;
if(iMpegVersion == 1)
- m_iPackHeaderLen = MPEG1_PACK_HEADER_LEN;
+ m_iPackHeaderLen = MPEG1_PACK_HEADER_LEN - START_CODE_LEN;
else
- m_iPackHeaderLen = MPEG2_PACK_HEADER_LEN;
+ m_iPackHeaderLen = MPEG2_PACK_HEADER_LEN - START_CODE_LEN;
}
@@ -89,62 +94,62 @@
C_Ps2Ts<Reader, TsProvider>::~C_Ps2Ts()
{
// The packets belong to the netlist, so don't delete them twice
- for(unsigned int i = 0; i < m_cPendingTS.Size(); i++)
+ while(m_cPendingTS.Size() > 0)
{
C_TsPacket* pPacket = m_cPendingTS.Remove(0);
- ASSERT(pPacket);
+ if (pPacket) {
m_pTsProvider->ReleasePacket(pPacket);
}
+ }
}
//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
-// The data in the buffer can be anything: only rely on DataType and DataLen
+// The data in the buffer can be anything: only rely on DataType
//------------------------------------------------------------------------------
template <class Reader, class TsProvider>
int C_Ps2Ts<Reader, TsProvider>::Synch()
{
- int iRc = m_pReader->Read(m_bBuff, START_CODE_LEN);
- ASSERT(iRc >= 0);
- m_iStatus = (iRc != START_CODE_LEN);
-
- unsigned int iPos = START_CODE_LEN;
-
- // Check the last bytes read to look for a start code
- while((U32_AT(m_bBuff[iPos-START_CODE_LEN]) != PES_H_PACK_HEADER) &&
- !m_iStatus)
- {
- iRc = m_pReader->Read(m_bBuff+iPos, 1);
- ASSERT(iRc >= 0);
- m_iStatus = (iRc != 1);
+ int iRc;
+ u8 headerCode[4];
+ u64 startPos;
+
+ // prefill the headercode
+ startPos = m_pReader->GetPos();
+ if (iRc = ReadData(headerCode, 3)) {
+ m_iStatus = iRc;
+ return m_iStatus;
+ }
- iPos++;
- if(iPos >= sizeof(m_bBuff))
- {
- printf("Looping in Synch !!!!!!!!! (buffer size=%d)\n", sizeof(m_bBuff));
- memcpy(m_bBuff, &m_bBuff[sizeof(m_bBuff)-(START_CODE_LEN-1)],
- (START_CODE_LEN-1));
- iPos = START_CODE_LEN-1;
+ // loop, trying to find a PES_H_PACK_HEADER
+ while(true) {
+ // read the last byte of the headercode
+ if (iRc = ReadData(headerCode+3, 1)) {
+ m_iStatus = iRc;
+ break;
}
+
+ // found it?
+ if (U32_AT(headerCode) == PES_H_PACK_HEADER) {
+ m_bInMiddleOfPES = false;
+ m_bJustSynched = true;
+ m_bNeedToSendPCR = false;
+ m_iNextPCR = 0;
+ m_iPrevPCR = 0;
+ break;
}
- // Check the last bytes read to detect why we left the loop
- if(U32_AT(m_bBuff[iPos-START_CODE_LEN]) != PES_H_PACK_HEADER)
- {
- // We left the while loop because of a read error
+ // OK, move the topmost 3 bytes into position
+ memcpy(headerCode, headerCode+1, 3);
+
+ // just give up if we haven't found one within a reasonable distance
+ if ((m_pReader->GetPos() - startPos) > 1024 * 1024) {
+ printf("Failed to find a PACK_HEADER within 1Mb.\n");
m_iStatus = GEN_ERR;
+ break;
}
- else
- {
- printf("Synchronised with PS stream\n");
- m_iDataType = PES_H_PACK_HEADER;
- iRc = m_pReader->Read(m_bBuff+iPos, PES_SIZE_LEN);
- ASSERT(iRc >= 0);
- m_iStatus = (iRc != PES_SIZE_LEN);
- m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF);
- m_iDataLen = U16_AT(m_bBuff[iPos]);
}
return m_iStatus;
@@ -155,58 +160,44 @@
//
//------------------------------------------------------------------------------
template <class Reader, class TsProvider>
- C_TsPacket* C_Ps2Ts<Reader, TsProvider>::GetPacket()
+ C_TsPacket* C_Ps2Ts<Reader, TsProvider>::GetPacket(bool bPreparsing)
{
- if(m_cPendingTS.Size() == 0)
- {
- if(!m_bSendPSI)
- {
- if(m_pDelayedPacket)
- {
- m_cPendingTS.PushEnd(m_pDelayedPacket);
- m_pDelayedPacket = NULL;
- }
- else
- {
- int iRc = FetchPackets();
- if(iRc && !m_bSendPSI)
- {
- do
- {
- if(iRc == UNKNOWN_DATA)
- {
- iRc = Synch();
- if(!iRc)
- iRc = FetchPackets();
- }
- else if(iRc == SKIPPED_DATA)
- iRc = FetchPackets();
- }
- while((iRc == SKIPPED_DATA || iRc == UNKNOWN_DATA) && !m_bSendPSI);
- }
- else if(!m_bSendPSI)
- {
- // Check if we will have to insert PSI on the next iteration: we
- // add the PSI in the stream every half second
- // (For 1.5 Mbps streams, about 1000 TS packets are sent every second)
- m_bSendPSI = m_bResetPSI = (m_iTSCounter % 500 <= m_iMaxBufferedTs);
-// printf("mitscounter: %d\n", m_iTSCounter);
+ int iRc;
+ bool bStreamLooped = false;
+
+ // if there's nothing left in the buffer. we need to fill it
+ if (m_cPendingTS.Size() == 0) {
+
+ // keep looping until the buffer is full
+ while((m_cPendingTS.Size() < m_iMaxBufferedTs) && (!bStreamLooped)) {
+
+ // If we're not already sending PSI, check if we need to send it again
+ if ((!m_bSendPSI) && (!bPreparsing)) {
+ // check if resend interval is up
+ if (m_bSendPSI = (m_iTSCounter % 500 <= m_iMaxBufferedTs)) {
+ m_cPat.TsReset();
+ m_cPmt.TsReset();
}
+
+ // check if a new PMT has appeared
+ if (m_cPgrmDescriptor.m_bNewPmt) {
+ m_bSendPSI = true;
+ m_bGenPmt = true;
+ m_cPgrmDescriptor.m_bNewPmt = false;
}
}
- if(m_bSendPSI)
- {
- if(m_bGenPat)
- {
+ // Send PSI packets if necessary
+ if ((m_bSendPSI) && (!bPreparsing)) {
+ // first of all regenerate any of the PSI information necessary
+ if(m_bGenPat) {
*m_cPat.GetLowLevelPat() = m_cPgrmDescriptor.m_sPat;
m_cPat.Generate();
m_cPat.GetLowLevelPat()->p_first_program = NULL;
m_bGenPat = false;
+ m_cPat.TsReset();
}
-
- if(m_bGenPmt)
- {
+ if(m_bGenPmt) {
m_cPgrmDescriptor.m_sPmt.i_version =
(m_cPgrmDescriptor.m_sPmt.i_version + 1) & 0x1f;
*m_cPmt.GetLowLevelPmt() = m_cPgrmDescriptor.m_sPmt;
@@ -214,50 +205,85 @@
m_cPmt.GetLowLevelPmt()->p_first_es = NULL;
m_cPmt.GetLowLevelPmt()->p_first_descriptor = NULL;
m_bGenPmt = false;
- }
-
- if(m_bResetPSI)
- {
- m_cPat.TsReset();
m_cPmt.TsReset();
- m_bResetPSI = false;
}
- for(unsigned int i = m_cPendingTS.Size(); i < m_iMaxBufferedTs; i++)
- {
+ // output PSI information as necessary
+ if (m_cPat.TsHasNext()) {
C_TsPacket* pPacket = m_pTsProvider->GetPacket();
- ASSERT(pPacket);
+ if (pPacket == NULL) {
+ m_iStatus = GEN_ERR;
+ break;
+ }
- if(m_cPat.TsHasNext())
- {
m_cPat.TsWrite(pPacket);
m_cPendingTS.PushEnd(pPacket);
m_iTSCounter++;
+ } else if (m_cPmt.TsHasNext()) {
+ C_TsPacket* pPacket = m_pTsProvider->GetPacket();
+ if (pPacket == NULL) {
+ m_iStatus = GEN_ERR;
+ break;
}
- else if(m_cPmt.TsHasNext())
- {
+
m_cPmt.TsWrite(pPacket);
m_cPendingTS.PushEnd(pPacket);
m_iTSCounter++;
- }
- else
- {
+ } else {
+ // we've finished sending PSI for this time
m_bSendPSI = false;
- m_pTsProvider->ReleasePacket(pPacket);
- if(m_pDelayedPacket)
- {
- m_cPendingTS.PushEnd(m_pDelayedPacket);
- m_pDelayedPacket = NULL;
}
}
- if(!m_cPat.TsHasNext() && !m_cPmt.TsHasNext())
- m_bSendPSI = false;
+
+ // not sending PSI => grab some REAL data packets
+ if ((!m_bSendPSI) || (bPreparsing)) {
+ // fetch some packets
+ if (iRc = FetchPackets(bPreparsing)) {
+ // special handling for some return codes
+ switch(iRc) {
+ case UNKNOWN_DATA:
+ iRc = Synch();
+ break;
+
+ case SKIPPED_DATA:
+ iRc = 0;
+ break;
+
+ case END_OF_STREAM:
+ if (m_bLooping) {
+ // try and reset the stream
+ m_pReader->ResetEndOfStream();
+
+ // if that failed, the reader must not support
+ // resetting the end of stream. We have to stop.
+ if (m_pReader->EndOfStream()) {
+ break;
}
+
+ // OK, synch with the stream again
+ iRc = Synch();
+ m_bSendPSI = true;
+ m_bGenPat = true;
+ m_bGenPmt = true;
+ bStreamLooped = true;
}
+ break;
}
- ASSERT(m_cPendingTS.Size() > 0);
- ASSERT(m_cPendingTS.Size() <= m_iMaxBufferedTs);
+ // OK, was there really a problem?
+ if (iRc) {
+ m_iStatus = iRc;
+ break;
+ }
+ }
+
+ // if we're preparsing, exit as soon as we have one packet
+ if (bPreparsing && m_cPendingTS.Size()) {
+ break;
+ }
+ }
+ }
+ }
// Return the first packet
if(m_cPendingTS.Size() > 0)
@@ -271,83 +297,58 @@
//
//------------------------------------------------------------------------------
template <class Reader, class TsProvider>
- int C_Ps2Ts<Reader, TsProvider>::FetchPackets()
+ int C_Ps2Ts<Reader, TsProvider>::FetchPackets(bool bPreparsing)
{
- ASSERT(!m_iStatus || m_iStatus == SKIPPED_DATA || m_iStatus == UNKNOWN_DATA);
-
- u8 iPosInTs = 0;
- C_TsPacket* pPacket = m_pTsProvider->GetPacket();
- ASSERT(pPacket);
-
- // Handle the pack header if any at the current position in the stream
- if(m_iDataType == PES_H_PACK_HEADER)
- {
- m_iStatus = ParsePackHeader(pPacket, &iPosInTs);
+ int iRc;
- // There also can be a system header following the pack header
- if(m_iDataType == PES_H_SYSTEM_HEADER && !m_iStatus)
- {
- m_iStatus = ParseSystemHeader(pPacket, &iPosInTs);
+ // if we're in the middle of parsing a PES packet,
+ // just do that immediately with no further ado
+ if (m_bInMiddleOfPES) {
+ return ParsePES(bPreparsing);
}
- // Leave now if something wrong occured
- if(m_iStatus != NO_ERR)
- return GEN_ERR;
+ // attempt to read in the start code/ data type
+ if (!m_bJustSynched) {
+ if (iRc = ReadData(m_bBuff, START_CODE_LEN)) {
+ return iRc;
}
-
- // No we must have reached the beginning of a PES packet or the end of
- // the stream
- if(IsDataPesHeader(m_iDataType))
- {
- // This is a data PES
- m_iStatus = ParsePES(pPacket, &iPosInTs);
+ m_iDataType = U32_AT(m_bBuff);
+ } else {
+ // if we've just synched we _know_ we're just after a
+ // PACK_HEADER start code.
+ m_bJustSynched = false;
+ return ParsePackHeader(bPreparsing);
}
- else
- {
- // This is a control PES
- switch(m_iDataType)
- {
+
+ // OK, process the packet
+ switch(m_iDataType) {
+ case PES_H_PACK_HEADER:
+ return ParsePackHeader(bPreparsing);
+
+ case PES_H_SYSTEM_HEADER:
+ return ParseSystemHeader();
+
case PES_H_PADDING:
- {
-// printf("Padding pes encountered\n");
- //m_iStatus = ParsePadding(pPacket, &iPosInTs);
- m_iStatus = ParsePES(pPacket, &iPosInTs);
- break;
- }
+ return ParsePES(bPreparsing);
+
case PES_H_PGRM_MAP:
- {
-// printf("Program map pes encountered\n");
- m_iStatus = ParsePgrmMap(pPacket, &iPosInTs);
- // A foutre dans parse pgrm_map_pes quand le pes est completement fini
- m_bSendPSI = m_bResetPSI = true;
- break;
- }
case PES_H_PRIVATE_2:
case PES_H_PGRM_DIR:
- {
- // Not interessting -> Trash
-// printf("not interesting pes encountered -> trash \n");
- m_iStatus = SkipPES(pPacket, &iPosInTs);
- break;
- }
+ return SkipPES();
+
case PES_H_END_OF_PS:
- {
- // Just return NULL
-// printf("end of ps encountered\n");
- m_pTsProvider->ReleasePacket(pPacket);
- m_iStatus = END_OF_STREAM;
- break;
- }
+ return END_OF_STREAM;
+
default:
- {
-// printf("unknown packet (%x) encoutered\n", m_iDataType);
- m_pTsProvider->ReleasePacket(pPacket);
- m_iStatus = UNKNOWN_DATA;
- }
+ if (IsDataPesHeader(m_iDataType)) {
+ return ParsePES(bPreparsing);
+ } else {
+ return UNKNOWN_DATA;
}
}
- return m_iStatus;
+ // should never get here
+ return GEN_ERR;
}
@@ -355,88 +356,62 @@
//
//------------------------------------------------------------------------------
template <class Reader, class TsProvider>
- int C_Ps2Ts<Reader, TsProvider>::ParsePackHeader(C_TsPacket* pPacket, u8* pPosInTs)
+ int C_Ps2Ts<Reader, TsProvider>::ParsePackHeader(bool bPreparsing)
{
- ASSERT(pPacket);
-
-// printf("Parsing PACK_HEADER\n");
+ int iRc;
- int iRc = m_pReader->Read(m_bBuff+LOOK_AHEAD_LEN, m_iPackHeaderLen);
- ASSERT(iRc >= 0);
- iRc = (iRc != m_iPackHeaderLen);
+ // try to read in the data for the pack header
+ if (iRc = ReadData(m_bBuff, m_iPackHeaderLen)) {
+ return iRc;
+ }
- // No stuffing by default
- u8 iStuffLen = 0;
+ // don't bother doing anything more if we're preparsing
+ if (bPreparsing) {
+ return iRc;
+ }
if(m_iPackHeaderLen == MPEG1_PACK_HEADER_LEN)
{
// Parse the SCR (MPEG1 format)
- u64 iHighBits = m_bBuff[START_CODE_LEN] & 0x0E;
- u64 iMiddleBits = U16_AT(m_bBuff[START_CODE_LEN+1]) & 0xFFFE;
- u64 iLowBits = U16_AT(m_bBuff[START_CODE_LEN+3]) & 0xFFFE;
- ASSERT((m_bBuff[START_CODE_LEN] & 0x01));
- ASSERT((m_bBuff[START_CODE_LEN+2] & 0x01));
- ASSERT((m_bBuff[START_CODE_LEN+4] & 0x01));
-
- u64 iSCR = iHighBits << 29 | iMiddleBits << 14 | iLowBits >> 1;
-// printf("Date mpeg1: %Ld\n", iSCR);
-
- // Build the TS header to put this date
- *pPosInTs = pPacket->BuildAdaptionField(iSCR);
+ u64 iHighBits = m_bBuff[0] & 0x0E;
+ u64 iMiddleBits = U16_AT(m_bBuff[1]) & 0xFFFE;
+ u64 iLowBits = U16_AT(m_bBuff[3]) & 0xFFFE;
+ ASSERT((m_bBuff[0] & 0x01));
+ ASSERT((m_bBuff[2] & 0x01));
+ ASSERT((m_bBuff[4] & 0x01));
+
+ // store it for when we need to output it
+ m_iNextPCR = iHighBits << 29 | iMiddleBits << 14 | iLowBits >> 1;
+ m_bNeedToSendPCR = true;
}
else
{
// Parse the SCR (MPEG2 format)
- u64 iHighBits = m_bBuff[START_CODE_LEN] & 0x38;
- u64 iMiddleBits = U32_AT(m_bBuff[START_CODE_LEN]) & 0x03FFF800;
- u64 iLowBits = U32_AT(m_bBuff[START_CODE_LEN+2]) & 0x03FFF800;
- ASSERT((m_bBuff[START_CODE_LEN] & 0x4));
- ASSERT((m_bBuff[START_CODE_LEN+2] & 0x4));
- ASSERT((m_bBuff[START_CODE_LEN+4] & 0x4));
-
- u64 iSCR = iHighBits << 27 | iMiddleBits << 4 | iLowBits >> 11;
-
- // Kludge pour tester horloge
-// struct timeval sTimeval;
-// gettimeofday(&sTimeval, NULL);
-// printf("Date mpeg2: %Ld, date systeme %d (en s)\n", iSCR, sTimeval.tv_sec);
-
- // Build the TS header to put this date
- *pPosInTs = pPacket->BuildAdaptionField(iSCR);
-
-// if(iSCR - m_iPrevSCR > 800)
-// printf("time : %Ld ; delta : %Ld\n", iSCR, iSCR - m_iPrevSCR);
- if(m_iPrevSCR >= iSCR)
- {
- printf("Time discontinuity in PS stream\n");
- m_bDiscontinuity = true;
+ u64 iHighBits = m_bBuff[0] & 0x38;
+ u64 iMiddleBits = U32_AT(m_bBuff[0]) & 0x03FFF800;
+ u64 iLowBits = U32_AT(m_bBuff[2]) & 0x03FFF800;
+ ASSERT((m_bBuff[0] & 0x4));
+ ASSERT((m_bBuff[2] & 0x4));
+ ASSERT((m_bBuff[4] & 0x4));
+
+ // store it for when we need to output it
+ m_iNextPCR = iHighBits << 27 | iMiddleBits << 4 | iLowBits >> 11;
+ m_bNeedToSendPCR = true;
+
+ // Read additional stuffing bytes if any
+ int iStuffLen = m_bBuff[m_iPackHeaderLen-1] & 0x7;
+ if (iStuffLen) {
+ iRc = SkipData(iStuffLen);
}
- m_iPrevSCR = iSCR;
-
- // Read additional stuffing bytes if any (MPEG2 only)
- if(m_iPackHeaderLen == 10 + START_CODE_LEN)
- {
- iStuffLen = m_bBuff[m_iPackHeaderLen-1] & 0x7;
- if(iStuffLen && !iRc)
- {
- iRc = m_pReader->Read(m_bBuff+LOOK_AHEAD_LEN+m_iPackHeaderLen, iStuffLen);
- ASSERT(iRc >= 0);
- iRc = (iRc != iStuffLen);
}
-// printf("Stuffing of size %d found: actual length is: %d\n", iStuffLen, m_iPackHeaderLen+iStuffLen);
- }
+ // check for discontinuity
+ if (m_iPrevPCR >= m_iNextPCR) {
+ m_bDiscontinuity = true;
}
+ m_iPrevPCR = m_iNextPCR;
- // Look Ahead of 6
- m_iDataType = U32_AT(m_bBuff[m_iPackHeaderLen+iStuffLen]);
- m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF);
- m_iDataLen = U16_AT(m_bBuff[m_iPackHeaderLen+iStuffLen+START_CODE_LEN]);
- m_bPESStart = true;
-
- //printf("Next data will be: %X (len: %d)\n", m_iNextData, m_iNextLength);
-// printf("Next data will be: %X (len: %d)\n", m_iDataType, m_iDataLen);
-
+ // finished
return iRc;
}
@@ -445,21 +420,17 @@
//
//------------------------------------------------------------------------------
template <class Reader, class TsProvider>
- int C_Ps2Ts<Reader, TsProvider>::ParseSystemHeader(C_TsPacket* pPacket, u8* iPosInTs)
+ int C_Ps2Ts<Reader, TsProvider>::ParseSystemHeader()
{
-// printf("Parsing SYSTEM_HEADER\n");
-
- int iRc = m_pReader->Read(m_bBuff, m_iDataLen+LOOK_AHEAD_LEN);
- ASSERT(iRc >= 0);
- iRc = (iRc != m_iDataLen+LOOK_AHEAD_LEN);
-
-// printf("Length: %d\n", m_iDataLen);
-
- m_iDataType = U32_AT(m_bBuff[m_iDataLen]);
- m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF);
- m_iDataLen = U16_AT(m_bBuff[m_iDataLen+START_CODE_LEN]);
+ int iRc;
+ // read size of the system header
+ if (iRc = ReadDataLength(&m_iDataLen)) {
return iRc;
+ }
+
+ // skip the data
+ return SkipData(m_iDataLen);
}
@@ -467,242 +438,170 @@
//
//------------------------------------------------------------------------------
template <class Reader, class TsProvider>
- int C_Ps2Ts<Reader, TsProvider>::ParsePES(C_TsPacket* pPacket, u8* pPosInTs)
+ int C_Ps2Ts<Reader, TsProvider>::ParsePES(bool bPreparsing)
{
- ASSERT(pPacket);
- ASSERT(pPosInTs);
-
- // Pour le debug uniquement
-// if(m_bPESStart)
-// {
-// printf("Parsing PES of type %x\n", m_iDataType);
-// printf("PES Length: %d (without the 6 first bytes)\n", m_iDataLen);
-// }
-// else
-// printf("Continuing to parse PES (remaining length: %d)\n", m_iDataLen);
-
-
- // This variable only exists to speed up the process of looking the value of
- // pPosInTs
- u8 iPos;
-
- // Write the data in the TS that depends on our position in the PES
- if(m_bPESStart)
- {
- // Write the header with the bUnitStart flag set to true
- ASSERT(m_pCurrentData);
- ASSERT(m_pCurrentData->GetId() == (m_iDataType&0xFF));
- u8 iCounter = m_pCurrentData->GetCounter();
- u16 iPid = m_pCurrentData->GetPid();
- iPos = pPacket->BuildHeader(iPid, true, iCounter);
+ int iPos = 0;
+ int iPesPos = 0;
+ int iRc;
+
+ // read size of the PES packet
+ if (!m_bInMiddleOfPES) {
+ if (iRc = ReadDataLength(&m_iDataLen)) {
+ return iRc;
+ }
+ }
- // We can have parsed an adaption field if the PES comes just after a
- // pack header
- if(iPos < *pPosInTs)
- {
- if(iPid == m_cPgrmDescriptor.GetPcrPid())
- {
- // The adaption_field_control has been overwritten so that the bit
- // which indicates an adaption_field is no more set to 1
- byte* pTsPayload = (byte*)(*pPacket);
- pTsPayload[iPos-1] |= 0x20;
+ // Extract the current TS descriptor.
+ C_ElementDescriptor* curDesc;
+ if ((m_iDataType & 0xff) != PES_ID_PRIVATE_1) {
+ curDesc = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF);
+ } else {
+ // Is an encapsulated MPEG1 stream.. special handling needed
+ // if we're at the start of a PES packet, read (and cache) the
+ // header and find the MPEG1 stream ID
+ if (!m_bInMiddleOfPES) {
+ // read in the start of the PES header
+ if (iRc = ReadData(m_bCache, 3)) {
+ return iRc;
+ }
+ m_iCacheLen = 3;
- // Set the right position
- iPos = *pPosInTs;
- if(m_bDiscontinuity)
- {
- ASSERT(pPacket->HasPCR());
- ASSERT(pPacket->SetDiscontinuityFlag());
- pPacket->SetDiscontinuityFlag();
- m_bDiscontinuity = false;
+ // read in the rest of the PES header
+ if (iRc = ReadData(m_bCache + m_iCacheLen, m_bCache[2])) {
+ return iRc;
}
+ m_iCacheLen += m_bCache[2];
+
+ // read in the start of the MPEG1 header
+ u8* mpeg1Header = m_bCache + m_iCacheLen;
+ if (iRc = ReadData(m_bCache + m_iCacheLen, 4)) {
+ return iRc;
}
+ m_iCacheLen += 4;
+
+ // finally, grab the mpeg1 header stream id
+ m_iPrivateId = mpeg1Header[3];
}
- // Write the beginning of the PES packet (corresponds to the look ahead)
- byte* pTsPayload = (byte*)(*pPacket);
- SET_U32_TO(pTsPayload[iPos], m_iDataType);
- SET_U16_TO(pTsPayload[iPos+START_CODE_LEN], m_iDataLen);
- iPos += START_CODE_LEN + PES_SIZE_LEN;
+ // get the descriptor taking into account the MPEG1 stream id
+ curDesc = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF, m_iPrivateId);
}
- else
- {
- // We shouldn't have any adaption field
- ASSERT(*pPosInTs == 0);
- // Write the header with the bUnitStart flag set to false
- ASSERT(m_pCurrentData);
- ASSERT(m_pCurrentData->GetId() == (m_iDataType&0xFF));
- u8 iCounter = m_pCurrentData->GetCounter();
- u16 iPid = m_pCurrentData->GetPid();
- iPos = pPacket->BuildHeader(iPid, false, iCounter);
+ // process the PES data
+ while((m_iDataLen > 0) && (m_cPendingTS.Size() < m_iMaxBufferedTs)) {
+ // check if a new PMT has appeared. If so, just exit this loop.
+ // The caller will take care of generating it and possibly calling us
+ // again to add in more PES data
+ if ((!bPreparsing) && (m_cPgrmDescriptor.m_bNewPmt)) {
+ break;
}
+ // Grab a new TS packet to use
+ C_TsPacket* pPacket = m_pTsProvider->GetPacket();
- // Now read the data carried in the PES
- for(unsigned int i = 0; i < m_iMaxBufferedTs; i++)
- {
- // Fill the Ts packet
- if(m_iDataLen >= TS_PACKET_LEN - iPos)
- {
- // Fill the remaining payload of the TS packet
- m_iStatus = m_pReader->Read(((byte*)(*pPacket)+iPos), TS_PACKET_LEN-iPos);
- ASSERT(m_iStatus >= 0);
- m_iStatus = (m_iStatus != TS_PACKET_LEN-iPos);
+ // build the start of the TS packet
+ if(!m_bInMiddleOfPES) { // we're at the start of the PES packet
+ // build the header
+ u16 iPid = curDesc->GetPid();
+ u8 iCounter = curDesc->GetCounter();
+ iPos = pPacket->BuildHeader(iPid, true, iCounter);
- m_iDataLen -= (TS_PACKET_LEN-iPos);
+ // if we need to send the PCR, and we're sending a packet for the stream
+ // which contains the PCR, do it!
+ if ((m_bNeedToSendPCR) && (iPid == m_cPgrmDescriptor.GetPcrPid())) {
+ // build the adaptation field
+ iPos = pPacket->BuildAdaptionField(m_iNextPCR);
+ m_bNeedToSendPCR = false;
- //-----------------
- if(m_bPESStart)
- {
- if(*((byte*)(*pPacket) + iPos - 3) == PES_ID_PRIVATE_1)
- {
-// printf("Id : 0x%x", *((byte*)(*pPacket) + iPos - 3));
- u8 iOffset = *((byte*)(*pPacket) + iPos + 2);
-// printf(" Offset : 0x%x", iOffset);
- u8 iPrivateId = *((byte*)(*pPacket) + iPos + 3 + iOffset);
-// printf(" PrivateId : 0x%x", iPrivateId);
-/* if((iPrivateId & 0xf0) == 0x80)
- {*/
- m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF,
- iPrivateId);
- u16 iPid = m_pCurrentData->GetPid();
- u16 iData = U16_AT(*((byte*)(pPacket) + 1));
-// printf(" Data : 0x%x", iData);
- iPid = (iPid & 0x1fff) | (iData & 0xe000);
-// printf(" NewPid : 0x%x", iPid);
- SET_U16_TO(*((byte*)(pPacket) + 1), iPid);
- *((byte*)(pPacket) + 3) = (m_pCurrentData->GetCounter() & 0x0f) |
- (*((byte*)(pPacket) + 3) & 0xf0);
-/* }*/
-// printf("\n");
- }
+ // handle any discontinuity
+ if(m_bDiscontinuity) {
+ pPacket->SetDiscontinuityFlag();
+ m_bDiscontinuity = false;
}
- //-----------------
}
- else
- {
- // m_iDataLen shouldn't be null
- ASSERT(m_iDataLen > 0);
-// printf("Stuffing needed: iPos=%d, DataLen=%d\n", iPos, m_iDataLen);
+ // write the beginning of the PES packet (since we've already read it)
+ byte* pTsPayload = (byte*)(*pPacket);
+ SET_U32_TO(pTsPayload[iPos], m_iDataType);
+ SET_U16_TO(pTsPayload[iPos+START_CODE_LEN], m_iDataLen);
+ iPesPos = START_CODE_LEN + PES_SIZE_LEN;
+ iPos += iPesPos;
+ } else {
+ // somewhere in the middle of a PES packet
+ u16 iPid = curDesc->GetPid();
+ u8 iCounter = curDesc->GetCounter();
+ iPos = pPacket->BuildHeader(iPid, false, iCounter);
+ iPesPos = 0;
+ }
- // Write the end of the PES packet in the TS packet
+ // calculate how much data we can send
+ int readSize = TS_PACKET_LEN - iPos;
- if(m_bPESStart)
- {
- // We have already written the PES start code and the pes length at the
- // beginning of the TS packet, which will be erased by the stuffing bytes:
- // we must rewrite them
- iPos = pPacket->AddStuffingBytes(m_iDataLen+START_CODE_LEN+PES_SIZE_LEN);
+ // If there is not enough data to completely fill the TS packet,
+ // add stuffing bytes
+ if((m_iDataLen+iPesPos) < readSize) {
+ // add enough stuffing bytes
+ iPos = pPacket->AddStuffingBytes(m_iDataLen+iPesPos);
+ readSize = m_iDataLen;
+
+ // if we're at the start of a PES packet,
+ // we'll need to rewrite the start of it again as it has moved
+ if (!m_bInMiddleOfPES) {
byte* pTsPayload = (byte*)(*pPacket);
SET_U32_TO(pTsPayload[iPos], m_iDataType);
SET_U16_TO(pTsPayload[iPos+START_CODE_LEN], m_iDataLen);
- iPos += START_CODE_LEN+PES_SIZE_LEN;
+ iPos += START_CODE_LEN + PES_SIZE_LEN;
}
- else
- {
- // Simply add the stuffing bytes at the end of the TS header
- iPos = pPacket->AddStuffingBytes(m_iDataLen);
}
- m_iStatus = m_pReader->Read(((byte*)(*pPacket)+iPos), m_iDataLen);
- ASSERT(m_iStatus >= 0);
- m_iStatus = (m_iStatus != m_iDataLen);
-
- //-----------------
- if(m_bPESStart)
- {
- if(*((byte*)(*pPacket) + iPos - 3) == PES_ID_PRIVATE_1)
- {
-// printf("Id : 0x%x", *((byte*)(*pPacket) + iPos - 3));
- u8 iOffset = *((byte*)(*pPacket) + iPos + 2);
-// printf(" Offset : 0x%x", iOffset);
- u8 iPrivateId = *((byte*)(*pPacket) + iPos + 3 + iOffset);
-// printf(" PrivateId : 0x%x", iPrivateId);
-/* if((iPrivateId & 0xf0) == 0x80)
- {*/
- m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF,
- iPrivateId);
- u16 iPid = m_pCurrentData->GetPid();
- u16 iData = U16_AT(*((byte*)(pPacket) + 1));
-// printf(" Data : 0x%x", iData);
- iPid = (iPid & 0x1fff) | (iData & 0xe000);
-// printf(" NewPid : 0x%x", iPid);
- SET_U16_TO(*((byte*)(pPacket) + 1), iPid);
- *((byte*)(pPacket) + 3) = (m_pCurrentData->GetCounter() & 0x0f) |
- (*((byte*)(pPacket) + 3) & 0xf0);
-/* }*/
-// printf("\n");
- }
- }
- //-----------------
-
- // All data have been read
- m_iDataLen = 0;
+ // first of all copy any data we've cached across
+ if (m_iCacheLen) {
+ // work out how much to read from the cache
+ int cacheReadSize = m_iCacheLen;
+ if (cacheReadSize > readSize) {
+ cacheReadSize = readSize;
+ }
+
+ // copy it across and update
+ memcpy(((byte*)(*pPacket)+iPos), m_bCache, cacheReadSize);
+ readSize -= cacheReadSize;
+ iPos += cacheReadSize;
+ m_iDataLen -= cacheReadSize;
+ m_iCacheLen -= cacheReadSize;
+ }
+
+ // OK, read the data from the stream into the TS packet
+ if (readSize) {
+ if (iRc = ReadData(((byte*)(*pPacket)+iPos), readSize)) {
+ m_pTsProvider->ReleasePacket(pPacket);
+ return iRc;
}
-
- // We are no more at the beginning of the PES yet
- m_bPESStart = false;
-
- // Increase the number of TS packets that have been build
- m_pCurrentData->IncreaseCounter();
- m_iTSCounter++;
-
- if(m_cPgrmDescriptor.m_bNewPmt)
- {
- // Delay this packet to send PSI first
- ASSERT(!m_pDelayedPacket);
- m_pDelayedPacket = pPacket;
- m_bSendPSI = m_bGenPmt = m_bResetPSI = true;
- m_cPgrmDescriptor.m_bNewPmt = false;
- i = m_iMaxBufferedTs - 1;
+ m_iDataLen -= readSize;
}
- else
- {
+
// Put the TS packet in the list of pending TS
m_cPendingTS.PushEnd(pPacket);
- }
- ZERO(pPacket);
- // Prepare the next iteration if we must loop
- if(m_iDataLen > 0)
- {
- // There is a second condition for looping since we don't read
- // the complete PES in a single operation
- if(i < m_iMaxBufferedTs - 1)
- {
- // Get another TS packet to fill
- pPacket = m_pTsProvider->GetPacket();
- ASSERT(pPacket);
-
- // Build the new TS header
- ASSERT(m_pCurrentData);
- ASSERT(m_pCurrentData->GetId() == (m_iDataType&0xFF));
- u8 iCounter = m_pCurrentData->GetCounter();
- u16 iPid = m_pCurrentData->GetPid();
- iPos = pPacket->BuildHeader(iPid, false, iCounter);
- }
+ // Update TS counters
+ if (!bPreparsing) {
+ curDesc->IncreaseCounter();
+ m_iTSCounter++;
}
- else
- {
- // Look ahead for next iteration
- m_iStatus = m_pReader->Read(m_bBuff, LOOK_AHEAD_LEN);
- ASSERT(m_iStatus >= 0);
- m_iStatus = (m_iStatus != LOOK_AHEAD_LEN);
- m_iDataType = U32_AT(m_bBuff[0]);
- m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF);
- m_iDataLen = U16_AT(m_bBuff[4]);
- m_bPESStart = true;
-// printf("Next data will be: %x (len = %d)\n", m_iDataType, m_iDataLen);
+ // Update the flag to show we're in the middle of a PES packet
+ m_bInMiddleOfPES = true;
- // Don't loop
- break;
+ // if we're preparsing, we only ever deal with one packet at a time
+ if (bPreparsing) break;
}
+
+ // if we're NOT still in the middle of a PES, clear the flag
+ if (!m_iDataLen) {
+ m_bInMiddleOfPES = false;
}
- return m_iStatus;
+ // if we get here, there isn't a problem
+ return NO_ERR;
}
@@ -710,54 +609,66 @@
//
//------------------------------------------------------------------------------
template <class Reader, class TsProvider>
- int C_Ps2Ts<Reader, TsProvider>::SkipPES(C_TsPacket* pPacket, u8* iPosInTs)
+ int C_Ps2Ts<Reader, TsProvider>::SkipPES()
{
- // Release the TS packet, we won't need it
- m_pTsProvider->ReleasePacket(pPacket);
+ int iRc;
- int iRc = m_pReader->Seek(m_iDataLen, SEEK_CUR);
- if(iRc)
- m_iStatus = FILE_ERR;
- else
- {
- // Look ahead for next iteration
- m_iStatus = m_pReader->Read(m_bBuff, LOOK_AHEAD_LEN);
- ASSERT(m_iStatus >= 0);
- m_iStatus = (m_iStatus != LOOK_AHEAD_LEN);
- m_iDataType = U32_AT(m_bBuff[0]);
- m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF);
- m_iDataLen = U16_AT(m_bBuff[4]);
- m_bPESStart = true;
-// printf("Next data will be: %x (len = %d)\n", m_iDataType, m_iDataLen);
-
- if(m_iStatus == NO_ERR)
- m_iStatus = SKIPPED_DATA;
+ // read size of the PS packet
+ if (iRc = ReadDataLength(&m_iDataLen)) {
+ return iRc;
}
- return m_iStatus;
+ // skip it
+ return SkipData(m_iDataLen);
}
-//------------------------------------------------------------------------------
-//
-//------------------------------------------------------------------------------
template <class Reader, class TsProvider>
- int C_Ps2Ts<Reader, TsProvider>::ParsePgrmMap(C_TsPacket* pPacket, u8* iPosInTs)
+ int C_Ps2Ts<Reader, TsProvider>::ReadData(u8* buf, int length)
{
-// printf("Parsing pgrm map PES: WARNING, code never tested\n");
+ int iRc;
-// printf("Pgrm map length: %d\n", m_iDataLen);
+ // try to read the data
+ iRc = m_pReader->Read(buf, length);
+ if (iRc < 0) return iRc;
- ASSERT(false);
+ // check for lack of data
+ if (m_pReader->EndOfStream()) return END_OF_STREAM;
- while(m_iDataLen >= sizeof(m_bBuff))
- {
-/* int iRc = */m_pReader->Read(m_bBuff, sizeof(m_bBuff));
- m_iDataLen -= sizeof(m_bBuff);
- }
+ // success
+ return 0;
+}
- // push PAT et PMT dans la liste des pendingpackets
- return NO_ERR;
+template <class Reader, class TsProvider>
+ int C_Ps2Ts<Reader, TsProvider>::SkipData(int length)
+{
+ int iRc;
+
+ // try to skip
+ iRc = m_pReader->Seek(length, FILE_SEEK_CURRENT);
+ if (iRc < 0) return iRc;
+
+ // check for lack of data
+ if (m_pReader->EndOfStream()) return END_OF_STREAM;
+
+ // success
+ return 0;
}
+template <class Reader, class TsProvider>
+ int C_Ps2Ts<Reader, TsProvider>::ReadDataLength(u16* lengthDest)
+{
+ int iRc;
+ u8 buf[2];
+ // try to skip
+ iRc = m_pReader->Read(buf, 2);
+ if (iRc < 0) return iRc;
+ *lengthDest = U16_AT(buf);
+
+ // check for lack of data
+ if (m_pReader->EndOfStream()) return END_OF_STREAM;
+
+ // success
+ return 0;
+}
--- vls.orig/src/mpeg/ps2ts.h 2002-05-14 23:10:08.000000000 +0100
+++ vls/src/mpeg/ps2ts.h 2003-08-11 15:38:04.000000000 +0100
@@ -37,29 +37,31 @@
{
public:
C_Ps2Ts(Reader* pReader, TsProvider* pTsProvider, unsigned int iMaxBufferedTs,
- unsigned int iMpegVersion);
+ unsigned int iMpegVersion, bool bLooping);
~C_Ps2Ts();
// Find the first pack header in the stream
int Synch();
//
- C_TsPacket* GetPacket();
+ C_TsPacket* GetPacket(bool bPreparsing = false);
+
// To check whenever GetPacket returns NULL
int GetStatus() { return m_iStatus; };
C_ProgramDescriptor* GetPgrmDescriptor() { return &m_cPgrmDescriptor; };
protected:
- int FetchPackets();
-
- int ParsePackHeader(C_TsPacket* pPacket, u8* iPosInTs);
- int ParseSystemHeader(C_TsPacket* pPacket, u8* iPosInTs);
- int ParsePrivate1Header(C_TsPacket* pPacket, u8* iPosInTs);
- int ParsePES(C_TsPacket* pPacket, u8* iPosInTs);
- int ParsePgrmMap(C_TsPacket* pPacket, u8* iPosInTs);
+ int FetchPackets(bool bPreparsing);
- int SkipPES(C_TsPacket* pPacket, u8* iPosInTs);
+ int ParsePackHeader(bool bPreparsing);
+ int ParseSystemHeader();
+ int ParsePES(bool bPreparsing);
+ int SkipPES();
+
+ int ReadData(u8* buf, int length);
+ int SkipData(int length);
+ int ReadDataLength(u16* lengthDest);
private:
Reader* m_pReader;
@@ -72,8 +74,10 @@
// Parser state
u32 m_iDataType;
u16 m_iDataLen;
+ u8 m_iPrivateId;
bool m_bPESStart;
byte m_bBuff[TS_PACKET_LEN];
+ bool m_bJustSynched;
// Output state
u32 m_iTSCounter;
@@ -81,7 +85,6 @@
bool m_bGenPat;
bool m_bGenPmt;
bool m_bResetPSI;
- C_ElementDescriptor* m_pCurrentData;
C_ProgramDescriptor m_cPgrmDescriptor;
C_DvbPsiPat m_cPat;
@@ -93,9 +96,16 @@
// Global status
int m_iStatus;
+ u64 m_iNextPCR;
+ bool m_bNeedToSendPCR;
+ bool m_bLooping;
+
+ u8 m_bCache[512];
+ int m_iCacheLen;
+ bool m_bInMiddleOfPES;
// discontinuity management
- u64 m_iPrevSCR;
+ u64 m_iPrevPCR;
bool m_bDiscontinuity;
};
--- vls.orig/src/server/tsstreamer.cpp 2003-08-11 11:15:48.000000000 +0100
+++ vls/src/server/tsstreamer.cpp 2003-08-12 10:28:38.000000000 +0100
@@ -188,6 +188,7 @@
// buffer is ready to be send
if(m_iHowMany == m_pOutput->GetBuffCapacity())
{
+ if (!m_bFirstPCR)
WaitSendDate();
m_iHowMany = 0;
}