Доброго времени суток.
Недавно у меня возникла такая проблема: есть карта NetUP Dual DVB-S2-CI для приёма спутникового сигнала и неделя на то, чтобы написать ПО для получения всего транспортного потока с неё. При этом использовать готовое стороннее ПО нельзя. Ниже описывается как удалось решить эту проблему.

С программированием DVB плат я столкнулся впервые. При этом никакого CD с ПО и документацией к карте не прилагалось. Поэтому я решил сначала изучить все характеристики карты. Вышел на сайт производителя www.netup.tv, информация оказалась весьма скудной:
NetUP Dual DVB-S2-CI
Профессиональная карта для приема спутникового сигнала
NetUP Dual DVB-S2-CI – это профессиональная карта для приема спутникового сигнала. Может применяться в шлюзах DVB-IP, домашних кинотеатрах, системах спутникового интернета и других решениях. По сравнению со стандартными DVB-S картами, NetUP Dual DVB-S2-CI занимает в 4 раза меньше места на сервере – 2 входа DVB-S/S2 и 2 слота Common Interface (CI) размещены на одной плате и занимают 1 PCE-e слот. Высокая производительность карты позволяет сохранить свободное место в серверах, что особенно ценно в системах с ограниченным количеством свободных слотов. К примеру, стандартный сервер высотой 1U с двумя слотами PCI-e способен принимать и декодировать контент с 4 транспондеров одновременно: NetUP IPTV Combine 4x или DVB-IP шлюз 4x.
Характеристики:
2 входа DVB-S/DVB-S2 позволяют принимать контент с двух транспондеров одновременно;
2 CI-слота для дешифрации двух потоков;
Поддерживается профессиональные CA-модули (PowerCAM Pro, Aston Pro Solutions, и другие);
PCE-e x1;
DiSEqC 2.x;
Драйвера для операционной системы Linux.
Поддерживаемые типы модуляции: DVB-S QPSK; DVB-S2 QPSK и 8PSK;
Опционально: 16APSK и 32APSK.
Награды: карта была награждена журналом «TELE-satellite», как «Лучшая карта для PC, которую мы когда-либо тестировали». Более подробную информацию можно узнать из статьи о тестировании NetUP Dual DVB-S2-CI.
Получается, что драйвера для этой карты существуют только для ОС Linux. Значит ПО должно быть написано под эту ОС. Удалось узнать, что существует команда разработчиков, которая пишет и отлаживает драйвера для DVB. Вышел на их сайт www.linuxtv.org, где узнал, что данная DVB карта поддерживается и начиная с ядра Linux версии 2.6.32.хх драйвера входят в состав ядра и устанавливать их дополнительно не нужно.
1. Установка DVB карты в слот PCI Express
2. Выбор и установка ОС
Драйверам требовался Linux с ядром выше 2.6.32.хх. Графическая среда не важна, поэтому, для удобства написания и отладки приложения Qt лучше использовать KDE. Стабильная и хорошо сопровождаемая сборка на сегодняшний день – это Kubuntu. Установка прошла быстро (минут 15-20) и хорошо.
3. Проверяем видит ли ядро новое устройство
Используем команду dmesg | grep NetUP.
Видит. Теперь проверяем наличие интерфейсов устройств, которые должны располагаться в системном каталоге /dev/. Они находятся по пути: /dev/dvb/adapter0/, в котором находилось три файла: frontend, dmx, dvr. Для чего так много пока не понятно, но теперь нужно расшарить права доступа к ним иначе просто не получиться открыть эти интерфейсы. Проще это сделать, добавив текущего пользователя в группу этого устройства (video).
4. Проверяем работу устройства
Два этапа.
Сначала настраиваем DVB на частоту через консольную утилиту szap (man szap), она с третьего раза захватывает частоту! В нашем случае это означает что устройство работает и с ним можно «общаться».
Теперь тестируем приём данных с карты. Для этого нужно найти ПО считывающее ТВ или интернет трафик с карты. Находим GUI приложение для просмотра видео Xine (мощный проигрыватель видео для Linux), спустя примерно 10 секунд удаётся получить передаваемый ТВ-сигнал хорошего качества.
5. Изучаем особенности работы с драйвером DVB карты
Задача оказалась не тривиальной. После долгого поиска информации (к сожалению только на английском языке) и изучения данного вопроса удалось получить достаточно материала для написания программы:
Для драйвера DVB карта представляется в таком логическом виде:

Для доступа к API необходимо в программе заинклудить нужные из схемы устройства. Пример для Frontend:
В этих исходниках содержаться все команды для работы с ним.
Алгоритм следующий:
а. Настраивается Frontend. Это устройство настраивается на заданную частоту с заданной символьной скоростью, инверсией. Затем передаёт полученный после демодуляции данные демультиплексору. Здесь получить все данные (которые нам нужны), к сожалению, не возможно.
б. Настраивается Demultiplexor. Он оперирует фильтрами и их у него два вида: секционный и PES. С этого устройства можно получить данные, но только настроив эти фильтры. Самое интересное в том, что чтобы прочитать все данные, нужно PES-фильтр настроить на маску 8192 и направить его выход в логическое DVR устройство. Отмечу, что об этом не сказано в официальной документации и на форумах. Я узнал это, покопавшись в исходниках DVBStream.
в. Настраивается DVR. На самом деле оказалось, что это файл, который постоянно пополняется данными от DMX (Demultiplexor) и из которого в итоге получаются данные для программы.
6. Выбираем SDK для написания ПО под Linux, устонвка, реализация
Qt – позволяет создавать ПО для многих ОС, удобен и очень понятен для изучения и главное, в нём уже реализовано много современных технологий (базы данных, интернет, кодировки, сигналы и слоты, GUI, 3D, скрипты и другие). Поэтому выбираем его. Установил Qt, написал приложение, отладил, всё прекрасно заработало.
Приведу исходники реализации класса работы с устройством.
Заголовочный файл:
Недавно у меня возникла такая проблема: есть карта NetUP Dual DVB-S2-CI для приёма спутникового сигнала и неделя на то, чтобы написать ПО для получения всего транспортного потока с неё. При этом использовать готовое стороннее ПО нельзя. Ниже описывается как удалось решить эту проблему.
Изучение платы
С программированием DVB плат я столкнулся впервые. При этом никакого CD с ПО и документацией к карте не прилагалось. Поэтому я решил сначала изучить все характеристики карты. Вышел на сайт производителя www.netup.tv, информация оказалась весьма скудной:
NetUP Dual DVB-S2-CI
Профессиональная карта для приема спутникового сигнала
NetUP Dual DVB-S2-CI – это профессиональная карта для приема спутникового сигнала. Может применяться в шлюзах DVB-IP, домашних кинотеатрах, системах спутникового интернета и других решениях. По сравнению со стандартными DVB-S картами, NetUP Dual DVB-S2-CI занимает в 4 раза меньше места на сервере – 2 входа DVB-S/S2 и 2 слота Common Interface (CI) размещены на одной плате и занимают 1 PCE-e слот. Высокая производительность карты позволяет сохранить свободное место в серверах, что особенно ценно в системах с ограниченным количеством свободных слотов. К примеру, стандартный сервер высотой 1U с двумя слотами PCI-e способен принимать и декодировать контент с 4 транспондеров одновременно: NetUP IPTV Combine 4x или DVB-IP шлюз 4x.
Характеристики:
2 входа DVB-S/DVB-S2 позволяют принимать контент с двух транспондеров одновременно;
2 CI-слота для дешифрации двух потоков;
Поддерживается профессиональные CA-модули (PowerCAM Pro, Aston Pro Solutions, и другие);
PCE-e x1;
DiSEqC 2.x;
Драйвера для операционной системы Linux.
Поддерживаемые типы модуляции: DVB-S QPSK; DVB-S2 QPSK и 8PSK;
Опционально: 16APSK и 32APSK.
Награды: карта была награждена журналом «TELE-satellite», как «Лучшая карта для PC, которую мы когда-либо тестировали». Более подробную информацию можно узнать из статьи о тестировании NetUP Dual DVB-S2-CI.
Получается, что драйвера для этой карты существуют только для ОС Linux. Значит ПО должно быть написано под эту ОС. Удалось узнать, что существует команда разработчиков, которая пишет и отлаживает драйвера для DVB. Вышел на их сайт www.linuxtv.org, где узнал, что данная DVB карта поддерживается и начиная с ядра Linux версии 2.6.32.хх драйвера входят в состав ядра и устанавливать их дополнительно не нужно.
Реализация
1. Установка DVB карты в слот PCI Express
2. Выбор и установка ОС
Драйверам требовался Linux с ядром выше 2.6.32.хх. Графическая среда не важна, поэтому, для удобства написания и отладки приложения Qt лучше использовать KDE. Стабильная и хорошо сопровождаемая сборка на сегодняшний день – это Kubuntu. Установка прошла быстро (минут 15-20) и хорошо.
3. Проверяем видит ли ядро новое устройство
Используем команду dmesg | grep NetUP.
Видит. Теперь проверяем наличие интерфейсов устройств, которые должны располагаться в системном каталоге /dev/. Они находятся по пути: /dev/dvb/adapter0/, в котором находилось три файла: frontend, dmx, dvr. Для чего так много пока не понятно, но теперь нужно расшарить права доступа к ним иначе просто не получиться открыть эти интерфейсы. Проще это сделать, добавив текущего пользователя в группу этого устройства (video).
4. Проверяем работу устройства
Два этапа.
Сначала настраиваем DVB на частоту через консольную утилиту szap (man szap), она с третьего раза захватывает частоту! В нашем случае это означает что устройство работает и с ним можно «общаться».
Теперь тестируем приём данных с карты. Для этого нужно найти ПО считывающее ТВ или интернет трафик с карты. Находим GUI приложение для просмотра видео Xine (мощный проигрыватель видео для Linux), спустя примерно 10 секунд удаётся получить передаваемый ТВ-сигнал хорошего качества.
5. Изучаем особенности работы с драйвером DVB карты
Задача оказалась не тривиальной. После долгого поиска информации (к сожалению только на английском языке) и изучения данного вопроса удалось получить достаточно материала для написания программы:
Для драйвера DVB карта представляется в таком логическом виде:

Для доступа к API необходимо в программе заинклудить нужные из схемы устройства. Пример для Frontend:
#include <linux/dvb/frontend.h>
В этих исходниках содержаться все команды для работы с ним.
Алгоритм следующий:
а. Настраивается Frontend. Это устройство настраивается на заданную частоту с заданной символьной скоростью, инверсией. Затем передаёт полученный после демодуляции данные демультиплексору. Здесь получить все данные (которые нам нужны), к сожалению, не возможно.
б. Настраивается Demultiplexor. Он оперирует фильтрами и их у него два вида: секционный и PES. С этого устройства можно получить данные, но только настроив эти фильтры. Самое интересное в том, что чтобы прочитать все данные, нужно PES-фильтр настроить на маску 8192 и направить его выход в логическое DVR устройство. Отмечу, что об этом не сказано в официальной документации и на форумах. Я узнал это, покопавшись в исходниках DVBStream.
в. Настраивается DVR. На самом деле оказалось, что это файл, который постоянно пополняется данными от DMX (Demultiplexor) и из которого в итоге получаются данные для программы.
6. Выбираем SDK для написания ПО под Linux, устонвка, реализация
Qt – позволяет создавать ПО для многих ОС, удобен и очень понятен для изучения и главное, в нём уже реализовано много современных технологий (базы данных, интернет, кодировки, сигналы и слоты, GUI, 3D, скрипты и другие). Поэтому выбираем его. Установил Qt, написал приложение, отладил, всё прекрасно заработало.
Исходники
Приведу исходники реализации класса работы с устройством.
Заголовочный файл:
#ifndef ADVBSDevice_H
#define ADVBSDevice_H
#include class ADVBSDevice : public QObject
{
Q_OBJECT
private:
#define FRONT "/dev/dvb/adapter0/frontend0"
#define DMX "/dev/dvb/adapter0/demux0"
#define DVR "/dev/dvb/adapter0/dvr0"
int _front;
int _demux;
int _dvr;
int _freq;
int _srate;
enum { DMX_ALL_PIDS = 8192, /* PES фильтр пропускает весь TS поток */
/*EOVERFLOW = 75, Код ошибки, означает: Value too large for defined data type */
MAX_ATTEMPT = 512 };
bool tuneDvr ();
bool tuneDemux ();
bool tuneFrontend ();
bool isFrontendTuned ();
public:
explicit ADVBSDevice(QObject *parent = 0);
~ADVBSDevice();
bool init();
void stop();
int readBlock(const char *, int);
void setFrecuency(int freq) { _freq = freq * 1000; }
void setSymbolRate(int srate) { _srate = srate * 1000; }
signals:
void message(const QString &);
};
#endif // ADVBSDevice_H
Файл *.cpp:
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/dmx.h>
#include <sys/poll.h>
#include "abvbsdevice.h"
ADVBSDevice::ADVBSDevice(QObject *parent) : QObject(parent)
{
_freq = -1;
_srate = -1;
_front = -1;
_demux = -1;
_dvr = -1;
}
ADVBSDevice::~ADVBSDevice()
{
stop();
}
bool ADVBSDevice::init()
{
if ((0 > _freq) || (0 > _srate)){
emit message(QString(tr("First set frecuensy and symbol rate!")));
return 0;
}
if ( tuneDvr() &&
tuneDemux() &&
tuneFrontend()
)
return true;
stop();
return false;
}
void ADVBSDevice::stop()
{
if (0 < _front) close(_front);
if (0 < _demux) { ioctl(_demux, DMX_STOP); close(_demux); }
if (0 < _dvr) close(_dvr);
_freq = -1;
_srate = -1;
_front = -1;
_demux = -1;
_dvr = -1;
}
int ADVBSDevice::readBlock(const char *buffer, int bufLen)
{
// return 0 - false, else - readed bytes.
if (0 > _dvr) {
emit message(QString(tr("First call: ADVBSDevice->init()!")));
return 0;
}
int readedBytes = 0;
int attempt = MAX_ATTEMPT;
pollfd pfd;
pfd.fd = _dvr;
pfd.events = POLLIN;
do
{
if (poll(&pfd ,1, 1))
{
if (pfd.revents & POLLIN)
{
if (-1 == (readedBytes = read(_dvr, (void*) buffer, bufLen)))
{
emit message(QString(tr("No data in device.")));
return 0;
}
}
}
}
while (--attempt && !readedBytes);
if (!attempt) {
emit message(QString(tr("No poll in device.")));
return 0;
}
return readedBytes;
}
bool ADVBSDevice::isFrontendTuned()
{
quint32 num32 = 0;
quint32 max32 = 0;
max32 = ~max32;
if (ioctl (_front, FE_READ_BER, &num32) >= 0) {
if (num32 > 0)
num32 = num32 / max32 * 100;
else num32 = 0;
emit message(QString("%1 %2%").arg(tr("Bit error rate:")).arg(num32));
}
num32 = 0;
if (ioctl (_front, FE_READ_UNCORRECTED_BLOCKS, &num32) >= 0) {
if (num32 > 0)
num32 = num32 / max32 * 100;
else num32 = 0;
emit message(QString("%1 %2%").arg(tr("Uncorrected blcks:")).arg(num32));
}
quint16 num16 = 0;
quint16 max16 = 0;
max16 = ~ max16;
if (ioctl (_front, FE_READ_SIGNAL_STRENGTH, &num16) >= 0) {
if (num16 > 0)
num16 = num16 / max16 * 100;
else num16 = 0;
emit message(QString("%1 %2%").arg(tr("Signal strength:")).arg(num16));
}
num16 = 0;
if (ioctl(_front, FE_READ_SNR, &num16) >= 0) {
if (num16 > 0)
num16 = num16 / max16 * 100;
else num16 = 0;
emit message(QString("%1 %2%").arg(tr("Signal/Noise Ratio:")).arg(num16));
}
fe_status_t status;
memset(&status, 0, sizeof(fe_status_t));
if (ioctl (_front, FE_READ_STATUS, &status) < 0){
emit message(QString(tr("Can't read status from frontend")));
return false;
}
if (!(status & FE_HAS_LOCK) || (status & FE_TIMEDOUT)) {
emit message(QString(tr("Can't lock frontend.")));
return false;
}
emit message(QString(tr("Frontend status:")));
if (status & FE_HAS_SIGNAL) emit message(QString(tr("Found something above the noise level.")));
if (status & FE_HAS_CARRIER) emit message(QString(tr("Found a DVB signal.")));
if (status & FE_HAS_VITERBI) emit message(QString(tr("FEC (code rate) is stable.")));
if (status & FE_HAS_SYNC) emit message(QString(tr("Found sync bytes.")));
if (status & FE_HAS_LOCK) emit message(QString(tr("Everything's working.")));
if (status & FE_TIMEDOUT) emit message(QString(tr("No lock within the last ~2 seconds.")));
if (status & FE_REINIT) emit message(QString(tr("Recommended to reset DiSEqC, tone and parameters.")));
// dvb_frontend_info info;
// if (ioctl (_front, FE_GET_INFO, &info) >= 0)
// {
// emit message(QString("Frontend info:"));
// emit message(QString("Name: %1.").arg(info.name));
// if (info.type == FE_QPSK) emit message(QString("Type: SAT Card."));
// if (info.type == FE_QAM) emit message(QString("Type: CAB Card."));
// if (info.type == FE_OFDM) emit message(QString("Type: TER Card."));
// if (info.type == FE_ATSC) emit message(QString("Type: US Card."));
// emit message(QString("Frequency min: %1.").arg(info.frequency_min));
// emit message(QString("Frequency max: %1.").arg(info.frequency_max));
// emit message(QString("Frequency step size: %1.").arg(info.frequency_stepsize));
// emit message(QString("Frequency tolerance: %1.").arg(info.frequency_tolerance));
// emit message(QString("Symbol rate min: %1.").arg(info.symbol_rate_min));
// emit message(QString("Symbol rate max: %1.").arg(info.symbol_rate_max));
// emit message(QString("Symbol rate tolerance: %1.").arg(info.symbol_rate_tolerance));
// emit message(QString("Notifier delay: %1.").arg(info.notifier_delay));
// emit message(QString("Capabiletes of card:"));
// if (info.caps & FE_CAN_INVERSION_AUTO) emit message(QString("FE_CAN_INVERSION_AUTO"));
// if (info.caps & FE_CAN_FEC_1_2) emit message(QString("FE_CAN_FEC_1_2"));
// if (info.caps & FE_CAN_FEC_2_3) emit message(QString("FE_CAN_FEC_2_3"));
// if (info.caps & FE_CAN_FEC_3_4) emit message(QString("FE_CAN_FEC_3_4"));
// if (info.caps & FE_CAN_FEC_4_5) emit message(QString("FE_CAN_FEC_4_5"));
// if (info.caps & FE_CAN_FEC_5_6) emit message(QString("FE_CAN_FEC_5_6"));
// if (info.caps & FE_CAN_FEC_6_7) emit message(QString("FE_CAN_FEC_6_7"));
// if (info.caps & FE_CAN_FEC_7_8) emit message(QString("FE_CAN_FEC_7_8"));
// if (info.caps & FE_CAN_FEC_8_9) emit message(QString("FE_CAN_FEC_8_9"));
// if (info.caps & FE_CAN_FEC_AUTO) emit message(QString("FE_CAN_FEC_AUTO"));
// if (info.caps & FE_CAN_QPSK) emit message(QString("FE_CAN_QPSK"));
// if (info.caps & FE_CAN_QAM_16) emit message(QString("FE_CAN_QAM_16"));
// if (info.caps & FE_CAN_QAM_32) emit message(QString("FE_CAN_QAM_32"));
// if (info.caps & FE_CAN_QAM_64) emit message(QString("FE_CAN_QAM_64"));
// if (info.caps & FE_CAN_QAM_128) emit message(QString("FE_CAN_QAM_128"));
// if (info.caps & FE_CAN_QAM_256) emit message(QString("FE_CAN_QAM_256"));
// if (info.caps & FE_CAN_QAM_AUTO) emit message(QString("FE_CAN_QAM_AUTO"));
// if (info.caps & FE_CAN_TRANSMISSION_MODE_AUTO) emit message(QString("FE_CAN_TRANSMISSION_MODE_AUTO"));
// if (info.caps & FE_CAN_BANDWIDTH_AUTO) emit message(QString("FE_CAN_BANDWIDTH_AUTO"));
// if (info.caps & FE_CAN_GUARD_INTERVAL_AUTO) emit message(QString("FE_CAN_GUARD_INTERVAL_AUTO"));
// if (info.caps & FE_CAN_HIERARCHY_AUTO) emit message(QString("FE_CAN_HIERARCHY_AUTO"));
// if (info.caps & FE_CAN_8VSB) emit message(QString("FE_CAN_8VSB"));
// if (info.caps & FE_CAN_16VSB) emit message(QString("FE_CAN_16VSB"));
// if (info.caps & FE_HAS_EXTENDED_CAPS) emit message(QString("FE_HAS_EXTENDED_CAPS: may be ACM."));
// if (info.caps & FE_CAN_2G_MODULATION) emit message(QString("FE_CAN_2G_MODULATION: DVB-S2."));
// if (info.caps & FE_NEEDS_BENDING) emit message(QString("FE_NEEDS_BENDING: ")); // not used
// if (info.caps & FE_CAN_RECOVER) emit message(QString("FE_CAN_RECOVER: frontend can recover from a cable unplug automatically."));
// if (info.caps & FE_CAN_MUTE_TS) emit message(QString("FE_CAN_MUTE_TS: frontend can stop spurious TS data output."));
// }
emit message(QString(tr("Frontend parameters:")));
struct dvb_frontend_parameters frp;
if (ioctl(_front, FE_GET_FRONTEND, &frp) >= 0)
{
emit message(QString("Frequency: %1 kHz.").arg(frp.frequency));
// if (frp.inversion == INVERSION_OFF) emit message(QString("Spectral inversion off."));
// if (frp.inversion == INVERSION_ON) emit message(QString("Spectral inversion on."));
// if (frp.inversion == INVERSION_AUTO) emit message(QString("Spectral inversion auto."));
emit message(QString("Symbol rate: %1 sym/sec.").arg(frp.u.qpsk.symbol_rate));
// if (frp.u.qpsk.fec_inner & FEC_NONE) emit message(QString("Code rate: %1.").arg("FEC_NONE"));
// if (frp.u.qpsk.fec_inner & FEC_1_2) emit message(QString("Code rate: %1.").arg("FEC_1_2"));
// if (frp.u.qpsk.fec_inner & FEC_2_3) emit message(QString("Code rate: %1.").arg("FEC_2_3"));
// if (frp.u.qpsk.fec_inner & FEC_3_4) emit message(QString("Code rate: %1.").arg("FEC_3_4"));
// if (frp.u.qpsk.fec_inner & FEC_4_5) emit message(QString("Code rate: %1.").arg("FEC_4_5"));
// if (frp.u.qpsk.fec_inner & FEC_5_6) emit message(QString("Code rate: %1.").arg("FEC_5_6"));
// if (frp.u.qpsk.fec_inner & FEC_6_7) emit message(QString("Code rate: %1.").arg("FEC_6_7"));
// if (frp.u.qpsk.fec_inner & FEC_7_8) emit message(QString("Code rate: %1.").arg("FEC_7_8"));
// if (frp.u.qpsk.fec_inner & FEC_8_9) emit message(QString("Code rate: %1.").arg("FEC_8_9"));
// if (frp.u.qpsk.fec_inner & FEC_AUTO) emit message(QString("Code rate: %1.").arg("FEC_AUTO"));
// if (frp.u.qpsk.fec_inner & FEC_3_5) emit message(QString("Code rate: %1.").arg("FEC_3_5"));
// if (frp.u.qpsk.fec_inner & FEC_9_10) emit message(QString("Code rate: %1.").arg("FEC_9_10"));
}
emit message(QString(""));
return true;
}
bool ADVBSDevice::tuneFrontend()
{
if ((_front = open(FRONT,O_RDWR)) < 0) {
emit message(QString(tr("Can't open frontend.")));
return false;
}
dvb_frontend_parameters frp;
frp.frequency = _freq;
frp.inversion = INVERSION_AUTO;
frp.u.qpsk.symbol_rate = _srate;
frp.u.qpsk.fec_inner = FEC_AUTO;
int attempt = 3;
do
{
emit message(QString(tr("Frontend is tunning...")));
if (ioctl(_front, FE_SET_FRONTEND, &frp) < 0) {
emit message(QString(tr("Can't set frontend.")));
return false;
}
if (isFrontendTuned()) break;
emit message (QString(tr("%1. Restart after ~3 seconds.")).arg(attempt));
sleep(3);
}
while (--attempt);
if (!attempt) {
emit message(QString(tr("Failed. Is there signal?")));
return false;
}
// pollfd pfd;
// pfd.fd = _front;
// pfd.events = POLLIN;
// dvb_frontend_event event;
// if (poll(&pfd,1,3000))
// {
// if (pfd.revents & POLLIN)
// {
// emit message(QString(tr("Getting frontend event...")));
// if ( ioctl(_front, FE_GET_EVENT, &event) == -EOVERFLOW) {
// emit message(QString(tr("Failed: overflow.")));
// return false;
// }
// }
// }
return true;
}
bool ADVBSDevice::tuneDemux()
{
if ((_demux = open(DMX, O_RDWR|O_NONBLOCK)) < 0)
{
emit message(QString(tr("Can't open demux.")));
return false;
}
dmx_pes_filter_params pesFilter;
pesFilter.pid = DMX_ALL_PIDS;
pesFilter.input = DMX_IN_FRONTEND;
pesFilter.output = DMX_OUT_TS_TAP;
pesFilter.pes_type = DMX_PES_OTHER;
pesFilter.flags = DMX_IMMEDIATE_START;
if (ioctl(_demux, DMX_SET_PES_FILTER, &pesFilter) < 0)
{
emit message(QString(tr("Can't set pes to demux.")));
return false;
}
return true;
}
bool ADVBSDevice::tuneDvr()
{
if ((_dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0)
{
emit message(QString(tr("Can't open DVR.")));
return false;
}
return true;
}
Отмечу, что данное решение подходит для любых, поддерживаемых www.linuxtv.org устройств (DVB-S\T\C\H).
Если что-то будет не понятно по исходникам или содержанию статью, с радостью отвечу на все вопросы.