i have made some tests about a usb dvb-t device in my dm800. Either with OE 1.5 and OE 1.6 i can get an accettable use with vtuner interface.
there are some bugs in the different usb device's backported drivers but nothing major.
BTW, I have noticed a common issue with dvb-t HD channels, using the Homey's usbtuner (patched for dvb-t/c standard), the CPU load is about 30/40% making enigma2 unstable (maybe you can watch an HD channel but if you open some GUI menu or try to make an HDD recording enigma2 hangs).
with SD channels the usbtuner cpu load is about 3/6%.
I think the high cpu load is due by ioctl calls to transer by usb the HD ts.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <poll.h>
#include <sys/ioctl.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#define PVR_FLUSH_BUFFER 0
#define VTUNER_GET_MESSAGE 1
#define VTUNER_SET_RESPONSE 2
#define VTUNER_SET_NAME 3
#define VTUNER_SET_TYPE 4
#define VTUNER_SET_HAS_OUTPUTS 5
#define VTUNER_SET_FE_INFO 6
#define MAX_PIDS 32
#define BSIZE 1024*16
#define DMX_ADD_PID _IO('o', 51)
#define DMX_REMOVE_PID _IO('o', 52)
typedef enum {
DMX_TAP_TS = 0,
DMX_TAP_PES = DMX_PES_OTHER, /* for backward binary compat. */
} dmx_tap_type_t;
int active_pids[MAX_PIDS];
int die(const char *reason)
{
fprintf(stderr, "%s failed - %m\n", reason);
exit(1);
}
#define require(x, reason) if (!(x)) die(reason)
#define MSG_SET_FRONTEND 1
#define MSG_GET_FRONTEND 2
#define MSG_READ_STATUS 3
#define MSG_READ_BER 4
#define MSG_READ_SIGNAL_STRENGTH 5
#define MSG_READ_SNR 6
#define MSG_READ_UCBLOCKS 7
#define MSG_SET_TONE 8
#define MSG_SET_VOLTAGE 9
#define MSG_ENABLE_HIGH_VOLTAGE 10
#define MSG_SEND_DISEQC_MSG 11
#define MSG_SEND_DISEQC_BURST 13
#define MSG_PIDLIST 14
int main(void)
{
/* Initalize Frontend Device */
int fe = open("/dev/dvb/adapter1/frontend0", O_RDWR);
if (fe < 0)
{
perror("vTuner: adapter1/frontend0");
return 1;
} else {
perror("FE Open");
}
struct dvb_frontend_info fe_info;
if( ioctl(fe, FE_GET_INFO, &fe_info) ) {
perror("vTuner: FE_GET_INFO failed\n");
return 1;
} else {
perror(fe_info.name);
}
/* Initalize Demux Device */
int i;
for (i=0; i<MAX_PIDS; ++i)
active_pids[i]=-1;
struct dmx_pes_filter_params flt;
char demuxfn[32];
int demux=0;
sprintf(demuxfn, "/dev/dvb/adapter1/demux%d", demux);
int demux_fd= open(demuxfn, O_RDWR|O_NONBLOCK);
require(demux_fd >= 0, "demux");
flt.pid = -1;
flt.input = DMX_IN_FRONTEND;
flt.output = DMX_OUT_TAP;
flt.pes_type = DMX_TAP_TS;
flt.flags = 0;
require (ioctl(demux_fd, DMX_SET_PES_FILTER, &flt) ==0, "DMX_SET_PES_FILTER");
ioctl(demux_fd, DMX_SET_BUFFER_SIZE, 1024*1024);
require(ioctl(demux_fd, DMX_START, 0) == 0, "DMX_START");
int vtuner_control = open("/dev/misc/vtuner0", O_RDWR);
if (vtuner_control < 0)
{
perror("/dev/misc/vtuner0");
return 1;
} else {
perror("vtuner aperto");
}
if (ioctl(vtuner_control, VTUNER_SET_NAME, "USB-Tuner"))
perror("VTUNER_SET_NAME");
char type[8];
switch(fe_info.type) {
case FE_QPSK: strcpy(type,"DVB-S2"); break;
case FE_QAM: strcpy(type,"DVB-C"); break;
case FE_OFDM: strcpy(type,"DVB-T"); break;
}
if (ioctl(vtuner_control, VTUNER_SET_TYPE, type))
perror("VTUNER_SET_TYPE");
if (ioctl(vtuner_control, VTUNER_SET_FE_INFO, &fe_info))
perror("VTUNER_SET_FE_INFO");
if (ioctl(vtuner_control, VTUNER_SET_HAS_OUTPUTS, "no"))
perror("VTUNER_SET_HAS_OUTPUTS");
struct dvb_frontend_parameters feparm;
while (1)
{
struct pollfd pfd[] = {{vtuner_control, POLLPRI}, {demux_fd, POLLIN}};
poll(pfd, 2, -1);
if (pfd[0].revents & POLLPRI)
{
struct {
int type;
union {
struct dvb_frontend_parameters dvb_frontend_parameters;
fe_status_t status;
__u32 ber;
__u16 ss, snr;
__u32 ucb;
fe_sec_tone_mode_t tone;
fe_sec_voltage_t voltage;
fe_sec_mini_cmd_t burst;
unsigned short pidlist[30];
unsigned char pad[60];
} body;
} msg;
if (ioctl(vtuner_control, VTUNER_GET_MESSAGE, &msg))
perror("VTUNER_GET_MESSAGE");
printf("vtuner message: %d\n", msg.type);
switch (msg.type)
{
case MSG_SET_FRONTEND:
printf("FE_SET_FRONTEND: %d\n", msg.body.dvb_frontend_parameters.frequency);
require(ioctl(fe, FE_SET_FRONTEND, &msg.body.dvb_frontend_parameters) == 0, "FE_SET_FRONTEND");
break;
case MSG_GET_FRONTEND:
require(ioctl(fe, FE_GET_FRONTEND, &msg.body.dvb_frontend_parameters) == 0, "FE_GET_FRONTEND");
break;
case MSG_READ_STATUS:
require(ioctl(fe, FE_READ_STATUS, &msg.body.status) == 0, "FE_READ_STATUS");
break;
case MSG_READ_BER:
require(ioctl(fe, FE_READ_BER, &msg.body.ber) == 0, "FE_READ_BER");
break;
case MSG_READ_SIGNAL_STRENGTH:
require(ioctl(fe, FE_READ_SIGNAL_STRENGTH, &msg.body.ss) == 0, "FE_READ_SIGNAL_STRENGTH");
break;
case MSG_READ_SNR:
require(ioctl(fe, FE_READ_SNR, &msg.body.snr) == 0, "FE_READ_SNR");
break;
case MSG_READ_UCBLOCKS:
require(ioctl(fe, FE_READ_UNCORRECTED_BLOCKS, &msg.body.ucb) == 0, "FE_READ_UNCORRECTED_BLOCKS");
break;
case MSG_SET_TONE:
require(ioctl(fe, FE_SET_TONE, msg.body.tone) == 0, "FE_SET_TONE");
break;
/* case MSG_SET_VOLTAGE:
* require(ioctl(fe, FE_SET_VOLTAGE, msg.body.voltage) == 0, "FE_SET_VOLTAGE");
* break;
*/
case MSG_ENABLE_HIGH_VOLTAGE:
break;
case MSG_SEND_DISEQC_MSG:
require(ioctl(fe, FE_DISEQC_SEND_MASTER_CMD, msg.body.pad) == 0, "FE_DISEQC_SEND_MASTER_CMD");
break;
case MSG_SEND_DISEQC_BURST:
require(ioctl(fe, FE_DISEQC_SEND_BURST, msg.body.pad) == 0, "FE_DISEQC_SEND_BURST");
break;
case MSG_PIDLIST:
{
printf("pidlist:\n");
int i;
for (i=0; i<30; ++i)
if (msg.body.pidlist[i] != 0xFFFF)
{
printf("\t%04x\n", msg.body.pidlist[i]);
}
int old_active_pids[MAX_PIDS];
memcpy(old_active_pids, active_pids, sizeof(active_pids));
int nr_pids = 0, j;
for (j=0; j<30; ++j)
{
int pid = msg.body.pidlist[j];
for (i = 0; i < nr_pids; ++i)
if (active_pids[i] == pid)
break;
if (i != nr_pids)
continue;
active_pids[nr_pids++] = pid;
if (nr_pids == MAX_PIDS)
break;
}
for (i = nr_pids; i < MAX_PIDS; ++i)
active_pids[i] = -1;
for (i = 0; i < nr_pids; ++i)
{
for (j = 0; j < MAX_PIDS; ++j)
if (active_pids[i] == old_active_pids[j])
break;
if (j == MAX_PIDS)
ioctl(demux_fd, DMX_ADD_PID, active_pids[i]);
}
for (i = 0; i < MAX_PIDS; ++i)
{
if (old_active_pids[i] == -1)
continue;
for (j = 0; j < nr_pids; ++j)
if (old_active_pids[i] == active_pids[j])
break;
if (j == nr_pids)
ioctl(demux_fd, DMX_REMOVE_PID, old_active_pids[i]);
}
break;
}
default:
printf("unknown msg %d!\n", msg.type);
break;
}
if (msg.type != MSG_PIDLIST)
{
msg.type = 0;
if (ioctl(vtuner_control, VTUNER_SET_RESPONSE, &msg))
{
perror("VTUNER_SET_RESPONSE");
printf("msg: %d\n", msg.type);
}
}
}
if (pfd[1].revents & POLLIN)
{
unsigned char buf[1024*1024];
int r = read(demux_fd, buf, 1024*1024);
fprintf(stderr, "wrote %d bytes\n", r);
if (write(vtuner_control, buf, r) != r)
{
perror("write");
return 1;
}
}
}
return 0;
}
Alles anzeigen
playing with the buffer's value (lines 246-247) seems to change cpu load. with some devices works ok with 512*512 or 1024*1024, some others requires highest values.
higher values seems to reduce cpu laod, but make enigma2 unstable.
Do you have some hints to optimize this values and code?
Thanks a lot.