summaryrefslogtreecommitdiffstats
path: root/Src/Multiplexer/SourceFileConverted.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Multiplexer/SourceFileConverted.cpp')
-rw-r--r--Src/Multiplexer/SourceFileConverted.cpp188
1 files changed, 188 insertions, 0 deletions
diff --git a/Src/Multiplexer/SourceFileConverted.cpp b/Src/Multiplexer/SourceFileConverted.cpp
new file mode 100644
index 0000000..2816663
--- /dev/null
+++ b/Src/Multiplexer/SourceFileConverted.cpp
@@ -0,0 +1,188 @@
+/*
+ * Video On Demand Samples
+ *
+ * Copyright (C) 2016 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 <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "Console.h"
+#include "SourceFileConverted.h"
+
+
+CSourceFileConverted::CSourceFileConverted(const char *szFile, bool autoDestroy)
+ : m_hFile(-1)
+ , m_nLength(0)
+ , m_nChildPid(0)
+{
+ m_bAutoDestroy = autoDestroy;
+ strncpy(m_szFileName, szFile, sizeof(m_szFileName));
+ m_nLength = 6*60; // TODO: determine actual stream length, assume 6 minutes for now...
+
+ Start(0);
+
+ m_nPPid = 0x1000; // avconv default / -mpegts_pmt_start_pid X
+ m_nAPid = 0x101; // avconv default / -streamid 1:X
+ m_nVPid = 0x100; // avconv default / -streamid 0:X
+
+ m_nLastPcr = PCR_INVALID;
+}
+
+
+
+
+CSourceFileConverted::~CSourceFileConverted()
+{
+ Close();
+}
+
+
+
+
+void CSourceFileConverted::Start(int64_t nPos)
+{
+ // fork() and start avconv in child:
+ int fd[2];
+ if (pipe(fd)) {
+ ConsolePrintf(PRIO_ERROR, RED"CSourceFileConverted: failed to open pipe for %s"RESETCOLOR"\n", m_szFileName);
+ return;
+ }
+ pid_t forkret = fork();
+ char *ext;
+ char chstr[20] = "";
+ switch (forkret) {
+ case 0:
+ /* the child process: */
+ close(fd[0]);
+ dup2(fd[1], 1); // close stdout, duplicate input side of the pipe to stdout
+// execl("/bin/cat", "/bin/cat", m_szFileName, NULL);
+ sprintf(chstr, "%lli", nPos);
+ ext = rindex(m_szFileName, '.');
+ if (ext && !strcasecmp(ext, ".mp3"))
+ execl("/usr/bin/avconv", "/usr/bin/avconv",
+ "-ss", chstr, "-i", m_szFileName,
+ "-f", "mpegts", "-codec", "copy",
+ "-map", "0:a:0",
+ "-streamid", "0:0x101", "-mpegts_pmt_start_pid", "0x1000",
+ "pipe:1", NULL);
+ else
+ execl("/usr/bin/avconv", "/usr/bin/avconv",
+ "-ss", chstr, "-i", m_szFileName,
+ "-f", "mpegts", "-codec", "copy", "-bsf:v", "h264_mp4toannexb",
+ "-map", "0:v:0", "-map", "0:a:0",
+ "-streamid", "0:0x100", "-streamid", "1:0x101", "-mpegts_pmt_start_pid", "0x1000",
+ "pipe:1", NULL);
+ ConsolePrintf(PRIO_ERROR, RED"CSourceFileConverted: execl() call failed for %s"RESETCOLOR"\n", m_szFileName);
+ exit(0);
+ case -1:
+ /* fork() failed */
+ close(fd[0]);
+ close(fd[1]);
+ ConsolePrintf(PRIO_ERROR, RED"CSourceFileConverted: failed to fork for %s"RESETCOLOR"\n", m_szFileName);
+ return;
+ default:
+ /* parent process after fork: */
+ m_nChildPid = forkret;
+ close(fd[1]);
+ m_hFile = fd[0]; /* read from child via pipe */
+ }
+
+ m_nLastPcr = PCR_INVALID;
+
+ ConsolePrintf( PRIO_MEDIUM, "Stream started file: %s\n", m_szFileName);
+}
+
+
+
+
+void CSourceFileConverted::Close()
+{
+ if (m_nChildPid > 0) {
+ ConsolePrintf(PRIO_LOW, "sending SIGKILL to pid %u\n", m_nChildPid);
+ kill(m_nChildPid, SIGKILL);
+ ConsolePrintf(PRIO_LOW, "waiting for child to exit...\n");
+ int childStatus = 0;
+ waitpid(m_nChildPid, &childStatus, 0);
+ m_nChildPid = 0;
+ if (WIFEXITED(childStatus))
+ ConsolePrintf(PRIO_LOW, "child terminated normally (exit status %u)\n", WEXITSTATUS(childStatus));
+ else if (WIFSIGNALED(childStatus))
+ ConsolePrintf(PRIO_LOW, "child terminated by signal number %u\n", WTERMSIG(childStatus));
+ }
+ if (m_hFile > 0) {
+ close(m_hFile);
+ m_hFile = -1;
+ ConsolePrintf( PRIO_MEDIUM, "Stream closed file: %s\n", m_szFileName);
+ }
+}
+
+
+
+
+bool CSourceFileConverted::FillBuffer()
+{
+ if (true == m_bPause || // source paused?
+ 0 == m_Stream.Size() || // no receiving streams?
+ m_hFile < 0 || // 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 / 1000);
+
+ ConsolePrintf( PRIO_MEDIUM, "Stream seek to %lld (%lld per mil) for file: %s\r\n", nPos,(1000 * nPos / m_nLength), m_szFileName);
+
+ m_fReqPos = INVALID_POS;
+
+ Close();
+ Start(nPos);
+ }
+
+
+ unsigned int readcnt = 0;
+ while (readcnt < READ_LEN) {
+ int readres = read(m_hFile, GetWritePos()+readcnt, READ_LEN-readcnt);
+ if (readres <= 0) { // remote pipe end closed, or other error?
+ ConsolePrintf( PRIO_MEDIUM, "CSourceFileConverted: EOF for file: %s (result=%i, errno=%i)\r\n", m_szFileName, readres, errno);
+
+ //TODO: remove quick hack:
+ if (true || m_bRepetition)
+ m_fReqPos = 0;
+ else
+ Close();
+
+ return false;
+ }
+ readcnt += readres;
+ }
+
+ m_nBytesRead += READ_LEN;
+ WriteDone();
+ return true;
+}