Пример #1
0
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;
    }
}
Пример #2
0
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;
}
Пример #3
0
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;
}