/* * 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(); }