diff options
Diffstat (limited to 'Src/Multiplexer/SourceFile.cpp')
-rw-r--r-- | Src/Multiplexer/SourceFile.cpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/Src/Multiplexer/SourceFile.cpp b/Src/Multiplexer/SourceFile.cpp new file mode 100644 index 0000000..3105145 --- /dev/null +++ b/Src/Multiplexer/SourceFile.cpp @@ -0,0 +1,176 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * You may also obtain this software under a propriety license from Microchip. + * Please contact Microchip for further information. + * + */ + +#include <stdint.h> +#include "Console.h" +#include "SourceFile.h" + +uint32_t CSource::m_nInstCnt = 0; + +CSourceFile::CSourceFile(const char *szFile, bool autoDestroy) +{ + m_bAutoDestroy = autoDestroy; + m_hFile = fopen64(szFile, "rb"); // try to open file + if (NULL == m_hFile) { + ConsolePrintf( PRIO_ERROR, RED"CSourceFile: unable to open file %s"RESETCOLOR"\n", szFile); + return; + } + strncpy(m_szFileName, szFile, sizeof(m_szFileName)); + + fseek(m_hFile, 0, SEEK_END); // get file's length + fpos64_t pos; + int result = fgetpos64(m_hFile, &pos); + if (result == 0) + m_nLength = pos.__pos; + else + m_nLength = -1; + fseek(m_hFile, 0, SEEK_SET); // start reading from start of file + + uint8_t Ts[READ_LEN]; // get PIDs for video and audio + uint32_t bytesRead = fread(// read a chunk from file and write it into ring buffer + Ts, + 1, + READ_LEN, + m_hFile); + + if (READ_LEN != bytesRead) { // no complete block available? + Close(); + return; + } + + for (uint8_t *pTs = Ts; pTs < Ts + READ_LEN; pTs += 188) { + if (PID_INVALID == m_nPPid) { + if (GetIsPat(pTs)) + m_nPPid = GetPmtPidFromPat(pTs, 0); + } else if (GetHasPid(pTs, m_nPPid)) { + m_nAPid = GetAudioPidFromPmt(pTs); + m_nVPid = GetVideoPidFromPmt(pTs); + break; + } + } + + if (PID_INVALID == m_nPPid) { // PMT found ? + ConsolePrintf( PRIO_ERROR, RED"CSourceFile: no PMT found in file %s"RESETCOLOR"\n", szFile); + Close(); + return; + } + + uint64_t nBlocks = (m_nLength / READ_LEN) - + 1; // number of read blocks in file + + for (; (nBlocks) && (PCR_INVALID == m_nLastPcr); nBlocks--) { + fseek(m_hFile, nBlocks * READ_LEN, + SEEK_SET); // read backwards from end of file + if (READ_LEN != + fread( // read a chunk from file and write it into ring buffer + Ts, + 1, + READ_LEN, + m_hFile)) { // no complete block available? + Close(); + return; + } + for (uint8_t *pTs = Ts; (pTs < Ts + READ_LEN) + && (PCR_INVALID == m_nLastPcr); pTs += 188) { + m_nLastPcr = GetPcr(pTs); + } + } + + fseek(m_hFile, 0, SEEK_SET); // start reading from start of file + ConsolePrintf( PRIO_MEDIUM, "Stream started file: %s\n", m_szFileName); +} + + + + +CSourceFile::~CSourceFile() +{ + Close(); +} + + + + +void CSourceFile::Close() +{ + if (NULL != m_hFile) { + fclose(m_hFile); + m_hFile = NULL; + ConsolePrintf( PRIO_MEDIUM, "Stream closed file: %s\n", m_szFileName); + } +} + + + + +bool CSourceFile::FillBuffer() +{ + if (true == m_bPause || // source paused? + 0 == m_Stream.Size() || // no receiving streams? + NULL == m_hFile || // file already closed? + !GetCanWrite() ) // ring buffer full? + { + return false; + } + + + if ( INVALID_POS != m_fReqPos) { // user requested to play from other position? + int64_t nPos = ((m_nLength * (int64_t)m_fReqPos / (int64_t)1000) / + (int64_t)TS_PACKET_LEN) * (int64_t)TS_PACKET_LEN; // stay TS packet aligned + + ConsolePrintf( PRIO_MEDIUM, "Stream seek to %lld (%lld per mil) for file: %s\r\n", nPos,((int64_t)1000 * nPos / m_nLength), m_szFileName); + + m_fReqPos = INVALID_POS; + + if (PID_INVALID != GetVPid()) { // if there is a video ES, seek to previous I frame + uint8_t Ts[TS_PACKET_LEN]; + + for (; nPos; nPos -= TS_PACKET_LEN) { + fseeko64(m_hFile, nPos, SEEK_SET); + if ( TS_PACKET_LEN != fread(Ts, 1, TS_PACKET_LEN, m_hFile) ) + break; + + if (GetIsStartOfIFrame(Ts)) // start of I frame? + break; + } + } + fseeko64(m_hFile, nPos, SEEK_SET); // seek to requested position + } + + + if ( READ_LEN != fread(GetWritePos(),1,READ_LEN,m_hFile) ) { // no complete chunk available? + ConsolePrintf( PRIO_MEDIUM, "CSourceFile: EOF for file: %s\r\n", m_szFileName); + + //TODO: remove quick hack: + if (true || m_bRepetition) + m_fReqPos = 0; + else + Close(); + + return false; + } + + m_nBytesRead += READ_LEN; + WriteDone(); + return true; +} |