static gboolean gst_dvbsrc_start (GstBaseSrc * bsrc) { GstDvbSrc *src = GST_DVBSRC (bsrc); gst_dvbsrc_open_frontend (src); if (!gst_dvbsrc_tune (src)) { GST_ERROR_OBJECT (src, "Not able to lock on to the dvb channel"); close (src->fd_frontend); return FALSE; } if (!gst_dvbsrc_frontend_status (src)) { /* unset filters also */ gst_dvbsrc_unset_pes_filters (src); close (src->fd_frontend); return FALSE; } if (!gst_dvbsrc_open_dvr (src)) { GST_ERROR_OBJECT (src, "Not able to open dvr_device"); /* unset filters also */ gst_dvbsrc_unset_pes_filters (src); close (src->fd_frontend); return FALSE; } return TRUE; }
static gboolean gst_dvbsrc_close_devices (GstDvbSrc * object) { gst_dvbsrc_unset_pes_filters (object); close (object->fd_dvr); object->fd_dvr = -1; close (object->fd_frontend); object->fd_frontend = -1; return TRUE; }
static gboolean gst_dvbsrc_start (GstBaseSrc * bsrc) { GstDvbSrc *src = GST_DVBSRC (bsrc); gst_dvbsrc_open_frontend (src, TRUE); if (!gst_dvbsrc_tune (src)) { GST_ERROR_OBJECT (src, "Not able to lock on to the dvb channel"); close (src->fd_frontend); return FALSE; } if (!gst_dvbsrc_frontend_status (src)) { /* unset filters also */ gst_dvbsrc_unset_pes_filters (src); close (src->fd_frontend); return FALSE; } if (!gst_dvbsrc_open_dvr (src)) { GST_ERROR_OBJECT (src, "Not able to open dvr_device"); /* unset filters also */ gst_dvbsrc_unset_pes_filters (src); close (src->fd_frontend); return FALSE; } if (!(src->poll = gst_poll_new (TRUE))) { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL), ("could not create an fdset: %s (%d)", g_strerror (errno), errno)); /* unset filters also */ gst_dvbsrc_unset_pes_filters (src); close (src->fd_frontend); return FALSE; } else { gst_poll_fd_init (&src->poll_fd_dvr); src->poll_fd_dvr.fd = src->fd_dvr; gst_poll_add_fd (src->poll, &src->poll_fd_dvr); gst_poll_fd_ctl_read (src->poll, &src->poll_fd_dvr, TRUE); } return TRUE; }
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 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; }