Commit 3b816310 authored by Andrew de Quincey's avatar Andrew de Quincey

Now supports the convertor-controller looping introduced with the ps2ts

changes.
General cleanup and removal of redundant code.
parent 41a08806
......@@ -2,7 +2,7 @@
* ts2ts.cpp: TS to TS converter
*-------------------------------------------------------------------------------
* (c)1999-2001 VideoLAN
* $Id: ts2ts.cpp,v 1.8 2003/08/05 18:03:52 tooney Exp $
* $Id: ts2ts.cpp,v 1.9 2003/08/23 21:38:48 adq Exp $
*
* Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
*
......@@ -80,6 +80,7 @@ C_Ts2TsMpegConverter::C_Ts2TsMpegConverter(C_Module* pModule,
C_MpegConverter(pModule, cConfig),
m_iCorrectPercentage(10)
{
m_iLoop = cConfig.m_pBroadcast->GetOption("loop").ToInt();
}
......@@ -126,9 +127,7 @@ s64 C_Ts2TsMpegConverter::GetNextTsPackets(C_Fifo<C_TsPacket>* pPackets
s64 iRc = 0;
bool bDiscontinuity = false;
C_TsPacket * pPacket = m_pTsProvider->GetPacket();
ASSERT(pPacket);
// do any skipping required
if (skip>0)
{
iRc = m_pReader->Seek(CorrectForward(skip*TS_PACKET_LEN), FILE_SEEK_CURRENT);
......@@ -136,56 +135,95 @@ s64 C_Ts2TsMpegConverter::GetNextTsPackets(C_Fifo<C_TsPacket>* pPackets
{
C_String strPgrmName = m_pBroadcast->GetProgram()->GetName();
LogDbg(m_hLog, "End of program \"" + strPgrmName + "\" reached");
m_pTsProvider->ReleasePacket(pPacket);
return iRc;
}
else if(iRc != NO_ERR)
{
C_String strPgrmName = m_pBroadcast->GetProgram()->GetName();
Log(m_hLog, LOG_ERROR, "Read error for program \"" + strPgrmName + "\"");
m_pTsProvider->ReleasePacket(pPacket);
return iRc;
}
}
// Fill it with the data from the file
iRc = FillPacket(pPacket);
pPackets->Push(pPacket);
// grab a new packet
C_TsPacket * pPacket = m_pTsProvider->GetPacket();
if ((*pPacket)[0] != 0x47)
bDiscontinuity = true;
// packet fill loop.. keeps going until a valid packet is found
while(true) {
// get data for it
iRc = m_pReader->Read((byte*) (*pPacket), TS_PACKET_LEN);
// Check stream discontinuity
if(!iRc && (m_pReader->HasDiscontinuity() || bDiscontinuity))
{
while((((*pPacket)[0] != 0x47) || !pPacket->HasPCR()) && !iRc)
iRc = SyncFillPacket(pPacket);
if(!iRc)
{
ASSERT(pPacket->SetDiscontinuityFlag());
pPacket->SetDiscontinuityFlag();
m_pReader->ResetDiscontinuity();
bDiscontinuity = false;
// first, check that the read went OK
if (iRc == TS_PACKET_LEN) {
// read was fine
iRc = NO_ERR;
} else if ((iRc == FILE_EOF) || (m_pReader->EndOfStream())) {
// we hit the EOF
if (m_iLoop) {
// try and reset the stream
m_pReader->ResetEndOfStream();
// if that was successful, do loop setup stuff
if (!m_pReader->EndOfStream()) {
if ((iRc = Synch()) != 0) {
return iRc;
}
m_iLoop--;
}
} else {
// not looping.
iRc = MPEG_ENDOFSTREAM;
}
if(iRc == MPEG_ENDOFSTREAM)
{
C_String strPgrmName = m_pBroadcast->GetProgram()->GetName();
LogDbg(m_hLog, "End of program \"" + strPgrmName + "\" reached");
// Don't new to release
// Trickplay will do that when flushing fifo
// m_pTsProvider->ReleasePacket(pPacket);
// we always add an error packet at the end. We
// don't analyse the data in the stream to know for sure
// it completed any ES packets etc, so for the benefit of
// the doubt, we add one in.
ZeroPacket(pPacket);
pPacket->SetErrorFlag();
} else if (iRc >= 0) {
// truncated read
ZeroPacket(pPacket);
pPacket->SetErrorFlag();
iRc = NO_ERR;
} else {
// we had some other error.
m_pTsProvider->ReleasePacket(pPacket);
return MPEG_STREAMERROR;
}
else if(iRc != NO_ERR)
{
C_String strPgrmName = m_pBroadcast->GetProgram()->GetName();
Log(m_hLog, LOG_ERROR, "Read error for program \"" + strPgrmName + "\"");
// Don't new to release
// Trickplay will do that when flushing fifo
// m_pTsProvider->ReleasePacket(pPacket);
// Now, was it a valid packet?
if ((*pPacket)[0] == 0x47) {
// if the discontinuity flag is set, the packet
// HAS to contain the PCR
if (bDiscontinuity) {
if (pPacket->HasPCR()) {
break;
}
} else {
// normal mode => any packet will do
break;
}
} else {
// invalid packet => attempt to resynchronise with the stream,
// and set discontinuity flag so the next one we output has the PCR
bDiscontinuity = true;
if ((iRc = Synch()) != 0) {
m_pTsProvider->ReleasePacket(pPacket);
return iRc;
}
}
}
// remember to warn of discontinuity if necessary
if (bDiscontinuity) {
pPacket->SetDiscontinuityFlag();
}
// OK, add the packet to the list
pPackets->Push(pPacket);
// return status
return iRc;
}
......@@ -196,12 +234,8 @@ s64 C_Ts2TsMpegConverter::GetPrevTsPackets(C_Fifo<C_TsPacket> * pPackets,
int skip)
{
s64 iRc = 0;
bool bDiscontinuity = false;
C_TsPacket * pPacket = m_pTsProvider->GetPacket();
ASSERT(pPacket);
// After jumping backwards read forward ;-)
// perform any seeking necessary
if (skip>0)
{
iRc = m_pReader->Seek(- CorrectRewind(skip*TS_PACKET_LEN), FILE_SEEK_CURRENT);
......@@ -209,7 +243,6 @@ s64 C_Ts2TsMpegConverter::GetPrevTsPackets(C_Fifo<C_TsPacket> * pPackets,
{
C_String strPgrmName = m_pBroadcast->GetProgram()->GetName();
LogDbg(m_hLog, "Begin of program \"" + strPgrmName + "\" reached");
m_pTsProvider->ReleasePacket(pPacket);
// Jump to start of stream
iRc = m_pReader->Seek(0, FILE_SEEK_BEGIN);
......@@ -220,155 +253,53 @@ s64 C_Ts2TsMpegConverter::GetPrevTsPackets(C_Fifo<C_TsPacket> * pPackets,
{
C_String strPgrmName = m_pBroadcast->GetProgram()->GetName();
Log(m_hLog, LOG_ERROR, "Read error for program \"" + strPgrmName + "\"");
m_pTsProvider->ReleasePacket(pPacket);
return iRc;
}
}
// Fill it with the data from the file
iRc = FillPacket(pPacket);
if ((*pPacket)[0] != 0x47)
bDiscontinuity = true;
// Check stream discontinuity
if (!iRc && (m_pReader->HasDiscontinuity() || bDiscontinuity))
{
while((((*pPacket)[0] != 0x47) || !pPacket->HasPCR()) && !iRc)
iRc = SyncFillPacket(pPacket);
if(!iRc)
{
ASSERT(pPacket->SetDiscontinuityFlag());
pPacket->SetDiscontinuityFlag();
m_pReader->ResetDiscontinuity();
bDiscontinuity = false;
pPackets->Push(pPacket);
}
}
if (iRc == MPEG_BEGINOFSTREAM)
{
C_String strPgrmName = m_pBroadcast->GetProgram()->GetName();
LogDbg(m_hLog, "Begin of program \"" + strPgrmName + "\" reached");
// Don't new to release
// Trickplay will do that when flushing fifo
//m_pTsProvider->ReleasePacket(pPacket);
}
else if(iRc != NO_ERR)
{
C_String strPgrmName = m_pBroadcast->GetProgram()->GetName();
Log(m_hLog, LOG_ERROR, "Read error for program \"" + strPgrmName + "\"");
// Don't new to release
// Trickplay will do that when flushing fifo
//m_pTsProvider->ReleasePacket(pPacket);
}
return iRc;
// read the data.
return GetNextTsPackets(pPackets, 0);
}
//------------------------------------------------------------------------------
// Get the next 188 bytes to fill the TS packet
// Synchronize in the TS stream
//------------------------------------------------------------------------------
int C_Ts2TsMpegConverter::FillPacket(C_TsPacket* pPacket)
int C_Ts2TsMpegConverter::Synch()
{
int iRc = m_pReader->Read((*pPacket), TS_PACKET_LEN);
if(iRc == TS_PACKET_LEN)
{
iRc = NO_ERR;
unsigned char c;
int iRc;
// loop until we find a sync byte or an error
c = 0;
iRc = 0;
while((c != 0x47) && (!iRc)) {
iRc = m_pReader->Read(&c, 1);
if ((iRc == FILE_EOF) || (m_pReader->EndOfStream())) {
if (m_iLoop) {
// try and reset the stream
m_pReader->ResetEndOfStream();
// if that was successful, do loop setup stuff
if (!m_pReader->EndOfStream()) {
m_iLoop--;
iRc = 0;
}
else if(iRc >= 0)
{
// Mark the packet as bad
pPacket->SetErrorFlag();
iRc = NO_ERR;
} else {
// not looping.
iRc = MPEG_ENDOFSTREAM;
}
else if(iRc == MPEG_ENDOFSTREAM)
{
// Pad the end of the packet with 0 and mark it as bad if not some
// decoders could crash
(*pPacket)[0] = 0x47;
for(int i = 1; i < TS_PACKET_LEN; i++)
(*pPacket)[i] = 0;
pPacket->SetErrorFlag();
} else if (iRc == 1) {
// successful read (but not necessarily a sync byte)
iRc = 0;
}
else
{
// Mark the packet as bad
pPacket->SetErrorFlag();
iRc = MPEG_STREAMERROR;
}
return iRc;
}
//------------------------------------------------------------------------------
// Synchronize in the TS stream and then fill the TS packet
//------------------------------------------------------------------------------
int C_Ts2TsMpegConverter::SyncFillPacket(C_TsPacket* pPacket)
{
(*pPacket)[0] = 0;
int iRc = 1;
while(((*pPacket)[0] != 0x47) && (iRc == 1))
iRc = m_pReader->Read((*pPacket), 1);
if(iRc == 1)
{
iRc = NO_ERR;
}
else if(iRc >= 0)
{
// Mark the packet as bad
pPacket->SetErrorFlag();
iRc = NO_ERR;
}
else if(iRc == MPEG_ENDOFSTREAM)
{
// Pad the end of the packet with 0 and mark it as bad if not some
// decoders could crash
void C_Ts2TsMpegConverter::ZeroPacket(C_TsPacket* pPacket) {
(*pPacket)[0] = 0x47;
for(int i = 1; i < TS_PACKET_LEN; i++)
(*pPacket)[i] = 0;
pPacket->SetErrorFlag();
}
else
{
// Mark the packet as bad
pPacket->SetErrorFlag();
iRc = MPEG_STREAMERROR;
}
if(!iRc)
{
iRc = m_pReader->Read((byte*)(*pPacket) + 1, TS_PACKET_LEN - 1);
if(iRc == TS_PACKET_LEN - 1)
{
iRc = NO_ERR;
}
else if(iRc >= 0)
{
// Mark the packet as bad
pPacket->SetErrorFlag();
iRc = NO_ERR;
}
else if(iRc == MPEG_ENDOFSTREAM)
{
// Pad the end of the packet with 0 and mark it as bad if not some
// decoders could crash
for(int i = 1; i < TS_PACKET_LEN; i++)
(*pPacket)[i] = 0;
pPacket->SetErrorFlag();
}
else
{
// Mark the packet as bad
pPacket->SetErrorFlag();
iRc = MPEG_STREAMERROR;
}
}
return iRc;
}
......@@ -2,7 +2,7 @@
* ts2ts.h: TS to TS converter
*-------------------------------------------------------------------------------
* (c)1999-2001 VideoLAN
* $Id: ts2ts.h,v 1.5 2003/08/05 18:03:52 tooney Exp $
* $Id: ts2ts.h,v 1.6 2003/08/23 21:38:48 adq Exp $
*
* Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
*
......@@ -44,13 +44,14 @@ public:
virtual s64 GetPrevTsPackets(C_Fifo<C_TsPacket> * pPacket, int skip = 0);
protected:
int FillPacket(C_TsPacket* pPacket);
int SyncFillPacket(C_TsPacket* pPacket);
int Synch();
s64 inline CorrectForward(s64 size);
s64 inline CorrectRewind(s64 size);
void ZeroPacket(C_TsPacket* pPacket);
private:
const int m_iCorrectPercentage;
int m_iLoop;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment