static gboolean gst_dvbsrc_tune (GstDvbSrc * object) { #if DVB_API_VERSION == 3 && DVB_API_VERSION_MINOR == 3 struct dvbfe_params feparams; #else struct dvb_frontend_parameters feparams; #endif fe_sec_voltage_t voltage; fe_status_t status; int i; int j; unsigned int freq = object->freq; unsigned int sym_rate = object->sym_rate * 1000; /* found in mail archive on linuxtv.org * What works well for us is: * - first establish a TS feed (i.e. tune the frontend and check for success) * - then set filters (PES/sections) * - then tell the MPEG decoder to start * - before tuning: first stop the MPEG decoder, then stop all filters */ GST_INFO_OBJECT (object, "gst_dvbsrc_tune"); if (object->fd_frontend < 0) { /* frontend not opened yet, tune later */ GST_INFO_OBJECT (object, "Frontend not open: tuning later"); return FALSE; } gst_dvbsrc_unset_pes_filters (object); for (j = 0; j < 5; j++) { switch (object->adapter_type) { case FE_QPSK: object->tone = SEC_TONE_OFF; if (freq > 2200000) { // this must be an absolute frequency if (freq < SLOF) { feparams.frequency = (freq - LOF1); } else { feparams.frequency = (freq - LOF2); object->tone = SEC_TONE_ON; } } else { // this is an L-Band frequency feparams.frequency = freq; } feparams.inversion = INVERSION_AUTO; GST_DEBUG_OBJECT (object, "api version %d.%d", DVB_API_VERSION, DVB_API_VERSION_MINOR); #if DVB_API_VERSION == 3 && DVB_API_VERSION_MINOR == 3 GST_DEBUG_OBJECT (object, "using multiproto driver"); feparams.delsys.dvbs.symbol_rate = sym_rate; feparams.delsys.dvbs.fec = object->code_rate_hp; #else feparams.u.qpsk.symbol_rate = sym_rate; feparams.u.qpsk.fec_inner = object->code_rate_hp; #endif GST_INFO_OBJECT (object, "tuning DVB-S to L-Band:%u, Pol:%d, srate=%u, 22kHz=%s", feparams.frequency, object->pol, sym_rate, object->tone == SEC_TONE_ON ? "on" : "off"); if (object->pol == DVB_POL_H) voltage = SEC_VOLTAGE_18; else voltage = SEC_VOLTAGE_13; if (object->diseqc_src == -1 || object->send_diseqc == FALSE) { if (ioctl (object->fd_frontend, FE_SET_VOLTAGE, voltage) < 0) { g_warning ("Unable to set voltage on dvb frontend device"); } if (ioctl (object->fd_frontend, FE_SET_TONE, object->tone) < 0) { g_warning ("Error setting tone: %s", strerror (errno)); } } else { GST_DEBUG_OBJECT (object, "Sending DISEqC"); diseqc (object->fd_frontend, object->diseqc_src, voltage, object->tone); /* Once diseqc source is set, do not set it again until * app decides to change it */ //object->send_diseqc = FALSE; } break; case FE_OFDM: feparams.frequency = freq; #if DVB_API_VERSION == 3 && DVB_API_VERSION_MINOR == 3 #else feparams.u.ofdm.bandwidth = object->bandwidth; feparams.u.ofdm.code_rate_HP = object->code_rate_hp; feparams.u.ofdm.code_rate_LP = object->code_rate_lp; feparams.u.ofdm.constellation = object->modulation; feparams.u.ofdm.transmission_mode = object->transmission_mode; feparams.u.ofdm.guard_interval = object->guard_interval; feparams.u.ofdm.hierarchy_information = object->hierarchy_information; #endif feparams.inversion = object->inversion; GST_INFO_OBJECT (object, "tuning DVB-T to %d Hz\n", freq); break; case FE_QAM: GST_INFO_OBJECT (object, "Tuning DVB-C to %d, srate=%d", freq, sym_rate); feparams.frequency = freq; feparams.inversion = object->inversion; feparams.u.qam.fec_inner = object->code_rate_hp; feparams.u.qam.modulation = object->modulation; feparams.u.qam.symbol_rate = sym_rate; break; case FE_ATSC: GST_INFO_OBJECT (object, "Tuning ATSC to %d", freq); feparams.frequency = freq; feparams.u.vsb.modulation = object->modulation; break; default: g_error ("Unknown frontend type: %d", object->adapter_type); } usleep (100000); /* now tune the frontend */ #if DVB_API_VERSION == 3 && DVB_API_VERSION_MINOR == 3 if (ioctl (object->fd_frontend, DVBFE_SET_PARAMS, &feparams) < 0) { #else if (ioctl (object->fd_frontend, FE_SET_FRONTEND, &feparams) < 0) { #endif g_warning ("Error tuning channel: %s", strerror (errno)); } for (i = 0; i < 5; i++) { usleep (100000); if (ioctl (object->fd_frontend, FE_READ_STATUS, &status) == -1) { perror ("FE_READ_STATUS"); break; } GST_LOG_OBJECT (object, "status == 0x%02x", status); } if (status & FE_HAS_LOCK) break; } if (!(status & FE_HAS_LOCK)) return FALSE; /* set pid filters */ gst_dvbsrc_set_pes_filters (object); return TRUE; } static void gst_dvbsrc_unset_pes_filters (GstDvbSrc * object) { int i = 0; GST_INFO_OBJECT (object, "clearing PES filter"); for (i = 0; i < MAX_FILTERS; i++) { if (object->fd_filters[i] == -1) continue; close (object->fd_filters[i]); object->fd_filters[i] = -1; } }
static int zap_to(unsigned int adapter, unsigned int frontend, unsigned int demux, unsigned int sat_no, unsigned int freq, unsigned int pol, unsigned int sr, unsigned int vpid, unsigned int apid, int sid, int dvr, int rec_psi, int bypass, int human_readable) { char fedev[128], dmxdev[128], auddev[128]; static int fefd, dmxfda, dmxfdv, audiofd = -1, patfd, pmtfd; int pmtpid; uint32_t ifreq, mstd; int hiband, result; if (!fefd) { snprintf(fedev, sizeof(fedev), FRONTENDDEVICE, adapter, frontend); snprintf(dmxdev, sizeof(dmxdev), DEMUXDEVICE, adapter, demux); snprintf(auddev, sizeof(auddev), AUDIODEVICE, adapter, demux); printf("using '%s' and '%s'\n", fedev, dmxdev); if ((fefd = open(fedev, O_RDWR | O_NONBLOCK)) < 0) { perror("opening frontend failed"); return FALSE; } if (check_frontend(fefd, FE_QPSK, &mstd) < 0) { close(fefd); return FALSE; } /* TODO! Some frontends need to be explicit delivery system */ if ((dmxfdv = open(dmxdev, O_RDWR)) < 0) { perror("opening video demux failed"); close(fefd); return FALSE; } if ((dmxfda = open(dmxdev, O_RDWR)) < 0) { perror("opening audio demux failed"); close(fefd); return FALSE; } if (dvr == 0) /* DMX_OUT_DECODER */ audiofd = open(auddev, O_RDWR); if (rec_psi) { if ((patfd = open(dmxdev, O_RDWR)) < 0) { perror("opening pat demux failed"); close(audiofd); close(dmxfda); close(dmxfdv); close(fefd); return FALSE; } if ((pmtfd = open(dmxdev, O_RDWR)) < 0) { perror("opening pmt demux failed"); close(patfd); close(audiofd); close(dmxfda); close(dmxfdv); close(fefd); return FALSE; } } } hiband = 0; if (lnb_type.switch_val && lnb_type.high_val && freq >= lnb_type.switch_val) hiband = 1; if (hiband) ifreq = freq - lnb_type.high_val; else { if (freq < lnb_type.low_val) ifreq = lnb_type.low_val - freq; else ifreq = freq - lnb_type.low_val; } result = FALSE; if (diseqc(fefd, sat_no, pol, hiband)) if (do_tune(fefd, ifreq, sr)) if (set_pesfilter(dmxfdv, vpid, DMX_PES_VIDEO, dvr)) if (audiofd >= 0) (void)ioctl(audiofd, AUDIO_SET_BYPASS_MODE, bypass); if (set_pesfilter(dmxfda, apid, DMX_PES_AUDIO, dvr)) { if (rec_psi) { pmtpid = get_pmt_pid(dmxdev, sid); if (pmtpid < 0) { result = FALSE; } if (pmtpid == 0) { fprintf(stderr,"couldn't find pmt-pid for sid %04x\n",sid); result = FALSE; } if (set_pesfilter(patfd, 0, DMX_PES_OTHER, dvr)) if (set_pesfilter(pmtfd, pmtpid, DMX_PES_OTHER, dvr)) result = TRUE; } else { result = TRUE; } } monitor_frontend (fefd, dvr, human_readable); if (!interactive) { close(patfd); close(pmtfd); if (audiofd >= 0) close(audiofd); close(dmxfda); close(dmxfdv); close(fefd); } return result; }
static gboolean gst_dvbsrc_tune (GstDvbSrc * object) { struct dtv_properties props; struct dtv_property dvb_prop[NUM_DTV_PROPS]; fe_sec_voltage_t voltage; fe_status_t status; int n; int i; int j; unsigned int del_sys = SYS_UNDEFINED; unsigned int freq = object->freq; unsigned int sym_rate = object->sym_rate * 1000; unsigned int bandwidth; int inversion = object->inversion; /* found in mail archive on linuxtv.org * What works well for us is: * - first establish a TS feed (i.e. tune the frontend and check for success) * - then set filters (PES/sections) * - then tell the MPEG decoder to start * - before tuning: first stop the MPEG decoder, then stop all filters */ GST_INFO_OBJECT (object, "gst_dvbsrc_tune"); if (object->fd_frontend < 0) { /* frontend not opened yet, tune later */ GST_INFO_OBJECT (object, "Frontend not open: tuning later"); return FALSE; } GST_DEBUG_OBJECT (object, "api version %d.%d", DVB_API_VERSION, DVB_API_VERSION_MINOR); gst_dvbsrc_unset_pes_filters (object); for (j = 0; j < 5; j++) { memset (dvb_prop, 0, sizeof (dvb_prop)); dvb_prop[0].cmd = DTV_CLEAR; props.num = 1; props.props = dvb_prop; if (ioctl (object->fd_frontend, FE_SET_PROPERTY, &props) < 0) { g_warning ("Error resetting tuner: %s", strerror (errno)); } /* First three entries are reserved */ n = 3; switch (object->adapter_type) { case FE_QPSK: object->tone = SEC_TONE_OFF; if (freq > 2200000) { // this must be an absolute frequency if (freq < SLOF) { freq -= LOF1; } else { freq -= LOF2; object->tone = SEC_TONE_ON; } } inversion = INVERSION_AUTO; set_prop (dvb_prop, &n, DTV_SYMBOL_RATE, sym_rate); set_prop (dvb_prop, &n, DTV_INNER_FEC, object->code_rate_hp); /* TODO add dvbs2 */ del_sys = SYS_DVBS; GST_INFO_OBJECT (object, "tuning DVB-S to L-Band:%u, Pol:%d, srate=%u, 22kHz=%s", freq, object->pol, sym_rate, object->tone == SEC_TONE_ON ? "on" : "off"); if (object->pol == DVB_POL_H) voltage = SEC_VOLTAGE_18; else voltage = SEC_VOLTAGE_13; if (object->diseqc_src == -1 || object->send_diseqc == FALSE) { set_prop (dvb_prop, &n, DTV_VOLTAGE, voltage); // DTV_TONE not yet implemented // set_prop (fe_props_array, &n, DTV_TONE, object->tone) } else { GST_DEBUG_OBJECT (object, "Sending DISEqC"); diseqc (object->fd_frontend, object->diseqc_src, voltage, object->tone); /* Once diseqc source is set, do not set it again until * app decides to change it */ //object->send_diseqc = FALSE; } break; case FE_OFDM: del_sys = SYS_DVBT; bandwidth = 0; if (object->bandwidth != BANDWIDTH_AUTO) { /* Presumably not specifying bandwidth with s2api is equivalent * to BANDWIDTH_AUTO. */ switch (object->bandwidth) { case BANDWIDTH_8_MHZ: bandwidth = 8000000; break; case BANDWIDTH_7_MHZ: bandwidth = 7000000; break; case BANDWIDTH_6_MHZ: bandwidth = 6000000; break; default: break; } } if (bandwidth) { set_prop (dvb_prop, &n, DTV_BANDWIDTH_HZ, bandwidth); } set_prop (dvb_prop, &n, DTV_CODE_RATE_HP, object->code_rate_hp); set_prop (dvb_prop, &n, DTV_CODE_RATE_LP, object->code_rate_lp); set_prop (dvb_prop, &n, DTV_MODULATION, object->modulation); set_prop (dvb_prop, &n, DTV_TRANSMISSION_MODE, object->transmission_mode); set_prop (dvb_prop, &n, DTV_GUARD_INTERVAL, object->guard_interval); set_prop (dvb_prop, &n, DTV_HIERARCHY, object->hierarchy_information); GST_INFO_OBJECT (object, "tuning DVB-T to %d Hz", freq); break; case FE_QAM: GST_INFO_OBJECT (object, "Tuning DVB-C to %d, srate=%d", freq, sym_rate); del_sys = SYS_DVBC_ANNEX_AC; set_prop (dvb_prop, &n, DTV_INNER_FEC, object->code_rate_hp); set_prop (dvb_prop, &n, DTV_MODULATION, object->modulation); set_prop (dvb_prop, &n, DTV_SYMBOL_RATE, sym_rate); break; case FE_ATSC: GST_INFO_OBJECT (object, "Tuning ATSC to %d", freq); del_sys = SYS_ATSC; set_prop (dvb_prop, &n, DTV_MODULATION, object->modulation); break; default: g_error ("Unknown frontend type: %d", object->adapter_type); } usleep (100000); /* now tune the frontend */ set_prop (dvb_prop, &n, DTV_TUNE, 0); props.num = n; props.props = dvb_prop; /* set first three entries */ n = 0; set_prop (dvb_prop, &n, DTV_DELIVERY_SYSTEM, del_sys); set_prop (dvb_prop, &n, DTV_FREQUENCY, freq); set_prop (dvb_prop, &n, DTV_INVERSION, inversion); GST_DEBUG_OBJECT (object, "Setting %d properties", props.num); if (ioctl (object->fd_frontend, FE_SET_PROPERTY, &props) < 0) { g_warning ("Error tuning channel: %s", strerror (errno)); } for (i = 0; i < 50; i++) { usleep (100000); if (ioctl (object->fd_frontend, FE_READ_STATUS, &status) == -1) { perror ("FE_READ_STATUS"); break; } GST_LOG_OBJECT (object, "status == 0x%02x", status); if (status & FE_HAS_LOCK) break; } if (status & FE_HAS_LOCK) break; } if (!(status & FE_HAS_LOCK)) return FALSE; /* set pid filters */ gst_dvbsrc_set_pes_filters (object); return TRUE; }