summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkos <kos@dev3>2013-11-04 10:14:14 (GMT)
committerkos <kos@dev3>2013-11-04 10:14:14 (GMT)
commit4f510c2c80a85a14ff2d0ce16f1323a6a66f0366 (patch)
tree1893e7a4c96eb062c23fc9f1d0a13817fb90b613
parente6d6277466860e4dd779f566cead24a360a87d43 (diff)
added live-transcoding module.
modified switch clause at uridecoder. enhanced filepumpthread and networkpumpthread.
-rw-r--r--src/Makefile.manual7
-rw-r--r--src/eDemuxPumpThread.cpp279
-rw-r--r--src/eDemuxPumpThread.h59
-rw-r--r--src/eFilePumpThread.cpp68
-rw-r--r--src/eFilePumpThread.h11
-rw-r--r--src/eNetworkPumpThread.cpp19
-rw-r--r--src/eNetworkPumpThread.h6
-rw-r--r--src/eParser.cpp277
-rw-r--r--src/eParser.h29
-rw-r--r--src/ePreDefine.h14
-rw-r--r--src/eTransCodingDevice.cpp107
-rw-r--r--src/eTransCodingDevice.h31
-rw-r--r--src/eURIDecoder.cpp3
-rw-r--r--src/eUpstreamSocket.cpp101
-rw-r--r--src/eUpstreamSocket.h35
-rw-r--r--src/main.cpp314
-rw-r--r--src/uStringTool.h56
17 files changed, 1239 insertions, 177 deletions
diff --git a/src/Makefile.manual b/src/Makefile.manual
index 5161951..12b4bde 100644
--- a/src/Makefile.manual
+++ b/src/Makefile.manual
@@ -15,15 +15,19 @@ BIN = filestreamproxy
SRC = \
main.cpp \
uThread.cpp \
+ eParser.cpp \
eURIDecoder.cpp \
+ eUpstreamSocket.cpp \
+ eTransCodingDevice.cpp \
eFilePumpThread.cpp \
eNetworkPumpThread.cpp \
+ eDemuxPumpThread.cpp \
CFLAGS ?=
LDFLAGS ?=
-CFLAGS += -DDEBUG_LOG
+#CFLAGS += -DNORMAL_STREAMPROXY
ifeq ($(SILENT_BUILD_MODE),y)
Q=@
@@ -40,6 +44,7 @@ endif
ifeq ($(BUILD_MODE),debug)
CFLAGS += -g
+CFLAGS += -DDEBUG_LOG
else ifeq ($(BUILD_MODE),release)
CFLAGS += -O2
endif
diff --git a/src/eDemuxPumpThread.cpp b/src/eDemuxPumpThread.cpp
new file mode 100644
index 0000000..576cd51
--- /dev/null
+++ b/src/eDemuxPumpThread.cpp
@@ -0,0 +1,279 @@
+/*
+ * eDemuxPumpThread.cpp
+ *
+ * Created on: 2013. 10. 29.
+ * Author: kos
+ */
+
+#include <poll.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/version.h>
+
+#include "ePreDefine.h"
+#include "eDemuxPumpThread.h"
+
+using namespace std;
+
+#ifdef DEBUG_LOG
+//#undef LOG
+//#define LOG(X,...) { do{}while(0); }
+#endif
+
+eDemuxPumpThread::eDemuxPumpThread()
+ : mTermFlag(0), mDemuxFd(0), mDeviceFd(0), mState(eDemuxState::stNotOpened),
+#ifdef NORMAL_STREAMPROXY
+ mErrMessage(""), uThread("eDemuxPumpThread")
+#else
+ mErrMessage(""), uThread("eDemuxPumpThread", TYPE_DETACHABLE)
+#endif
+{
+}
+//-------------------------------------------------------------------------------
+
+eDemuxPumpThread::~eDemuxPumpThread()
+{
+ Close();
+}
+//-------------------------------------------------------------------------------
+
+void eDemuxPumpThread::Run()
+{
+ if(!mState) {
+ mTermFlag = false;
+ return;
+ }
+ int rc = 0, wc = 0;
+ static unsigned char buffer[BUFFER_SIZE];
+
+ struct pollfd pollevt;
+ pollevt.fd = mDeviceFd;
+ pollevt.events = POLLOUT;
+
+ fd_set demux_readfds;
+#ifdef NORMAL_STREAMPROXY
+ const char *c = "\
+HTTP/1.0 200 OK\r\n\
+Connection: close\r\n\
+Content-Type: video/mpeg\r\n\
+Server: stream_enigma2\r\n\
+\r\n";
+ wc = write(1, c, strlen(c));
+#endif
+
+ mTermFlag = true;
+#ifdef DEBUG_LOG
+ LOG("demux pump start.");
+#endif
+ while(mTermFlag) {
+ FD_ZERO(&demux_readfds);
+ FD_SET(mDemuxFd, &demux_readfds);
+ if (select(mDemuxFd + 1, &demux_readfds, 0, 0, 0) < 0) {
+ break;
+ }
+ if(FD_ISSET(mDemuxFd, &demux_readfds)) {
+ rc = read(mDemuxFd, buffer, BUFFER_SIZE);
+ if(rc < 0) {
+#ifdef DEBUG_LOG
+ LOG("read fail : %d", errno);
+#endif
+ if(errno == EOVERFLOW) {
+ continue;
+ }
+ break;
+ }
+#ifdef NORMAL_STREAMPROXY
+ wc = write(1, buffer, rc);
+#else
+ wc = write(mDeviceFd, buffer, rc);
+#endif
+ if(wc != rc) {
+#ifdef DEBUG_LOG
+ LOG("write fail.. rc[%d], wc[%d]", rc, wc);
+#endif
+ int read_len = rc;
+ fd_set device_writefds;
+
+ FD_ZERO(&device_writefds);
+ FD_SET(mDeviceFd, &device_writefds);
+
+ for(int i = wc; i < read_len; i += wc) {
+ if (select(mDeviceFd + 1, 0, &device_writefds, 0, 0) < 0)
+ break;
+ wc = write(mDeviceFd, buffer + i, read_len - i);
+ }
+ }
+ }
+ }
+#ifdef DEBUG_LOG
+ LOG("demux pump stoped.");
+#endif
+ mTermFlag = false;
+}
+//-------------------------------------------------------------------------------
+
+void eDemuxPumpThread::Terminate()
+{
+ mTermFlag = false;
+}
+//-------------------------------------------------------------------------------
+
+bool eDemuxPumpThread::Open(int aDemuxId)
+{
+ char demuxpath[32] = {0};
+ sprintf(demuxpath, "/dev/dvb/adapter0/demux%d", aDemuxId);
+
+ mDemuxFd = open(demuxpath, O_RDWR | O_NONBLOCK);
+ if (mDemuxFd < 0) {
+ mErrMessage = "DEMUX OPEN FAILED";
+ mDemuxFd = 0;
+#ifdef DEBUG_LOG
+ LOG("demux open failed (%s).", demuxpath);
+#endif
+ return false;
+ }
+#ifdef DEBUG_LOG
+ LOG("demux open succeed : %s (%d).", demuxpath, mDemuxFd);
+#endif
+
+ mState = eDemuxState::stOpened;
+ return true;
+}
+//-------------------------------------------------------------------------------
+
+void eDemuxPumpThread::Close()
+{
+ mState = eDemuxState::stNotOpened;
+ if(mDemuxFd > 0) {
+ close(mDemuxFd);
+ }
+ mDemuxFd = 0;
+}
+//-------------------------------------------------------------------------------
+
+
+bool eDemuxPumpThread::ExistPid(std::vector<unsigned long>& aPids, unsigned long aPid)
+{
+ for(int i = 0; i < aPids.size(); ++i) {
+ if(aPids[i] == aPid) {
+ return true;
+ }
+ }
+ return false;
+}
+//-------------------------------------------------------------------------------
+
+bool eDemuxPumpThread::SetFilter(std::vector<unsigned long>& aPidList)
+{
+ if(!mDemuxFd) {
+ mErrMessage = "DMX_SET_PES_FILTER FAILED (Demux is not opened).";
+ return false;
+ }
+
+ struct dmx_pes_filter_params filter;
+ ioctl(mDemuxFd, DMX_SET_BUFFER_SIZE, 1024*1024);
+
+ filter.pid = aPidList[0];
+ filter.input = DMX_IN_FRONTEND;
+#if DVB_API_VERSION > 3
+ filter.output = DMX_OUT_TSDEMUX_TAP;
+ filter.pes_type = DMX_PES_OTHER;
+#else
+ filter.output = DMX_OUT_TAP;
+ filter.pes_type = DMX_TAP_TS;
+#endif
+ filter.flags = DMX_IMMEDIATE_START;
+
+ if (ioctl(mDemuxFd, DMX_SET_PES_FILTER, &filter) < 0) {
+ mErrMessage = "DEMUX PES FILTER SET FAILED";
+#ifdef DEBUG_LOG
+ LOG("demux filter setting failed.");
+#endif
+ return false;
+ }
+#ifdef DEBUG_LOG
+ LOG("demux filter setting ok.");
+#endif
+
+ mState = eDemuxState::stSetedFilter;
+ return true;
+}
+//-------------------------------------------------------------------------------
+
+bool eDemuxPumpThread::SetPidList(std::vector<unsigned long>& aPidList)
+{
+ if(!mDemuxFd) {
+ mErrMessage = "DMX_ADD_PID FAILED (Demux is not opened).";
+ return false;
+ }
+
+ int rc = 0, i = 0;
+ int pidsize = aPidList.size();
+
+
+ for(i = 0; i < pidsize; ++i) {
+ uint16_t pid = aPidList[i];
+
+ if(eDemuxPumpThread::ExistPid(mPidList, pid)) {
+ continue;
+ }
+
+#if DVB_API_VERSION > 3
+ rc = ioctl(mDemuxFd, DMX_ADD_PID, &pid);
+#else
+ rc = ioctl(mDemuxFd, DMX_ADD_PID, pid);
+#endif
+#ifdef DEBUG_LOG
+ LOG("add [%x]!!!", pid);
+#endif
+ if(rc < 0) {
+ mErrMessage = "DMX_ADD_PID FAILED.";
+#ifdef DEBUG_LOG
+ LOG("demux add PID failed.");
+#endif
+ return false;
+ }
+ }
+
+ pidsize = mPidList.size();
+ for(i = 0; i < pidsize; ++i) {
+ uint16_t pid = mPidList[i];
+
+ if(eDemuxPumpThread::ExistPid(aPidList, pid)) {
+ continue;
+ }
+
+ if(i == 4) {
+ break;
+ }
+
+#if DVB_API_VERSION > 3
+ rc = ioctl(mDemuxFd, DMX_REMOVE_PID, &pid);
+#else
+ rc = ioctl(mDemuxFd, DMX_REMOVE_PID, pid);
+#endif
+#ifdef DEBUG_LOG
+ LOG("remove [%x]!!!", pid);
+#endif
+ if(rc < 0) {
+ mErrMessage = "DMX_REMOVE_PID FAILED.";
+#ifdef DEBUG_LOG
+ LOG("demux remove PID failed.");
+#endif
+ return false;
+ }
+ }
+#ifdef DEBUG_LOG
+ LOG("demux setting PID ok.");
+#endif
+ mPidList = aPidList;
+ return true;
+}
+//-------------------------------------------------------------------------------
+
diff --git a/src/eDemuxPumpThread.h b/src/eDemuxPumpThread.h
new file mode 100644
index 0000000..662e345
--- /dev/null
+++ b/src/eDemuxPumpThread.h
@@ -0,0 +1,59 @@
+/*
+ * eDemuxPumpThread.h
+ *
+ * Created on: 2013. 10. 29.
+ * Author: kos
+ */
+
+#ifndef EDEMUXPUMPTHREAD_H_
+#define EDEMUXPUMPTHREAD_H_
+
+#include <vector>
+#include <string>
+
+#include "uThread.h"
+//-------------------------------------------------------------------------------
+
+namespace eDemuxState {
+ enum {
+ stNotOpened = 0,
+ stOpened,
+ stSetedFilter,
+ END
+ };
+};
+//-------------------------------------------------------------------------------
+
+class eDemuxPumpThread : public uThread
+{
+private:
+ int mDemuxFd, mDeviceFd, mState;
+ bool mTermFlag;
+
+ std::string mErrMessage;
+
+ std::vector<unsigned long> mPidList;
+protected:
+ void Run();
+ void Terminate();
+public:
+ eDemuxPumpThread();
+ virtual ~eDemuxPumpThread();
+
+ bool Open(int aDemuxId);
+ void Close();
+
+ int GetState() { return mState; }
+ int GetDemuxFd() { return mDemuxFd; }
+ std::string GetMessage() { return mErrMessage; }
+
+ void SetDeviceFd(int aDeviceFd) { mDeviceFd = aDeviceFd; }
+
+ bool SetFilter(std::vector<unsigned long>& aPidList);
+ bool SetPidList(std::vector<unsigned long>& aPidList);
+
+ static bool ExistPid(std::vector<unsigned long>& aPids, unsigned long aPid);
+};
+//-------------------------------------------------------------------------------
+
+#endif /* EDEMUXPUMPTHREAD_H_ */
diff --git a/src/eFilePumpThread.cpp b/src/eFilePumpThread.cpp
index 4cd7fa6..c15cae9 100644
--- a/src/eFilePumpThread.cpp
+++ b/src/eFilePumpThread.cpp
@@ -11,6 +11,7 @@
#include <poll.h>
#include <stdio.h>
+#include <unistd.h>
#include <fcntl.h>
#include "ePreDefine.h"
@@ -22,45 +23,90 @@
//#define LOG(X,...) { do{}while(0); }
#endif
-eFilePumpThread::eFilePumpThread(int aDeviceFd, std::string aFileName)
- : mDeviceFd(aDeviceFd), mFileName(aFileName), mTermFlag(false), uThread("FilePumpThread", TYPE_DETACHABLE)
+eFilePumpThread::eFilePumpThread(int aDeviceFd)
+ : mDeviceFd(aDeviceFd), mFileFd(0), mFileSize(0), mTermFlag(false),
+ uThread("FilePumpThread", TYPE_DETACHABLE)
{
}
//-------------------------------------------------------------------------------
eFilePumpThread::~eFilePumpThread()
{
+ Close();
+}
+//-------------------------------------------------------------------------------
+
+bool eFilePumpThread::Open(std::string aFileName)
+{
+ mFileFd = open(aFileName.c_str(), O_RDONLY | O_LARGEFILE);
+ if(mFileFd <= 0) {
+ return false;
+ }
+ mFileSize = lseek(mFileFd, 0, SEEK_END);
+ SeekOffset(0);
+ return true;
+}
+//-------------------------------------------------------------------------------
+
+void eFilePumpThread::Close()
+{
+ if(mFileFd > 0) {
+ close(mFileFd);
+ }
+ mFileFd = 0;
+}
+//-------------------------------------------------------------------------------
+
+void eFilePumpThread::SeekOffset(int aOffset)
+{
+ int offset = aOffset;
+ if(offset > mFileSize) {
+ offset = mFileSize;
+ }
+ lseek(mFileFd, offset, SEEK_SET);
}
//-------------------------------------------------------------------------------
void eFilePumpThread::Run()
{
- int rc = 0;
+ int rc = 0, wc = 0;
unsigned char buffer[BUFFER_SIZE];
- int mediafilefd = open(mFileName.c_str(), O_RDONLY | O_LARGEFILE);
struct pollfd pollevt;
- pollevt.fd = mDeviceFd;
- pollevt.events = POLLOUT;
- pollevt.revents = 0;
+ pollevt.fd = mDeviceFd;
+ pollevt.events = POLLOUT;
mTermFlag = true;
while(mTermFlag) {
+ pollevt.revents = 0;
rc = poll((struct pollfd*)&pollevt, 1, 1000);
if (pollevt.revents & POLLOUT) {
- rc = read(mediafilefd, buffer, BUFFER_SIZE);
+ rc = read(mFileFd, buffer, BUFFER_SIZE);
if(rc < 0) {
break;
}
+ wc = write(mDeviceFd, buffer, rc);
+ if(wc != rc) {
#ifdef DEBUG_LOG
- LOG("%d byte write.", rc);
+ LOG("write fail.. rc[%d], wc[%d]", rc, wc);
#endif
- rc = write(mDeviceFd, buffer, rc);
+ int read_len = rc;
+ fd_set device_writefds;
+
+ FD_ZERO(&device_writefds);
+ FD_SET(mDeviceFd, &device_writefds);
+
+ for(int i = wc; i < read_len; i += wc) {
+ if (select(mDeviceFd + 1, 0, &device_writefds, 0, 0) < 0)
+ break;
+ wc = write(mDeviceFd, buffer + i, read_len - i);
+ }
+ }
}
}
- close(mediafilefd);
+ Close();
mTermFlag = false;
}
//-------------------------------------------------------------------------------
diff --git a/src/eFilePumpThread.h b/src/eFilePumpThread.h
index 1e8136d..62f3715 100644
--- a/src/eFilePumpThread.h
+++ b/src/eFilePumpThread.h
@@ -14,16 +14,21 @@
class eFilePumpThread : public uThread
{
private:
- bool mTermFlag;
int mDeviceFd;
- std::string mFileName;
+ int mFileFd, mFileSize;
+ bool mTermFlag;
+
protected:
void Run();
void Terminate();
public:
- eFilePumpThread(int aDeviceFd, std::string aFileName);
+ eFilePumpThread(int aDeviceFd);
~eFilePumpThread();
+
+ bool Open(std::string aFileName);
+ void Close();
+ void SeekOffset(int aOffset);
};
//-------------------------------------------------------------------------------
diff --git a/src/eNetworkPumpThread.cpp b/src/eNetworkPumpThread.cpp
index dc8972e..236a05d 100644
--- a/src/eNetworkPumpThread.cpp
+++ b/src/eNetworkPumpThread.cpp
@@ -12,6 +12,7 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
+#include <unistd.h>
#include <sys/ioctl.h>
#include "ePreDefine.h"
@@ -53,10 +54,12 @@ Content-Type: video/mpeg\r\n\
Server: stream_enigma2\r\n\
\r\n";
- write(1, c, strlen(c));
-
+ wc = write(1, c, strlen(c));
+#ifdef DEBUG_LOG
+ LOG("network pump start.", rc);
+#endif
while(mTermFlag) {
- rc = poll((struct pollfd*)&pollevt, 1, 1000);
+ rc = poll((struct pollfd*)&pollevt, 1, 500);
if (pollevt.revents & POLLIN) {
rc = read(mDeviceFd, buffer, BUFFER_SIZE);
@@ -66,18 +69,20 @@ Server: stream_enigma2\r\n\
#endif
continue;
}
-#ifdef DEBUG_LOG
- LOG("%d byte read", rc);
-#endif
wc = write(1, buffer, rc);
#ifdef DEBUG_LOG
- LOG("%d byte write", wc);
+ if(wc != rc) {
+ LOG("write fail.. rc[%d], wc[%d]", rc, wc);
+ }
#endif
} else if (pollevt.revents & POLLHUP) {
ioctl(mDeviceFd, 200, 0);
break;
}
}
+#ifdef DEBUG_LOG
+ LOG("network pump stoped.", rc);
+#endif
mTermFlag = false;
}
//-------------------------------------------------------------------------------
diff --git a/src/eNetworkPumpThread.h b/src/eNetworkPumpThread.h
index 892c161..bd694b5 100644
--- a/src/eNetworkPumpThread.h
+++ b/src/eNetworkPumpThread.h
@@ -5,8 +5,8 @@
* Author: kos
*/
-#ifndef EDEMUXPUMPTHREAD_H_
-#define EDEMUXPUMPTHREAD_H_
+#ifndef ENETWORKPUMPTHREAD_H_
+#define ENETWORKPUMPTHREAD_H_
#include "uThread.h"
//-------------------------------------------------------------------------------
@@ -25,4 +25,4 @@ public:
};
//-------------------------------------------------------------------------------
-#endif /* EDEMUXPUMPTHREAD_H_ */
+#endif /* ENETWORKPUMPTHREAD_H_ */
diff --git a/src/eParser.cpp b/src/eParser.cpp
new file mode 100644
index 0000000..43b3466
--- /dev/null
+++ b/src/eParser.cpp
@@ -0,0 +1,277 @@
+/*
+ * eParser.cpp
+ *
+ * Created on: 2013. 10. 29.
+ * Author: kos
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+
+#include <vector>
+#include <string>
+#include <fstream>
+#include <iterator>
+
+#include "eParser.h"
+#include "ePreDefine.h"
+#include "eURIDecoder.h"
+#include "uStringTool.h"
+#include "eDemuxPumpThread.h"
+
+using namespace std;
+//-------------------------------------------------------------------------------
+
+#ifdef DEBUG_LOG
+//#undef LOG
+//#define LOG(X,...) { do{}while(0); }
+#endif
+//-------------------------------------------------------------------------------
+
+bool eParser::Authorization(char* aAuthorization)
+{
+ char request[MAX_LINE_LENGTH] = {0};
+ while(true) {
+ int nullidx = 0;
+
+ request[0] = 0;
+ if(!ReadRequest(request)) {
+ return 1;
+ }
+ if(!strncasecmp(request, "Authorization: ", 15)) {
+ strcpy(aAuthorization, request);
+ }
+ nullidx = strlen(request);
+ if(nullidx) {
+ nullidx = (request[nullidx - 2] == '\r') ? nullidx - 2 : nullidx -1;
+ request[nullidx] = 0;
+ }
+#ifdef DEBUG_LOG
+ LOG("[%s](%d)", request, nullidx);
+#endif
+ if(!request[0]) break;
+ }
+ return 0;
+}
+//-------------------------------------------------------------------------------
+
+void eParser::FileName(char* aRequest, char* aHttp, std::string& aOutData)
+{
+ char tmp[256] = {0};
+ char* file = aRequest + 5;
+ if (strncmp(file, "file?file=", strlen("file?file="))) {
+ return;
+ }
+ strncpy(tmp, file+10, aHttp-file-10);
+ aOutData = eURIDecoder().Decode(tmp);
+}
+//-------------------------------------------------------------------------------
+
+namespace eCacheID {
+ enum {
+ cVPID = 0,
+ cAPID,
+ cTPID,
+ cPCRPID,
+ cAC3PID,
+ cVTYPE,
+ cACHANNEL,
+ cAC3DELAY,
+ cPCMDELAY,
+ cSUBTITLE,
+ cacheMax
+ };
+};
+//-------------------------------------------------------------------------------
+
+/* f:40,c:00007b,c:01008f,c:03007b */
+bool eParser::MetaData(std::string aMediaFileName, int& aVideoPid, int& aAudioPid)
+{
+ std::string metafilename = aMediaFileName;
+ metafilename += ".meta";
+
+ std::ifstream ifs(metafilename.c_str());
+
+ if (!ifs.is_open()) {
+#ifdef DEBUG_LOG
+ LOG("metadata is not exists..");
+#endif
+ return false;
+ }
+
+ size_t rc = 0, i = 0;
+ char buffer[1024] = {0};
+ while (!ifs.eof()) {
+ ifs.getline(buffer, 1024);
+ if (i++ == 7) {
+#ifdef DEBUG_LOG
+ LOG("%d [%s]", i, buffer);
+#endif
+ std::vector<string> tokens;
+ uStringTool::Split(buffer, ',', tokens);
+ if(tokens.size() < 3) {
+#ifdef DEBUG_LOG
+ LOG("pid count size error : %d", tokens.size());
+#endif
+ return false;
+ }
+
+ int setting_done = false;
+ for (int ii = 0; ii < tokens.size(); ++ii) {
+ std::string token = tokens[ii];
+ if(token.length() <= 0) continue;
+ if(token.at(0) != 'c') continue;
+
+ int cache_id = atoi(token.substr(2,2).c_str());
+#ifdef DEBUG_LOG
+ LOG("token : %d [%s], chcke_id : [%d]", ii, token.c_str(), cache_id);
+#endif
+ switch(cache_id) {
+ case(eCacheID::cVPID):
+ aVideoPid = strtol(token.substr(4,4).c_str(), NULL, 16);
+#ifdef DEBUG_LOG
+ LOG("video pid : %d", aVideoPid);
+#endif
+ setting_done = (aVideoPid && aAudioPid) ? true : false;
+ break;
+ case(eCacheID::cAC3PID):
+ aAudioPid = strtol(token.substr(4,4).c_str(), NULL, 16);
+#ifdef DEBUG_LOG
+ LOG("audio pid : %d", aAudioPid);
+#endif
+ break;
+ case(eCacheID::cAPID):
+ aAudioPid = strtol(token.substr(4,4).c_str(), NULL, 16);
+#ifdef DEBUG_LOG
+ LOG("audio pid : %d", aAudioPid);
+#endif
+ setting_done = (aVideoPid && aAudioPid) ? true : false;
+ break;
+ }
+ if(setting_done) break;
+ }
+ break;
+ }
+ }
+ ifs.close();
+ return true;
+}
+//-------------------------------------------------------------------------------
+
+unsigned long StripPid(std::string aData, std::string& aOutType)
+{
+ std::vector<std::string> token;
+ if(uStringTool::Split(aData, ':', token)) {
+ aOutType = token[1].c_str();
+ return strtoul(token[0].c_str(), 0, 0x10);
+ }
+ return -1;
+}
+//-------------------------------------------------------------------------------
+
+bool eParser::LiveStreamPid(std::string aData, std::vector<unsigned long>& aPidList,
+ int& aDemuxId, int& aVideoPid, int& aAudioPid, std::string& aWWWAuth)
+{
+ int state = 0;
+ int responsecode = 0;
+
+ std::string reason = "";
+
+ std::vector<std::string> tokens;
+ if(uStringTool::Split(aData, '\n', tokens)) {
+ int tokenlen = tokens.size();
+ for(int i = 0; i < tokenlen; i++) {
+ std::string line = uStringTool::Trim(tokens[i]);
+#ifdef DEBUG_LOG
+ LOG("[%d] [%s]", state, line.c_str());
+#endif
+ switch (state) {
+ case 0:
+ if(strncmp(line.c_str(), "HTTP/1.", 7) || line.length() < 9) {
+ return false;
+ }
+ responsecode = atoi(line.c_str() + 9);
+ if(responsecode != 200) {
+ reason = line.c_str() + 9;
+ }
+ ++state;
+ break;
+ case 1:
+ if(line.length()) {
+ if (!strncasecmp(line.c_str(), "WWW-Authenticate: ", 18)) {
+ aWWWAuth = line;
+ }
+ } else {
+ if(responsecode == 200) {
+ ++state;
+ }
+ }
+ break;
+ case 2:
+ case 3:
+ if(line.length() > 0 && line.at(0) == '+') {
+ /*+0:0:pat,17d4:pmt,17de:video,17e8:audio,17e9:audio,17eb:audio,17ea:audio,17f3:subtitle,17de:pcr,17f2:text*/
+ aDemuxId = atoi(line.substr(1,1).c_str());
+
+ std::vector<std::string> pidtokens;
+ if(uStringTool::Split(line.c_str()+3, ',', pidtokens)) {
+ for(int ii = 0; ii < pidtokens.size(); ++ii) {
+ std::string pidtype = "";
+ unsigned long pid = StripPid(pidtokens[ii], pidtype);
+
+ if(pid == -1) {
+ continue;
+ }
+ if(aVideoPid == 0) {
+ if(strcmp(pidtype.c_str(), "video") == 0) {
+ aVideoPid = pid;
+ }
+ }
+ if(aAudioPid == 0) {
+ if(strcmp(pidtype.c_str(), "audio") == 0) {
+ aAudioPid = pid;
+ }
+ }
+
+ if(!eDemuxPumpThread::ExistPid(aPidList, pid)) {
+ aPidList.push_back(pid);
+ }
+#ifdef DEBUG_LOG
+ LOG("pid : %s [%04X]", pidtokens[ii].c_str(), pid);
+#endif
+// if(aAudioPid && aVideoPid) {
+// return true;
+// }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+#ifdef DEBUG_LOG
+ LOG("response code : %d, wwwathenticate : [%s]", responsecode, aWWWAuth.c_str());
+#endif
+ return true;
+}
+//-------------------------------------------------------------------------------
+
+/*GET /1:0:19:2B66:3F3:1:C00000:0:0:0: HTTP/1.1*/
+std::string eParser::ServiceRef(std::string aData, std::string aAuthorization)
+{
+ std::string request = "";
+ std::vector<std::string> tokens;
+ if(uStringTool::Split(aData, ' ', tokens)) {
+ request += "GET /web/stream?StreamService=";
+ request += tokens[0];
+ request += " HTTP/1.0\r\n";
+ request += aAuthorization;
+ request += "\r\n";
+ }
+ return request;
+}
+//-------------------------------------------------------------------------------
+
+
diff --git a/src/eParser.h b/src/eParser.h
new file mode 100644
index 0000000..60581cd
--- /dev/null
+++ b/src/eParser.h
@@ -0,0 +1,29 @@
+/*
+ * eParser.h
+ *
+ * Created on: 2013. 10. 29.
+ * Author: kos
+ */
+
+#ifndef EPARSER_H_
+#define EPARSER_H_
+
+#include <vector>
+#include <string>
+
+using namespace std;
+//-------------------------------------------------------------------------------
+
+class eParser
+{
+public:
+ static bool Authorization(char* aAuthorization);
+ static void FileName(char* aRequest, char* aHttp, std::string& aOutData);
+ static bool MetaData(std::string aMediaFileName, int& aVideoPid, int& aAudioPid);
+ static bool LiveStreamPid(std::string aData, std::vector<unsigned long>& aPidList,
+ int& aDemuxId, int& aVideoPid, int& aAudioPid, std::string& aWWWAuth);
+ static std::string ServiceRef(std::string aData, std::string aAuthorization);
+};
+//-------------------------------------------------------------------------------
+
+#endif /* EPARSER_H_ */
diff --git a/src/ePreDefine.h b/src/ePreDefine.h
index 57a8688..cb20892 100644
--- a/src/ePreDefine.h
+++ b/src/ePreDefine.h
@@ -16,9 +16,17 @@
#define RETURN_ERR_502(FMT,...) { printf("HTTP/1.0 502 Bad Gateway\r\n"FMT"\r\n\r\n", ##__VA_ARGS__); return 1; }
//-------------------------------------------------------------------------------
+char* ReadRequest(char* aRequest);
+
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
#ifdef DEBUG_LOG
-extern FILE* fpLog;
-#define LOG(X,...) { fprintf(fpLog, "%s:%s(%d) "X"\n",__FILE__,__FUNCTION__,__LINE__,##__VA_ARGS__); fflush(fpLog); }
-#endif
+ extern FILE* fpLog;
+ #define LOG(X,...) { fprintf(fpLog, "%s:%s(%d) "X"\n",__FILE__,__FUNCTION__,__LINE__,##__VA_ARGS__); fflush(fpLog); }
+#endif /*DEBUG_LOG*/
#endif /* FILESTREAMPROXY_H_ */
diff --git a/src/eTransCodingDevice.cpp b/src/eTransCodingDevice.cpp
new file mode 100644
index 0000000..280ba73
--- /dev/null
+++ b/src/eTransCodingDevice.cpp
@@ -0,0 +1,107 @@
+/*
+ * eTransCodingDevice.cpp
+ *
+ * Created on: 2013. 11. 3.
+ * Author: kos
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include "ePreDefine.h"
+#include "eTransCodingDevice.h"
+//-------------------------------------------------------------------------------
+
+#ifdef DEBUG_LOG
+//#undef LOG
+//#define LOG(X,...) { do{}while(0); }
+#endif
+
+eTransCodingDevice::eTransCodingDevice()
+ : mDeviceFd(0)
+{
+}
+//-------------------------------------------------------------------------------
+
+eTransCodingDevice::~eTransCodingDevice()
+{
+ Close();
+}
+//-------------------------------------------------------------------------------
+
+bool eTransCodingDevice::Open()
+{
+ mDeviceFd = open("/dev/bcm_enc0", O_RDWR);
+ if(mDeviceFd <= 0) {
+ mDeviceFd = 0;
+#ifdef DEBUG_LOG
+ LOG("transcoding device open failed.");
+#endif
+ return false;
+ }
+#ifdef DEBUG_LOG
+ LOG("transcoding device open ok.");
+#endif
+ return true;
+}
+//-------------------------------------------------------------------------------
+
+void eTransCodingDevice::Close()
+{
+ StopTranscoding();
+ if(mDeviceFd == 0) {
+ close(mDeviceFd);
+ }
+ mDeviceFd = 0;
+}
+//-------------------------------------------------------------------------------
+
+int eTransCodingDevice::GetDeviceFd()
+{
+ return mDeviceFd;
+}
+//-------------------------------------------------------------------------------
+
+bool eTransCodingDevice::SetStreamPid(int aVideoPid, int aAudioPid)
+{
+ if(ioctl(mDeviceFd, 1, aVideoPid) < 0) {
+#ifdef DEBUG_LOG
+ LOG("setting stream video pid failed.");
+#endif
+ return false;
+ }
+ if(ioctl(mDeviceFd, 2, aAudioPid) < 0) {
+#ifdef DEBUG_LOG
+ LOG("setting stream audio pid failed.");
+#endif
+ return false;
+ }
+#ifdef DEBUG_LOG
+ LOG("setting stream pid ok.");
+#endif
+ return true;
+}
+//-------------------------------------------------------------------------------
+
+bool eTransCodingDevice::StartTranscoding()
+{
+ if(ioctl(mDeviceFd, 100, 0) < 0) {
+#ifdef DEBUG_LOG
+ LOG("start transcoding failed.");
+#endif
+ return false;
+ }
+#ifdef DEBUG_LOG
+ LOG("start transcoding ok.");
+#endif
+ return true;
+}
+//-------------------------------------------------------------------------------
+
+void eTransCodingDevice::StopTranscoding()
+{
+ ioctl(mDeviceFd, 200, 0);
+}
+//-------------------------------------------------------------------------------
diff --git a/src/eTransCodingDevice.h b/src/eTransCodingDevice.h
new file mode 100644
index 0000000..fbc1fcf
--- /dev/null
+++ b/src/eTransCodingDevice.h
@@ -0,0 +1,31 @@
+/*
+ * eTransCodingDevice.h
+ *
+ * Created on: 2013. 11. 3.
+ * Author: kos
+ */
+
+#ifndef ETRANSCODINGDEVICE_H_
+#define ETRANSCODINGDEVICE_H_
+
+class eTransCodingDevice
+{
+private:
+ int mDeviceFd;
+public:
+ eTransCodingDevice();
+ ~eTransCodingDevice();
+
+ bool Open();
+ void Close();
+
+ int GetDeviceFd();
+
+ bool SetStreamPid(int aVideoPid, int aAudioPid);
+
+ bool StartTranscoding();
+ void StopTranscoding();
+};
+//-------------------------------------------------------------------------------
+
+#endif /* ETRANSCODINGDEVICE_H_ */
diff --git a/src/eURIDecoder.cpp b/src/eURIDecoder.cpp
index ea95751..cbbbf12 100644
--- a/src/eURIDecoder.cpp
+++ b/src/eURIDecoder.cpp
@@ -204,6 +204,7 @@ const wchar_t* eURIDecoder::DecodeURI(wchar_t* aData, int aBreakCond)
write += 2;
prevWasCr = false;
+ break;
}
break;
@@ -215,6 +216,7 @@ const wchar_t* eURIDecoder::DecodeURI(wchar_t* aData, int aBreakCond)
write++;
prevWasCr = false;
+ break;
}
break;
@@ -236,6 +238,7 @@ const wchar_t* eURIDecoder::DecodeURI(wchar_t* aData, int aBreakCond)
write++;
prevWasCr = false;
+ break;
}
}
return NULL;
diff --git a/src/eUpstreamSocket.cpp b/src/eUpstreamSocket.cpp
new file mode 100644
index 0000000..b16251b
--- /dev/null
+++ b/src/eUpstreamSocket.cpp
@@ -0,0 +1,101 @@
+/*
+ * eUpstreamPumpThread.cpp
+ *
+ * Created on: 2013. 10. 30.
+ * Author: kos
+ */
+
+#include "eUpstreamSocket.h"
+#include "ePreDefine.h"
+
+#include <poll.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+using namespace std;
+
+#ifdef DEBUG_LOG
+//#undef LOG
+//#define LOG(X,...) { do{}while(0); }
+#endif
+
+eUpstreamSocket::eUpstreamSocket()
+ : mSockFd(-1)
+{
+}
+//-------------------------------------------------------------------------------
+
+eUpstreamSocket::~eUpstreamSocket()
+{
+}
+//-------------------------------------------------------------------------------
+
+bool eUpstreamSocket::Connect()
+{
+ mSockFd = socket(PF_INET, SOCK_STREAM, 0);
+
+ mSockAddr.sin_family = AF_INET;
+ mSockAddr.sin_port = htons(80);
+ mSockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+ if(connect(mSockFd, (struct sockaddr*)&mSockAddr, sizeof(struct sockaddr_in))) {
+ return false;
+ }
+ return true;
+}
+//-------------------------------------------------------------------------------
+
+int eUpstreamSocket::Send(std::string aData)
+{
+#ifdef DEBUG_LOG
+ LOG("Send : %s", aData.c_str());
+#endif
+ return write(mSockFd, aData.c_str(), aData.length());
+}
+//-------------------------------------------------------------------------------
+
+int eUpstreamSocket::Recv(std::string& aData)
+{
+ int rc = 0;
+ char buffer[4096] = {0};
+ struct pollfd pollevt;
+
+ pollevt.fd = mSockFd;
+ pollevt.events = POLLIN | POLLERR;
+
+ while(true) {
+ buffer[0] = 0;
+ pollevt.revents = 0;
+
+ rc = poll((struct pollfd*)&pollevt, 1, 1000);
+
+ if (pollevt.revents == 0) {
+ break;
+ } else if (pollevt.revents & POLLIN) {
+ rc = read(mSockFd, buffer, 4096);
+#ifdef DEBUG_LOG
+ LOG("Buffer : %s", buffer);
+#endif
+ aData += buffer;
+ }
+ }
+ return aData.length();
+}
+//-------------------------------------------------------------------------------
+
+int eUpstreamSocket::Request(std::string aSendData, std::string& aRecvData)
+{
+ int rc = Send(aSendData);
+ if(rc > 0) {
+ std::string recvdata;
+ rc = Recv(recvdata);
+ if(rc > 0) {
+ aRecvData = recvdata;
+ }
+ }
+ return rc;
+}
+//-------------------------------------------------------------------------------
+
+
diff --git a/src/eUpstreamSocket.h b/src/eUpstreamSocket.h
new file mode 100644
index 0000000..72c5ba7
--- /dev/null
+++ b/src/eUpstreamSocket.h
@@ -0,0 +1,35 @@
+/*
+ * eUpstreamPumpThread.h
+ *
+ * Created on: 2013. 10. 30.
+ * Author: kos
+ */
+
+#ifndef EUPSTREAMSOCKET_H_
+#define EUPSTREAMSOCKET_H_
+
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+
+#include <string>
+//-------------------------------------------------------------------------------
+
+class eUpstreamSocket
+{
+private:
+ int mSockFd;
+ struct sockaddr_in mSockAddr;
+
+public:
+ eUpstreamSocket();
+ virtual ~eUpstreamSocket();
+
+ bool Connect();
+ int Send(std::string aData);
+ int Recv(std::string& aData);
+
+ int Request(std::string aSendData, std::string& aRecvData);
+};
+//-------------------------------------------------------------------------------
+
+#endif /* EUPSTREAMSOCKET_H_ */
diff --git a/src/main.cpp b/src/main.cpp
index 967b64b..f029591 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -10,7 +10,10 @@
#include <fcntl.h>
#include <poll.h>
#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
#include <sys/ioctl.h>
+#include <stdint.h>
#include <vector>
#include <string>
@@ -18,8 +21,13 @@
#include <fstream>
#include "ePreDefine.h"
-#include "eURIDecoder.h"
+#include "eParser.h"
+#include "eUpstreamSocket.h"
+#include "eTransCodingDevice.h"
+#include "uStringTool.h"
+
#include "eFilePumpThread.h"
+#include "eDemuxPumpThread.h"
#include "eNetworkPumpThread.h"
#ifdef DEBUG_LOG
@@ -31,27 +39,30 @@ FILE* fpLog = fopen("/tmp/filestreamproxy.log", "w");
using namespace std;
//-------------------------------------------------------------------------------
-int gDeviceFd = 0;
+eFilePumpThread* hFilePumpThread = 0;
+eDemuxPumpThread* hDemuxPumpThread = 0;
+eNetworkPumpThread* hNetworkPumpThread = 0;
+eTransCodingDevice* hTranscodingDevice = 0;
-char* ReadRequest(char* aRequest)
-{
- return fgets(aRequest, MAX_LINE_LENGTH-1, stdin);
-}
+void SignalHandler(int aSigNo);
//-------------------------------------------------------------------------------
-namespace eParser {
- int gVideoPid = 0, gAudioPid = 0;
- std::vector<string> Split(std::string aBuffer, char aDelimiter);
- void FileName(char* aRequest, char* aHttp, std::string& aOutData);
- bool MetaData(std::string aMediaFileName);
-};
-using namespace eParser;
-//-------------------------------------------------------------------------------
-
-/* GET /file?file=/home/kos/work/workspace/filestreamproxy/data/20131023%200630%20-%20FASHION%20TV%20-%20instant%20record.ts HTTP/1.0 */
+/*
+GET /1:0:19:2B66:3F3:1:C00000:0:0:0: HTTP/1.1
+Host: 192.168.102.177:8002
+User-Agent: VLC/2.0.8 LibVLC/2.0.8
+Range: bytes=0-
+Connection: close
+Icy-MetaData: 1
+
+GET /file?file=/hdd/movie/20131023%201005%20-%20DW%20-%20Germany%20Today.ts HTTP/1.1
+*/
int main(int argc, char** argv)
{
char request[MAX_LINE_LENGTH] = {0};
+ int videopid = 0, audiopid = 0;
+
+ signal(SIGINT, SignalHandler);
if (!ReadRequest(request)) {
RETURN_ERR_400();
@@ -69,170 +80,175 @@ int main(int argc, char** argv)
RETURN_ERR_400("Not support request (%s).", http);
}
- std::string srcfilename = "";
- eParser::FileName(request, http, srcfilename);
-
- bool isSuccessMeta = eParser::MetaData(srcfilename);
-
#ifdef DEBUG_LOG
- LOG("meta parsing result : %d, video : %d, audio : %d", isSuccessMeta, eParser::gVideoPid, eParser::gAudioPid);
+ LOG("%s", request + 5);
#endif
- gDeviceFd = open("/dev/bcm_enc0", O_RDWR);
- if(gDeviceFd < 0 ) {
- close(gDeviceFd);
- RETURN_ERR_502("Fail to opne device.");
+ eTransCodingDevice transcoding;
+ if(transcoding.Open() == false) {
+ RETURN_ERR_502("Opne device failed.");
}
+ hTranscodingDevice = &transcoding;
- if(isSuccessMeta) {
- if(ioctl(gDeviceFd, 1, eParser::gVideoPid)) {
- RETURN_ERR_502("Fail to set video pid");
- }
- if(ioctl(gDeviceFd, 2, eParser::gAudioPid)) {
- RETURN_ERR_502("Fail to set audio pid");
- }
- }
+ bool ispidseted = false;
+ eNetworkPumpThread networkpump(transcoding.GetDeviceFd());
+ hNetworkPumpThread = &networkpump;
- eFilePumpThread filepump(gDeviceFd, srcfilename);
- filepump.Start();
-
- sleep(1);
-
- if(ioctl(gDeviceFd, 100, 0)) {
- RETURN_ERR_502("Fail to start transcoding.");
- }
- eNetworkPumpThread networkpump(gDeviceFd);
- networkpump.Start();
-
- networkpump.Join();
- filepump.Stop();
- filepump.Join();
+ if(strncmp(request + 4, "/file?", 6) != 0) {
+ char authorization[MAX_LINE_LENGTH] = {0};
+ if(eParser::Authorization(authorization)) {
+ RETURN_ERR_401();
+ }
- close(gDeviceFd);
+ eUpstreamSocket upstreamsocket;
+ if(!upstreamsocket.Connect()) {
+ RETURN_ERR_502("Upstream connect failed.");
+ }
+ std::string responsedata = "";
+ if(upstreamsocket.Request(eParser::ServiceRef(request + 5, authorization), responsedata) < 0) {
+ RETURN_ERR_502("Upstream request failed.");
+ }
+ int demuxno = 0;
+ std::string wwwauthenticate = "";
+ std::vector<unsigned long> pidlist;
+ ispidseted = eParser::LiveStreamPid(responsedata, pidlist, demuxno, videopid, audiopid, wwwauthenticate);
+ if(ispidseted) {
+ if(transcoding.SetStreamPid(videopid, audiopid) == false) {
+ RETURN_ERR_502("Pid setting failed.");
+ }
+ } else {
#ifdef DEBUG_LOG
- fclose(fpLog);
+ LOG("Invalid upstream response.");
#endif
- return 0;
-}
-//-------------------------------------------------------------------------------
-
-std::vector<string> eParser::Split(std::string aBuffer, char aDelimiter)
-{
- int b = 0, i = 0, l = aBuffer.length();
- std::vector<string> t;
-
- while (i++ < l) {
- if (aBuffer[i] == aDelimiter) {
- t.push_back(aBuffer.substr(b, i-b));
- b = i + 1;
- continue;
+ RETURN_ERR_502("Invalid upstream response.");
}
- if (i == (l - 1)) {
- t.push_back(aBuffer.substr(b, l));
- }
- }
- return t;
-}
-//-------------------------------------------------------------------------------
-void eParser::FileName(char* aRequest, char* aHttp, std::string& aOutData)
-{
- char tmp[256] = {0};
- char* file = aRequest + 5;
- if (strncmp(file, "file?file=", strlen("file?file="))) {
- return;
- }
- strncpy(tmp, file+10, aHttp-file-10);
- aOutData = eURIDecoder().Decode(tmp);
-}
-//-------------------------------------------------------------------------------
-
-namespace eCacheID {
- enum {
- cVPID = 0,
- cAPID,
- cTPID,
- cPCRPID,
- cAC3PID,
- cVTYPE,
- cACHANNEL,
- cAC3DELAY,
- cPCMDELAY,
- cSUBTITLE,
- cacheMax
- };
-};
-//-------------------------------------------------------------------------------
-
-/* f:40,c:00007b,c:01008f,c:03007b */
-bool eParser::MetaData(std::string aMediaFileName)
-{
- std::string metafilename = aMediaFileName;
- metafilename += ".meta";
-
- std::ifstream ifs(metafilename.c_str());
-
- if (!ifs.is_open()) {
#ifdef DEBUG_LOG
- LOG("metadata is not exists..");
+ LOG("stream pids parsing result : %d, video : %d, audio : %d, pids size : [%d]", ispidseted, videopid, audiopid, pidlist.size());
+ for(int j = 0; j < pidlist.size(); ++j) {
+ LOG("saved pid : [%x]", pidlist[j]);
+ }
#endif
- return false;
- }
- size_t rc = 0, i = 0;
- char buffer[1024] = {0};
- while (!ifs.eof()) {
- ifs.getline(buffer, 1024);
- if (i++ == 7) {
+ eDemuxPumpThread demuxpump;
+ if(!demuxpump.Open(demuxno)) {
+ RETURN_ERR_502("%s", demuxpump.GetMessage().c_str());
+ }
+ demuxpump.SetDeviceFd(transcoding.GetDeviceFd());
+ demuxpump.Start();
+ hDemuxPumpThread = &demuxpump;
+
+ if(pidlist.size() > 0) {
+ if(demuxpump.GetState() < eDemuxState::stSetedFilter) {
+ if(!demuxpump.SetFilter(pidlist)) {
#ifdef DEBUG_LOG
- LOG("%d [%s]", i, buffer);
+ LOG("Demux setting filter failed.");
#endif
- std::vector<string> tokens = eParser::Split(buffer, ',');
- if(tokens.size() < 3) {
+ RETURN_ERR_502("Demux setting filter failed.");
+ }
+ }
+ if(!demuxpump.SetPidList(pidlist)) {
#ifdef DEBUG_LOG
- LOG("pid count size error : %d", tokens.size());
+ LOG("PID setting failed.");
#endif
- return false;
+ RETURN_ERR_502("PID setting failed.");
}
+ } else {
+#ifdef DEBUG_LOG
+ LOG("No found PID for selected stream.");
+#endif
+ RETURN_ERR_502("No found PID for selected stream.");
+ }
+#ifdef NORMAL_STREAMPROXY
+ demuxpump.Join();
+#else
+ if(transcoding.StartTranscoding() == false) {
+ RETURN_ERR_502("Transcoding start failed.");
+ }
+ networkpump.Start();
+ networkpump.Join();
+ demuxpump.Stop();
+ demuxpump.Join();
+#endif
+ } else {
+ std::string srcfilename = "";
+ eParser::FileName(request, http, srcfilename);
- int setting_done = false;
- for (int ii = 0; ii < tokens.size(); ++ii) {
- std::string token = tokens[ii];
- if(token.at(0) != 'c') continue;
+ ispidseted = eParser::MetaData(srcfilename, videopid, audiopid);
+ if(ispidseted) {
+ if(transcoding.SetStreamPid(videopid, audiopid) == false) {
+#ifdef DEBUG_LOG
+ LOG("No found PID for selected stream.");
+#endif
+ RETURN_ERR_502("Pid setting failed.");
+ }
+ }
+#ifdef DEBUG_LOG
+ LOG("meta parsing result : %d, video : %d, audio : %d", ispidseted, videopid, audiopid);
+#endif
- int cache_id = atoi(token.substr(2,2).c_str());
+ eFilePumpThread filepump(transcoding.GetDeviceFd());
+ if(filepump.Open(srcfilename) == false) {
#ifdef DEBUG_LOG
- LOG("token : %d [%s], chcke_id : [%d]", ii, token.c_str(), cache_id);
+ LOG("TS file open failed.");
#endif
- switch(cache_id) {
- case(eCacheID::cVPID):
- gVideoPid = strtol(token.substr(4,4).c_str(), NULL, 16);
+ RETURN_ERR_502("TS file open failed.");
+ }
+ filepump.Start();
+ hFilePumpThread = &filepump;
+
+ if(transcoding.StartTranscoding() == false) {
#ifdef DEBUG_LOG
- LOG("video pid : %d", gVideoPid);
+ LOG("Transcoding start failed.");
#endif
- setting_done = (gVideoPid && gAudioPid) ? true : false;
- break;
- case(eCacheID::cAC3PID):
- gAudioPid = strtol(token.substr(4,4).c_str(), NULL, 16);
+ RETURN_ERR_502("Transcoding start failed.");
+ }
+ filepump.SeekOffset(0);
+
+ networkpump.Start();
+ networkpump.Join();
+ filepump.Stop();
+ filepump.Join();
+ }
#ifdef DEBUG_LOG
- LOG("audio pid : %d", gAudioPid);
+ fclose(fpLog);
#endif
- break;
- case(eCacheID::cAPID):
- gAudioPid = strtol(token.substr(4,4).c_str(), NULL, 16);
+ return 0;
+}
+//-------------------------------------------------------------------------------
+
+char* ReadRequest(char* aRequest)
+{
+ return fgets(aRequest, MAX_LINE_LENGTH-1, stdin);
+}
+//-------------------------------------------------------------------------------
+
+void SignalHandler(int aSigNo)
+{
+ switch(aSigNo) {
+ case (SIGINT):
#ifdef DEBUG_LOG
- LOG("audio pid : %d", gAudioPid);
+ LOG("Detected SIGINT.");
#endif
- setting_done = (gVideoPid && gAudioPid) ? true : false;
- break;
- }
- if(setting_done) break;
- }
- break;
+ if(hFilePumpThread) {
+ hFilePumpThread->Stop();
+ }
+ if(hDemuxPumpThread) {
+ hDemuxPumpThread->Stop();
+ }
+ if(hNetworkPumpThread) {
+ hNetworkPumpThread->Stop();
}
+ if(hTranscodingDevice) {
+ hTranscodingDevice->Close();
+ }
+ sleep(2);
+ exit(1);
}
- ifs.close();
- return true;
}
//-------------------------------------------------------------------------------
+
+
+
+
diff --git a/src/uStringTool.h b/src/uStringTool.h
new file mode 100644
index 0000000..5dd0f5e
--- /dev/null
+++ b/src/uStringTool.h
@@ -0,0 +1,56 @@
+/*
+ * uStringTool.h
+ *
+ * Created on: 2013. 10. 30.
+ * Author: kos
+ */
+
+#ifndef USTRINGTOOL_H_
+#define USTRINGTOOL_H_
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+using namespace std;
+
+#define trim_default_delimiter " \t\n\v\r"
+
+namespace uStringTool
+{
+ inline std::string Trim(std::string& s, const std::string& drop = trim_default_delimiter)
+ {
+ std::string r = s.erase(s.find_last_not_of(drop) + 1);
+ return r.erase(0, r.find_first_not_of(drop));
+ }
+
+ inline std::string RTrim(std::string s, const std::string& drop = trim_default_delimiter)
+ {
+ std::string r = s.erase(s.find_last_not_of(drop) + 1);
+ return r;
+ }
+
+ inline std::string LTrim(std::string s, const std::string& drop = trim_default_delimiter)
+ {
+ std::string r = s.erase(0, s.find_first_not_of(drop));
+ return r;
+ }
+
+ inline std::string ReplaceAll(const std::string &in, const std::string &entity, const std::string &symbol)
+ {
+ std::string out = in;
+ std::string::size_type loc = 0;
+ while (( loc = out.find(entity, loc)) != std::string::npos )
+ out.replace(loc, entity.length(), symbol);
+ return out;
+ }
+
+ inline int Split(std::string data, const char delimiter, std::vector<string>& tokens)
+ {
+ std::stringstream data_stream(data);
+ for(std::string token; std::getline(data_stream, token, delimiter); tokens.push_back(Trim(token)));
+ return tokens.size();
+ }
+};
+
+#endif /* USTRINGTOOL_H_ */