/*
* Video On Demand Samples
*
* Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
*
* 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 3 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, see .
*
* You may also obtain this software under a propriety license from Microchip.
* Please contact Microchip for further information.
*
*/
#include
#include "StreamList.h"
#include "TsPacket.h"
uint32_t CStreamList::m_nInstCnt = 0;
CStreamList::CStreamList()
: m_nInst(m_nInstCnt++)
, m_nPatVersion(1)
, m_nPatCont(0)
, m_nNextStreamSending(0)
{
}
bool CStreamList::ReadHdd()
{
bool bRead = false; // no read done yet
for (uint32_t n = 0; n < MAX_STREAM_LIST_LEN; n++) // run over all streams
bRead |= m_Stream[n].ReadHdd(); // read from HDD
return bRead; // return if there was a read
}
void CStreamList::SetSource(CSource *pSource)
{
for (uint32_t n = 0; n < MAX_STREAM_LIST_LEN; n++) // run over all streams
if (NULL !=
m_Stream[n].GetMacAddr()) // only set in active streams
m_Stream[n].SetSource(pSource);
}
void CStreamList::GetPat(uint8_t *pTs)
{
// ---------------------------------------------------- //
// create PAT packet //
// ---------------------------------------------------- //
pTs[0] = 0x47; // packet start
pTs[1] = (1 << 6); // Payload Unit start indicator, PID = 0;
pTs[2] = 0;
pTs[3] = (1 << 4) | // no adaption field
m_nPatCont; // continuity counter
m_nPatCont = (m_nPatCont + 1) & 0xF; // update 4 bit continuity counter
pTs[4] = 0; // PointerField: new section
uint8_t *pPat = pTs + 5; // pointer to PAT
pPat[0] = 0; // Table ID: Program Association Section
uint16_t wSectionLength = 4 + 5 + 0; // 4 byte CRC, 5 bytes offset to entries, zero 4 byte entry,
pPat[3] = 0; // stream ID (HB)
pPat[4] = 0; // stream ID (LB)
pPat[5] = (3 << 6) | // reserved
(m_nPatVersion << 1) | // version
1; // current/next
pPat[6] = 0; // section number
pPat[7] = 0; // last section number
for (uint32_t n = 0; n < MAX_STREAM_LIST_LEN; n++) { // run over all streams
CMacAddr *pMac = m_Stream[n].GetMacAddr();
if (pMac) {
pPat[wSectionLength - 4 + 3 + 0] = (PID_PMT((*pMac)[5]) >> 8); // program number
pPat[wSectionLength - 4 + 3 + 1] = PID_PMT((*pMac)[5]) & 0xFF;
pPat[wSectionLength - 4 + 3 + 2] = (7 << 5) | // reserved
(PID_PMT((*pMac)[5]) >> 8); // Pmt PID (HB)
pPat[wSectionLength - 4 + 3 + 3] = PID_PMT((*pMac)[5]) & 0xFF; // Pmt PID (LB)
wSectionLength += 4;
}
}
pPat[1] = (1 << 7) | // section syntax indicator
(3 << 4) | // reserved
(wSectionLength >> 8); // section syntax 1, section length
pPat[2] = wSectionLength & 0xFF;
uint32_t nCrc = CTsPacket::GetCrc32(pPat,wSectionLength + 3 - 4); // CRC over entire PAT section without 4 CRC bytes
pPat[wSectionLength + 3 - 4 + 0] = (nCrc >> 24) & 0xFF;
pPat[wSectionLength + 3 - 4 + 1] = (nCrc >> 16) & 0xFF;
pPat[wSectionLength + 3 - 4 + 2] = (nCrc >> 8) & 0xFF;
pPat[wSectionLength + 3 - 4 + 3] = (nCrc) & 0xFF;
// fill remaining packet with 0xFF
for (uint8_t *p = 1 + &pPat[wSectionLength + 3 - 4 + 3]; p < pTs + 188; p++)
*p = 0xFF;
}
bool CStreamList::GetPatPacket(uint8_t *pTs)
{
GetPat(pTs);
return true;
}
bool CStreamList::GetTsPacket(uint8_t *pTs)
{
for (uint32_t n = 0; n < MAX_STREAM_LIST_LEN; n++) // run over all streams
{
m_nNextStreamSending++;
if ( m_nNextStreamSending >= MAX_STREAM_LIST_LEN )
m_nNextStreamSending = 0;
if ( m_Stream[m_nNextStreamSending].GetTsPacket(pTs) )
return true;
}
return false;
}
uint32_t CStreamList::GetBytesRead()
{
uint32_t nSum = 0;
for (uint32_t n = 0; n < MAX_STREAM_LIST_LEN; n++) // run over all streams
nSum += m_Stream[n].GetBytesRead();
return nSum;
}
uint32_t CStreamList::GetBytesSent()
{
uint32_t nSum = 0;
for (uint32_t n = 0; n < MAX_STREAM_LIST_LEN; n++) // run over all streams
nSum += m_Stream[n].GetBytesSent();
return nSum;
}
uint32_t CStreamList::GetErrPcr()
{
uint32_t nSum = 0;
for (uint32_t n = 0; n < MAX_STREAM_LIST_LEN; n++) // run over all streams
nSum += m_Stream[n].GetErrPcr();
return nSum;
}
uint32_t CStreamList::GetErrBufUnderflow()
{
uint32_t nSum = 0;
for (uint32_t n = 0; n < MAX_STREAM_LIST_LEN; n++) // run over all streams
nSum += m_Stream[n].GetErrBufUnderflow();
return nSum;
}
uint32_t CStreamList::GetErrTs()
{
uint32_t nSum = 0;
for (uint32_t n = 0; n < MAX_STREAM_LIST_LEN; n++) // run over all streams
nSum += m_Stream[n].GetErrTs();
return nSum;
}
CStream *CStreamList::GetStream(CMacAddr *pMacAddr)
{
for (uint32_t n = 0; n < MAX_STREAM_LIST_LEN; n++) {
CMacAddr *pSource = m_Stream[n].GetMacAddr();
if (NULL == pMacAddr) {
//In case of a given NULL pointer, return the first unassigned stream
if (NULL == pSource)
return &m_Stream[n];
} else if (NULL != pSource) {
//Else search for the correct instance
if (*pMacAddr == *pSource)
return &m_Stream[n];
}
}
return NULL;
}
void CStreamList::PrintStreamList()
{
ConsolePrintfStart( PRIO_HIGH, "StreamListID: %u\n\n", m_nInst);
ConsolePrintfContinue("StreamID SourceID Ovfl MAC \n");
ConsolePrintfExit("-----------------------------------------------------------\n");
for (uint32_t n = 0; n < MAX_STREAM_LIST_LEN; n++)
m_Stream[n].PrintStream();
}