Skip to content

Instantly share code, notes, and snippets.

Created September 4, 2014 11:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/570aa60b21fc28295662 to your computer and use it in GitHub Desktop.
Save anonymous/570aa60b21fc28295662 to your computer and use it in GitHub Desktop.
b25 patch for BonDriverProxy_Linux
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