summaryrefslogtreecommitdiffstats
path: root/Src/Multiplexer/SourceFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Multiplexer/SourceFile.cpp')
-rw-r--r--Src/Multiplexer/SourceFile.cpp176
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;
+}