diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/.config | 18 | ||||
-rw-r--r-- | src/Makefile.am | 11 | ||||
-rw-r--r-- | src/Makefile.manual | 109 | ||||
-rw-r--r-- | src/eFilePumpThread.cpp | 69 | ||||
-rw-r--r-- | src/eFilePumpThread.h | 30 | ||||
-rw-r--r-- | src/eNetworkPumpThread.cpp | 90 | ||||
-rw-r--r-- | src/eNetworkPumpThread.h | 28 | ||||
-rw-r--r-- | src/ePreDefine.h | 24 | ||||
-rw-r--r-- | src/eURIDecoder.cpp | 283 | ||||
-rw-r--r-- | src/eURIDecoder.h | 43 | ||||
-rw-r--r-- | src/main.cpp | 211 | ||||
-rw-r--r-- | src/uThread.cpp | 156 | ||||
-rw-r--r-- | src/uThread.h | 66 |
13 files changed, 1138 insertions, 0 deletions
diff --git a/src/.config b/src/.config new file mode 100644 index 0000000..1251fac --- /dev/null +++ b/src/.config @@ -0,0 +1,18 @@ +############################################# +# BUILD OPTION +############################################# +# - BUILD_MODE : debug | release +# - BUILD_CROSS : y | n +# - SILENT_BUILD_MODE : y | n +############################################# + +BUILD_MODE=release +BUILD_CROSS=y + +SILENT_BUILD_MODE=y + +ifeq ($(BUILD_CROSS),y) +ARCH=mipsel +FLATFORM=mipsel-oe-linux +OE_TOP=/media/840EVO/vuplus/16/vuduo2/build/tmp +endif diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..06573d0 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,11 @@ +## Process this file with automake to produce Makefile.in +bin_PROGRAMS = filestreamproxy +filestreamproxy_SOURCES = main.cpp +filestreamproxy_SOURCES += eFilePumpThread.cpp +filestreamproxy_SOURCES += eNetworkPumpThread.cpp +filestreamproxy_SOURCES += eURIDecoder.cpp +filestreamproxy_SOURCES += uThread.cpp + +filestreamproxy_LDADD = $(LIBLTDL) @PTHREAD_LIBS@ + + diff --git a/src/Makefile.manual b/src/Makefile.manual new file mode 100644 index 0000000..5161951 --- /dev/null +++ b/src/Makefile.manual @@ -0,0 +1,109 @@ +#============================================================================ +# Name : Makefile +# Author : oskwon(oskwon@marusys.com) +# Version : +# Copyright : Copyright(c)2013 Marusys. All right reserved. +# Description : +#============================================================================ + +include .config + +VER = v1.0 +REV = $(shell cat .revision) +BIN = filestreamproxy + +SRC = \ + main.cpp \ + uThread.cpp \ + eURIDecoder.cpp \ + eFilePumpThread.cpp \ + eNetworkPumpThread.cpp \ + + +CFLAGS ?= +LDFLAGS ?= + +CFLAGS += -DDEBUG_LOG + +ifeq ($(SILENT_BUILD_MODE),y) +Q=@ +endif + +ifeq ($(REV),) +REV = 0 +endif + +ifeq ($(ARCH),mipsel) +BUILD_TOP = $(OE_TOP)/staging/$(FLATFORM) +CROSS = $(OE_TOP)/cross/mipsel/bin/$(FLATFORM)- +endif + +ifeq ($(BUILD_MODE),debug) +CFLAGS += -g +else ifeq ($(BUILD_MODE),release) +CFLAGS += -O2 +endif + +CXX= $(CROSS)g++ +LD= $(CROSS)ld +STRIP= $(CROSS)strip +RM= rm -f + +CFLAGS += -I$(BUILD_TOP)/usr/include +LDFLAGS += -L$(BUILD_TOP)/usr/lib -lpthread + +OBJ=$(SRC:.cpp=.o) + +.SUFFIXES : .cpp .o +.PHONY : all clean erase .showinfo .version + +.cpp.o: + $(Q)echo "Compile... "$< + $(Q)$(CXX) $(CFLAGS) -c $< + +all: .showinfo .version $(BIN) + +$(BIN):$(OBJ) + $(Q)echo "Linking... "$@ + $(Q)$(CXX) -o $@ $(OBJ) $(LDFLAGS) + $(Q)if [ "$(BUILD_MODE)" == "release" ]; then \ + echo "Strip... "$@; \ + $(STRIP) $@; \ + fi + @echo `expr $(REV) + 1` > .revision + +clean: + $(Q)$(RM) $(BIN) *.o *.log version.h + +install: + @./upload.sh + +erase:clean + $(Q)$(RM) .revision + +.showinfo: + @echo "-----------------------------------------------------" + @echo " [ BUILD ENVIRONMENT ] " + @echo "-----------------------------------------------------" + @echo "OUTPUT : "$(BIN) + @echo "VERSION : "$(VER) + @echo "REVISION : "$(REV) + @echo "" + @echo "CXX : "$(CXX) + @echo "LD : "$(LD) + @echo "STRIP : "$(STRIP) + @echo "CFLAGS : "$(CFLAGS) + @echo "LDFLAGS : "$(LDFLAGS) + @echo "-----------------------------------------------------" + @echo + +.version: + @echo "/*" > version.h + @echo " * uVersion.h" >> version.h + @echo " * Auto generated code." >> version.h + @echo " */" >> version.h + @echo "#ifndef UVERSION_H_" >> version.h + @echo "#define UVERSION_H_" >> version.h + @echo "#define PN \"$(BIN)\"" >> version.h + @echo "#define PV \"$(VER)\"" >> version.h + @echo "#endif /* UVERSION_H_ */" >> version.h diff --git a/src/eFilePumpThread.cpp b/src/eFilePumpThread.cpp new file mode 100644 index 0000000..7659a4d --- /dev/null +++ b/src/eFilePumpThread.cpp @@ -0,0 +1,69 @@ +/* + * eFilePumpThread.cpp + * + * Created on: 2013. 9. 12. + * Author: kos + */ + +//#include "uLogger.h" + +//#include "uDemux.h" + +#include <poll.h> +#include <stdio.h> + +#include "ePreDefine.h" +#include "eFilePumpThread.h" +//------------------------------------------------------------------------------- + +#ifdef DEBUG_LOG +//#undef LOG +//#define LOG(X,...) { do{}while(0); } +#endif + +eFilePumpThread::eFilePumpThread(int aDeviceFd, std::string aFileName) + : mDeviceFd(aDeviceFd), mFileName(aFileName), mTermFlag(false), uThread("FilePumpThread", TYPE_DETACHABLE) +{ +} +//------------------------------------------------------------------------------- + +eFilePumpThread::~eFilePumpThread() +{ +} +//------------------------------------------------------------------------------- + +void eFilePumpThread::Run() +{ + int rc = 0; + unsigned char buffer[BUFFER_SIZE]; + FILE* mediafilefd = fopen(mFileName.c_str(), "rb"); + struct pollfd pollevt; + + pollevt.fd = mDeviceFd; + pollevt.events = POLLOUT; + pollevt.revents = 0; + + mTermFlag = true; + while(mTermFlag) { + rc = poll((struct pollfd*)&pollevt, 1, 1000); + + if (pollevt.revents & POLLOUT) { + rc = fread(buffer, 1, BUFFER_SIZE, mediafilefd); + if(!rc) break; +#ifdef DEBUG_LOG + LOG("%d byte write.", rc); +#endif + rc = write(mDeviceFd, buffer, rc); + } + } + fclose(mediafilefd); + mTermFlag = false; +} +//------------------------------------------------------------------------------- + +void eFilePumpThread::Terminate() +{ + mTermFlag = false; +} +//------------------------------------------------------------------------------- + diff --git a/src/eFilePumpThread.h b/src/eFilePumpThread.h new file mode 100644 index 0000000..1e8136d --- /dev/null +++ b/src/eFilePumpThread.h @@ -0,0 +1,30 @@ +/* + * eFilePumpThread.h + * + * Created on: 2013. 9. 12. + * Author: kos + */ + +#ifndef EFILEPUMPTHREAD_H_ +#define EFILEPUMPTHREAD_H_ + +#include "uThread.h" +//------------------------------------------------------------------------------- + +class eFilePumpThread : public uThread +{ +private: + bool mTermFlag; + int mDeviceFd; + std::string mFileName; +protected: + void Run(); + void Terminate(); + +public: + eFilePumpThread(int aDeviceFd, std::string aFileName); + ~eFilePumpThread(); +}; +//------------------------------------------------------------------------------- + +#endif /* EFILEPUMPTHREAD_H_ */ diff --git a/src/eNetworkPumpThread.cpp b/src/eNetworkPumpThread.cpp new file mode 100644 index 0000000..dc8972e --- /dev/null +++ b/src/eNetworkPumpThread.cpp @@ -0,0 +1,90 @@ +/* + * eDemuxPumpThread.cpp + * + * Created on: 2013. 9. 12. + * Author: kos + */ + +//#include "uLogger.h" +//#include "uDemux.h" + +#include <poll.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <sys/ioctl.h> + +#include "ePreDefine.h" +#include "eNetworkPumpThread.h" +//------------------------------------------------------------------------------- + +#ifdef DEBUG_LOG +//#undef LOG +//#define LOG(X,...) { do{}while(0); } +#endif + +eNetworkPumpThread::eNetworkPumpThread(int aDeviceFd) + : mTermFlag(0), mDeviceFd(aDeviceFd), uThread("eNetworkPumpThread") +{ +} +//------------------------------------------------------------------------------- + +eNetworkPumpThread::~eNetworkPumpThread() +{ +} +//------------------------------------------------------------------------------- + +void eNetworkPumpThread::Run() +{ + int rc = 0, wc = 0; + unsigned char buffer[BUFFER_SIZE]; + struct pollfd pollevt; + + pollevt.fd = mDeviceFd; + pollevt.events = POLLIN | POLLHUP; + pollevt.revents = 0; + + mTermFlag = true; + + const char *c = "\ +HTTP/1.0 200 OK\r\n\ +Connection: close\r\n\ +Content-Type: video/mpeg\r\n\ +Server: stream_enigma2\r\n\ +\r\n"; + + write(1, c, strlen(c)); + + while(mTermFlag) { + rc = poll((struct pollfd*)&pollevt, 1, 1000); + if (pollevt.revents & POLLIN) { + rc = read(mDeviceFd, buffer, BUFFER_SIZE); + + if (errno == EINTR || errno == EAGAIN || errno == EBUSY || errno == EOVERFLOW) { +#ifdef DEBUG_LOG + LOG("(retry... errno : %d)", errno); +#endif + continue; + } +#ifdef DEBUG_LOG + LOG("%d byte read", rc); +#endif + wc = write(1, buffer, rc); +#ifdef DEBUG_LOG + LOG("%d byte write", wc); +#endif + } else if (pollevt.revents & POLLHUP) { + ioctl(mDeviceFd, 200, 0); + break; + } + } + mTermFlag = false; +} +//------------------------------------------------------------------------------- + +void eNetworkPumpThread::Terminate() +{ + mTermFlag = false; +} +//------------------------------------------------------------------------------- + diff --git a/src/eNetworkPumpThread.h b/src/eNetworkPumpThread.h new file mode 100644 index 0000000..892c161 --- /dev/null +++ b/src/eNetworkPumpThread.h @@ -0,0 +1,28 @@ +/* + * eDemuxPumpThread.h + * + * Created on: 2013. 9. 12. + * Author: kos + */ + +#ifndef EDEMUXPUMPTHREAD_H_ +#define EDEMUXPUMPTHREAD_H_ + +#include "uThread.h" +//------------------------------------------------------------------------------- + +class eNetworkPumpThread : public uThread +{ +private: + int mDeviceFd; + bool mTermFlag; +protected: + void Run(); + void Terminate(); +public: + eNetworkPumpThread(int aDeviceFd); + virtual ~eNetworkPumpThread(); +}; +//------------------------------------------------------------------------------- + +#endif /* EDEMUXPUMPTHREAD_H_ */ diff --git a/src/ePreDefine.h b/src/ePreDefine.h new file mode 100644 index 0000000..57a8688 --- /dev/null +++ b/src/ePreDefine.h @@ -0,0 +1,24 @@ +/* + * main.h + * + * Created on: 2013. 9. 12. + * Author: kos + */ + +#ifndef FILESTREAMPROXY_H_ +#define FILESTREAMPROXY_H_ + +#define BUFFER_SIZE (188*256) +#define MAX_LINE_LENGTH (1024) + +#define RETURN_ERR_400(FMT,...) { printf("HTTP/1.0 400 Bad Request\r\n"FMT"\r\n\r\n", ##__VA_ARGS__); return 1; } +#define RETURN_ERR_401(FMT,...) { printf("HTTP/1.0 401 Unauthorized\r\n"FMT"\r\n\r\n",##__VA_ARGS__); return 1; } +#define RETURN_ERR_502(FMT,...) { printf("HTTP/1.0 502 Bad Gateway\r\n"FMT"\r\n\r\n", ##__VA_ARGS__); return 1; } +//------------------------------------------------------------------------------- + +#ifdef DEBUG_LOG +extern FILE* fpLog; +#define LOG(X,...) { fprintf(fpLog, "%s:%s(%d) "X"\n",__FILE__,__FUNCTION__,__LINE__,##__VA_ARGS__); fflush(fpLog); } +#endif + +#endif /* FILESTREAMPROXY_H_ */ diff --git a/src/eURIDecoder.cpp b/src/eURIDecoder.cpp new file mode 100644 index 0000000..e04e60d --- /dev/null +++ b/src/eURIDecoder.cpp @@ -0,0 +1,283 @@ +/* + * URIDecoder.cpp + * + * Created on: 2013. 10. 21. + * Author: kos + */ + +#include <stdio.h> +#include <string.h> + +#include "eURIDecoder.h" +//------------------------------------------------------------------------------- + +eURIDecoder::eURIDecoder() +{ +} +//------------------------------------------------------------------------------- + +eURIDecoder::~eURIDecoder() +{ +} +//------------------------------------------------------------------------------- + +unsigned char eURIDecoder::H2I(wchar_t aHexDigit) +{ + switch (aHexDigit) { + case _UL_('0'): + case _UL_('1'): + case _UL_('2'): + case _UL_('3'): + case _UL_('4'): + case _UL_('5'): + case _UL_('6'): + case _UL_('7'): + case _UL_('8'): + case _UL_('9'): + return (unsigned char)(9 + aHexDigit - _UL_('9')); + case _UL_('a'): + case _UL_('b'): + case _UL_('c'): + case _UL_('d'): + case _UL_('e'): + case _UL_('f'): + return (unsigned char)(15 + aHexDigit - _UL_('f')); + case _UL_('A'): + case _UL_('B'): + case _UL_('C'): + case _UL_('D'): + case _UL_('E'): + case _UL_('F'): + return (unsigned char)(15 + aHexDigit - _UL_('F')); + default: + return 0; + } +} +//------------------------------------------------------------------------------- + +const wchar_t* eURIDecoder::DecodeURI(wchar_t* aData, int aBreakCond) +{ + wchar_t* read = aData; + wchar_t* write = aData; + bool prevWasCr = false; + + if (aData == NULL) { + return NULL; + } + + for (;;) { + switch (read[0]) { + case _UL_('\0'): + if (read > write) { + write[0] = _UL_('\0'); + } + return write; + + case _UL_('%'): + switch (read[1]) { + case _UL_('0'): + case _UL_('1'): + case _UL_('2'): + case _UL_('3'): + case _UL_('4'): + case _UL_('5'): + case _UL_('6'): + case _UL_('7'): + case _UL_('8'): + case _UL_('9'): + case _UL_('a'): + case _UL_('b'): + case _UL_('c'): + case _UL_('d'): + case _UL_('e'): + case _UL_('f'): + case _UL_('A'): + case _UL_('B'): + case _UL_('C'): + case _UL_('D'): + case _UL_('E'): + case _UL_('F'): + switch (read[2]) { + case _UL_('0'): + case _UL_('1'): + case _UL_('2'): + case _UL_('3'): + case _UL_('4'): + case _UL_('5'): + case _UL_('6'): + case _UL_('7'): + case _UL_('8'): + case _UL_('9'): + case _UL_('a'): + case _UL_('b'): + case _UL_('c'): + case _UL_('d'): + case _UL_('e'): + case _UL_('f'): + case _UL_('A'): + case _UL_('B'): + case _UL_('C'): + case _UL_('D'): + case _UL_('E'): + case _UL_('F'): { + const unsigned char left = H2I(read[1]); + const unsigned char right = H2I(read[2]); + const int code = 16 * left + right; + switch (code) { + case 10: + switch (aBreakCond) { + case BR_TO_LF: + if (!prevWasCr) { + write[0] = (wchar_t)10; + write++; + } + break; + + case BR_TO_CRLF: + if (!prevWasCr) { + write[0] = (wchar_t)13; + write[1] = (wchar_t)10; + write += 2; + } + break; + + case BR_TO_CR: + if (!prevWasCr) { + write[0] = (wchar_t)13; + write++; + } + break; + + case BR_DONT_TOUCH: + default: + write[0] = (wchar_t)10; + write++; + + } + prevWasCr = false; + break; + + case 13: + switch (aBreakCond) { + case BR_TO_LF: + write[0] = (wchar_t)10; + write++; + break; + + case BR_TO_CRLF: + write[0] = (wchar_t)13; + write[1] = (wchar_t)10; + write += 2; + break; + + case BR_TO_CR: + write[0] = (wchar_t)13; + write++; + break; + + case BR_DONT_TOUCH: + default: + write[0] = (wchar_t)13; + write++; + + } + prevWasCr = true; + break; + + default: + write[0] = (wchar_t)(code); + write++; + + prevWasCr = false; + + } + read += 3; + } + break; + + default: + if (read > write) { + write[0] = read[0]; + write[1] = read[1]; + } + read += 2; + write += 2; + + prevWasCr = false; + } + break; + + default: + if (read > write) { + write[0] = read[0]; + } + read++; + write++; + + prevWasCr = false; + } + break; + + case _UL_('+'): + if (read > write) { + write[0] = _UL_(' '); + } + read++; + write++; + + prevWasCr = false; + break; + + default: + if (read > write) { + write[0] = read[0]; + } + read++; + write++; + + prevWasCr = false; + } + } +} +//------------------------------------------------------------------------------- + +std::wstring eURIDecoder::Decode(const wchar_t* aInput) +{ + wchar_t working[1024] = {0}; + + wcscpy(working, aInput); + DecodeURI(working, BR_DONT_TOUCH); + + return std::wstring(working); +} +//------------------------------------------------------------------------------- + +std::string eURIDecoder::Decode(const char* aInput) +{ + std::string tmp = aInput; + std::wstring in = L""; + in.assign(tmp.begin(), tmp.end()); + + std::wstring decode = Decode(in.c_str()); + + tmp.assign(decode.begin(), decode.end()); + + return tmp; +} +//------------------------------------------------------------------------------- + +#ifdef UNIT_TEST +#include <iostream> +int main() +{ + std::string in = "/home/kos/work/workspace/tsstreamproxy/test/20130528%201415%20-%20ZDF%20-%20Die%20K%C3%BCchenschlacht.ts"; + std::string out = URIDecoder().Decode(in.c_str()); + + cout << out << endl; + + FILE* fp = fopen(out.c_str(), "rb"); + + cout << (fp == NULL) ? "OPEN FAIL!!" : "OPEN OK" << endl; +} + +#endif diff --git a/src/eURIDecoder.h b/src/eURIDecoder.h new file mode 100644 index 0000000..e0833b5 --- /dev/null +++ b/src/eURIDecoder.h @@ -0,0 +1,43 @@ +/* + * URIDecoder.h + * + * Created on: 2013. 10. 21. + * Author: kos + */ + +#ifndef URIDECODER_H_ +#define URIDECODER_H_ + +#include <memory> +#include <string> + +#include <wchar.h> +//------------------------------------------------------------------------------- + +#define BR_TO_LF 0 +#define BR_TO_CRLF 1 +#define BR_TO_CR 2 +#define BR_TO_UNIX BR_TO_LF +#define BR_TO_WINDOWS BR_TO_CRLF +#define BR_TO_MAC BR_TO_CR +#define BR_DONT_TOUCH 6 + +#define _UL_(x) L##x +//------------------------------------------------------------------------------- + +class eURIDecoder +{ +protected: + unsigned char H2I(wchar_t aHexDigit); + const wchar_t* DecodeURI(wchar_t* aData, int aBreakCond); + +public: + eURIDecoder(); + virtual ~eURIDecoder(); + + std::string Decode(const char* aInput); + std::wstring Decode(const wchar_t* aInput); +}; +//------------------------------------------------------------------------------- + +#endif /* URIDECODER_H_ */ diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..2baaf4d --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,211 @@ +/* + * main.cpp + * + * Created on: 2013. 9. 12. + * Author: kos + */ + +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <poll.h> +#include <stdlib.h> +#include <sys/ioctl.h> + +#include <vector> +#include <string> +#include <iterator> +#include <fstream> + +#include "ePreDefine.h" +#include "eURIDecoder.h" +#include "eFilePumpThread.h" +#include "eNetworkPumpThread.h" + +#ifdef DEBUG_LOG +FILE* fpLog = fopen("/tmp/filestreamproxy.log", "w"); +//#undef LOG +//#define LOG(X,...) { do{}while(0); } +#endif + +using namespace std; +//------------------------------------------------------------------------------- + +int gDeviceFd = 0; + +char* ReadRequest(char* aRequest) +{ + return fgets(aRequest, MAX_LINE_LENGTH-1, stdin); +} +//------------------------------------------------------------------------------- + +namespace eParser { + int gVideoPid = 0, gAudioPid = 0; + std::vector<string> Split(std::string aBuffer, char aDelimiter); + void FileName(char* aRequest, char* aHttp, std::string& aOutData); + bool MetaData(std::string aMediaFileName); +}; +using namespace eParser; +//------------------------------------------------------------------------------- + +/* GET /file?file=/home/kos/work/workspace/filestreamproxy/data/20131023%200630%20-%20FASHION%20TV%20-%20instant%20record.ts HTTP/1.0 */ +int main(int argc, char** argv) +{ + char request[MAX_LINE_LENGTH] = {0}; + + if (!ReadRequest(request)) { + RETURN_ERR_400(); + } +#ifdef DEBUG_LOG + LOG("%s", request); +#endif + + if (strncmp(request, "GET /", 5)) { + RETURN_ERR_400(); + } + + char* http = strchr(request + 5, ' '); + if (!http || strncmp(http, " HTTP/1.", 7)) { + RETURN_ERR_400("Not support request (%s).", http); + } + + std::string srcfilename = ""; + eParser::FileName(request, http, srcfilename); + + bool isSuccessMeta = eParser::MetaData(srcfilename); + +#ifdef DEBUG_LOG + LOG("meta parsing result : %d, video : %d, audio : %d", isSuccessMeta, eParser::gVideoPid, eParser::gAudioPid); +#endif + + gDeviceFd = open("/dev/bcm_enc0", O_RDWR); + if(gDeviceFd < 0 ) { + close(gDeviceFd); + RETURN_ERR_502("Fail to opne device."); + } + + if(isSuccessMeta) { + if(ioctl(gDeviceFd, 1, eParser::gVideoPid)) { + RETURN_ERR_502("Fail to set video pid"); + } + if(ioctl(gDeviceFd, 2, eParser::gAudioPid)) { + RETURN_ERR_502("Fail to set audio pid"); + } + } + + eFilePumpThread filepump(gDeviceFd, srcfilename); + filepump.Start(); + + sleep(1); + + if(ioctl(gDeviceFd, 100, 0)) { + RETURN_ERR_502("Fail to start transcoding."); + } + eNetworkPumpThread networkpump(gDeviceFd); + networkpump.Start(); + + networkpump.Join(); + filepump.Stop(); + filepump.Join(); + + close(gDeviceFd); + +#ifdef DEBUG_LOG + fclose(fpLog); +#endif + return 0; +} +//------------------------------------------------------------------------------- + +std::vector<string> eParser::Split(std::string aBuffer, char aDelimiter) +{ + int b = 0, i = 0, l = aBuffer.length(); + std::vector<string> t; + + while (i++ < l) { + if (aBuffer[i] == aDelimiter) { + t.push_back(aBuffer.substr(b, i-b)); + b = i + 1; + continue; + } + if (i == (l - 1)) { + t.push_back(aBuffer.substr(b, l)); + } + } + return t; +} +//------------------------------------------------------------------------------- + +void eParser::FileName(char* aRequest, char* aHttp, std::string& aOutData) +{ + char tmp[256] = {0}; + char* file = aRequest + 5; + if (strncmp(file, "file?file=", strlen("file?file="))) { + return; + } + strncpy(tmp, file+10, aHttp-file-10); + aOutData = eURIDecoder().Decode(tmp); +} +//------------------------------------------------------------------------------- + +/* f:40,c:00007b,c:01008f,c:03007b */ +bool eParser::MetaData(std::string aMediaFileName) +{ + std::string metafilename = aMediaFileName; + metafilename += ".meta"; + + std::ifstream ifs(metafilename.c_str()); + + if (!ifs.is_open()) { +#ifdef DEBUG_LOG + LOG("metadata is not exists.."); +#endif + return false; + } + + size_t rc = 0, i = 0; + char buffer[1024] = {0}; + while (!ifs.eof()) { + ifs.getline(buffer, 1024); + if (i++ == 7) { +#ifdef DEBUG_LOG + LOG("%d [%s]", i, buffer); +#endif + std::vector<string> tokens = eParser::Split(buffer, ','); + if(tokens.size() < 3) { +#ifdef DEBUG_LOG + LOG("pid count size error : %d", tokens.size()); +#endif + return false; + } + + for (int ii = 0; ii < tokens.size(); ++ii) { + std::string token = tokens[ii]; +#ifdef DEBUG_LOG + LOG("token : %d [%s]", ii, token.c_str()); +#endif + switch(ii) { + case(1): + gVideoPid = strtol(token.substr(4,8).c_str(), NULL, 16); +#ifdef DEBUG_LOG + LOG("video pid : %d", gVideoPid); +#endif + break; + case(2): + gAudioPid = strtol(token.substr(4,8).c_str(), NULL, 16); +#ifdef DEBUG_LOG + + LOG("audio pid : %d", gAudioPid); +#endif + break; + } + } + break; + } + } + ifs.close(); + return true; +} +//------------------------------------------------------------------------------- + + diff --git a/src/uThread.cpp b/src/uThread.cpp new file mode 100644 index 0000000..6a7a4a5 --- /dev/null +++ b/src/uThread.cpp @@ -0,0 +1,156 @@ +/* + * uThread.cpp + * + * Created on: 2013. 9. 10. + * Author: kos + */ + +#include "uThread.h" + +#include <stdio.h> +#include <pthread.h> + +//#include "uLogger.h" + +using namespace std; +//------------------------------------------------------------------------------- + +uThread::uThread(std::string aName, uThread::EXIT_TYPE aExitType) + : mTid(0), mState(uThread::STATE_READY), mExitType(aExitType), mName(aName) +{ +} +//------------------------------------------------------------------------------- + +uThread::~uThread() +{ + if(mState == uThread::STATE_ZOMBIE) { + Join(mTid); + } +} +//------------------------------------------------------------------------------- + +bool uThread::Start() +{ +#ifdef SUPPORT_PTHREAD_ATTR + pthread_attr_t attr; + pthread_attr_init(&attr); + if(mExitType == uThread::TYPE_JOINABLE) { + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + } else { + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + } +#endif /* SUPPORT_PTHREAD_ATTR */ + if(pthread_create(&mTid, NULL, ThreadMain, reinterpret_cast<void *>(this)) == 0) { +#ifndef SUPPORT_PTHREAD_ATTR + if(mExitType == uThread::TYPE_DETACHABLE) { + pthread_detach(mTid); + } +#endif /* !SUPPORT_PTHREAD_ATTR */ + } else { + SetState(uThread::STATE_ABORTED); +#ifdef SUPPORT_PTHREAD_ATTR + pthread_attr_destroy(&attr); +#endif /* SUPPORT_PTHREAD_ATTR */ + return false; + } + //cout << mTid << endl; +#ifdef SUPPORT_PTHREAD_ATTR + pthread_attr_destroy(&attr); +#endif /* SUPPORT_PTHREAD_ATTR */ + return true; +} +//------------------------------------------------------------------------------- + +void* uThread::ThreadMain(void* aParam) +{ + uThread* thiz = reinterpret_cast<uThread*>(aParam); + + std::string threadName = thiz->GetName(); + //INFO("start thread...[%s]", threadName.c_str()); + + thiz->SetState(uThread::STATE_RUNNING); + thiz->Run(); + + if(thiz->GetExitType() == uThread::TYPE_DETACHABLE) + thiz->SetState(uThread::STATE_TERMINATED); + else thiz->SetState(uThread::STATE_ZOMBIE); + + pthread_exit((void*)0); + + //INFO("terminated thread...[%s]", threadName.c_str()); + return NULL; +} +//------------------------------------------------------------------------------- + +void uThread::Stop() +{ + switch(mState) { + case uThread::STATE_RUNNING: { + switch(mExitType) { + case uThread::TYPE_DETACHABLE: { + Terminate(); + } break; + case uThread::TYPE_JOINABLE: { + Terminate(); + Join(mTid); + } break; + } + } break; + case uThread::STATE_ZOMBIE: { + Join(mTid); + } break; + } +} +//------------------------------------------------------------------------------- + +bool uThread::Join(pthread_t aTid) +{ + if (!pthread_join(aTid, NULL)) { + SetState(uThread::STATE_TERMINATED); + return true; + } + return false; +} +//------------------------------------------------------------------------------- + +void uThread::SetState(uThread::STATE aState) +{ + mState = aState; +} +//------------------------------------------------------------------------------- + +uThread::STATE uThread::GetState() const +{ + return mState; +} +//------------------------------------------------------------------------------- + +uThread::EXIT_TYPE uThread::GetExitType() const +{ + return mExitType; +} +//------------------------------------------------------------------------------- + +std::string uThread::GetName() const +{ + return mName; +} +//------------------------------------------------------------------------------- + +bool uThread::IsTerminated() const +{ + return (mState == uThread::STATE_TERMINATED) ? true : false; +} +//------------------------------------------------------------------------------- + +bool uThread::IsRunning() const +{ + return mState == uThread::STATE_RUNNING ? true : false; +} +//------------------------------------------------------------------------------- + +bool uThread::Join() +{ + return Join(mTid); +} +//------------------------------------------------------------------------------- diff --git a/src/uThread.h b/src/uThread.h new file mode 100644 index 0000000..a9cc5df --- /dev/null +++ b/src/uThread.h @@ -0,0 +1,66 @@ +/* + * uThread.h + * + * Created on: 2013. 9. 10. + * Author: kos + */ + +#ifndef UTHREAD_H_ +#define UTHREAD_H_ + +#include <string> +#include <pthread.h> +//------------------------------------------------------------------------------- + +class uThread +{ +public: + enum STATE { + STATE_READY = 0, + STATE_RUNNING, + STATE_TERMINATED, + STATE_ZOMBIE, + STATE_ABORTED + }; + enum EXIT_TYPE { + TYPE_JOINABLE = 0, + TYPE_DETACHABLE + }; +private: + uThread(const uThread&); + uThread& operator=(const uThread&); + + uThread::STATE mState; + uThread::EXIT_TYPE mExitType; +protected: + pthread_t mTid; + std::string mName; + + static void* ThreadMain(void *aParam); + + virtual void Run() = 0; + virtual void Terminate() = 0; + + bool Join(pthread_t aTid); + void SetState(STATE aState); + + void SetName(std::string aName) { mName = aName; } +public: + uThread(std::string aName="", uThread::EXIT_TYPE aExitType=uThread::TYPE_JOINABLE); + virtual ~uThread(); + + void Stop(); + bool Start(); + + pthread_t GetTid() { return mTid; } + uThread::STATE GetState() const; + uThread::EXIT_TYPE GetExitType() const; + std::string GetName() const; + + bool IsTerminated() const; + bool IsRunning() const; + bool Join(); +}; +//------------------------------------------------------------------------------- + +#endif /* UTHREAD_H_ */ |