libtriple: add measure mode to cDemux to fix streaminfo

since the TD drivers apparently only allow each PID to be captured
once, cheat and implement the measure mode for streaminfo with
special ioctls. now streaminfo no longer breaks recordings
This commit is contained in:
Stefan Seyfried
2011-11-05 23:11:18 +01:00
parent 1814291ced
commit 15282e5ae1
2 changed files with 90 additions and 10 deletions

View File

@@ -51,6 +51,9 @@ cDemux::cDemux(int n)
else else
num = n; num = n;
fd = -1; fd = -1;
measure = false;
last_measure = 0;
last_data = 0;
} }
cDemux::~cDemux() cDemux::~cDemux()
@@ -62,22 +65,35 @@ cDemux::~cDemux()
bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize) bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize)
{ {
int devnum = num; int devnum = num;
int flags = O_RDWR;
if (fd > -1) if (fd > -1)
lt_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd); lt_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd);
if (pes_type == DMX_TP_CHANNEL) if (pes_type == DMX_TP_CHANNEL)
{ {
/* it looks like the drivers can only do one TS at a time */ if (num == 0) /* streaminfo measurement, let's cheat... */
if (dmx_tp_count >= MAX_TS_COUNT)
{ {
lt_info("%s too many DMX_TP_CHANNEL requests :-(\n", __FUNCTION__); lt_info("%s num=0 and DMX_TP_CHANNEL => measurement demux\n", __func__);
dmx_type = DMX_INVALID; devnum = 2; /* demux 0 is used for live, demux 1 for recording */
fd = -1; measure = true;
return false; last_measure = 0;
last_data = 0;
flags |= O_NONBLOCK;
}
else
{
/* it looks like the drivers can only do one TS at a time */
if (dmx_tp_count >= MAX_TS_COUNT)
{
lt_info("%s too many DMX_TP_CHANNEL requests :-(\n", __FUNCTION__);
dmx_type = DMX_INVALID;
fd = -1;
return false;
}
dmx_tp_count++;
devnum = dmx_tp_count;
} }
dmx_tp_count++;
devnum = dmx_tp_count;
} }
fd = open(devname[devnum], O_RDWR); fd = open(devname[devnum], flags);
if (fd < 0) if (fd < 0)
{ {
lt_info("%s %s: %m\n", __FUNCTION__, devname[devnum]); lt_info("%s %s: %m\n", __FUNCTION__, devname[devnum]);
@@ -95,6 +111,8 @@ bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBuffe
} }
if (pes_type == DMX_TP_CHANNEL) if (pes_type == DMX_TP_CHANNEL)
{ {
if (measure)
return true;
struct demux_bucket_para bp; struct demux_bucket_para bp;
bp.unloader.unloader_type = UNLOADER_TYPE_TRANSPORT; bp.unloader.unloader_type = UNLOADER_TYPE_TRANSPORT;
bp.unloader.threshold = 128; bp.unloader.threshold = 128;
@@ -135,6 +153,8 @@ void cDemux::Close(void)
ioctl(fd, DEMUX_STOP); ioctl(fd, DEMUX_STOP);
close(fd); close(fd);
fd = -1; fd = -1;
if (measure)
return;
if (dmx_type == DMX_TP_CHANNEL) if (dmx_type == DMX_TP_CHANNEL)
{ {
dmx_tp_count--; dmx_tp_count--;
@@ -194,6 +214,51 @@ int cDemux::Read(unsigned char *buff, int len, int timeout)
ufds.events = POLLIN; ufds.events = POLLIN;
ufds.revents = 0; ufds.revents = 0;
if (measure)
{
uint64_t now;
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
now = t.tv_sec * 1000;
now += t.tv_nsec / 1000000;
if (now - last_measure < 333)
return 0;
unsigned char dummy[12];
unsigned long long bit_s = 0;
S_STREAM_MEASURE m;
ioctl(fd, DEMUX_STOP);
rc = read(fd, dummy, 12);
lt_debug("%s measure read: %d\n", __func__, rc);
if (rc == 12)
{
ioctl(fd, DEMUX_GET_MEASURE_TIMING, &m);
if (m.rx_bytes > 0 && m.rx_time_us > 0)
{
// -- current bandwidth in kbit/sec
// --- cast to unsigned long long so it doesn't overflow as
// --- early, add time / 2 before division for correct rounding
/* the correction factor is found out like that:
- with 8000 (guessed), a 256 kbit radio stream shows as 262kbit...
- 8000*256/262 = 7816.793131
BUT! this is only true for some Radio stations (DRS3 for example), for
others (DLF) 8000 does just fine.
bit_s = (m.rx_bytes * 7816793ULL + (m.rx_time_us / 2ULL)) / m.rx_time_us;
*/
bit_s = (m.rx_bytes * 8000ULL + (m.rx_time_us / 2ULL)) / m.rx_time_us;
if (now - last_data < 5000)
rc = bit_s * (now - last_data) / 8ULL;
else
rc = 0;
lt_debug("%s measure bit_s: %llu rc: %d timediff: %lld\n",
__func__, bit_s, rc, (now - last_data));
last_data = now;
} else
rc = 0;
}
last_measure = now;
ioctl(fd, DEMUX_START);
return rc;
}
if (timeout > 0) if (timeout > 0)
{ {
retry: retry:
@@ -363,7 +428,7 @@ bool cDemux::pesFilter(const unsigned short pid)
lt_debug("%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]); lt_debug("%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]);
if (dmx_type == DMX_TP_CHANNEL) if (dmx_type == DMX_TP_CHANNEL && !measure)
{ {
unsigned int n = pesfds.size(); unsigned int n = pesfds.size();
addPid(pid); addPid(pid);
@@ -390,6 +455,13 @@ bool cDemux::pesFilter(const unsigned short pid)
flt.unloader.threshold = 8; // 1k, teletext flt.unloader.threshold = 8; // 1k, teletext
flt.pesType = DMX_PES_OTHER; flt.pesType = DMX_PES_OTHER;
flt.output = OUT_MEMORY; flt.output = OUT_MEMORY;
case DMX_TP_CHANNEL:
/* must be measure == true or we would have returned above */
flt.output = OUT_MEMORY;
flt.pesType = DMX_PES_OTHER;
flt.unloader.threshold = 1;
flt.unloader.unloader_type = UNLOADER_TYPE_MEASURE_DUMMY;
ioctl(fd, DEMUX_SET_MEASURE_TIME, 250000);
default: default:
flt.pesType = DMX_PES_OTHER; flt.pesType = DMX_PES_OTHER;
} }
@@ -423,6 +495,11 @@ bool cDemux::addPid(unsigned short Pid)
lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid); lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
return false; return false;
} }
if (measure)
{
lt_info("%s measurement demux -> skipping\n", __func__);
return true;
}
if (fd == -1) if (fd == -1)
lt_info("%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid); lt_info("%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid);
pfd.fd = open(devname[num], O_RDWR); pfd.fd = open(devname[num], O_RDWR);

View File

@@ -4,6 +4,7 @@
#include <cstdlib> #include <cstdlib>
#include <vector> #include <vector>
extern "C" { extern "C" {
#include <inttypes.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <hardware/xp/xp_osd_user.h> #include <hardware/xp/xp_osd_user.h>
} }
@@ -36,6 +37,8 @@ class cDemux
int num; int num;
int fd; int fd;
int buffersize; int buffersize;
bool measure;
uint64_t last_measure, last_data;
DMX_CHANNEL_TYPE dmx_type; DMX_CHANNEL_TYPE dmx_type;
std::vector<pes_pids> pesfds; std::vector<pes_pids> pesfds;
public: public: