summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoroskwon <kos@dev3>2014-06-18 08:17:14 (GMT)
committeroskwon <kos@dev3>2014-06-18 10:17:42 (GMT)
commit0d5d66cdee3921eba4c11859fb4edc296339e746 (patch)
tree46b377ceb7cb93a4b5a1a35d2bf2496e58435ef8
parent48a6d1332dc7f6791854511133bac81161db9a4d (diff)
Add request type(/m3u) for Vu+PlayerHD (IOS).
Remove up.sh and add some scripts. Some sources refactoring.
-rw-r--r--.gitignore6
-rwxr-xr-xscript/script.config42
-rwxr-xr-xscript/script.upload33
-rw-r--r--src/Demuxer.cpp10
-rw-r--r--src/Demuxer.h5
-rw-r--r--src/Encoder.cpp22
-rw-r--r--src/Http.cpp174
-rw-r--r--src/Http.h49
-rw-r--r--src/Logger.cpp30
-rw-r--r--src/Logger.h6
-rw-r--r--src/Makefile57
-rw-r--r--src/Mpeg.cpp46
-rw-r--r--src/Mpeg.h29
-rw-r--r--src/Util.cpp145
-rw-r--r--src/Util.h49
-rw-r--r--src/Utils.cpp278
-rw-r--r--src/Utils.h84
-rw-r--r--src/main.cpp305
-rwxr-xr-xsrc/up.sh8
19 files changed, 810 insertions, 568 deletions
diff --git a/.gitignore b/.gitignore
index 79f27fc..1ffb871 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
-*.o
-transtreamproxy
.cproject
.project
+config.mk
+config.mk.bak
+*.o
+transtreamproxy
diff --git a/script/script.config b/script/script.config
new file mode 100755
index 0000000..3f85083
--- /dev/null
+++ b/script/script.config
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+IP=192.168.0.1
+MODEL=vusolo2
+OETOP=/openembedded/path/here
+
+CONFIG_PATH=$PWD/../config.mk
+
+function getValue() {
+ IN=$1
+ set -- "$IN"
+ IFS="="; declare -a Array=($*)
+ echo "${Array[1]}"
+}
+
+# set default config value from old config.
+if [ -e $CONFIG_PATH ]; then
+ IP="$(getValue `cat $CONFIG_PATH | grep 'IP='`)"
+ MODEL="$(getValue `cat $CONFIG_PATH | grep 'MODEL='`)"
+ OETOP="$(getValue `cat $CONFIG_PATH | grep 'OETOP='`)"
+fi
+
+# input new config.
+read -p "Please, input target ip [$IP] : " NEW_IP
+read -p "Please, input model name [$MODEL] : " NEW_MODEL
+read -p "Please, input openembeded root path [$OETOP] : " NEW_OETOP
+
+# check new config value.
+if [ ! -z $NEW_IP ]; then IP=$NEW_IP; fi
+if [ ! -z $NEW_MODEL ]; then MODEL=$NEW_MODEL; fi
+if [ ! -z $NEW_OETOP ]; then OETOP=$NEW_OETOP; fi
+
+# backup config file.
+if [ -e $CONFIG_PATH ]; then
+ cp -a $CONFIG_PATH $CONFIG_PATH.bak
+fi
+
+# write config file.
+echo "MODEL=$MODEL" > $CONFIG_PATH
+echo "OETOP=$OETOP" >> $CONFIG_PATH
+echo "" >> $CONFIG_PATH
+echo "IP=$IP" >> $CONFIG_PATH
diff --git a/script/script.upload b/script/script.upload
new file mode 100755
index 0000000..841a5e1
--- /dev/null
+++ b/script/script.upload
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+IP=$1
+LOC=$2
+BIN=$3
+TAR=$4
+
+usage() {
+ echo ""
+ echo "usage : $0 [IP] [LOCAL] [BIN] [TARGET]"
+ echo " - IP : target ip"
+ echo " - BIN : binary name"
+ echo " - LOCAL : binary path"
+ echo " - TARGET : target path to install"
+ exit
+}
+
+if [ -z $IP ]; then echo "[!] IP is not set."; usage; fi
+if [ -z $BIN ]; then echo "[!] BIN is not set."; usage; fi
+if [ -z $LOC ]; then echo "[!] LOCAL is not set."; usage; fi
+if [ -z $TAR ]; then echo "[!] TARGET is not set."; usage; fi
+
+echo "[*] upload... $LOC/$BIN to $IP:$TAR"
+cd $LOC
+ftp -n $IP << +
+user root a
+prompt off
+bi
+cd $TAR
+put $BIN
+bye
++
+
diff --git a/src/Demuxer.cpp b/src/Demuxer.cpp
index a943bab..04cd35b 100644
--- a/src/Demuxer.cpp
+++ b/src/Demuxer.cpp
@@ -15,7 +15,7 @@
#include <linux/dvb/dmx.h>
#include <linux/dvb/version.h>
-#include "Utils.h"
+#include "Util.h"
#include "Logger.h"
#include "Demuxer.h"
@@ -149,11 +149,11 @@ bool Demuxer::parse_webif_response(std::string& response, std::vector<unsigned l
demux_id = atoi(line.substr(1,1).c_str());
std::vector<std::string> pidtokens;
- if (split(line.c_str() + 3, ',', pidtokens)) {
+ if (Util::split(line.c_str() + 3, ',', pidtokens)) {
for (int i = 0; i < pidtokens.size(); ++i) {
std::string pidstr, pidtype;
std::string toekn = pidtokens[i];
- if (!split_key_value(toekn, ":", pidstr, pidtype))
+ if (!Util::split_key_value(toekn, ":", pidstr, pidtype))
continue;
unsigned long pid = strtoul(pidstr.c_str(), 0, 0x10);
@@ -183,7 +183,7 @@ bool Demuxer::parse_webif_response(std::string& response, std::vector<unsigned l
}
//-------------------------------------------------------------------------------
-Demuxer::Demuxer(RequestHeader *header) throw(trap)
+Demuxer::Demuxer(HttpHeader *header) throw(trap)
{
demux_id = pat_pid = fd = sock = -1;
pmt_pid = audio_pid = video_pid = 0;
@@ -197,7 +197,7 @@ Demuxer::Demuxer(RequestHeader *header) throw(trap)
if (!parse_webif_response(webif_response, new_pids))
throw(trap("webif response parsing fail."));
- std::string demuxpath = "/dev/dvb/adapter0/demux" + ultostr(demux_id);
+ std::string demuxpath = "/dev/dvb/adapter0/demux" + Util::ultostr(demux_id);
if ((fd = open(demuxpath.c_str(), O_RDWR | O_NONBLOCK)) < 0) {
throw(trap(std::string("demux open fail : ") + demuxpath));
}
diff --git a/src/Demuxer.h b/src/Demuxer.h
index 2b8e636..033c54d 100644
--- a/src/Demuxer.h
+++ b/src/Demuxer.h
@@ -13,7 +13,8 @@
#include "trap.h"
-#include "Utils.h"
+#include "Util.h"
+#include "Http.h"
#include "Source.h"
//----------------------------------------------------------------------
@@ -39,7 +40,7 @@ protected:
bool parse_webif_response(std::string& response, std::vector<unsigned long> &new_pids);
public:
- Demuxer(RequestHeader *header) throw(trap);
+ Demuxer(HttpHeader *header) throw(trap);
virtual ~Demuxer() throw();
int get_fd() const throw();
};
diff --git a/src/Encoder.cpp b/src/Encoder.cpp
index 3b59b07..d6f817f 100644
--- a/src/Encoder.cpp
+++ b/src/Encoder.cpp
@@ -14,7 +14,7 @@
#include <string.h>
#include <sys/ioctl.h>
-#include "Utils.h"
+#include "Util.h"
#include "Logger.h"
#include "Encoder.h"
@@ -50,7 +50,7 @@ Encoder::Encoder() throw(trap)
DEBUG("shm-info : fd [%d], name [%s], size [%d], data [%p]", mShmFd, mShmName.c_str(), mShmSize, mShmData);
DEBUG("sem-info : id [%p], name [%s]", mSemId, mSemName.c_str());
- std::vector<int> pidlist = find_process_by_name("transtreamproxy", 0);
+ std::vector<int> pidlist = Util::find_process_by_name("transtreamproxy", 0);
session_dump("before init.");
@@ -66,7 +66,7 @@ Encoder::Encoder() throw(trap)
Post();
int mypid = getpid();
- std::string ipaddr = get_host_addr();
+ std::string ipaddr = Util::host_addr();
if (session_already_exist(ipaddr) > 0) {
encoder_id = session_update(ipaddr, mypid);
}
@@ -92,7 +92,7 @@ Encoder::~Encoder()
bool Encoder::encoder_open()
{
- std::string path = "/dev/bcm_enc" + ultostr(encoder_id);
+ std::string path = "/dev/bcm_enc" + Util::ultostr(encoder_id);
fd = ::open(path.c_str(), O_RDWR, 0);
if (fd >= 0) {
state = ENCODER_STAT_OPENED;
@@ -141,12 +141,14 @@ int Encoder::get_fd()
void Encoder::session_dump(const char* aMessage)
{
- DUMMY(" >> %s", aMessage);
- DUMMY("-------- [ DUMP HOST INFO ] ---------");
- for (int i = 0; i < max_encodr_count; i++) {
- DUMMY("%d : ip [%s], pid [%d]", i, mShmData[i].ip, mShmData[i].pid);
+ if (Logger::instance()->get_level() >= Logger::INFO) {
+ DUMMY(" >> %s", aMessage);
+ DUMMY("-------- [ DUMP HOST INFO ] ---------");
+ for (int i = 0; i < max_encodr_count; i++) {
+ DUMMY("%d : ip [%s], pid [%d]", i, mShmData[i].ip, mShmData[i].pid);
+ }
+ DUMMY("-------------------------------------");
}
- DUMMY("-------------------------------------");
}
//----------------------------------------------------------------------
@@ -220,7 +222,7 @@ int Encoder::session_update(std::string aIpAddr, int aPid)
for (; i < max_encodr_count; i++) {
if (strcmp(mShmData[i].ip, aIpAddr.c_str()) == 0) {
result = true;
- kill_process(mShmData[i].pid);
+ Util::kill_process(mShmData[i].pid);
memset(mShmData[i].ip, 0, 16);
mShmData[i].pid = 0;
break;
diff --git a/src/Http.cpp b/src/Http.cpp
new file mode 100644
index 0000000..7b736c6
--- /dev/null
+++ b/src/Http.cpp
@@ -0,0 +1,174 @@
+/*
+ * Http.cpp
+ *
+ * Created on: 2014. 6. 18.
+ * Author: oskwon
+ */
+
+#include <string.h>
+
+#include <sstream>
+
+#include "Util.h"
+#include "Logger.h"
+
+#include "Http.h"
+#include "UriDecoder.h"
+
+using namespace std;
+//----------------------------------------------------------------------
+
+bool HttpHeader::parse_request(std::string header)
+{
+ std::string line, key, value;
+ std::istringstream request_stream;
+ request_stream.str(header);
+
+ request_stream >> method;
+ request_stream >> path;
+ request_stream >> version;
+ std::getline(request_stream, line);
+
+ while(std::getline(request_stream, line)) {
+ if ((line = Util::trim(line)) != "") {
+ Util::split_key_value(line, ":", key, value);
+
+ key = Util::trim(key);
+ value = Util::trim(value);
+
+ params[key] = value;
+ DEBUG("add param : [%s] - [%s]", key.c_str(), value.c_str());
+ }
+ }
+
+ int idx = path.find("?");
+ // page
+ if (idx != std::string::npos) {
+ page = path.substr(0,idx);
+ std::string page_param = path.substr(idx + 1);
+
+ DEBUG("request url : [%s] - [%s]", page.c_str(), page_param.c_str());
+ std::istringstream request_params_stream;
+ request_params_stream.str(page_param);
+ while(std::getline(request_params_stream, line, '&')) {
+ if ((line = Util::trim(line)) != "") {
+ Util::split_key_value(line, "=", key, value);
+
+ key = Util::trim(key);
+ value = Util::trim(value);
+
+ page_params[key] = value;
+ DEBUG("add page param : [%s] - [%s]", key.c_str(), value.c_str());
+ }
+ }
+
+ if (page == "/file") {
+ type = HttpHeader::TRANSCODING_FILE;
+ }
+ else if (page == "/m3u") {
+ type = HttpHeader::M3U;
+ }
+ }
+ // live
+ else {
+ type = HttpHeader::TRANSCODING_LIVE;
+ }
+ return true;
+}
+//----------------------------------------------------------------------
+
+static const char *http_ok = "HTTP/1.1 200 OK\r\n";
+static const char *http_partial = "HTTP/1.1 206 Partial Content\r\n";
+static const char *http_connection = "Connection: Close\r\n";
+static const char *http_server = "Server: transtreamproxy\r\n";
+static const char *http_done = "\r\n";
+std::string HttpHeader::build_response(Mpeg *source)
+{
+ std::ostringstream oss;
+
+ switch(type) {
+ case HttpHeader::TRANSCODING_FILE: {
+ std::string range = params["Range"];
+ off_t seek_offset = 0, content_length = 0;
+
+ if((range.length() > 7) && (range.substr(0, 6) == "bytes=")) {
+ range = range.substr(6);
+ if(range.find('-') == (range.length() - 1)) {
+ seek_offset = Util::strtollu(range);
+ }
+ }
+
+ content_length = source->stream_length - seek_offset;
+ if (seek_offset > 0) {
+ content_length += 1;
+ oss << http_partial;
+ }
+ else {
+ oss << http_ok;
+ }
+ oss << http_connection;
+ oss << "Content-Type: video/mpeg\r\n";
+ oss << http_server;
+ oss << "Accept-Ranges: bytes\r\n";
+ oss << "Content-Length: " << Util::ultostr(content_length) << "\r\n";
+ oss << "Content-Range: bytes " <<
+ Util::ultostr(seek_offset) << "-" <<
+ Util::ultostr(source->stream_length - 1) << "/" <<
+ Util::ultostr(source->stream_length) << "\r\n";
+ oss << http_done;
+ }
+ break;
+ case HttpHeader::TRANSCODING_LIVE: {
+ oss << http_ok;
+ oss << http_connection;
+ oss << "Content-Type: video/mpeg\r\n";
+ oss << http_server;
+ oss << http_done;
+ }
+ break;
+ case HttpHeader::M3U: {
+ std::ostringstream m3u_oss;
+ m3u_oss << "#EXTM3U\n";
+ m3u_oss << "#EXTVLCOPT--http-reconnect=true\n";
+ m3u_oss << "http://" << params["Host"] << "/file?file=" << page_params["file"];
+ if (page_params["position"] != "") {
+ m3u_oss << "&position=" << page_params["position"];
+ }
+ m3u_oss << "\n";
+ m3u_oss << http_done;
+
+ std::string m3u_content = m3u_oss.str();
+
+ oss << http_partial;
+ oss << "Content-Type: audio/x-mpegurl\r\n";
+ oss << "Accept-Ranges: bytes\r\n";
+ oss << http_connection;
+ oss << http_server;
+ oss << "Content-Length: " << Util::ultostr(m3u_content.length()) << "\r\n";
+ oss << "Content-Range: bytes 0-" <<
+ Util::ultostr(m3u_content.length() - 1) << "/" <<
+ Util::ultostr(m3u_content.length()) << "\r\n";
+ oss << http_done;
+ oss << m3u_content;
+ }
+ break;
+ default: return "";
+ }
+ return oss.str();
+}
+//----------------------------------------------------------------------
+
+std::string HttpHeader::read_request()
+{
+ std::string request = "";
+ while (true) {
+ char buffer[128] = {0};
+ fgets(buffer, 127, stdin);
+
+ request += buffer;
+ if(request.find("\r\n\r\n") != string::npos)
+ break;
+ }
+ return request;
+}
+//----------------------------------------------------------------------
diff --git a/src/Http.h b/src/Http.h
new file mode 100644
index 0000000..31246bc
--- /dev/null
+++ b/src/Http.h
@@ -0,0 +1,49 @@
+/*
+ * Http.h
+ *
+ * Created on: 2014. 6. 18.
+ * Author: oskwon
+ */
+
+#ifndef HTTP_H_
+#define HTTP_H_
+
+#include <map>
+#include <string>
+
+#include "Mpeg.h"
+//----------------------------------------------------------------------
+
+class HttpHeader
+{
+public:
+ enum {
+ UNKNOWN = 0,
+ TRANSCODING_LIVE,
+ TRANSCODING_FILE,
+ M3U
+ };
+
+ int type;
+ std::string method;
+ std::string path;
+ std::string version;
+ std::map<std::string, std::string> params;
+
+ std::string page;
+ std::map<std::string, std::string> page_params;
+
+private:
+
+public:
+ HttpHeader() : type(UNKNOWN) {}
+ virtual ~HttpHeader() {}
+
+ bool parse_request(std::string header);
+ std::string build_response(Mpeg *source);
+
+ static std::string read_request();
+};
+//----------------------------------------------------------------------
+
+#endif /* HTTP_H_ */
diff --git a/src/Logger.cpp b/src/Logger.cpp
index 8d06b88..963a783 100644
--- a/src/Logger.cpp
+++ b/src/Logger.cpp
@@ -11,6 +11,7 @@
#include <sys/types.h>
#include "Logger.h"
+//----------------------------------------------------------------------
#define USE_COLOR_LOG 1
@@ -80,9 +81,25 @@ Logger* Logger::instance()
}
//----------------------------------------------------------------------
-bool Logger::init(const char* aName, int aLogLevel, bool aWithTimestamp, const char* aVersion)
+bool Logger::init(const char* aName, int aLogLevel, bool aWithTimestamp)
{
- mLogLevel = aLogLevel;
+ if (access("/tmp/.debug_on", F_OK) == 0) {
+ FILE *fp = fopen("/tmp/.debug_on", "r");
+
+ int lv = 0;
+ fscanf(fp, "%d", &lv);
+ if (Logger::NONE < lv && lv <= Logger::LOG) {
+ mLogLevel = lv;
+ }
+ else {
+ mLogLevel = aLogLevel;
+ }
+ fclose(fp);
+ }
+ else {
+ mLogLevel = aLogLevel;
+ }
+
if (aName == NULL) {
mLogHandle = stdout;
INFO("logger initialized.");
@@ -97,7 +114,14 @@ bool Logger::init(const char* aName, int aLogLevel, bool aWithTimestamp, const c
printf("fail to open logger [%s].", path);
return false;
}
- DUMMY("Logger initialized. (Ver %s)", aVersion);
+
+ if (mLogLevel >= Logger::INFO) {
+#if defined(_MAJOR) && defined(_MINOR)
+ DUMMY("Logger initialized. (Ver %d.%d)", _MAJOR, _MINOR);
+#else
+ DUMMY("Logger initialized.");
+#endif
+ }
return true;
}
//----------------------------------------------------------------------
diff --git a/src/Logger.h b/src/Logger.h
index eaa77c5..e9bcb23 100644
--- a/src/Logger.h
+++ b/src/Logger.h
@@ -53,7 +53,9 @@ private:
static void logger_release()
{
if (mInstHandle) {
- DUMMY("Logger Released.");
+ if (Logger::instance()->get_level() >= Logger::INFO) {
+ DUMMY("Logger Released.");
+ }
delete mInstHandle;
}
};
@@ -62,7 +64,7 @@ public:
enum { NONE = 0, ERROR, WARNING, INFO, DEBUG, LOG };
#ifndef _DISABLE_LOGGER
- bool init(const char* aFileName = 0, int aLogLevel = Logger::ERROR, bool aWithTimestamp = true, const char* aVersion = 0);
+ bool init(const char* aFileName = 0, int aLogLevel = Logger::ERROR, bool aWithTimestamp = false);
void log(const char* aFormat, ...);
void log(int aLogLevel, const char* aFormat, ...);
diff --git a/src/Makefile b/src/Makefile
index a5a32d8..9b6cd84 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,67 +1,62 @@
#============================================================================
-# Name : Makefile
+# Name : Makefile (transtreamproxy)
# Author : oskwon(kos@dev3)
# Version :
# Copyright : Copyright(c)2013 Vu+ Team. All right reserved.
# Description :
#============================================================================
-VER = v3.0
+-include ../config.mk
+ifeq ($(MODEL),)
+$(error config.mk is not set. please run script.config before make.)
+endif
-Q=@
-IP=100.214
-MODEL=vuduo2
-OETOP=/home/oskwon/works/workrounds/openembedded
-CROSS=$(OETOP)/$(MODEL)/build/tmp/cross/mipsel/bin/mipsel-oe-linux-
-SYSROOT=$(OETOP)/$(MODEL)/build/tmp/staging/mipsel-oe-linux
-
-BIN = transtreamproxy
-SRCS = $(shell find . -name "*.cpp")
+MAJOR = 3
+MINOR = 0
+PROJECT = transtreamproxy
-CFLAGS ?=
-LDFLAGS ?=
+TOP=$(PWD)/..
-#CFLAGS += -Wno-unused-result
-
-CFLAGS += -O2 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
+CROSS=$(OETOP)/$(MODEL)/build/tmp/cross/mipsel/bin/mipsel-oe-linux-
+SYSROOT=$(OETOP)/$(MODEL)/build/tmp/staging/mipsel-oe-linux
+RM=rm -f
CXX=$(CROSS)g++
LD=$(CROSS)ld
STRIP=$(CROSS)strip
-RM=rm -f
-
-CFLAGS += -I. -I./external -I$(SYSROOT)/usr/include
-LDFLAGS += -L$(SYSROOT)/usr/lib -lpthread -lrt
+UPLOAD=$(TOP)/script/script.upload
+SRCS = $(shell find . -name "*.cpp")
OBJS=$(SRCS:.cpp=.o)
+CFLAGS += -D_MAJOR=$(MAJOR) -D_MINOR=$(MINOR)
+CFLAGS += -O2 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -I. -I./external -I$(SYSROOT)/usr/include
+LDFLAGS += -L$(SYSROOT)/usr/lib -lpthread -lrt
+
.SUFFIXES : .cpp .o
.PHONY : all clean install .showinfo
.cpp.o:
- $(Q)echo "Compile... "$<
- $(Q)$(CXX) -c $(CFLAGS) -o $@ $<
+ $(CXX) -c $(CFLAGS) -o $@ $<
-all: .showinfo $(BIN)
+all: .showinfo $(PROJECT)
-$(BIN):$(OBJS)
- $(Q)echo "Linking... "$@
- $(Q)$(CXX) -o $@ $(OBJS) $(LDFLAGS)
- $(Q)$(STRIP) $@
+$(PROJECT):$(OBJS)
+ $(CXX) -o $@ $(OBJS) $(LDFLAGS)
+ $(STRIP) $@
install:
- $(Q)./up.sh $(IP)
+ @$(UPLOAD) $(IP) . $(PROJECT) /usr/bin
clean:
- $(Q)$(RM) $(BIN) $(OBJS) *.log
+ $(RM) $(PROJECT) $(OBJS) *.log
.showinfo:
@echo "-----------------------------------------------------"
@echo " [ BUILD ENVIRONMENT ] "
@echo "-----------------------------------------------------"
- @echo "OUTPUT : "$(STREAMER_BIN) $(TRANSTREAMPROXY_BIN)
- @echo "VERSION : "$(VER)
+ @echo "PROJECT : "$(PROJECT)" (v"$(MAJOR)"."$(MINOR)")"
@echo ""
@echo "CXX : "$(CXX)
@echo "LD : "$(LD)
diff --git a/src/Mpeg.cpp b/src/Mpeg.cpp
new file mode 100644
index 0000000..bbcc935
--- /dev/null
+++ b/src/Mpeg.cpp
@@ -0,0 +1,46 @@
+/*
+ * Mpeg.cpp
+ *
+ * Created on: 2014. 6. 18.
+ * Author: oskwon
+ */
+
+#include "Mpeg.h"
+#include "Http.h"
+#include "Util.h"
+#include "Logger.h"
+//----------------------------------------------------------------------
+
+void Mpeg::seek(HttpHeader &header)
+{
+ try {
+ std::string position = header.page_params["position"];
+ if (position == "") {
+ off_t byte_offset = 0;
+ std::string range = header.params["Range"];
+ if((range.length() > 7) && (range.substr(0, 6) == "bytes=")) {
+ range = range.substr(6);
+ if(range.find('-') == (range.length() - 1)) {
+ byte_offset = Util::strtollu(range);
+ }
+ }
+ if (is_time_seekable && byte_offset > 0) {
+ DEBUG("seek to byte_offset %llu", byte_offset);
+ seek_absolute(byte_offset);
+ DEBUG("seek ok");
+ }
+ }
+ else {
+ unsigned int position_offset = Util::strtollu(position);
+ if (is_time_seekable && position_offset > 0) {
+ DEBUG("seek to position_offset %ds", position_offset);
+ seek_time((position_offset * 1000) + first_pcr_ms);
+ DEBUG("seek ok");
+ }
+ }
+ }
+ catch (const trap &e) {
+ WARNING("Exception : %s", e.what());
+ }
+}
+//----------------------------------------------------------------------
diff --git a/src/Mpeg.h b/src/Mpeg.h
new file mode 100644
index 0000000..780d080
--- /dev/null
+++ b/src/Mpeg.h
@@ -0,0 +1,29 @@
+/*
+ * Mpeg.h
+ *
+ * Created on: 2014. 6. 18.
+ * Author: oskwon
+ */
+
+#ifndef MPEG_H_
+#define MPEG_H_
+
+#include "trap.h"
+#include "mpegts.h"
+//----------------------------------------------------------------------
+
+class HttpHeader;
+
+class Mpeg : public MpegTS
+{
+public:
+ Mpeg(std::string file, bool request_time_seek) throw (trap)
+ : MpegTS(file, request_time_seek)
+ {}
+ virtual ~Mpeg() throw () {}
+
+ void seek(HttpHeader &header);
+};
+//----------------------------------------------------------------------
+
+#endif /* MPEG_H_ */
diff --git a/src/Util.cpp b/src/Util.cpp
new file mode 100644
index 0000000..0473d08
--- /dev/null
+++ b/src/Util.cpp
@@ -0,0 +1,145 @@
+/*
+ * Utils.cpp
+ *
+ * Created on: 2014. 6. 10.
+ * Author: oskwon
+ */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <dirent.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#include <sstream>
+#include <fstream>
+
+#include "Util.h"
+#include "Logger.h"
+
+using namespace std;
+//----------------------------------------------------------------------
+
+std::string Util::ultostr(int64_t data)
+{
+ std::stringstream ss;
+ ss << data;
+ return ss.str();
+}
+//----------------------------------------------------------------------
+
+int Util::strtollu(std::string data)
+{
+ long long retval;
+ std::stringstream ss;
+ try {
+ ss.str(data);
+ ss >> retval;
+ }
+ catch(...) {
+ return -1;
+ }
+ return retval;
+}
+//----------------------------------------------------------------------
+
+std::string Util::trim(std::string& s, const std::string& drop)
+{
+ std::string r = s.erase(s.find_last_not_of(drop) + 1);
+ return r.erase(0, r.find_first_not_of(drop));
+}
+//----------------------------------------------------------------------
+
+int Util::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();
+}
+//----------------------------------------------------------------------
+
+bool Util::split_key_value(std::string data, std::string delimiter, std::string &key, std::string &value)
+{
+ int idx = data.find(delimiter);
+ if (idx == string::npos) {
+ WARNING("split key & value (data : %s, delimiter : %s)", data.c_str(), delimiter.c_str());
+ return false;
+ }
+ key = data.substr(0, idx);
+ value = data.substr(idx+1, data.length()-idx);
+ return true;
+}
+//----------------------------------------------------------------------
+
+void Util::vlog(const char * format, ...) throw()
+{
+ static char vlog_buffer[MAX_PRINT_LEN];
+ memset(vlog_buffer, 0, MAX_PRINT_LEN);
+
+ va_list args;
+ va_start(args, format);
+ vsnprintf(vlog_buffer, MAX_PRINT_LEN-1, format, args);
+ va_end(args);
+
+ WARNING("%s", vlog_buffer);
+}
+//----------------------------------------------------------------------
+
+std::string Util::host_addr()
+{
+ std::stringstream ss;
+ struct sockaddr_in addr;
+ socklen_t addrlen = sizeof(addr);
+
+ getpeername(0, (struct sockaddr*)&addr, &addrlen);
+ ss << inet_ntoa(addr.sin_addr);
+
+ return ss.str();
+}
+//-------------------------------------------------------------------------------
+
+std::vector<int> Util::find_process_by_name(std::string name, int mypid)
+{
+ std::vector<int> pidlist;
+ char cmdlinepath[256] = {0};
+ DIR* d = opendir("/proc");
+ if (d != 0) {
+ struct dirent* de;
+ while ((de = readdir(d)) != 0) {
+ int pid = atoi(de->d_name);
+ if (pid > 0) {
+ sprintf(cmdlinepath, "/proc/%s/cmdline", de->d_name);
+
+ std::string cmdline;
+ std::ifstream cmdlinefile(cmdlinepath);
+ std::getline(cmdlinefile, cmdline);
+ if (!cmdline.empty()) {
+ size_t pos = cmdline.find('\0');
+ if (pos != string::npos)
+ cmdline = cmdline.substr(0, pos);
+ pos = cmdline.rfind('/');
+ if (pos != string::npos)
+ cmdline = cmdline.substr(pos + 1);
+ if ((name == cmdline) && ((mypid != pid) || (mypid == 0))) {
+ pidlist.push_back(pid);
+ }
+ }
+ }
+ }
+ closedir(d);
+ }
+ return pidlist;
+}
+//-------------------------------------------------------------------------------
+
+void Util::kill_process(int pid)
+{
+ int result = kill(pid, SIGINT);
+ DEBUG("SEND SIGINT to %d, result : %d", pid, result);
+ sleep(1);
+}
+//----------------------------------------------------------------------
diff --git a/src/Util.h b/src/Util.h
new file mode 100644
index 0000000..089ffb5
--- /dev/null
+++ b/src/Util.h
@@ -0,0 +1,49 @@
+/*
+ * Utils.h
+ *
+ * Created on: 2014. 6. 10.
+ * Author: oskwon
+ */
+
+#ifndef UTILS_H_
+#define UTILS_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include <stdint.h>
+
+#include "Http.h"
+#include "Source.h"
+#include "Encoder.h"
+//----------------------------------------------------------------------
+
+class Util {
+public:
+ static void vlog(const char * format, ...) throw();
+
+ static int strtollu(std::string data);
+ static std::string ultostr(int64_t data);
+
+ static std::string trim(std::string& s, const std::string& drop = " \t\n\v\r");
+
+ static int split(std::string data, const char delimiter, std::vector<std::string>& tokens);
+ static bool split_key_value(std::string data, std::string delimiter, std::string &key, std::string &value);
+
+ static void kill_process(int pid);
+
+ static std::string host_addr();
+
+ static std::vector<int> find_process_by_name(std::string name, int mypid);
+};
+//----------------------------------------------------------------------
+
+typedef struct _thread_params_t {
+ Source *source;
+ Encoder *encoder;
+ HttpHeader *request;
+} ThreadParams;
+//----------------------------------------------------------------------
+
+#endif /* UTILS_H_ */
diff --git a/src/Utils.cpp b/src/Utils.cpp
deleted file mode 100644
index af7ac4b..0000000
--- a/src/Utils.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Utils.cpp
- *
- * Created on: 2014. 6. 10.
- * Author: oskwon
- */
-
-#include <errno.h>
-#include <stdarg.h>
-#include <string.h>
-#include <dirent.h>
-#include <signal.h>
-#include <sys/wait.h>
-
-#include <arpa/inet.h>
-#include <sys/socket.h>
-
-#include <sstream>
-#include <fstream>
-
-#include "mpegts.h"
-
-#include "Utils.h"
-#include "Logger.h"
-#include "UriDecoder.h"
-
-using namespace std;
-//----------------------------------------------------------------------
-
-std::string ultostr(int64_t data)
-{
- std::stringstream ss;
- ss << data;
- return ss.str();
-}
-//----------------------------------------------------------------------
-
-int strtollu(std::string data)
-{
- long long retval;
- std::stringstream ss;
- try {
- ss.str(data);
- ss >> retval;
- }
- catch(...) {
- return -1;
- }
- return retval;
-}
-//----------------------------------------------------------------------
-
-std::string trim(std::string& s, const std::string& drop)
-{
- std::string r = s.erase(s.find_last_not_of(drop) + 1);
- return r.erase(0, r.find_first_not_of(drop));
-}
-//----------------------------------------------------------------------
-
-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();
-}
-//----------------------------------------------------------------------
-
-bool split_key_value(std::string data, std::string delimiter, std::string &key, std::string &value)
-{
- int idx = data.find(delimiter);
- if (idx == string::npos) {
- WARNING("split key & value (data : %s, delimiter : %s)", data.c_str(), delimiter.c_str());
- return false;
- }
- key = data.substr(0, idx);
- value = data.substr(idx+1, data.length()-idx);
- return true;
-}
-//----------------------------------------------------------------------
-
-std::string read_request()
-{
- std::string request = "";
- while (true) {
- char buffer[128] = {0};
- fgets(buffer, 127, stdin);
-
- request += buffer;
- if(request.find("\r\n\r\n") != string::npos)
- break;
- }
- return request;
-}
-//----------------------------------------------------------------------
-
-bool RequestHeader::parse_header(std::string header)
-{
- std::vector<string> lines;
- split(header, '\n', lines);
-
- DEBUG("header lines count : %d", lines.size());
- std::vector<string>::iterator iter = lines.begin();
- std::vector<string> infos;
- if (split(*iter, ' ', infos) != 3) {
- ERROR("fail to parse info : %d", infos.size());
- return false;
- }
-
- type = REQ_TYPE_TRANSCODING_LIVE;
- method = infos[0];
- path = infos[1];
- version = infos[2];
-
- if (strncmp(path.c_str(), "/file", 5) == 0) {
- std::vector<std::string> tokens;
- if (split(path.substr(6), '&', tokens) > 0) {
- for (int i = 0; i < tokens.size(); ++i) {
- std::string data = tokens[i];
- std::string key = "", value = "";
- if (!split_key_value(data, "=", key, value)) {
- ERROR("fail to request : %s", data.c_str());
- continue;
- }
- if (key == "file") {
- extension[key] = UriDecoder().decode(value.c_str());;
- continue;
- }
- extension[key] = value;
- }
- }
- type = REQ_TYPE_TRANSCODING_FILE;
-
-// DEBUG(":: HEADER :: %s", extension["file"].c_str());
-// std::map<std::string, std::string>::iterator iter = extension.begin();
-// for (; iter != extension.end(); ++iter) {
-// std::string key = iter->first;
-// std::string value = iter->second;
-// DEBUG("[%s] -> [%s]", key.c_str(), value.c_str());
-// }
- }
- DEBUG("info (%d) -> type : [%s], path : [%s], version : [%s]", infos.size(), method.c_str(), path.c_str(), version.c_str());
-
- for (++iter; iter != lines.end(); ++iter) {
- std::string key = "", value = "";
- if (!split_key_value(*iter, ":", key, value))
- continue;
- if (key == "")
- continue;
- key = trim(key);
- value = trim(value);
-
- if (key.length() > 0) {
- params[key] = value;
- DEBUG("add params : %s -> %s", key.c_str(), value.c_str());
- }
- }
- return true;
-}
-//----------------------------------------------------------------------
-
-off_t make_response(ThreadParams *params, std::string& response)
-{
- response = "";
-
- LINESTAMP();
-
- off_t byte_offset = 0;
- RequestHeader *header = ((ThreadParams*) params)->request;
- switch(header->type) {
- case REQ_TYPE_TRANSCODING_FILE: {
- MpegTS *source = (MpegTS*)((ThreadParams*) params)->source;
-
- std::string range = header->params["Range"];
- if((range.length() > 7) && (range.substr(0, 6) == "bytes=")) {
- range = range.substr(6);
- if(range.find('-') == (range.length() - 1)) {
- byte_offset = strtollu(range);
- }
- }
-
- off_t content_length = source->stream_length - byte_offset;
- if (byte_offset > 0) {
- content_length += 1;
- response += HTTP_PARTIAL;
- }
- else {
- response += HTTP_OK;
- }
- response += HTTP_PARAMS;
- response += "Accept-Ranges: bytes\r\n"
- "Content-Length: " + ultostr(content_length) + "\r\n";
- response += string("Content-Range: bytes ") +
- ultostr(byte_offset) + "-" +
- ultostr(source->stream_length - 1) + "/" +
- ultostr(source->stream_length) + "\r\n";
- response += HTTP_DONE;
- }
- break;
- case REQ_TYPE_TRANSCODING_LIVE: {
- response += HTTP_OK;
- response += HTTP_PARAMS;
- response += HTTP_DONE;
- }
- break;
- default: return -1;
- }
- return byte_offset;
-}
-//----------------------------------------------------------------------
-
-void Util::vlog(const char * format, ...) throw()
-{
- static char vlog_buffer[MAX_PRINT_LEN];
- memset(vlog_buffer, 0, MAX_PRINT_LEN);
-
- va_list args;
- va_start(args, format);
- vsnprintf(vlog_buffer, MAX_PRINT_LEN-1, format, args);
- va_end(args);
-
- WARNING("%s", vlog_buffer);
-}
-//----------------------------------------------------------------------
-
-std::string get_host_addr()
-{
- std::stringstream ss;
- struct sockaddr_in addr;
- socklen_t addrlen = sizeof(addr);
-
- getpeername(0, (struct sockaddr*)&addr, &addrlen);
- ss << inet_ntoa(addr.sin_addr);
-
- return ss.str();
-}
-//-------------------------------------------------------------------------------
-
-std::vector<int> find_process_by_name(std::string name, int mypid)
-{
- std::vector<int> pidlist;
- char cmdlinepath[256] = {0};
- DIR* d = opendir("/proc");
- if (d != 0) {
- struct dirent* de;
- while ((de = readdir(d)) != 0) {
- int pid = atoi(de->d_name);
- if (pid > 0) {
- sprintf(cmdlinepath, "/proc/%s/cmdline", de->d_name);
-
- std::string cmdline;
- std::ifstream cmdlinefile(cmdlinepath);
- std::getline(cmdlinefile, cmdline);
- if (!cmdline.empty()) {
- size_t pos = cmdline.find('\0');
- if (pos != string::npos)
- cmdline = cmdline.substr(0, pos);
- pos = cmdline.rfind('/');
- if (pos != string::npos)
- cmdline = cmdline.substr(pos + 1);
- if ((name == cmdline) && ((mypid != pid) || (mypid == 0))) {
- pidlist.push_back(pid);
- }
- }
- }
- }
- closedir(d);
- }
- return pidlist;
-}
-//-------------------------------------------------------------------------------
-
-void kill_process(int pid)
-{
- int result = kill(pid, SIGINT);
- DEBUG("SEND SIGINT to %d, result : %d", pid, result);
- sleep(1);
-}
-//----------------------------------------------------------------------
diff --git a/src/Utils.h b/src/Utils.h
deleted file mode 100644
index a64a780..0000000
--- a/src/Utils.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Utils.h
- *
- * Created on: 2014. 6. 10.
- * Author: oskwon
- */
-
-#ifndef UTILS_H_
-#define UTILS_H_
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include <stdint.h>
-
-#include "Source.h"
-#include "Encoder.h"
-//----------------------------------------------------------------------
-
-int strtollu(std::string data);
-std::string ultostr(int64_t data);
-std::string trim(std::string& s, const std::string& drop = " \t\n\v\r");
-int split(std::string data, const char delimiter, std::vector<std::string>& tokens);
-bool split_key_value(std::string data, std::string delimiter, std::string &key, std::string &value);
-
-std::string read_request();
-//----------------------------------------------------------------------
-
-typedef enum {
- REQ_TYPE_UNKNOWN = 0,
- REQ_TYPE_LIVE,
- REQ_TYPE_TRANSCODING_LIVE,
- REQ_TYPE_FILE,
- REQ_TYPE_TRANSCODING_FILE
-} RequestType;
-//----------------------------------------------------------------------
-
-class RequestHeader
-{
-public:
- RequestType type;
- std::string method;
- std::string path;
- std::string version;
- std::map<std::string, std::string> params;
- std::map<std::string, std::string> extension;
-
-public:
- bool parse_header(std::string header);
-};
-//----------------------------------------------------------------------
-
-#define HTTP_OK "HTTP/1.1 200 OK\r\n"
-#define HTTP_PARTIAL "HTTP/1.1 206 Partial Content\r\n"
-#define HTTP_PARAMS "Connection: Close\r\n" \
- "Content-Type: video/mpeg\r\n" \
- "Server: transtreamproxy\r\n"
-#define HTTP_DONE "\r\n"
-//----------------------------------------------------------------------
-
-typedef struct _thread_params_t {
- Source *source;
- Encoder *encoder;
- RequestHeader *request;
-} ThreadParams;
-//----------------------------------------------------------------------
-
-off_t make_response(ThreadParams *params, std::string& response);
-//----------------------------------------------------------------------
-
-class Util
-{
-public:
- static void vlog(const char * format, ...) throw();
-};
-//----------------------------------------------------------------------
-
-void kill_process(int pid);
-std::string get_host_addr();
-std::vector<int> find_process_by_name(std::string name, int mypid);
-//----------------------------------------------------------------------
-
-#endif /* UTILS_H_ */
diff --git a/src/main.cpp b/src/main.cpp
index 42bed62..9121be6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -15,34 +15,172 @@
#include <string>
-#include "trap.h"
-#include "mpegts.h"
-
-#include "Utils.h"
+#include "Util.h"
#include "Logger.h"
+#include "Http.h"
+#include "Mpeg.h"
+
#include "Demuxer.h"
#include "Encoder.h"
+#include "UriDecoder.h"
using namespace std;
//----------------------------------------------------------------------
-#define RESPONSE_FD (1)
#define BUFFFER_SIZE (188 * 256)
+void show_help();
+
void signal_handler(int sig_no);
void do_exit(const char *message);
+void *source_thread_main(void *params);
+void *streaming_thread_main(void *params);
+
+int streaming_write(const char *buffer, size_t buffer_len, bool enable_log = false);
+//----------------------------------------------------------------------
+
static bool is_terminated = true;
//----------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+ if (argc > 1) {
+ if (strcmp(argv[1], "-h") == 0)
+ show_help();
+ exit(0);
+ }
+ Logger::instance()->init("/tmp/transtreamproxy", Logger::WARNING);
+
+ signal(SIGINT, signal_handler);
+
+ HttpHeader header;
+
+ int source_thread_id, stream_thread_id;
+ pthread_t source_thread_handle, stream_thread_handle;
+
+ std::string req = HttpHeader::read_request();
+
+ DEBUG("request head :\n%s", req.c_str());
+ if (header.parse_request(req)) {
+ Encoder encoder;
+ Source *source = 0;
+ ThreadParams thread_params = { 0, &encoder, &header };
+
+ int video_pid = 0, audio_pid = 0, pmt_pid = 0;
+
+ switch(header.type) {
+ case HttpHeader::TRANSCODING_FILE:
+ try {
+ std::string uri = UriDecoder().decode(header.page_params["file"].c_str());
+ Mpeg *ts = new Mpeg(uri, true);
+ pmt_pid = ts->pmt_pid;
+ video_pid = ts->video_pid;
+ audio_pid = ts->audio_pid;
+ source = ts;
+ }
+ catch (const trap &e) {
+ ERROR("fail to create source : %s", e.what());
+ exit(-1);
+ }
+ break;
+ case HttpHeader::TRANSCODING_LIVE:
+ try {
+ Demuxer *dmx = new Demuxer(&header);
+ pmt_pid = dmx->pmt_pid;
+ video_pid = dmx->video_pid;
+ audio_pid = dmx->audio_pid;
+ source = dmx;
+ }
+ catch (const trap &e) {
+ ERROR("fail to create source : %s", e.what());
+ exit(-1);
+ }
+ break;
+ case HttpHeader::M3U:
+ try {
+ std::string response = header.build_response((Mpeg*) source);
+ if (response != "") {
+ streaming_write(response.c_str(), response.length(), true);
+ }
+ }
+ catch (...) {
+ }
+ exit(0);
+ default:
+ ERROR("not support source type (type : %d)", header.type);
+ exit(-1);
+ }
+ thread_params.source = source;
+
+ if (!encoder.retry_open(2, 3)) {
+ exit(-1);
+ }
+
+ if (encoder.state == Encoder::ENCODER_STAT_OPENED) {
+ std::string response = header.build_response((Mpeg*) source);
+ if (response == "") {
+ do_exit(0);
+ return 0;
+ }
+
+ streaming_write(response.c_str(), response.length(), true);
+
+ if (header.type == HttpHeader::TRANSCODING_FILE) {
+ ((Mpeg*) source)->seek(header);
+ }
+
+ if (!encoder.ioctl(Encoder::IOCTL_SET_VPID, video_pid)) {
+ do_exit("fail to set video pid.");
+ exit(-1);
+ }
+ if (!encoder.ioctl(Encoder::IOCTL_SET_APID, audio_pid)) {
+ do_exit("fail to set audio pid.");
+ exit(-1);
+ }
+ if (!encoder.ioctl(Encoder::IOCTL_SET_PMTPID, pmt_pid)) {
+ do_exit("fail to set pmtid.");
+ exit(-1);
+ }
+ }
+
+ is_terminated = false;
+ source_thread_id = pthread_create(&source_thread_handle, 0, source_thread_main, (void *)&thread_params);
+ if (source_thread_id < 0) {
+ do_exit("fail to create source thread.");
+ }
+ else {
+ pthread_detach(source_thread_handle);
+ sleep(1);
+ if (!encoder.ioctl(Encoder::IOCTL_START_TRANSCODING, 0)) {
+ do_exit("fail to start transcoding.");
+ }
+ else {
+ stream_thread_id = pthread_create(&stream_thread_handle, 0, streaming_thread_main, (void *)&thread_params);
+ if (stream_thread_id < 0) {
+ do_exit("fail to create stream thread.");
+ }
+ }
+ }
+ pthread_join(stream_thread_handle, 0);
+
+ if (source != 0) {
+ delete source;
+ source = 0;
+ }
+ }
+ return 0;
+}
+//----------------------------------------------------------------------
+
void *streaming_thread_main(void *params)
{
if (is_terminated) return 0;
INFO("streaming thread start.");
Encoder *encoder = ((ThreadParams*) params)->encoder;
- RequestHeader *header = ((ThreadParams*) params)->request;
+ HttpHeader *header = ((ThreadParams*) params)->request;
try {
int poll_state, rc, wc;
@@ -67,15 +205,14 @@ void *streaming_thread_main(void *params)
break;
}
else if (rc > 0) {
- wc = write(RESPONSE_FD, buffer, rc);
- //DEBUG("write : %d", wc);
+ wc = streaming_write((const char*) buffer, rc);
if (wc < rc) {
//DEBUG("need rewrite.. remain (%d)", rc - wc);
int retry_wc = 0;
for (int remain_len = rc - wc; rc != wc; remain_len -= retry_wc) {
poll_fd[0].revents = 0;
- retry_wc = write(RESPONSE_FD, (buffer + rc - remain_len), remain_len);
+ retry_wc = streaming_write((const char*) (buffer + rc - remain_len), remain_len);
wc += retry_wc;
}
LOG("re-write result : %d - %d", wc, rc);
@@ -113,7 +250,7 @@ void *source_thread_main(void *params)
{
Source *source = ((ThreadParams*) params)->source;
Encoder *encoder = ((ThreadParams*) params)->encoder;
- RequestHeader *header = ((ThreadParams*) params)->request;
+ HttpHeader *header = ((ThreadParams*) params)->request;
INFO("source thread start.");
@@ -178,141 +315,12 @@ void *source_thread_main(void *params)
}
//----------------------------------------------------------------------
-int main(int argc, char **argv)
+int streaming_write(const char *buffer, size_t buffer_len, bool enable_log)
{
- if (access("/tmp/.debug_on", F_OK) == 0) {
- Logger::instance()->init("/tmp/transtreamproxy", Logger::DEBUG, false, "3.0");
- }
- else {
- Logger::instance()->init("/tmp/transtreamproxy", Logger::WARNING, false, "3.0");
- }
- signal(SIGINT, signal_handler);
-
- RequestHeader header;
-
- int source_thread_id, stream_thread_id;
- pthread_t source_thread_handle, stream_thread_handle;
-
- std::string req = read_request();
-
- DEBUG("request head :\n%s", req.c_str());
- if (header.parse_header(req)) {
- Encoder encoder;
- Source *source = 0;
- ThreadParams thread_params = { 0, &encoder, &header };
-
- int video_pid = 0, audio_pid = 0, pmt_pid = 0;
-
- switch(header.type) {
- case REQ_TYPE_TRANSCODING_FILE:
- try {
- MpegTS *ts = new MpegTS(header.extension["file"], true);
- pmt_pid = ts->pmt_pid;
- video_pid = ts->video_pid;
- audio_pid = ts->audio_pid;
- source = ts;
- }
- catch (const trap &e) {
- ERROR("fail to create source : %s", e.what());
- exit(-1);
- }
- break;
- case REQ_TYPE_TRANSCODING_LIVE:
- try {
- Demuxer *dmx = new Demuxer(&header);
- pmt_pid = dmx->pmt_pid;
- video_pid = dmx->video_pid;
- audio_pid = dmx->audio_pid;
- source = dmx;
- }
- catch (const trap &e) {
- ERROR("fail to create source : %s", e.what());
- exit(-1);
- }
- break;
- default:
- ERROR("not support source type (type : %d)", header.type);
- exit(-1);
- }
- thread_params.source = source;
-
- if (!encoder.retry_open(2, 3)) {
- exit(-1);
- }
-
- if (encoder.state == Encoder::ENCODER_STAT_OPENED) {
- std::string response;
- off_t byte_offset = 0;
- if ((byte_offset = make_response((ThreadParams*) &thread_params, response)) < 0) {
- do_exit(0);
- return 0;
- }
-
- write(RESPONSE_FD, response.c_str(), response.length());
- DEBUG("response data :\n%s", response.c_str());
-
- if (header.type == REQ_TYPE_TRANSCODING_FILE) {
- try {
- std::string position = header.extension["position"];
- if (position == "") {
- DEBUG("seek to byte_offset %llu", byte_offset);
- ((MpegTS*)source)->seek_absolute(byte_offset);
- DEBUG("seek ok");
- }
- else {
- unsigned int position_offset = strtollu(position);
- if(((MpegTS*)source)->is_time_seekable && (position_offset > 0)) {
- DEBUG("seek to position_offset %ds", position_offset);
- ((MpegTS*)source)->seek_time((position_offset * 1000) + ((MpegTS*)source)->first_pcr_ms);
- DEBUG("seek ok");
- }
- }
- }
- catch (const trap &e) {
- WARNING("Exception : %s", e.what());
- }
- }
-
- if (!encoder.ioctl(Encoder::IOCTL_SET_VPID, video_pid)) {
- do_exit("fail to set video pid.");
- exit(-1);
- }
- if (!encoder.ioctl(Encoder::IOCTL_SET_APID, audio_pid)) {
- do_exit("fail to set audio pid.");
- exit(-1);
- }
- if (!encoder.ioctl(Encoder::IOCTL_SET_PMTPID, pmt_pid)) {
- do_exit("fail to set pmtid.");
- exit(-1);
- }
- }
-
- is_terminated = false;
- source_thread_id = pthread_create(&source_thread_handle, 0, source_thread_main, (void *)&thread_params);
- if (source_thread_id < 0) {
- do_exit("fail to create source thread.");
- }
- else {
- pthread_detach(source_thread_handle);
- sleep(1);
- if (!encoder.ioctl(Encoder::IOCTL_START_TRANSCODING, 0)) {
- do_exit("fail to start transcoding.");
- }
- else {
- stream_thread_id = pthread_create(&stream_thread_handle, 0, streaming_thread_main, (void *)&thread_params);
- if (stream_thread_id < 0) {
- do_exit("fail to create stream thread.");
- }
- }
- }
- pthread_join(stream_thread_handle, 0);
-
- if (source != 0) {
- delete source;
- source = 0;
- }
+ if (enable_log) {
+ DEBUG("response data :\n%s", buffer);
}
- return 0;
+ return write(1, buffer, buffer_len);
}
//----------------------------------------------------------------------
@@ -331,3 +339,14 @@ void signal_handler(int sig_no)
do_exit("signal detected..");
}
//----------------------------------------------------------------------
+
+void show_help()
+{
+ printf("usage : transtreamproxy [-h]\n");
+ printf("\n");
+ printf(" * To active debug mode, input NUMBER on /tmp/debug_on file. (default : warning)\n");
+ printf(" NUMBER : error(1), warning(2), info(3), debug(4), log(5)\n");
+ printf("\n");
+ printf(" ex > echo \"4\" > /tmp/debug_on\n");
+}
+//----------------------------------------------------------------------
diff --git a/src/up.sh b/src/up.sh
deleted file mode 100755
index 0d52858..0000000
--- a/src/up.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-ftp -n 192.168.$1 << +
-user root a
-prompt off
-cd /usr/bin
-put transtreamproxy
-bye
-+
-