Add request type(/m3u) for Vu+PlayerHD (IOS).
authoroskwon <kos@dev3>
Wed, 18 Jun 2014 08:17:14 +0000 (17:17 +0900)
committeroskwon <kos@dev3>
Wed, 18 Jun 2014 10:17:42 +0000 (19:17 +0900)
Remove up.sh and add some scripts.
Some sources refactoring.

19 files changed:
.gitignore
script/script.config [new file with mode: 0755]
script/script.upload [new file with mode: 0755]
src/Demuxer.cpp
src/Demuxer.h
src/Encoder.cpp
src/Http.cpp [new file with mode: 0644]
src/Http.h [new file with mode: 0644]
src/Logger.cpp
src/Logger.h
src/Makefile
src/Mpeg.cpp [new file with mode: 0644]
src/Mpeg.h [new file with mode: 0644]
src/Util.cpp [new file with mode: 0644]
src/Util.h [new file with mode: 0644]
src/Utils.cpp [deleted file]
src/Utils.h [deleted file]
src/main.cpp
src/up.sh [deleted file]

index 79f27fc..1ffb871 100644 (file)
@@ -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 (executable)
index 0000000..3f85083
--- /dev/null
@@ -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 (executable)
index 0000000..841a5e1
--- /dev/null
@@ -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
++
+
index a943bab..04cd35b 100644 (file)
@@ -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));
        }
index 2b8e636..033c54d 100644 (file)
@@ -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();
 };
index 3b59b07..d6f817f 100644 (file)
@@ -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 (file)
index 0000000..7b736c6
--- /dev/null
@@ -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 (file)
index 0000000..31246bc
--- /dev/null
@@ -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_ */
index 8d06b88..963a783 100644 (file)
@@ -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;
 }
 //----------------------------------------------------------------------
index eaa77c5..e9bcb23 100644 (file)
@@ -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, ...);
index a5a32d8..9b6cd84 100644 (file)
@@ -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 (file)
index 0000000..bbcc935
--- /dev/null
@@ -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 (file)
index 0000000..780d080
--- /dev/null
@@ -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 (file)
index 0000000..0473d08
--- /dev/null
@@ -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 (file)
index 0000000..089ffb5
--- /dev/null
@@ -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 (file)
index af7ac4b..0000000
+++ /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 (file)
index a64a780..0000000
+++ /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_ */
index 42bed62..9121be6 100644 (file)
 
 #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 (executable)
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
-+
-