Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
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;
    }
}
Esempio n. 5
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;
}