Created
September 4, 2014 11:58
-
-
Save anonymous/570aa60b21fc28295662 to your computer and use it in GitHub Desktop.
b25 patch for BonDriverProxy_Linux
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -r 8455e6cc2457 -r b1732a1d4f3a BonDriverProxy.cpp | |
--- a/BonDriverProxy.cpp Wed Sep 03 07:16:55 2014 +0900 | |
+++ b/BonDriverProxy.cpp Thu Sep 04 18:59:50 2014 +0900 | |
@@ -1,5 +1,18 @@ | |
#include "BonDriverProxy.h" | |
+#ifdef HAVE_LIBARIB25 | |
+#include <getopt.h> | |
+#include "decoder.h" | |
+static int g_b25_enable = false; | |
+#else | |
+class B25Decoder { }; | |
+struct ARIB_STD_B25_BUFFER | |
+{ | |
+ uint8_t *data; | |
+ int32_t size; | |
+}; | |
+#endif | |
+ | |
namespace BonDriverProxy { | |
#define STRICT_LOCK | |
@@ -9,6 +22,39 @@ | |
static int Init(int ac, char *av[]) | |
{ | |
+#ifdef HAVE_LIBARIB25 | |
+ static const struct option options[] = { | |
+ {"b25", no_argument, &g_b25_enable, 1}, | |
+ {"strip", no_argument, &B25Decoder::strip, 1}, | |
+ {"EMM", no_argument, &B25Decoder::emm_proc, 1}, | |
+ {"round", required_argument, NULL, 'r'}, | |
+ {0} | |
+ }; | |
+ | |
+ int opt; | |
+ | |
+ while ((opt = getopt_long(ac, av, "", options, NULL)) != -1) | |
+ { | |
+ switch (opt) | |
+ { | |
+ case 0: // long options | |
+ break; | |
+ case 'r': // multi2 round | |
+ B25Decoder::multi2_round = strtoul(optarg, NULL, 10); | |
+ break; | |
+ default: | |
+ return -1; | |
+ } | |
+ } | |
+ | |
+ if (optind > 1) | |
+ { | |
+ int i = optind, j = 1; | |
+ while (i < ac) | |
+ av[j++] = av[i++]; | |
+ ac -= optind - 1; | |
+ } | |
+#endif | |
if (ac < 3) | |
return -1; | |
::strncpy(g_Host, av[1], sizeof(g_Host) - 1); | |
@@ -35,6 +81,7 @@ | |
m_pStopTsRead = NULL; | |
m_pTsLock = NULL; | |
m_ppos = NULL; | |
+ m_b25 = NULL; | |
pthread_mutexattr_t attr; | |
::pthread_mutexattr_init(&attr); | |
@@ -69,6 +116,7 @@ | |
delete m_pStopTsRead; | |
delete m_pTsLock; | |
delete m_ppos; | |
+ delete m_b25; | |
} | |
if (m_pIBon) | |
m_pIBon->Release(); | |
@@ -99,6 +147,7 @@ | |
delete m_pStopTsRead; | |
delete m_pTsLock; | |
delete m_ppos; | |
+ delete m_b25; | |
} | |
} | |
} | |
@@ -462,12 +511,20 @@ | |
m_pStopTsRead = new BOOL(FALSE); | |
m_pTsLock = new cCriticalSection(); | |
m_ppos = new DWORD(0); | |
- LPVOID *ppv = new LPVOID[5]; | |
+#ifdef HAVE_LIBARIB25 | |
+ if (g_b25_enable) | |
+ { | |
+ m_b25 = new B25Decoder(); | |
+ m_b25->init(); | |
+ } | |
+#endif | |
+ LPVOID *ppv = new LPVOID[6]; | |
ppv[0] = m_pIBon; | |
ppv[1] = m_pTsReceiversList; | |
ppv[2] = m_pStopTsRead; | |
ppv[3] = m_pTsLock; | |
ppv[4] = m_ppos; | |
+ ppv[5] = m_b25; | |
if (::pthread_create(&m_hTsRead, NULL, cProxyServer::TsReader, ppv)) | |
{ | |
m_hTsRead = 0; | |
@@ -480,6 +537,8 @@ | |
m_pTsLock = NULL; | |
delete m_ppos; | |
m_ppos = NULL; | |
+ delete m_b25; | |
+ m_b25 = NULL; | |
m_Error.Set(); | |
} | |
#ifndef STRICT_LOCK | |
@@ -729,6 +788,9 @@ | |
volatile BOOL &StopTsRead = *(static_cast<BOOL *>(ppv[2])); | |
cCriticalSection &TsLock = *(static_cast<cCriticalSection *>(ppv[3])); | |
DWORD &pos = *(static_cast<DWORD *>(ppv[4])); | |
+#ifdef HAVE_LIBARIB25 | |
+ B25Decoder *b25 = static_cast<B25Decoder *>(ppv[5]); | |
+#endif | |
delete[] ppv; | |
DWORD dwSize, dwRemain, now, before = 0; | |
float fSignalLevel = 0; | |
@@ -755,10 +817,37 @@ | |
LOCK(TsLock); | |
if (pIBon->GetTsStream(&pBuf, &dwSize, &dwRemain) && (dwSize != 0)) | |
{ | |
- if ((pos + dwSize) < TsPacketBufSize) | |
+ ARIB_STD_B25_BUFFER buf; | |
+#ifdef HAVE_LIBARIB25 | |
+ if (b25) | |
{ | |
- ::memcpy(&pTsBuf[pos], pBuf, dwSize); | |
- pos += dwSize; | |
+ buf.data = pBuf; | |
+ buf.size = dwSize; | |
+ int code; | |
+ if ((code = b25->put(&buf)) < 0) | |
+ { | |
+ b25->reset(); | |
+ continue; | |
+ } | |
+ if ((code = b25->get(&buf)) < 0) | |
+ { | |
+ //b25->reset(); /* resetするほどのエラーは発生しない模様 */ | |
+ continue; | |
+ } | |
+ if (buf.size == 0) | |
+ continue; | |
+ } | |
+ else | |
+#endif | |
+ { | |
+ buf.data = pBuf; | |
+ buf.size = dwSize; | |
+ } | |
+ | |
+ if ((pos + buf.size) < TsPacketBufSize) | |
+ { | |
+ ::memcpy(&pTsBuf[pos], buf.data, buf.size); | |
+ pos += buf.size; | |
if (dwRemain == 0) | |
{ | |
for (std::list<cProxyServer *>::iterator it = TsReceiversList.begin(); it != TsReceiversList.end(); ++it) | |
@@ -769,28 +858,28 @@ | |
else | |
{ | |
DWORD left, dwLen = TsPacketBufSize - pos; | |
- ::memcpy(&pTsBuf[pos], pBuf, dwLen); | |
+ ::memcpy(&pTsBuf[pos], buf.data, dwLen); | |
for (std::list<cProxyServer *>::iterator it = TsReceiversList.begin(); it != TsReceiversList.end(); ++it) | |
(*it)->makePacket(eGetTsStream, pTsBuf, TsPacketBufSize, fSignalLevel); | |
- left = dwSize - dwLen; | |
- pBuf += dwLen; | |
+ left = buf.size - dwLen; | |
+ buf.data += dwLen; | |
while (left > TsPacketBufSize) | |
{ | |
for (std::list<cProxyServer *>::iterator it = TsReceiversList.begin(); it != TsReceiversList.end(); ++it) | |
- (*it)->makePacket(eGetTsStream, pBuf, TsPacketBufSize, fSignalLevel); | |
+ (*it)->makePacket(eGetTsStream, buf.data, TsPacketBufSize, fSignalLevel); | |
left -= TsPacketBufSize; | |
- pBuf += TsPacketBufSize; | |
+ buf.data += TsPacketBufSize; | |
} | |
if (left != 0) | |
{ | |
if (dwRemain == 0) | |
{ | |
for (std::list<cProxyServer *>::iterator it = TsReceiversList.begin(); it != TsReceiversList.end(); ++it) | |
- (*it)->makePacket(eGetTsStream, pBuf, left, fSignalLevel); | |
+ (*it)->makePacket(eGetTsStream, buf.data, left, fSignalLevel); | |
left = 0; | |
} | |
else | |
- ::memcpy(pTsBuf, pBuf, left); | |
+ ::memcpy(pTsBuf, buf.data, left); | |
} | |
pos = left; | |
} | |
@@ -969,7 +1058,12 @@ | |
{ | |
if (BonDriverProxy::Init(argc, argv) != 0) | |
{ | |
+#ifdef HAVE_LIBARIB25 | |
+ fprintf(stderr, "usage: %s [--b25 [--round N] [--strip] [--EMM]] " | |
+ "address port (packet_fifo_size tspacket_bufsize)\ne.g. $ %s 192.168.0.100 1192\n", argv[0],argv[0]); | |
+#else | |
fprintf(stderr, "usage: %s address port (packet_fifo_size tspacket_bufsize)\ne.g. $ %s 192.168.0.100 1192\n", argv[0],argv[0]); | |
+#endif | |
return 0; | |
} | |
diff -r 8455e6cc2457 -r b1732a1d4f3a BonDriverProxy.h | |
--- a/BonDriverProxy.h Wed Sep 03 07:16:55 2014 +0900 | |
+++ b/BonDriverProxy.h Thu Sep 04 18:59:50 2014 +0900 | |
@@ -23,6 +23,8 @@ | |
#include "typedef.h" | |
#include "IBonDriver3.h" | |
+class B25Decoder; | |
+ | |
#if __APPLE__ | |
#undef daemon | |
extern "C" { | |
@@ -293,6 +295,7 @@ | |
BOOL m_bChannelLock; | |
cPacketFifo m_fifoSend; | |
cPacketFifo m_fifoRecv; | |
+ class B25Decoder *m_b25; | |
DWORD Process(); | |
int ReceiverHelper(char *pDst, DWORD left); | |
diff -r 8455e6cc2457 -r b1732a1d4f3a BonDriver_LinuxPT.conf | |
--- a/BonDriver_LinuxPT.conf Wed Sep 03 07:16:55 2014 +0900 | |
+++ b/BonDriver_LinuxPT.conf Thu Sep 04 18:59:50 2014 +0900 | |
@@ -1,6 +1,11 @@ | |
#DEVICE=/dev/pt3video0 | |
#USELNB=0 | |
#USESERVICEID=0 | |
+; #B25=1 | |
+; #STRIP=1 | |
+; #EMM=1 | |
+; #MULTI2ROUND=4 | |
+ | |
; 名称, BonDriverとしてのチャンネル番号, 周波数テーブル番号, スロット番号/加算する周波数 | |
; 記述はタブ区切り | |
#ISDB_S | |
diff -r 8455e6cc2457 -r b1732a1d4f3a BonDriver_LinuxPT.cpp | |
--- a/BonDriver_LinuxPT.cpp Wed Sep 03 07:16:55 2014 +0900 | |
+++ b/BonDriver_LinuxPT.cpp Thu Sep 04 18:59:50 2014 +0900 | |
@@ -1,5 +1,8 @@ | |
#include "BonDriver_LinuxPT.h" | |
#include "plex.cpp" | |
+#ifdef HAVE_LIBARIB25 | |
+#include "decoder.h" | |
+#endif | |
namespace BonDriver_LinuxPT { | |
@@ -10,6 +13,10 @@ | |
static BOOL g_UseLNB; | |
static BOOL g_UseServiceID; | |
static DWORD g_Crc32Table[256]; | |
+#ifdef HAVE_LIBARIB25 | |
+static BOOL g_b25_enable = false; | |
+static B25Decoder g_b25; | |
+#endif | |
static int Convert(char *src, char *dst, size_t dstsize) | |
{ | |
@@ -46,6 +53,26 @@ | |
return crc; | |
} | |
+static bool MatchDefLine(const char *line, const char *key, char **value) | |
+{ | |
+ const int keylen = ::strlen(key); | |
+ const char *p = line; | |
+ | |
+ if (::strncmp(p, key, keylen) != 0) | |
+ return false; | |
+ p += keylen; | |
+ while (*p == ' ' || *p == '\t') | |
+ ++p; | |
+ if (!value) | |
+ return *p == '\0'; | |
+ if (*p++ != '=') | |
+ return false; | |
+ while (*p == ' ' || *p == '\t') | |
+ ++p; | |
+ *value = const_cast<char *>(p); | |
+ return true; | |
+} | |
+ | |
static int Init() | |
{ | |
FILE *fp; | |
@@ -74,6 +101,14 @@ | |
BOOL bdFlag = FALSE; | |
BOOL blFlag = FALSE; | |
BOOL bsFlag = FALSE; | |
+#ifdef HAVE_LIBARIB25 | |
+ struct { | |
+ unsigned b25:1; | |
+ unsigned strip:1; | |
+ unsigned emm:1; | |
+ unsigned multi2round:1; | |
+ } flags = {0}; | |
+#endif | |
while (::fgets(buf, sizeof(buf), fp)) | |
{ | |
if (buf[0] == ';') | |
@@ -83,15 +118,12 @@ | |
*p-- = '\0'; | |
if (p < buf) | |
continue; | |
- if ((idx != 0) && (::strncmp(buf, "#ISDB_S", 7) == 0)) | |
+ if ((idx != 0) && MatchDefLine(buf, "#ISDB_S", NULL)) | |
idx = 0; | |
- else if ((idx != 1) && (::strncmp(buf, "#ISDB_T", 7) == 0)) | |
+ else if ((idx != 1) && MatchDefLine(buf, "#ISDB_T", NULL)) | |
idx = 1; | |
- else if (!bdFlag && (::strncmp(buf, "#DEVICE=", 8) == 0)) | |
+ else if (!bdFlag && MatchDefLine(buf, "#DEVICE", &p)) | |
{ | |
- p = &buf[8]; | |
- while (*p == ' ' || *p == '\t') | |
- p++; | |
::strncpy(g_Device, p, sizeof(g_Device) - 1); | |
g_Device[sizeof(g_Device) - 1] = '\0'; | |
if ((p = ::strstr(g_Device, "video")) != NULL) // PT | |
@@ -119,22 +151,38 @@ | |
} | |
bdFlag = TRUE; | |
} | |
- else if (!blFlag && (::strncmp(buf, "#USELNB=", 8) == 0)) | |
+ else if (!blFlag && MatchDefLine(buf, "#USELNB", &p)) | |
{ | |
- p = &buf[8]; | |
- while (*p == ' ' || *p == '\t') | |
- p++; | |
g_UseLNB = ::atoi(p); | |
blFlag = TRUE; | |
} | |
- else if (!bsFlag && (::strncmp(buf, "#USESERVICEID=", 14) == 0)) | |
+ else if (!bsFlag && MatchDefLine(buf, "#USESERVICEID", &p)) | |
{ | |
- p = &buf[14]; | |
- while (*p == ' ' || *p == '\t') | |
- p++; | |
g_UseServiceID = ::atoi(p); | |
bsFlag = TRUE; | |
} | |
+#ifdef HAVE_LIBARIB25 | |
+ else if (!flags.b25 && MatchDefLine(buf, "#B25", &p)) | |
+ { | |
+ g_b25_enable = ::atoi(p); | |
+ flags.b25 = 1; | |
+ } | |
+ else if (!flags.strip && MatchDefLine(buf, "#STRIP", &p)) | |
+ { | |
+ B25Decoder::strip = ::atoi(p); | |
+ flags.strip = 1; | |
+ } | |
+ else if (!flags.emm && MatchDefLine(buf, "#EMM", &p)) | |
+ { | |
+ B25Decoder::emm_proc = ::atoi(p); | |
+ flags.emm = 1; | |
+ } | |
+ else if (!flags.multi2round && MatchDefLine(buf, "#MULTI2ROUND", &p)) | |
+ { | |
+ B25Decoder::multi2_round = ::atoi(p); | |
+ flags.multi2round = 1; | |
+ } | |
+#endif | |
else | |
{ | |
int n = 0; | |
@@ -305,6 +353,10 @@ | |
LOCK(m_writeLock); | |
TsFlush(g_UseServiceID); | |
delete m_LastBuf; | |
+#ifdef HAVE_LIBARIB25 | |
+ if (g_b25_enable) | |
+ g_b25.release(); | |
+#endif | |
} | |
::pthread_cond_destroy(&m_c); | |
::pthread_mutex_destroy(&m_m); | |
@@ -323,6 +375,10 @@ | |
if (g_UseLNB && (g_Type == 0) && (::ioctl(m_fd, LNB_ENABLE, 2) < 0)) | |
::fprintf(stderr, "LNB ON failed: %s\n", g_Device); | |
m_bTuner = TRUE; | |
+#ifdef HAVE_LIBARIB25 | |
+ if (g_b25_enable) | |
+ g_b25.init(); | |
+#endif | |
return TRUE; | |
} | |
@@ -342,6 +398,10 @@ | |
::close(m_fd); | |
m_bTuner = FALSE; | |
m_fd = -1; | |
+#ifdef HAVE_LIBARIB25 | |
+ if (g_b25_enable) | |
+ g_b25.release(); | |
+#endif | |
} | |
} | |
@@ -391,14 +451,43 @@ | |
if (!m_bTuner) | |
return FALSE; | |
BOOL b; | |
+#ifdef HAVE_LIBARIB25 | |
+ timespec ts; | |
+ ts.tv_sec = 0; | |
+ ts.tv_nsec = 10 * 1000 * 1000; // 10ms | |
+#endif | |
+ for (;;) | |
{ | |
LOCK(m_writeLock); | |
if (m_fifoTS.Size() != 0) | |
{ | |
delete m_LastBuf; | |
m_fifoTS.Pop(&m_LastBuf); | |
- *ppDst = m_LastBuf->pbBuf; | |
- *pdwSize = m_LastBuf->dwSize; | |
+#ifdef HAVE_LIBARIB25 | |
+ if (g_b25_enable) | |
+ { | |
+ ARIB_STD_B25_BUFFER buf; | |
+ buf.data = m_LastBuf->pbBuf; | |
+ buf.size = m_LastBuf->dwSize; | |
+ if (g_b25.put(&buf) < 0) | |
+ { | |
+ g_b25.reset(); | |
+ goto next; | |
+ } | |
+ g_b25.get(&buf); | |
+ if (buf.size == 0) | |
+ { | |
+ goto next; | |
+ } | |
+ *ppDst = buf.data; | |
+ *pdwSize = buf.size; | |
+ } | |
+ else | |
+#endif | |
+ { | |
+ *ppDst = m_LastBuf->pbBuf; | |
+ *pdwSize = m_LastBuf->dwSize; | |
+ } | |
*pdwRemain = (DWORD)m_fifoTS.Size(); | |
b = TRUE; | |
} | |
@@ -408,6 +497,13 @@ | |
*pdwRemain = 0; | |
b = FALSE; | |
} | |
+ break; | |
+ | |
+#ifdef HAVE_LIBARIB25 | |
+ next: | |
+ if (m_fifoTS.Size() == 0) | |
+ nanosleep(&ts, NULL); | |
+#endif | |
} | |
return b; | |
} | |
diff -r 8455e6cc2457 -r b1732a1d4f3a Makefile | |
--- a/Makefile Wed Sep 03 07:16:55 2014 +0900 | |
+++ b/Makefile Thu Sep 04 18:59:50 2014 +0900 | |
@@ -3,7 +3,7 @@ | |
SRCDIR = . | |
LDFLAGS = | |
LIBS = -ldl | |
-SRCS = BonDriverProxy.cpp BonDriver_Proxy.cpp BonDriver_LinuxPT.cpp | |
+SRCS = BonDriverProxy.cpp BonDriver_Proxy.cpp BonDriver_LinuxPT.cpp sample.cpp | |
UNAME := $(shell uname) | |
ifeq ($(UNAME), Darwin) | |
@@ -18,18 +18,28 @@ | |
EXT = so | |
endif | |
-all: server client driver | |
+ifdef B25 | |
+CXXFLAGS += -DHAVE_LIBARIB25 | |
+LIBS += -larib25 | |
+SRCS += decoder.cpp | |
+B25OBJS = decoder.o | |
+endif | |
+ | |
+all: server client driver sample | |
server: BonDriverProxy | |
client: BonDriver_Proxy.$(EXT) | |
driver: BonDriver_LinuxPT.$(EXT) | |
-BonDriverProxy: BonDriverProxy.o | |
+sample: sample.o $(B25OBJS) | |
+ $(CXX) $(CXXFLAGS) -rdynamic -o $@ $^ $(LIBS) | |
+ | |
+BonDriverProxy: BonDriverProxy.o $(B25OBJS) | |
$(CXX) $(CXXFLAGS) -rdynamic -o $@ $^ $(LIBS) | |
BonDriver_Proxy.$(EXT): BonDriver_Proxy.$(EXT).o | |
$(CXX) $(SOFLAGS) $(CXXFLAGS) -o $@ $^ $(LIBS) | |
-BonDriver_LinuxPT.$(EXT): BonDriver_LinuxPT.$(EXT).o | |
+BonDriver_LinuxPT.$(EXT): BonDriver_LinuxPT.$(EXT).o $(B25OBJS) | |
ifeq ($(UNAME), Darwin) | |
$(CXX) $(SOFLAGS) $(CXXFLAGS) -o $@ $^ $(LIBS) -liconv | |
else | |
@@ -50,7 +60,7 @@ | |
endif | |
clean: | |
- $(RM) *.o *.so *.dylib BonDriverProxy .depend | |
+ $(RM) *.o *.so *.dylib BonDriverProxy sample .depend | |
distclean: clean | |
dep: .depend | |
diff -r 8455e6cc2457 -r b1732a1d4f3a decoder.cpp | |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
+++ b/decoder.cpp Thu Sep 04 18:59:50 2014 +0900 | |
@@ -0,0 +1,147 @@ | |
+#ifndef NDEBUG | |
+#define NDEBUG | |
+#endif | |
+#include "decoder.h" | |
+#include <cstdio> | |
+#include <cassert> | |
+ | |
+int B25Decoder::multi2_round = 4; | |
+int B25Decoder::strip = 0; | |
+int B25Decoder::emm_proc = 0; | |
+ | |
+#ifndef NDEBUG | |
+#define report(fmt, args...) do { fprintf(stderr, fmt, ##args); } while (0) | |
+#else | |
+#define report(fmt, args...) ((void) 0) | |
+#endif | |
+ | |
+B25Decoder::B25Decoder() | |
+ : _bcas(NULL) | |
+ , _b25(NULL) | |
+{ | |
+} | |
+ | |
+B25Decoder::~B25Decoder() | |
+{ | |
+ release(); | |
+} | |
+ | |
+int B25Decoder::init() | |
+{ | |
+ const char *fn; | |
+ int rc; | |
+ | |
+ assert(_bcas == NULL); | |
+ assert(_b25 == NULL); | |
+ | |
+ report("%s\n", __PRETTY_FUNCTION__); | |
+ | |
+ _bcas = create_b_cas_card(), | |
+ fn = "create_b_cas_card", rc = 0; | |
+ if (!_bcas) goto err; | |
+ | |
+ rc = _bcas->init(_bcas), | |
+ fn = "bcas::init"; | |
+ if (rc < 0) goto err; | |
+ | |
+ _b25 = create_arib_std_b25(), | |
+ fn = "create_arib_std_b25", rc = 0; | |
+ if (!_b25) goto err; | |
+ | |
+ rc = _b25->set_b_cas_card(_b25, _bcas), | |
+ fn = "b25::set_b_cas_card"; | |
+ if (rc < 0) goto err; | |
+ | |
+ rc = _b25->set_strip(_b25, strip), | |
+ fn = "b25::set_strip"; | |
+ if (rc < 0) goto err; | |
+ | |
+ rc = _b25->set_emm_proc(_b25, emm_proc), | |
+ fn = "b25::set_emm_proc"; | |
+ if (rc < 0) goto err; | |
+ | |
+ rc = _b25->set_multi2_round(_b25, multi2_round), | |
+ fn = "b25::set_multi2_round"; | |
+ if (rc < 0) goto err; | |
+ | |
+ _get_bytes = _put_bytes = 0; | |
+ | |
+ return rc; | |
+err: | |
+ fprintf(stderr, "%s() failed. (%d)\n", fn, rc); | |
+ release(); | |
+ return rc; | |
+} | |
+ | |
+void B25Decoder::release() | |
+{ | |
+ if (_b25) | |
+ { | |
+ _b25->release(_b25); | |
+ _b25 = NULL; | |
+ report("%s\n", __PRETTY_FUNCTION__); | |
+ } | |
+ if (_bcas) | |
+ { | |
+ _bcas->release(_bcas); | |
+ _bcas = NULL; | |
+ } | |
+} | |
+ | |
+int B25Decoder::put(ARIB_STD_B25_BUFFER *buf) | |
+{ | |
+ assert(_b25); | |
+ _put_bytes += buf->size; | |
+ int rc = _b25->put(_b25, buf); | |
+ if (rc < 0) | |
+ fprintf(stderr, "b25::put failed. (%d)\n", rc); | |
+ return rc; | |
+} | |
+ | |
+int B25Decoder::get(ARIB_STD_B25_BUFFER *buf) | |
+{ | |
+ assert(_b25); | |
+ int rc = _b25->get(_b25, buf); | |
+ _get_bytes += buf->size; | |
+ if (buf->size == 0) | |
+ { | |
+ report("%gMB\n", _put_bytes / double(1024*1024)); | |
+ if (_get_bytes && _put_bytes) | |
+ { | |
+ report("Changing the stream is detected.\n"); | |
+ reset(); | |
+ return 0; | |
+ } | |
+ if (_put_bytes > 1024*1024*1) | |
+ { | |
+ report("Congestion of the stream is detected.\n"); | |
+ reset(); | |
+ return 0; | |
+ } | |
+ } | |
+ if (rc < 0) | |
+ fprintf(stderr, "b25::get failed. (%d)\n", rc); | |
+ return rc; | |
+} | |
+ | |
+int B25Decoder::flush() | |
+{ | |
+ report("%s\n", __PRETTY_FUNCTION__); | |
+ assert(_b25); | |
+ int rc = _b25->flush(_b25); | |
+ if (rc < 0) | |
+ fprintf(stderr, "b25::flush failed. (%d)\n", rc); | |
+ return rc; | |
+} | |
+ | |
+int B25Decoder::reset() | |
+{ | |
+ report("%s\n", __PRETTY_FUNCTION__); | |
+ assert(_b25); | |
+ int rc = _b25->reset(_b25); | |
+ if (rc < 0) | |
+ fprintf(stderr, "b25::reset failed. (%d)\n", rc); | |
+ _get_bytes = _put_bytes = 0; | |
+ return rc; | |
+} | |
+ | |
diff -r 8455e6cc2457 -r b1732a1d4f3a decoder.h | |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
+++ b/decoder.h Thu Sep 04 18:59:50 2014 +0900 | |
@@ -0,0 +1,40 @@ | |
+// -*- coding: utf-8 -*- | |
+#pragma once | |
+#include <arib25/arib_std_b25.h> | |
+ | |
+class B25Decoder | |
+{ | |
+ B_CAS_CARD *_bcas; | |
+ ARIB_STD_B25 *_b25; | |
+ uint64_t _put_bytes; | |
+ uint64_t _get_bytes; | |
+ | |
+public: | |
+ B25Decoder(); | |
+ | |
+ ~B25Decoder(); | |
+ | |
+ int init(); | |
+ | |
+ void release(); | |
+ | |
+ int put(ARIB_STD_B25_BUFFER *buf); | |
+ | |
+ int get(ARIB_STD_B25_BUFFER *buf); | |
+ | |
+ int flush(); | |
+ | |
+ int reset(); | |
+ | |
+ bool isValid() const { return _b25 != 0; } | |
+ | |
+ // initialize parameter | |
+ | |
+ static int multi2_round; | |
+ static int strip; | |
+ static int emm_proc; | |
+ | |
+private: | |
+ B25Decoder(const B25Decoder &); // undef | |
+ B25Decoder &operator=(const B25Decoder &); // undef | |
+}; | |
diff -r 8455e6cc2457 -r b1732a1d4f3a sample.cpp | |
--- a/sample.cpp Wed Sep 03 07:16:55 2014 +0900 | |
+++ b/sample.cpp Thu Sep 04 18:59:50 2014 +0900 | |
@@ -1,5 +1,6 @@ | |
/* | |
$ g++ -O2 -Wall -rdynamic -o sample sample.cpp -ldl | |
+$ g++ -O2 -Wall -rdynamic -o sample sample.cpp decoder.cpp -ldl -larib25 -DHAVE_LIBARIB25 | |
*/ | |
#define _FILE_OFFSET_BITS 64 | |
#include <unistd.h> | |
@@ -15,6 +16,92 @@ | |
#include "typedef.h" | |
#include "IBonDriver2.h" | |
+static ssize_t write_full(int fd, const void *buf, size_t count); | |
+ | |
+#ifdef HAVE_LIBARIB25 | |
+#include <getopt.h> | |
+#include "decoder.h" | |
+ | |
+class B25Writer : public B25Decoder | |
+{ | |
+public: | |
+ ssize_t operator()(int fd, void *buf, size_t count) | |
+ { | |
+ if (!isValid()) | |
+ return write_full(fd, buf, count); | |
+ | |
+ ARIB_STD_B25_BUFFER sbuf, dbuf; | |
+ sbuf.data = static_cast<uint8_t*>(buf); | |
+ sbuf.size = count; | |
+ | |
+ int code; | |
+ if ((code = B25Decoder::put(&sbuf)) < 0) | |
+ return code; | |
+ | |
+ if ((code = B25Decoder::get(&dbuf)) < 0) | |
+ return code; | |
+ | |
+ if (dbuf.size > 0) | |
+ { | |
+ ssize_t len; | |
+ if ((len = write_full(fd, dbuf.data, dbuf.size)) < 0) | |
+ return len; | |
+ } | |
+ return count; | |
+ } | |
+ | |
+ int flush(int fd) | |
+ { | |
+ if (!isValid()) | |
+ return 0; | |
+ | |
+ int code; | |
+ if ((code = B25Decoder::flush()) < 0) | |
+ return code; | |
+ | |
+ ARIB_STD_B25_BUFFER dbuf; | |
+ if ((code = B25Decoder::get(&dbuf)) < 0) | |
+ return code; | |
+ | |
+ if (dbuf.size > 0) | |
+ return write_full(fd, dbuf.data, dbuf.size); | |
+ | |
+ return 0; | |
+ } | |
+}; | |
+ | |
+#else // HAVE_LIBARIB25 | |
+ | |
+class B25Writer | |
+{ | |
+public: | |
+ ssize_t operator()(int fd, const void *buf, size_t count) | |
+ { | |
+ return write_full(fd, buf, count); | |
+ } | |
+}; | |
+ | |
+#endif // HAVE_LIBARIB25 | |
+ | |
+static ssize_t write_full(int fd, const void *buf, size_t count) | |
+{ | |
+ size_t size_remain = count; | |
+ size_t offset = 0; | |
+ | |
+ while (size_remain > 0) | |
+ { | |
+ ssize_t wc = ::write(fd, static_cast<const char*>(buf) + offset, size_remain); | |
+ if (wc < 0) | |
+ { | |
+ perror("write"); | |
+ return wc; | |
+ } | |
+ size_remain -= wc; | |
+ offset += wc; | |
+ } | |
+ return count; | |
+} | |
+ | |
static volatile BOOL bStop = FALSE; | |
static void handler(int sig) | |
{ | |
@@ -23,7 +110,12 @@ | |
void usage(char *p) | |
{ | |
+#ifdef HAVE_LIBARIB25 | |
+ fprintf(stderr, "usage: %s [--b25 [--round N] [--strip] [--EMM]] " | |
+ "[-b bondriver] [-s space_no] [-c channel_no] ( [-t sec] [-o filename] )\n", p); | |
+#else | |
fprintf(stderr, "usage: %s [-b bondriver] [-s space_no] [-c channel_no] ( [-t sec] [-o filename] )\n", p); | |
+#endif | |
exit(0); | |
} | |
@@ -38,10 +130,31 @@ | |
bon = output = NULL; | |
bfind = sfind = cfind = ofind = 0; | |
dwSpace = dwChannel = 0; | |
+ | |
+#ifdef HAVE_LIBARIB25 | |
+ int b25_enable = false; | |
+ static const struct option options[] = { | |
+ {"b25", no_argument, &b25_enable, 1}, | |
+ {"strip", no_argument, &B25Decoder::strip, 1}, | |
+ {"EMM", no_argument, &B25Decoder::emm_proc, 1}, | |
+ {"round", required_argument, NULL, 'r'}, | |
+ {0} | |
+ }; | |
+ | |
+ while ((opt = getopt_long(argc, argv, "b:s:c:t:o:", options, NULL)) != -1) | |
+#else | |
while ((opt = getopt(argc, argv, "b:s:c:t:o:")) != -1) | |
+#endif | |
{ | |
switch (opt) | |
{ | |
+#ifdef HAVE_LIBARIB25 | |
+ case 0: // long options | |
+ break; | |
+ case 'r': // multi2 round | |
+ B25Decoder::multi2_round = strtoul(optarg, NULL, 10); | |
+ break; | |
+#endif | |
case 'b': // BonDriver指定 | |
bon = optarg; | |
bfind = 1; | |
@@ -150,6 +263,14 @@ | |
timespec ts; | |
ts.tv_sec = 0; | |
ts.tv_nsec = 10 * 1000 * 1000; // 10ms | |
+ B25Writer writer; | |
+#ifdef HAVE_LIBARIB25 | |
+ if (b25_enable) | |
+ { | |
+ if (writer.init() < 0) | |
+ goto err; | |
+ } | |
+#endif | |
while (!bStop) | |
{ | |
// TSストリーム取得 | |
@@ -158,18 +279,8 @@ | |
{ | |
// この時点でpBufに長さdwSize分のTSストリームを取得した状態なので、それを書き出し | |
// (もしバッファリングやデスクランブルやTS分離処理を入れるならこの辺で) | |
- int len, left = (int)dwSize; | |
- do | |
- { | |
- len = write(wfd, pBuf, left); | |
- if (len < 0) | |
- { | |
- perror("write"); | |
- goto err; | |
- } | |
- left -= len; | |
- pBuf += len; | |
- } while (left > 0); | |
+ if (writer(wfd, pBuf, dwSize) < 0) | |
+ goto err; | |
} | |
// 取得待ちTSデータが無ければ適当な時間待つ | |
if (dwRemain == 0) | |
@@ -180,29 +291,17 @@ | |
pIBon->CloseTuner(); | |
// BonDriver内のバッファに残っている分があれば一応回収 | |
- while (1) | |
+ if (pIBon->GetTsStream(&pBuf, &dwSize, &dwRemain) && (dwSize != 0)) | |
{ | |
- dwSize = dwRemain = 0; | |
- if (pIBon->GetTsStream(&pBuf, &dwSize, &dwRemain) && (dwSize != 0)) | |
- { | |
- int len, left = (int)dwSize; | |
- do | |
- { | |
- len = write(wfd, pBuf, left); | |
- if (len < 0) | |
- { | |
- perror("write"); | |
- goto err; | |
- } | |
- left -= len; | |
- pBuf += len; | |
- } while (left > 0); | |
- } | |
- if (dwRemain == 0) | |
- break; | |
+ if (writer(wfd, pBuf, dwSize) < 0) | |
+ goto err; | |
} | |
err: | |
+#ifdef HAVE_LIBARIB25 | |
+ writer.flush(wfd); | |
+ writer.release(); | |
+#endif | |
close(wfd); | |
// インスタンス解放 & モジュールリリース | |
pIBon->Release(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment