From 3abf26f019fa780877b64be16d1b82c1311fab5c Mon Sep 17 00:00:00 2001 From: Oliver Freyermuth Date: Tue, 30 Dec 2014 20:34:22 +0100 Subject: dvb_tune: (DVB-S) Initial S2API support. Also allows demuxers to buffer, and we explicitly discard stale QPSK events. Inspiration taken from the szap-s2 implementation. S2API is only used if available and for DVB-S cards - it might also be useful to have that for DVB-T2 / DVB-C2 tuning later, but I do not have the HW / no DVB-T2 broadcasting station nearby to test functionality. This should do no functional changes, only usage of the different API. The S2API is more extensible and a requirement for all the HD-deliveries (e.g. DVB-S2) and since 2.6.28 is the successor of the old API. Tuning to DVB-S2 channels actually already "works" like this if the delivery is hardcoded in - for a fully working implementation, the channels.conf.sat would need an additional field indicating the delivery type (VDR-type channels.conf have that). This commit also: - Cleans up some debug output. - Moves an unneeded usleep(100000) (only needed for diseqc switching for SAT) into the DVB-S-only part of the implementation. --- stream/dvb_tune.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 79 insertions(+), 13 deletions(-) diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c index 056592bceb..3178dc3ab2 100644 --- a/stream/dvb_tune.c +++ b/stream/dvb_tune.c @@ -170,10 +170,16 @@ int dvb_set_ts_filt(dvb_priv_t *priv, int fd, uint16_t pid, dmx_pes_type_t pesty pesFilterParams.pes_type = pestype; pesFilterParams.flags = DMX_IMMEDIATE_START; + { + int buffersize = 64 * 1024; + if (ioctl(fd, DMX_SET_BUFFER_SIZE, buffersize) < 0) + MP_ERR(priv, "ERROR IN DMX_SET_BUFFER_SIZE %i for fd %d: ERRNO: %d\n", pid, fd, errno); + } + errno = 0; if ((i = ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams)) < 0) { - MP_ERR(priv, "ERROR IN SETTING DMX_FILTER %i for fd %d: ERRNO: %d", pid, fd, errno); + MP_ERR(priv, "ERROR IN SETTING DMX_FILTER %i for fd %d: ERRNO: %d\n", pid, fd, errno); return 0; } @@ -326,7 +332,7 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, int fd_sec, unsigned int f struct dvb_frontend_parameters feparams; struct dvb_frontend_info fe_info; - MP_VERBOSE(priv, "TUNE_IT, fd_frontend %d, fd_sec %d\nfreq %lu, srate %lu, pol %c, tone %i, specInv, diseqc %u, fe_modulation_t modulation,fe_code_rate_t HP_CodeRate, fe_transmit_mode_t TransmissionMode,fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth\n", + MP_VERBOSE(priv, "TUNE_IT, fd_frontend %d, fd_sec %d\nfreq %lu, srate %lu, pol %c, tone %i, diseqc %u\n", fd_frontend, fd_sec, (long unsigned int)freq, (long unsigned int)srate, pol, tone, diseqc); @@ -339,6 +345,15 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, int fd_sec, unsigned int f MP_VERBOSE(priv, "Using DVB card \"%s\"\n", fe_info.name); + { + /* discard stale QPSK events */ + struct dvb_frontend_event ev; + while (true) { + if (ioctl(fd_frontend, FE_GET_EVENT, &ev) == -1) + break; + } + } + switch(fe_info.type) { case FE_OFDM: @@ -353,8 +368,14 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, int fd_sec, unsigned int f feparams.u.ofdm.guard_interval=guardInterval; feparams.u.ofdm.hierarchy_information=hier; MP_VERBOSE(priv, "tuning DVB-T to %d Hz, bandwidth: %d\n",freq, bandwidth); + if(ioctl(fd_frontend,FE_SET_FRONTEND,&feparams) < 0) + { + MP_ERR(priv, "ERROR tuning channel\n"); + return -1; + } break; case FE_QPSK: + // DVB-S if (freq > 2200000) { // this must be an absolute frequency @@ -383,39 +404,84 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, int fd_sec, unsigned int f MP_VERBOSE(priv, "tuning DVB-S to Freq: %u, Pol: %c Srate: %d, 22kHz: %s, LNB: %d\n",freq,pol,srate,hi_lo ? "on" : "off", diseqc); if(do_diseqc(dfd, diseqc, (pol == 'V' ? 1 : 0), hi_lo) == 0) - MP_VERBOSE(priv, "DISEQC SETTING SUCCEDED\n"); + MP_VERBOSE(priv, "DISEQC setting succeeded\n"); else { - MP_ERR(priv, "DISEQC SETTING FAILED\n"); + MP_ERR(priv, "DISEQC setting failed\n"); return -1; } + usleep(100000); + +#ifdef DVB_USE_S2API + /* S2API is the DVB API new since 2.6.28. + * It is needed to tune to new delivery systems, e.g. DVB-S2. + * It takes a struct with a list of pairs of command + parameter. + */ + + fe_delivery_system_t delsys = SYS_DVBS; + fe_rolloff_t rolloff = ROLLOFF_AUTO; + int stream_id = NO_STREAM_ID_FILTER; + + struct dtv_property p[] = { + { .cmd = DTV_DELIVERY_SYSTEM, .u.data = delsys }, + { .cmd = DTV_FREQUENCY, .u.data = freq }, + { .cmd = DTV_MODULATION, .u.data = modulation }, + { .cmd = DTV_SYMBOL_RATE, .u.data = srate }, + { .cmd = DTV_INNER_FEC, .u.data = HP_CodeRate }, + { .cmd = DTV_INVERSION, .u.data = specInv }, + { .cmd = DTV_ROLLOFF, .u.data = rolloff }, + { .cmd = DTV_PILOT, .u.data = PILOT_AUTO }, + { .cmd = DTV_STREAM_ID, .u.data = stream_id }, + { .cmd = DTV_TUNE }, + }; + struct dtv_properties cmdseq = { + .num = sizeof(p)/sizeof(p[0]), + .props = p + }; + MP_VERBOSE(priv, "Tuning via S2API.\n"); + if ((ioctl(fd_frontend, FE_SET_PROPERTY, &cmdseq)) == -1) + { + MP_ERR(priv, "ERROR tuning channel\n"); + return -1; + } +#else + MP_VERBOSE(priv, "Tuning via DVB-API version 3.\n"); + if(ioctl(fd_frontend,FE_SET_FRONTEND,&feparams) < 0) + { + MP_ERR(priv, "ERROR tuning channel\n"); + return -1; + } +#endif break; case FE_QAM: - MP_VERBOSE(priv, "tuning DVB-C to %d, srate=%d\n",freq,srate); feparams.frequency=freq; feparams.inversion=specInv; feparams.u.qam.symbol_rate = srate; feparams.u.qam.fec_inner = HP_CodeRate; feparams.u.qam.modulation = modulation; + MP_VERBOSE(priv, "tuning DVB-C to %d, srate=%d\n",freq,srate); + if(ioctl(fd_frontend,FE_SET_FRONTEND,&feparams) < 0) + { + MP_ERR(priv, "ERROR tuning channel\n"); + return -1; + } break; #ifdef DVB_ATSC case FE_ATSC: - MP_VERBOSE(priv, "tuning ATSC to %d, modulation=%d\n",freq,modulation); feparams.frequency=freq; feparams.u.vsb.modulation = modulation; + MP_VERBOSE(priv, "tuning ATSC to %d, modulation=%d\n",freq,modulation); + if(ioctl(fd_frontend,FE_SET_FRONTEND,&feparams) < 0) + { + MP_ERR(priv, "ERROR tuning channel\n"); + return -1; + } break; #endif default: MP_VERBOSE(priv, "Unknown FE type. Aborting\n"); return 0; } - usleep(100000); - - if(ioctl(fd_frontend,FE_SET_FRONTEND,&feparams) < 0) - { - MP_ERR(priv, "ERROR tuning channel\n"); - return -1; - } return check_status(priv, fd_frontend, timeout); } -- cgit v1.2.3