From eb54f03b279eb8bcdea1ff1c68c2e2392b6f35cc Mon Sep 17 00:00:00 2001 From: Zaheer Abbas Merali Date: Tue, 10 Oct 2006 15:05:32 +0000 Subject: [PATCH] Initial import of dvbsrc. Original commit message from CVS: 2006-10-10 Zaheer Abbas Merali * configure.ac: * sys/Makefile.am: * sys/dvb/AUTHORS: * sys/dvb/Makefile.am: * sys/dvb/README: * sys/dvb/dvb-api/Makefile.am: * sys/dvb/dvb-api/audio.h: * sys/dvb/dvb-api/ca.h: * sys/dvb/dvb-api/dmx.h: * sys/dvb/dvb-api/frontend.h: * sys/dvb/dvb-api/net.h: * sys/dvb/dvb-api/osd.h: * sys/dvb/dvb-api/version.h: * sys/dvb/dvb-api/video.h: * sys/dvb/gstdvbsrc.c: * sys/dvb/gstdvbsrc.h: Initial import of dvbsrc. Currently won't be built. --- ChangeLog | 21 + configure.ac | 1 + sys/Makefile.am | 2 +- sys/dvb/AUTHORS | 2 + sys/dvb/Makefile.am | 11 + sys/dvb/README | 19 + sys/dvb/dvb-api/Makefile.am | 2 + sys/dvb/dvb-api/audio.h | 125 ++++ sys/dvb/dvb-api/ca.h | 91 +++ sys/dvb/dvb-api/dmx.h | 180 ++++++ sys/dvb/dvb-api/frontend.h | 264 ++++++++ sys/dvb/dvb-api/net.h | 57 ++ sys/dvb/dvb-api/osd.h | 113 ++++ sys/dvb/dvb-api/version.h | 29 + sys/dvb/dvb-api/video.h | 202 ++++++ sys/dvb/gstdvbsrc.c | 1200 +++++++++++++++++++++++++++++++++++ sys/dvb/gstdvbsrc.h | 103 +++ 17 files changed, 2421 insertions(+), 1 deletion(-) create mode 100644 sys/dvb/AUTHORS create mode 100644 sys/dvb/Makefile.am create mode 100644 sys/dvb/README create mode 100644 sys/dvb/dvb-api/Makefile.am create mode 100644 sys/dvb/dvb-api/audio.h create mode 100644 sys/dvb/dvb-api/ca.h create mode 100644 sys/dvb/dvb-api/dmx.h create mode 100644 sys/dvb/dvb-api/frontend.h create mode 100644 sys/dvb/dvb-api/net.h create mode 100644 sys/dvb/dvb-api/osd.h create mode 100644 sys/dvb/dvb-api/version.h create mode 100644 sys/dvb/dvb-api/video.h create mode 100644 sys/dvb/gstdvbsrc.c create mode 100644 sys/dvb/gstdvbsrc.h diff --git a/ChangeLog b/ChangeLog index 78d1265639..cf8031e781 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2006-10-10 Zaheer Abbas Merali + + * configure.ac: + * sys/Makefile.am: + * sys/dvb/AUTHORS: + * sys/dvb/Makefile.am: + * sys/dvb/README: + * sys/dvb/dvb-api/Makefile.am: + * sys/dvb/dvb-api/audio.h: + * sys/dvb/dvb-api/ca.h: + * sys/dvb/dvb-api/dmx.h: + * sys/dvb/dvb-api/frontend.h: + * sys/dvb/dvb-api/net.h: + * sys/dvb/dvb-api/osd.h: + * sys/dvb/dvb-api/version.h: + * sys/dvb/dvb-api/video.h: + * sys/dvb/gstdvbsrc.c: + * sys/dvb/gstdvbsrc.h: + Initial import of dvbsrc. + Currently won't be built. + 2006-10-10 Wim Taymans * gst/qtdemux/qtdemux.c: (gst_qtdemux_init), diff --git a/configure.ac b/configure.ac index 32cc517860..538380f39e 100644 --- a/configure.ac +++ b/configure.ac @@ -799,6 +799,7 @@ gst-libs/Makefile gst-libs/gst/Makefile sys/Makefile sys/glsink/Makefile +sys/dvb/Makefile examples/Makefile examples/directfb/Makefile ext/amrwb/amrwb-code/Makefile diff --git a/sys/Makefile.am b/sys/Makefile.am index 5944a45eb0..dc2bf84832 100644 --- a/sys/Makefile.am +++ b/sys/Makefile.am @@ -30,4 +30,4 @@ endif SUBDIRS = $(GL_DIR) -DIST_SUBDIRS = glsink +DIST_SUBDIRS = glsink dvb diff --git a/sys/dvb/AUTHORS b/sys/dvb/AUTHORS new file mode 100644 index 0000000000..ecf8c594cf --- /dev/null +++ b/sys/dvb/AUTHORS @@ -0,0 +1,2 @@ +Martin Eikermann (meiker (at) uni-paderborn.de) +Zaheer Abbas Merali diff --git a/sys/dvb/Makefile.am b/sys/dvb/Makefile.am new file mode 100644 index 0000000000..7cbd460535 --- /dev/null +++ b/sys/dvb/Makefile.am @@ -0,0 +1,11 @@ + +plugin_LTLIBRARIES = libgstdvbsrc.la + +libgstdvbsrc_la_SOURCES = gstdvbsrc.c +libgstdvbsrc_la_CFLAGS = $(GST_CFLAGS) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE +libgstdvbsrc_la_LIBADD = $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) +libgstdvbsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +noinst_HEADERS = gstdvbsrc.h dvb-api/audio.h dvb-api/ca.h dvb-api/dmx.h \ + dvb-api/frontend.h dvb-api/net.h dvb-api/version.h \ + dvb-api/video.h diff --git a/sys/dvb/README b/sys/dvb/README new file mode 100644 index 0000000000..39bc052f6e --- /dev/null +++ b/sys/dvb/README @@ -0,0 +1,19 @@ +Gstreamer DVB Source + +GstDvbSrc makes it possible to view Digital TV with gstreamer. + + +Try: + + gst-launch dvbsrc freq=11954 pol=h srate=27500 pids=210:220 + ! flutsdemux es-pids=210:220 name=demux ! queue ! mpeg2dec ! + xvimagesink } + demux. ! queue ! mad ! osssink + + + +to view the German 3Sat telestation from the Astra 1 19.2E satellite. + +DVB-C is untested, feedback is welcomed. + +gstdvbtv is not yet ported to 0.10 diff --git a/sys/dvb/dvb-api/Makefile.am b/sys/dvb/dvb-api/Makefile.am new file mode 100644 index 0000000000..cdd36feb0e --- /dev/null +++ b/sys/dvb/dvb-api/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST = \ + audio.h ca.h dmx.h frontend.h net.h osd.h version.h video.h diff --git a/sys/dvb/dvb-api/audio.h b/sys/dvb/dvb-api/audio.h new file mode 100644 index 0000000000..58956c3bba --- /dev/null +++ b/sys/dvb/dvb-api/audio.h @@ -0,0 +1,125 @@ +/* + * audio.h + * + * Copyright (C) 2000 Ralph Metzler + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Lesser Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _DVBAUDIO_H_ +#define _DVBAUDIO_H_ + +#ifdef __KERNEL__ +#include +#else +#include +#endif + + +typedef enum { + AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */ + AUDIO_SOURCE_MEMORY /* Select internal memory as the main source */ +} audio_stream_source_t; + + +typedef enum { + AUDIO_STOPPED, /* Device is stopped */ + AUDIO_PLAYING, /* Device is currently playing */ + AUDIO_PAUSED /* Device is paused */ +} audio_play_state_t; + + +typedef enum { + AUDIO_STEREO, + AUDIO_MONO_LEFT, + AUDIO_MONO_RIGHT +} audio_channel_select_t; + + +typedef struct audio_mixer { + unsigned int volume_left; + unsigned int volume_right; + // what else do we need? bass, pass-through, ... +} audio_mixer_t; + + +typedef struct audio_status { + int AV_sync_state; /* sync audio and video? */ + int mute_state; /* audio is muted */ + audio_play_state_t play_state; /* current playback state */ + audio_stream_source_t stream_source; /* current stream source */ + audio_channel_select_t channel_select; /* currently selected channel */ + int bypass_mode; /* pass on audio data to */ + audio_mixer_t mixer_state; /* current mixer state */ +} audio_status_t; /* separate decoder hardware */ + + +typedef +struct audio_karaoke{ /* if Vocal1 or Vocal2 are non-zero, they get mixed */ + int vocal1; /* into left and right t at 70% each */ + int vocal2; /* if both, Vocal1 and Vocal2 are non-zero, Vocal1 gets*/ + int melody; /* mixed into the left channel and */ + /* Vocal2 into the right channel at 100% each. */ + /* if Melody is non-zero, the melody channel gets mixed*/ +} audio_karaoke_t; /* into left and right */ + + +typedef uint16_t audio_attributes_t; +/* bits: descr. */ +/* 15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, */ +/* 12 multichannel extension */ +/* 11-10 audio type (0=not spec, 1=language included) */ +/* 9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) */ +/* 7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit, */ +/* 5- 4 Sample frequency fs (0=48kHz, 1=96kHz) */ +/* 2- 0 number of audio channels (n+1 channels) */ + + +/* for GET_CAPABILITIES and SET_FORMAT, the latter should only set one bit */ +#define AUDIO_CAP_DTS 1 +#define AUDIO_CAP_LPCM 2 +#define AUDIO_CAP_MP1 4 +#define AUDIO_CAP_MP2 8 +#define AUDIO_CAP_MP3 16 +#define AUDIO_CAP_AAC 32 +#define AUDIO_CAP_OGG 64 +#define AUDIO_CAP_SDDS 128 +#define AUDIO_CAP_AC3 256 + +#define AUDIO_STOP _IO('o', 1) +#define AUDIO_PLAY _IO('o', 2) +#define AUDIO_PAUSE _IO('o', 3) +#define AUDIO_CONTINUE _IO('o', 4) +#define AUDIO_SELECT_SOURCE _IO('o', 5) +#define AUDIO_SET_MUTE _IO('o', 6) +#define AUDIO_SET_AV_SYNC _IO('o', 7) +#define AUDIO_SET_BYPASS_MODE _IO('o', 8) +#define AUDIO_CHANNEL_SELECT _IO('o', 9) +#define AUDIO_GET_STATUS _IOR('o', 10, audio_status_t) + +#define AUDIO_GET_CAPABILITIES _IOR('o', 11, unsigned int) +#define AUDIO_CLEAR_BUFFER _IO('o', 12) +#define AUDIO_SET_ID _IO('o', 13) +#define AUDIO_SET_MIXER _IOW('o', 14, audio_mixer_t) +#define AUDIO_SET_STREAMTYPE _IO('o', 15) +#define AUDIO_SET_EXT_ID _IO('o', 16) +#define AUDIO_SET_ATTRIBUTES _IOW('o', 17, audio_attributes_t) +#define AUDIO_SET_KARAOKE _IOW('o', 18, audio_karaoke_t) + +#endif /* _DVBAUDIO_H_ */ + diff --git a/sys/dvb/dvb-api/ca.h b/sys/dvb/dvb-api/ca.h new file mode 100644 index 0000000000..026e5c35c0 --- /dev/null +++ b/sys/dvb/dvb-api/ca.h @@ -0,0 +1,91 @@ +/* + * ca.h + * + * Copyright (C) 2000 Ralph Metzler + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Lesser Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _DVBCA_H_ +#define _DVBCA_H_ + +/* slot interface types and info */ + +typedef struct ca_slot_info { + int num; /* slot number */ + + int type; /* CA interface this slot supports */ +#define CA_CI 1 /* CI high level interface */ +#define CA_CI_LINK 2 /* CI link layer level interface */ +#define CA_CI_PHYS 4 /* CI physical layer level interface */ +#define CA_DESCR 8 /* built-in descrambler */ +#define CA_SC 128 /* simple smart card interface */ + + unsigned int flags; +#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */ +#define CA_CI_MODULE_READY 2 +} ca_slot_info_t; + + +/* descrambler types and info */ + +typedef struct ca_descr_info { + unsigned int num; /* number of available descramblers (keys) */ + unsigned int type; /* type of supported scrambling system */ +#define CA_ECD 1 +#define CA_NDS 2 +#define CA_DSS 4 +} ca_descr_info_t; + +typedef struct ca_caps { + unsigned int slot_num; /* total number of CA card and module slots */ + unsigned int slot_type; /* OR of all supported types */ + unsigned int descr_num; /* total number of descrambler slots (keys) */ + unsigned int descr_type; /* OR of all supported types */ +} ca_caps_t; + +/* a message to/from a CI-CAM */ +typedef struct ca_msg { + unsigned int index; + unsigned int type; + unsigned int length; + unsigned char msg[256]; +} ca_msg_t; + +typedef struct ca_descr { + unsigned int index; + unsigned int parity; /* 0 == even, 1 == odd */ + unsigned char cw[8]; +} ca_descr_t; + +typedef struct ca_pid { + unsigned int pid; + int index; /* -1 == disable*/ +} ca_pid_t; + +#define CA_RESET _IO('o', 128) +#define CA_GET_CAP _IOR('o', 129, ca_caps_t) +#define CA_GET_SLOT_INFO _IOR('o', 130, ca_slot_info_t) +#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t) +#define CA_GET_MSG _IOR('o', 132, ca_msg_t) +#define CA_SEND_MSG _IOW('o', 133, ca_msg_t) +#define CA_SET_DESCR _IOW('o', 134, ca_descr_t) +#define CA_SET_PID _IOW('o', 135, ca_pid_t) + +#endif + diff --git a/sys/dvb/dvb-api/dmx.h b/sys/dvb/dvb-api/dmx.h new file mode 100644 index 0000000000..089b217347 --- /dev/null +++ b/sys/dvb/dvb-api/dmx.h @@ -0,0 +1,180 @@ +/* + * dmx.h + * + * Copyright (C) 2000 Marcus Metzler + * & Ralph Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _DVBDMX_H_ +#define _DVBDMX_H_ + +#ifdef __KERNEL__ +#include +#else +#include +#include +#endif + +#define DMX_FILTER_SIZE 16 + +typedef enum +{ + DMX_OUT_DECODER, /* Streaming directly to decoder. */ + DMX_OUT_TAP, /* Output going to a memory buffer */ + /* (to be retrieved via the read command).*/ + DMX_OUT_TS_TAP /* Output multiplexed into a new TS */ + /* (to be retrieved by reading from the */ + /* logical DVR device). */ +} dmx_output_t; + + +typedef enum +{ + DMX_IN_FRONTEND, /* Input from a front-end device. */ + DMX_IN_DVR /* Input from the logical DVR device. */ +} dmx_input_t; + + +typedef enum +{ + DMX_PES_AUDIO0, + DMX_PES_VIDEO0, + DMX_PES_TELETEXT0, + DMX_PES_SUBTITLE0, + DMX_PES_PCR0, + + DMX_PES_AUDIO1, + DMX_PES_VIDEO1, + DMX_PES_TELETEXT1, + DMX_PES_SUBTITLE1, + DMX_PES_PCR1, + + DMX_PES_AUDIO2, + DMX_PES_VIDEO2, + DMX_PES_TELETEXT2, + DMX_PES_SUBTITLE2, + DMX_PES_PCR2, + + DMX_PES_AUDIO3, + DMX_PES_VIDEO3, + DMX_PES_TELETEXT3, + DMX_PES_SUBTITLE3, + DMX_PES_PCR3, + + DMX_PES_OTHER +} dmx_pes_type_t; + +#define DMX_PES_AUDIO DMX_PES_AUDIO0 +#define DMX_PES_VIDEO DMX_PES_VIDEO0 +#define DMX_PES_TELETEXT DMX_PES_TELETEXT0 +#define DMX_PES_SUBTITLE DMX_PES_SUBTITLE0 +#define DMX_PES_PCR DMX_PES_PCR0 + + +typedef enum +{ + DMX_SCRAMBLING_EV, + DMX_FRONTEND_EV +} dmx_event_t; + + +typedef enum +{ + DMX_SCRAMBLING_OFF, + DMX_SCRAMBLING_ON +} dmx_scrambling_status_t; + + +typedef struct dmx_filter +{ + uint8_t filter[DMX_FILTER_SIZE]; + uint8_t mask[DMX_FILTER_SIZE]; + uint8_t mode[DMX_FILTER_SIZE]; +} dmx_filter_t; + + +struct dmx_sct_filter_params +{ + uint16_t pid; + dmx_filter_t filter; + uint32_t timeout; + uint32_t flags; +#define DMX_CHECK_CRC 1 +#define DMX_ONESHOT 2 +#define DMX_IMMEDIATE_START 4 +#define DMX_KERNEL_CLIENT 0x8000 +}; + + +struct dmx_pes_filter_params +{ + uint16_t pid; + dmx_input_t input; + dmx_output_t output; + dmx_pes_type_t pes_type; + uint32_t flags; +}; + + +struct dmx_event +{ + dmx_event_t event; + time_t timeStamp; + union + { + dmx_scrambling_status_t scrambling; + } u; +}; + +typedef struct dmx_caps { + uint32_t caps; + int num_decoders; +} dmx_caps_t; + +typedef enum { + DMX_SOURCE_FRONT0 = 0, + DMX_SOURCE_FRONT1, + DMX_SOURCE_FRONT2, + DMX_SOURCE_FRONT3, + DMX_SOURCE_DVR0 = 16, + DMX_SOURCE_DVR1, + DMX_SOURCE_DVR2, + DMX_SOURCE_DVR3 +} dmx_source_t; + +struct dmx_stc { + unsigned int num; /* input : which STC? 0..N */ + unsigned int base; /* output: divisor for stc to get 90 kHz clock */ + uint64_t stc; /* output: stc in 'base'*90 kHz units */ +}; + + +#define DMX_START _IO('o',41) +#define DMX_STOP _IO('o',42) +#define DMX_SET_FILTER _IOW('o',43,struct dmx_sct_filter_params) +#define DMX_SET_PES_FILTER _IOW('o',44,struct dmx_pes_filter_params) +#define DMX_SET_BUFFER_SIZE _IO('o',45) +#define DMX_GET_EVENT _IOR('o',46,struct dmx_event) +#define DMX_GET_PES_PIDS _IOR('o',47,uint16_t[5]) +#define DMX_GET_CAPS _IOR('o',48,dmx_caps_t) +#define DMX_SET_SOURCE _IOW('o',49,dmx_source_t) +#define DMX_GET_STC _IOWR('o',50,struct dmx_stc) + +#endif /*_DVBDMX_H_*/ + diff --git a/sys/dvb/dvb-api/frontend.h b/sys/dvb/dvb-api/frontend.h new file mode 100644 index 0000000000..d35c65a83f --- /dev/null +++ b/sys/dvb/dvb-api/frontend.h @@ -0,0 +1,264 @@ +/* + * frontend.h + * + * Copyright (C) 2000 Marcus Metzler + * Ralph Metzler + * Holger Waechtler + * Andre Draszik + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _DVBFRONTEND_H_ +#define _DVBFRONTEND_H_ + +#ifdef __KERNEL__ +#include +#else +#include +#endif + + +typedef enum fe_type { + FE_QPSK, + FE_QAM, + FE_OFDM +} fe_type_t; + + +typedef enum fe_caps { + FE_IS_STUPID = 0, + FE_CAN_INVERSION_AUTO = 0x1, + FE_CAN_FEC_1_2 = 0x2, + FE_CAN_FEC_2_3 = 0x4, + FE_CAN_FEC_3_4 = 0x8, + FE_CAN_FEC_4_5 = 0x10, + FE_CAN_FEC_5_6 = 0x20, + FE_CAN_FEC_6_7 = 0x40, + FE_CAN_FEC_7_8 = 0x80, + FE_CAN_FEC_8_9 = 0x100, + FE_CAN_FEC_AUTO = 0x200, + FE_CAN_QPSK = 0x400, + FE_CAN_QAM_16 = 0x800, + FE_CAN_QAM_32 = 0x1000, + FE_CAN_QAM_64 = 0x2000, + FE_CAN_QAM_128 = 0x4000, + FE_CAN_QAM_256 = 0x8000, + FE_CAN_QAM_AUTO = 0x10000, + FE_CAN_TRANSMISSION_MODE_AUTO = 0x20000, + FE_CAN_BANDWIDTH_AUTO = 0x40000, + FE_CAN_GUARD_INTERVAL_AUTO = 0x80000, + FE_CAN_HIERARCHY_AUTO = 0x100000, + FE_NEEDS_BENDING = 0x20000000, // frontend requires frequency bending + FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically + FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output +} fe_caps_t; + + +struct dvb_frontend_info { + char name[128]; + fe_type_t type; + uint32_t frequency_min; + uint32_t frequency_max; + uint32_t frequency_stepsize; + uint32_t frequency_tolerance; + uint32_t symbol_rate_min; + uint32_t symbol_rate_max; + uint32_t symbol_rate_tolerance; /* ppm */ + uint32_t notifier_delay; /* ms */ + fe_caps_t caps; +}; + + +/** + * Check out the DiSEqC bus spec available on http://www.eutelsat.org/ for + * the meaning of this struct... + */ +struct dvb_diseqc_master_cmd { + uint8_t msg [6]; /* { framing, address, command, data [3] } */ + uint8_t msg_len; /* valid values are 3...6 */ +}; + + +struct dvb_diseqc_slave_reply { + uint8_t msg [4]; /* { framing, data [3] } */ + uint8_t msg_len; /* valid values are 0...4, 0 means no msg */ + int timeout; /* return from ioctl after timeout ms with */ +}; /* errorcode when no message was received */ + + +typedef enum fe_sec_voltage { + SEC_VOLTAGE_13, + SEC_VOLTAGE_18, + SEC_VOLTAGE_OFF +} fe_sec_voltage_t; + + +typedef enum fe_sec_tone_mode { + SEC_TONE_ON, + SEC_TONE_OFF +} fe_sec_tone_mode_t; + + +typedef enum fe_sec_mini_cmd { + SEC_MINI_A, + SEC_MINI_B +} fe_sec_mini_cmd_t; + + +typedef enum fe_status { + FE_HAS_SIGNAL = 0x01, /* found something above the noise level */ + FE_HAS_CARRIER = 0x02, /* found a DVB signal */ + FE_HAS_VITERBI = 0x04, /* FEC is stable */ + FE_HAS_SYNC = 0x08, /* found sync bytes */ + FE_HAS_LOCK = 0x10, /* everything's working... */ + FE_TIMEDOUT = 0x20, /* no lock within the last ~2 seconds */ + FE_REINIT = 0x40 /* frontend was reinitialized, */ +} fe_status_t; /* application is recommended to reset */ + /* DiSEqC, tone and parameters */ + +typedef enum fe_spectral_inversion { + INVERSION_OFF, + INVERSION_ON, + INVERSION_AUTO +} fe_spectral_inversion_t; + + +typedef enum fe_code_rate { + FEC_NONE = 0, + FEC_1_2, + FEC_2_3, + FEC_3_4, + FEC_4_5, + FEC_5_6, + FEC_6_7, + FEC_7_8, + FEC_8_9, + FEC_AUTO +} fe_code_rate_t; + + +typedef enum fe_modulation { + QPSK, + QAM_16, + QAM_32, + QAM_64, + QAM_128, + QAM_256, + QAM_AUTO +} fe_modulation_t; + + +typedef enum fe_transmit_mode { + TRANSMISSION_MODE_2K, + TRANSMISSION_MODE_8K, + TRANSMISSION_MODE_AUTO +} fe_transmit_mode_t; + +typedef enum fe_bandwidth { + BANDWIDTH_8_MHZ, + BANDWIDTH_7_MHZ, + BANDWIDTH_6_MHZ, + BANDWIDTH_AUTO +} fe_bandwidth_t; + + +typedef enum fe_guard_interval { + GUARD_INTERVAL_1_32, + GUARD_INTERVAL_1_16, + GUARD_INTERVAL_1_8, + GUARD_INTERVAL_1_4, + GUARD_INTERVAL_AUTO +} fe_guard_interval_t; + + +typedef enum fe_hierarchy { + HIERARCHY_NONE, + HIERARCHY_1, + HIERARCHY_2, + HIERARCHY_4, + HIERARCHY_AUTO +} fe_hierarchy_t; + + +struct dvb_qpsk_parameters { + uint32_t symbol_rate; /* symbol rate in Symbols per second */ + fe_code_rate_t fec_inner; /* forward error correction (see above) */ +}; + + +struct dvb_qam_parameters { + uint32_t symbol_rate; /* symbol rate in Symbols per second */ + fe_code_rate_t fec_inner; /* forward error correction (see above) */ + fe_modulation_t modulation; /* modulation type (see above) */ +}; + + +struct dvb_ofdm_parameters { + fe_bandwidth_t bandwidth; + fe_code_rate_t code_rate_HP; /* high priority stream code rate */ + fe_code_rate_t code_rate_LP; /* low priority stream code rate */ + fe_modulation_t constellation; /* modulation type (see above) */ + fe_transmit_mode_t transmission_mode; + fe_guard_interval_t guard_interval; + fe_hierarchy_t hierarchy_information; +}; + + +struct dvb_frontend_parameters { + uint32_t frequency; /* (absolute) frequency in Hz for QAM/OFDM */ + /* intermediate frequency in kHz for QPSK */ + fe_spectral_inversion_t inversion; + union { + struct dvb_qpsk_parameters qpsk; + struct dvb_qam_parameters qam; + struct dvb_ofdm_parameters ofdm; + } u; +}; + + +struct dvb_frontend_event { + fe_status_t status; + struct dvb_frontend_parameters parameters; +}; + + + +#define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info) + +#define FE_DISEQC_RESET_OVERLOAD _IO('o', 62) +#define FE_DISEQC_SEND_MASTER_CMD _IOW('o', 63, struct dvb_diseqc_master_cmd) +#define FE_DISEQC_RECV_SLAVE_REPLY _IOR('o', 64, struct dvb_diseqc_slave_reply) +#define FE_DISEQC_SEND_BURST _IO('o', 65) /* fe_sec_mini_cmd_t */ + +#define FE_SET_TONE _IO('o', 66) /* fe_sec_tone_mode_t */ +#define FE_SET_VOLTAGE _IO('o', 67) /* fe_sec_voltage_t */ +#define FE_ENABLE_HIGH_LNB_VOLTAGE _IO('o', 68) /* int */ + +#define FE_READ_STATUS _IOR('o', 69, fe_status_t) +#define FE_READ_BER _IOR('o', 70, uint32_t) +#define FE_READ_SIGNAL_STRENGTH _IOR('o', 71, uint16_t) +#define FE_READ_SNR _IOR('o', 72, uint16_t) +#define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, uint32_t) + +#define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters) +#define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters) +#define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event) + + +#endif /*_DVBFRONTEND_H_*/ + diff --git a/sys/dvb/dvb-api/net.h b/sys/dvb/dvb-api/net.h new file mode 100644 index 0000000000..4bac6ed8e2 --- /dev/null +++ b/sys/dvb/dvb-api/net.h @@ -0,0 +1,57 @@ +/* + * net.h + * + * Copyright (C) 2000 Marcus Metzler + * & Ralph Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _DVBNET_H_ +#define _DVBNET_H_ + +#ifdef __KERNEL__ +#include +#else +#include +#endif + + +struct dvb_net_if { + uint16_t pid; + uint16_t if_num; + uint8_t feedtype; +#define DVB_NET_FEEDTYPE_MPE 0 /* multi protocol encapsulation */ +#define DVB_NET_FEEDTYPE_ULE 1 /* ultra lightweight encapsulation */ +}; + + +#define NET_ADD_IF _IOWR('o', 52, struct dvb_net_if) +#define NET_REMOVE_IF _IO('o', 53) +#define NET_GET_IF _IOWR('o', 54, struct dvb_net_if) + + +/* binary compatibility cruft: */ +struct __dvb_net_if_old { + uint16_t pid; + uint16_t if_num; +}; +#define __NET_ADD_IF_OLD _IOWR('o', 52, struct __dvb_net_if_old) +#define __NET_GET_IF_OLD _IOWR('o', 54, struct __dvb_net_if_old) + + +#endif /*_DVBNET_H_*/ diff --git a/sys/dvb/dvb-api/osd.h b/sys/dvb/dvb-api/osd.h new file mode 100644 index 0000000000..cdaff25ecc --- /dev/null +++ b/sys/dvb/dvb-api/osd.h @@ -0,0 +1,113 @@ +/* + * osd.h + * + * Copyright (C) 2001 Ralph Metzler + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Lesser Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _DVBOSD_H_ +#define _DVBOSD_H_ + +#include + +typedef enum { + // All functions return -2 on "not open" + OSD_Close=1, // () + // Disables OSD and releases the buffers + // returns 0 on success + OSD_Open, // (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0)) + // Opens OSD with this size and bit depth + // returns 0 on success, -1 on DRAM allocation error, -2 on "already open" + OSD_Show, // () + // enables OSD mode + // returns 0 on success + OSD_Hide, // () + // disables OSD mode + // returns 0 on success + OSD_Clear, // () + // Sets all pixel to color 0 + // returns 0 on success + OSD_Fill, // (color) + // Sets all pixel to color + // returns 0 on success + OSD_SetColor, // (color,R{x0},G{y0},B{x1},opacity{y1}) + // set palette entry to , and apply + // R,G,B: 0..255 + // R=Red, G=Green, B=Blue + // opacity=0: pixel opacity 0% (only video pixel shows) + // opacity=1..254: pixel opacity as specified in header + // opacity=255: pixel opacity 100% (only OSD pixel shows) + // returns 0 on success, -1 on error + OSD_SetPalette, // (firstcolor{color},lastcolor{x0},data) + // Set a number of entries in the palette + // sets the entries "firstcolor" through "lastcolor" from the array "data" + // data has 4 byte for each color: + // R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel + OSD_SetTrans, // (transparency{color}) + // Sets transparency of mixed pixel (0..15) + // returns 0 on success + OSD_SetPixel, // (x0,y0,color) + // sets pixel , to color number + // returns 0 on success, -1 on error + OSD_GetPixel, // (x0,y0) + // returns color number of pixel ,, or -1 + OSD_SetRow, // (x0,y0,x1,data) + // fills pixels x0,y through x1,y with the content of data[] + // returns 0 on success, -1 on clipping all pixel (no pixel drawn) + OSD_SetBlock, // (x0,y0,x1,y1,increment{color},data) + // fills pixels x0,y0 through x1,y1 with the content of data[] + // inc contains the width of one line in the data block, + // inc<=0 uses blockwidth as linewidth + // returns 0 on success, -1 on clipping all pixel + OSD_FillRow, // (x0,y0,x1,color) + // fills pixels x0,y through x1,y with the color + // returns 0 on success, -1 on clipping all pixel + OSD_FillBlock, // (x0,y0,x1,y1,color) + // fills pixels x0,y0 through x1,y1 with the color + // returns 0 on success, -1 on clipping all pixel + OSD_Line, // (x0,y0,x1,y1,color) + // draw a line from x0,y0 to x1,y1 with the color + // returns 0 on success + OSD_Query, // (x0,y0,x1,y1,xasp{color}}), yasp=11 + // fills parameters with the picture dimensions and the pixel aspect ratio + // returns 0 on success + OSD_Test, // () + // draws a test picture. for debugging purposes only + // returns 0 on success +// TODO: remove "test" in final version + OSD_Text, // (x0,y0,size,color,text) + OSD_SetWindow, // (x0) set window with number 0 + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _DVBVERSION_H_ +#define _DVBVERSION_H_ + +#define DVB_API_VERSION 3 + +#endif /*_DVBVERSION_H_*/ + diff --git a/sys/dvb/dvb-api/video.h b/sys/dvb/dvb-api/video.h new file mode 100644 index 0000000000..bbc09826dd --- /dev/null +++ b/sys/dvb/dvb-api/video.h @@ -0,0 +1,202 @@ +/* + * video.h + * + * Copyright (C) 2000 Marcus Metzler + * & Ralph Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _DVBVIDEO_H_ +#define _DVBVIDEO_H_ + +#ifdef __KERNEL__ +#include +#else +#include +#include +#endif + + +typedef enum { + VIDEO_FORMAT_4_3, /* Select 4:3 format */ + VIDEO_FORMAT_16_9, /* Select 16:9 format. */ + VIDEO_FORMAT_221_1 /* 2.21:1 */ +} video_format_t; + + +typedef enum { + VIDEO_SYSTEM_PAL, + VIDEO_SYSTEM_NTSC, + VIDEO_SYSTEM_PALN, + VIDEO_SYSTEM_PALNc, + VIDEO_SYSTEM_PALM, + VIDEO_SYSTEM_NTSC60, + VIDEO_SYSTEM_PAL60, + VIDEO_SYSTEM_PALM60 +} video_system_t; + + +typedef enum { + VIDEO_PAN_SCAN, /* use pan and scan format */ + VIDEO_LETTER_BOX, /* use letterbox format */ + VIDEO_CENTER_CUT_OUT /* use center cut out format */ +} video_displayformat_t; + +typedef struct { + int w; + int h; + video_format_t aspect_ratio; +} video_size_t; + +typedef enum { + VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */ + VIDEO_SOURCE_MEMORY /* If this source is selected, the stream + comes from the user through the write + system call */ +} video_stream_source_t; + + +typedef enum { + VIDEO_STOPPED, /* Video is stopped */ + VIDEO_PLAYING, /* Video is currently playing */ + VIDEO_FREEZED /* Video is freezed */ +} video_play_state_t; + + +struct video_event { + int32_t type; +#define VIDEO_EVENT_SIZE_CHANGED 1 +#define VIDEO_EVENT_FRAME_RATE_CHANGED 2 + time_t timestamp; + union { + video_size_t size; + unsigned int frame_rate; /* in frames per 1000sec */ + } u; +}; + + +struct video_status { + int video_blank; /* blank video on freeze? */ + video_play_state_t play_state; /* current state of playback */ + video_stream_source_t stream_source; /* current source (demux/memory) */ + video_format_t video_format; /* current aspect ratio of stream*/ + video_displayformat_t display_format;/* selected cropping mode */ +}; + + +struct video_still_picture { + char *iFrame; /* pointer to a single iframe in memory */ + int32_t size; +}; + + +typedef +struct video_highlight { + int active; /* 1=show highlight, 0=hide highlight */ + uint8_t contrast1; /* 7- 4 Pattern pixel contrast */ + /* 3- 0 Background pixel contrast */ + uint8_t contrast2; /* 7- 4 Emphasis pixel-2 contrast */ + /* 3- 0 Emphasis pixel-1 contrast */ + uint8_t color1; /* 7- 4 Pattern pixel color */ + /* 3- 0 Background pixel color */ + uint8_t color2; /* 7- 4 Emphasis pixel-2 color */ + /* 3- 0 Emphasis pixel-1 color */ + uint32_t ypos; /* 23-22 auto action mode */ + /* 21-12 start y */ + /* 9- 0 end y */ + uint32_t xpos; /* 23-22 button color number */ + /* 21-12 start x */ + /* 9- 0 end x */ +} video_highlight_t; + + +typedef struct video_spu { + int active; + int stream_id; +} video_spu_t; + + +typedef struct video_spu_palette { /* SPU Palette information */ + int length; + uint8_t *palette; +} video_spu_palette_t; + + +typedef struct video_navi_pack { + int length; /* 0 ... 1024 */ + uint8_t data[1024]; +} video_navi_pack_t; + + +typedef uint16_t video_attributes_t; +/* bits: descr. */ +/* 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */ +/* 13-12 TV system (0=525/60, 1=625/50) */ +/* 11-10 Aspect ratio (0=4:3, 3=16:9) */ +/* 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */ +/* 7 line 21-1 data present in GOP (1=yes, 0=no) */ +/* 6 line 21-2 data present in GOP (1=yes, 0=no) */ +/* 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */ +/* 2 source letterboxed (1=yes, 0=no) */ +/* 0 film/camera mode (0=camera, 1=film (625/50 only)) */ + + +/* bit definitions for capabilities: */ +/* can the hardware decode MPEG1 and/or MPEG2? */ +#define VIDEO_CAP_MPEG1 1 +#define VIDEO_CAP_MPEG2 2 +/* can you send a system and/or program stream to video device? + (you still have to open the video and the audio device but only + send the stream to the video device) */ +#define VIDEO_CAP_SYS 4 +#define VIDEO_CAP_PROG 8 +/* can the driver also handle SPU, NAVI and CSS encoded data? + (CSS API is not present yet) */ +#define VIDEO_CAP_SPU 16 +#define VIDEO_CAP_NAVI 32 +#define VIDEO_CAP_CSS 64 + + +#define VIDEO_STOP _IO('o', 21) +#define VIDEO_PLAY _IO('o', 22) +#define VIDEO_FREEZE _IO('o', 23) +#define VIDEO_CONTINUE _IO('o', 24) +#define VIDEO_SELECT_SOURCE _IO('o', 25) +#define VIDEO_SET_BLANK _IO('o', 26) +#define VIDEO_GET_STATUS _IOR('o', 27, struct video_status) +#define VIDEO_GET_EVENT _IOR('o', 28, struct video_event) +#define VIDEO_SET_DISPLAY_FORMAT _IO('o', 29) +#define VIDEO_STILLPICTURE _IOW('o', 30, struct video_still_picture) +#define VIDEO_FAST_FORWARD _IO('o', 31) +#define VIDEO_SLOWMOTION _IO('o', 32) +#define VIDEO_GET_CAPABILITIES _IOR('o', 33, unsigned int) +#define VIDEO_CLEAR_BUFFER _IO('o', 34) +#define VIDEO_SET_ID _IO('o', 35) +#define VIDEO_SET_STREAMTYPE _IO('o', 36) +#define VIDEO_SET_FORMAT _IO('o', 37) +#define VIDEO_SET_SYSTEM _IO('o', 38) +#define VIDEO_SET_HIGHLIGHT _IOW('o', 39, video_highlight_t) +#define VIDEO_SET_SPU _IOW('o', 50, video_spu_t) +#define VIDEO_SET_SPU_PALETTE _IOW('o', 51, video_spu_palette_t) +#define VIDEO_GET_NAVI _IOR('o', 52, video_navi_pack_t) +#define VIDEO_SET_ATTRIBUTES _IO('o', 53) +#define VIDEO_GET_SIZE _IOR('o', 55, video_size_t) +#define VIDEO_GET_FRAME_RATE _IOR('o', 56, unsigned int) + +#endif /*_DVBVIDEO_H_*/ + diff --git a/sys/dvb/gstdvbsrc.c b/sys/dvb/gstdvbsrc.c new file mode 100644 index 0000000000..d7b7afd85d --- /dev/null +++ b/sys/dvb/gstdvbsrc.c @@ -0,0 +1,1200 @@ +/* + * + * GStreamer + * Copyright (C) 2006 Zaheer Abbas Merali + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdvbsrc.h" +#include +#include +#include +#include +#include +#include +#include + +#define _XOPEN_SOURCE 500 +#include + +#include "dvb-api/frontend.h" +#include "dvb-api/dmx.h" + +GST_DEBUG_CATEGORY_STATIC (gstdvbsrc_debug); +#define GST_CAT_DEFAULT (gstdvbsrc_debug) + +#define SLOF (11700*1000UL) +#define LOF1 (9750*1000UL) +#define LOF2 (10600*1000UL) + + +static GstElementDetails dvbsrc_details = { + "DVB Source", + "Source/Video", + "Digital Video Broadcast Source", + "P2P-VCR, C-Lab, University of Paderborn\n" + "Zaheer Abbas Merali " +}; + +/** + * SECTION:element-dvbsrc + * + * + * dvbsrc can be used to capture video from DVB cards, DVB-T, DVB-S or DVB-T. + * Example launch line + * + * + * gst-launch dvbsrc modulation="QAM 64" trans-mode=8k bandwidth=8MHz freq=514000000 code-rate-lp=AUTO code-rate-hp=2/3 guard=4 hierarchy=0 ! flutsdemux crc-check=false name=demux ! queue max-size-buffers=0 max-size-time=0 ! flumpeg2vdec ! xvimagesink sync=false demux. ! queue max-size-buffers=0 max-size-time=0 ! flump3dec ! alsasink sync=false + * + * This pipeline captures a full transport stream from dvb card 0 that is a DVB-T card at tuned frequency 514000000 with other parameters as seen in the + * pipeline and outputs the first tv program on the transport stream. The reason the sinks have to be set to have sync=false is due to bug #340482. + * + * + * + * gst-launch dvbsrc modulation="QAM 64" trans-mode=8k bandwidth=8MHz freq=514000000 code-rate-lp=AUTO code-rate-hp=2/3 guard=4 hierarchy=0 pids=256:257 ! flutsdemux crc-check=false name=demux es-pids=256:257 ! queue max-size-buffers=0 max-size-time=0 ! flumpeg2vdec ! xvimagesink sync=false demux. ! queue max-size-buffers=0 max-size-time=0 ! flump3dec ! alsasink sync=false + * + * This pipeline captures a partial transport stream from dvb card 0 that is a DVB-T card for a program at tuned frequency 514000000 and pids of 256:257 with other parameters as seen in the pipeline and outputs the program with the pids 256 and 257. The reason the sinks have to be set to + * have sync=false is due to bug #340482. + * + * + * + * gst-launch dvbsrc polarity="h" freq=11302000 srate=27500 diseqc-src=0 pids=102:103 ! queue max-size-buffers=0 max-size-time=0 ! flumpeg2vdec ! xvimagesink sync=false demux. ! queue max-size-buffers=0 max-size-time=0 ! flump3dec ! alsasink sync=false + * + * This pipeline captures a partial transport stream from dvb card 0 that is a DVB-S card for a program at tuned frequency 11302000 Hz, symbol rate of 27500 kHz and pids of 256:257 and outputs the program with the pids 256 and 257. The reason the sinks have to be set to have sync=false is due to bug #340482. + * + * + */ + +/* Arguments */ +enum +{ + ARG_0, + ARG_DVBSRC_ADAPTER_PREFIX, + ARG_DVBSRC_DISEQC_SRC, + ARG_DVBSRC_FREQ, + ARG_DVBSRC_POL, + ARG_DVBSRC_PIDS, + ARG_DVBSRC_SYM_RATE, + ARG_DVBSRC_BANDWIDTH, + ARG_DVBSRC_CODE_RATE_HP, + ARG_DVBSRC_CODE_RATE_LP, + ARG_DVBSRC_GUARD, + ARG_DVBSRC_MODULATION, + ARG_DVBSRC_TRANSMISSION_MODE, + ARG_DVBSRC_HIERARCHY_INF, + ARG_DVBSRC_TUNE, + ARG_DVBSRC_INVERSION +}; + +#define GST_TYPE_DVBSRC_CODE_RATE (gst_dvbsrc_code_rate_get_type ()) +static GType +gst_dvbsrc_code_rate_get_type (void) +{ + static GType dvbsrc_code_rate_type = 0; + static GEnumValue code_rate_types[] = { + {FEC_NONE, "NONE", "NONE"}, + {FEC_1_2, "1/2", "1/2"}, + {FEC_2_3, "2/3", "2/3"}, + {FEC_3_4, "3/4", "3/4"}, + {FEC_4_5, "4/5", "4/5"}, + {FEC_5_6, "5/6", "5/6"}, + {FEC_6_7, "6/7", "6/7"}, + {FEC_7_8, "7/8", "7/8"}, + {FEC_8_9, "8/9", "8/9"}, + {FEC_AUTO, "AUTO", ""}, + {0, NULL, NULL}, + }; + + if (!dvbsrc_code_rate_type) { + dvbsrc_code_rate_type = + g_enum_register_static ("GstDvbSrcCode_Rate", code_rate_types); + } + return dvbsrc_code_rate_type; +} + +#define GST_TYPE_DVBSRC_MODULATION (gst_dvbsrc_modulation_get_type ()) +static GType +gst_dvbsrc_modulation_get_type (void) +{ + static GType dvbsrc_modulation_type = 0; + static GEnumValue modulation_types[] = { + {QPSK, "QPSK", "QPSK"}, + {QAM_16, "QAM 16", "QAM 16"}, + {QAM_32, "QAM 32", "QAM 32"}, + {QAM_64, "QAM 64", "QAM 64"}, + {QAM_128, "QAM 128", "QAM 128"}, + {QAM_256, "QAM 256", "QAM 256"}, + {QAM_AUTO, "AUTO", "AUTO"}, + {0, NULL, NULL}, + }; + + if (!dvbsrc_modulation_type) { + dvbsrc_modulation_type = + g_enum_register_static ("GstDvbSrcModulation", modulation_types); + } + return dvbsrc_modulation_type; +} + +#define GST_TYPE_DVBSRC_TRANSMISSION_MODE (gst_dvbsrc_transmission_mode_get_type ()) +static GType +gst_dvbsrc_transmission_mode_get_type (void) +{ + static GType dvbsrc_transmission_mode_type = 0; + static GEnumValue transmission_mode_types[] = { + {TRANSMISSION_MODE_2K, "2k", "2k"}, + {TRANSMISSION_MODE_8K, "8k", "8k"}, + {TRANSMISSION_MODE_AUTO, "AUTO", "AUTO"}, + {0, NULL, NULL}, + }; + + if (!dvbsrc_transmission_mode_type) { + dvbsrc_transmission_mode_type = + g_enum_register_static ("GstDvbSrcTransmission_Mode", + transmission_mode_types); + } + return dvbsrc_transmission_mode_type; +} + +#define GST_TYPE_DVBSRC_BANDWIDTH (gst_dvbsrc_bandwidth_get_type ()) +static GType +gst_dvbsrc_bandwidth_get_type (void) +{ + static GType dvbsrc_bandwidth_type = 0; + static GEnumValue bandwidth_types[] = { + {BANDWIDTH_8_MHZ, "8", "8"}, + {BANDWIDTH_7_MHZ, "7", "7"}, + {BANDWIDTH_6_MHZ, "6", "6"}, + {BANDWIDTH_AUTO, "AUTO", "AUTO"}, + {0, NULL, NULL}, + }; + + if (!dvbsrc_bandwidth_type) { + dvbsrc_bandwidth_type = + g_enum_register_static ("GstDvbSrcBandwidth", bandwidth_types); + } + return dvbsrc_bandwidth_type; +} + +#define GST_TYPE_DVBSRC_GUARD (gst_dvbsrc_guard_get_type ()) +static GType +gst_dvbsrc_guard_get_type (void) +{ + static GType dvbsrc_guard_type = 0; + static GEnumValue guard_types[] = { + {GUARD_INTERVAL_1_32, "32", "32"}, + {GUARD_INTERVAL_1_16, "16", "16"}, + {GUARD_INTERVAL_1_8, "8", "8"}, + {GUARD_INTERVAL_1_4, "4", "4"}, + {GUARD_INTERVAL_AUTO, "AUTO", "AUTO"}, + {0, NULL, NULL}, + }; + + if (!dvbsrc_guard_type) { + dvbsrc_guard_type = g_enum_register_static ("GstDvbSrcGuard", guard_types); + } + return dvbsrc_guard_type; +} + +#define GST_TYPE_DVBSRC_HIERARCHY (gst_dvbsrc_hierarchy_get_type ()) +static GType +gst_dvbsrc_hierarchy_get_type (void) +{ + static GType dvbsrc_hierarchy_type = 0; + static GEnumValue hierarchy_types[] = { + {HIERARCHY_NONE, "NONE", "NONE"}, + {HIERARCHY_1, "1", "1"}, + {HIERARCHY_2, "2", "2"}, + {HIERARCHY_4, "4", "4"}, + {HIERARCHY_AUTO, "AUTO", "AUTO"}, + {0, NULL, NULL}, + }; + + if (!dvbsrc_hierarchy_type) { + dvbsrc_hierarchy_type = + g_enum_register_static ("GstDvbSrcHierarchy", hierarchy_types); + } + return dvbsrc_hierarchy_type; +} + +#define GST_TYPE_DVBSRC_INVERSION (gst_dvbsrc_inversion_get_type ()) +static GType +gst_dvbsrc_inversion_get_type (void) +{ + static GType dvbsrc_inversion_type = 0; + static GEnumValue inversion_types[] = { + {INVERSION_AUTO, "AUTO", "AUTO"}, + {INVERSION_ON, "ON", "ON"}, + {INVERSION_AUTO, "OFF", "OFF"}, + {0, NULL, NULL}, + }; + + if (!dvbsrc_inversion_type) { + dvbsrc_inversion_type = + g_enum_register_static ("GstDvbSrcInversion", inversion_types); + } + return dvbsrc_inversion_type; +} + +static void gst_dvbsrc_dispose (GObject * object); +static void gst_dvbsrc_finalize (GObject * object); +static void gst_dvbsrc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_dvbsrc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstFlowReturn gst_dvbsrc_create (GstPushSrc * element, + GstBuffer ** buffer); + +static gboolean gst_dvbsrc_start (GstBaseSrc * bsrc); +static gboolean gst_dvbsrc_stop (GstBaseSrc * bsrc); +static gboolean gst_dvbsrc_unlock (GstBaseSrc * bsrc); +static gboolean gst_dvbsrc_is_seekable (GstBaseSrc * bsrc); +static gboolean gst_dvbsrc_get_size (GstBaseSrc * src, guint64 * size); + +static gboolean gst_dvbsrc_tune (GstDvbSrc * object); +static void gst_dvbsrc_set_pes_filter (GstDvbSrc * object); +static void gst_dvbsrc_unset_pes_filters (GstDvbSrc * object); + +static gboolean gst_dvbsrc_frontend_status (GstDvbSrc * object); + +static GstStaticPadTemplate ts_src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS + ("video/mpegts, " + "mpegversion = (int) 2," "systemstream = (boolean) TRUE")); + +/* + ****************************** + * * + * GObject Related * + * * + * * + ****************************** + */ + +#define _do_init(bla) \ + GST_DEBUG_CATEGORY_INIT (gstdvbsrc_debug, "dvbsrc", 0, "DVB Source Element"); + +GST_BOILERPLATE_FULL (GstDvbSrc, gst_dvbsrc, GstPushSrc, + GST_TYPE_PUSH_SRC, _do_init); + +static void +gst_dvbsrc_base_init (gpointer gclass) +{ + GstDvbSrcClass *klass = (GstDvbSrcClass *) gclass; + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&ts_src_factory)); + + gst_element_class_set_details (element_class, &dvbsrc_details); +} + + +/* initialize the plugin's class */ +static void +gst_dvbsrc_class_init (GstDvbSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSrcClass *gstbasesrc_class; + GstPushSrcClass *gstpushsrc_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasesrc_class = (GstBaseSrcClass *) klass; + gstpushsrc_class = (GstPushSrcClass *) klass; + + gobject_class->set_property = gst_dvbsrc_set_property; + gobject_class->get_property = gst_dvbsrc_get_property; + gobject_class->dispose = gst_dvbsrc_dispose; + gobject_class->finalize = gst_dvbsrc_finalize; + + gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_dvbsrc_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_dvbsrc_stop); + gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_dvbsrc_unlock); + gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_dvbsrc_is_seekable); + gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_dvbsrc_get_size); + + gstpushsrc_class->create = gst_dvbsrc_create; + + g_object_class_install_property (gobject_class, ARG_DVBSRC_ADAPTER_PREFIX, + g_param_spec_string ("adapter-prefix", + "adapter-prefix", + "The adapter prefix. e.g. /dev/dvb/adapter0", + "/dev/dvb/adapter0", G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, ARG_DVBSRC_FREQ, + g_param_spec_int ("freq", + "freq", "Frequency", 0, G_MAXINT, 0, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, ARG_DVBSRC_POL, + g_param_spec_string ("pol", + "pol", "Polarity [vhHV] (DVB-S)", "h", G_PARAM_READWRITE)); + + + g_object_class_install_property (gobject_class, ARG_DVBSRC_PIDS, + g_param_spec_string ("pids", + "pids", + "Colon seperated list of pids (eg. 110:120)", + "8192", G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, ARG_DVBSRC_SYM_RATE, + g_param_spec_int ("srate", + "srate", + "Symbol Rate (DVB-S, DVB-C)", + 0, G_MAXINT, DEFAULT_SYMBOL_RATE, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, ARG_DVBSRC_TUNE, + g_param_spec_pointer ("tune", + "tune", "Atomically tune to channel. (For Apps)", G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, ARG_DVBSRC_DISEQC_SRC, + g_param_spec_int ("diseqc_src", + "diseqc_src", + "DISEqC selected source (-1 disabled) (DVB-S)", + -1, 7, DEFAULT_DISEQC_SRC, G_PARAM_READWRITE)); + + /* DVB-T, additional properties */ + + g_object_class_install_property (gobject_class, ARG_DVBSRC_BANDWIDTH, + g_param_spec_enum ("bandwidth", + "bandwidth", + "Bandwidth (DVB-T)", GST_TYPE_DVBSRC_BANDWIDTH, 1, G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, ARG_DVBSRC_CODE_RATE_HP, + g_param_spec_enum ("code-rate-hp", + "code-rate-hp", + "High Priority Code Rate (DVB-T)", + GST_TYPE_DVBSRC_CODE_RATE, 1, G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, ARG_DVBSRC_CODE_RATE_LP, + g_param_spec_enum ("code-rate-lp", + "code-rate-lp", + "Low Priority Code Rate (DVB-T)", + GST_TYPE_DVBSRC_CODE_RATE, 1, G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, ARG_DVBSRC_GUARD, + g_param_spec_enum ("guard", + "guard", + "Guard Interval (DVB-T)", + GST_TYPE_DVBSRC_GUARD, 1, G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, ARG_DVBSRC_MODULATION, + g_param_spec_enum ("modulation", + "modulation", + "Modulation (DVB-T)", + GST_TYPE_DVBSRC_MODULATION, 1, G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, + ARG_DVBSRC_TRANSMISSION_MODE, + g_param_spec_enum ("trans-mode", + "trans-mode", + "Transmission Mode (DVB-T)", + GST_TYPE_DVBSRC_TRANSMISSION_MODE, 1, G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, ARG_DVBSRC_HIERARCHY_INF, + g_param_spec_enum ("hierarchy", + "hierarchy", + "Hierarchy Information (DVB-T)", + GST_TYPE_DVBSRC_HIERARCHY, 1, G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, ARG_DVBSRC_INVERSION, + g_param_spec_enum ("inversion", + "inversion", + "Inversion Information (DVB-T)", + GST_TYPE_DVBSRC_INVERSION, 1, G_PARAM_WRITABLE)); + +} + +/* initialize the new element + * instantiate pads and add them to element + * set functions + * initialize structure + */ +static void +gst_dvbsrc_init (GstDvbSrc * object, GstDvbSrcClass * klass) +{ + int i = 0; + + GST_INFO ("gst_dvbsrc_init"); + + /* We are a live source */ + gst_base_src_set_live (GST_BASE_SRC (object), TRUE); + + object->fd_frontend = -1; + object->fd_dvr = -1; + + for (i = 0; i < MAX_FILTERS; i++) { + object->pids[i] = 0; + object->fd_filters[i] = -1; + } + /* Pid 8192 on DVB gets the whole transport stream */ + object->pids[0] = 8192; + + /* Setting standard devices */ + object->adapter_prefix = g_strdup (DEFAULT_ADAPTER_PREFIX); + object->frontend_dev = + g_strconcat (object->adapter_prefix, "/frontend0", NULL); + object->demux_dev = g_strconcat (object->adapter_prefix, "/demux0", NULL); + object->dvr_dev = g_strconcat (object->adapter_prefix, "/dvr0", NULL); + + object->sym_rate = DEFAULT_SYMBOL_RATE; + object->diseqc_src = DEFAULT_DISEQC_SRC; + object->send_diseqc = FALSE; + + object->tune_mutex = g_mutex_new (); +} + + +static void +gst_dvbsrc_set_property (GObject * _object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDvbSrc *object; + + g_return_if_fail (GST_IS_DVBSRC (_object)); + object = GST_DVBSRC (_object); + + switch (prop_id) { + case ARG_DVBSRC_ADAPTER_PREFIX: + { + char delim_str[] = "/\0"; + + if (object->adapter_prefix != NULL) + g_free (object->adapter_prefix); + object->adapter_prefix = g_value_dup_string (value); + + if (g_str_has_suffix (object->adapter_prefix, "/")) + delim_str[0] = '\0'; + + object->frontend_dev = + g_strconcat (object->adapter_prefix, delim_str, "frontend0", NULL); + object->demux_dev = + g_strconcat (object->adapter_prefix, delim_str, "demux0", NULL); + object->dvr_dev = + g_strconcat (object->adapter_prefix, delim_str, "dvr0", NULL); + } + GST_INFO ("Set Property: ARG_DVBSRC_ADAPTER_PREFIX"); + break; + case ARG_DVBSRC_DISEQC_SRC: + if (object->diseqc_src != g_value_get_int (value)) { + object->diseqc_src = g_value_get_int (value); + object->send_diseqc = TRUE; + } + GST_INFO ("Set Property: ARG_DVBSRC_DISEQC_ID"); + break; + case ARG_DVBSRC_FREQ: + object->freq = g_value_get_int (value); + GST_INFO ("Set Property: ARG_DVBSRC_FREQ"); + break; + case ARG_DVBSRC_POL: + { + const char *s = NULL; + + s = g_value_get_string (value); + if (s != NULL) + object->pol = (s[0] == 'h' || s[0] == 'H') ? DVB_POL_H : DVB_POL_V; + } + GST_INFO ("Set Property: ARG_DVBSRC_POL"); + break; + case ARG_DVBSRC_PIDS: + { + int pid = 0; + int pid_count = 0; + gchar *pid_string; + gchar **pids; + char **tmp; + + GST_INFO ("Set Property: ARG_DVBSRC_PIDS"); + pid_string = g_value_dup_string (value); + tmp = pids = g_strsplit (pid_string, ":", MAX_FILTERS); + while (*pids != NULL && pid_count < MAX_FILTERS) { + pid = strtol (*pids, NULL, 0); + if (pid > 0 && pid <= 8192) { + GST_INFO ("Parsed Pid: %d\n", pid); + object->pids[pid_count] = pid; + pid_count++; + } + pids++; + } + g_strfreev (tmp); + } + break; + case ARG_DVBSRC_SYM_RATE: + object->sym_rate = g_value_get_int (value); + GST_INFO ("Set Property: ARG_DVBSRC_SYM_RATE to value %d", + g_value_get_int (value)); + break; + + case ARG_DVBSRC_BANDWIDTH: + object->bandwidth = g_value_get_enum (value); + break; + case ARG_DVBSRC_CODE_RATE_HP: + object->code_rate_hp = g_value_get_enum (value); + break; + case ARG_DVBSRC_CODE_RATE_LP: + object->code_rate_lp = g_value_get_enum (value); + break; + case ARG_DVBSRC_GUARD: + object->guard_interval = g_value_get_enum (value); + break; + case ARG_DVBSRC_MODULATION: + object->modulation = g_value_get_enum (value); + break; + case ARG_DVBSRC_TRANSMISSION_MODE: + object->transmission_mode = g_value_get_enum (value); + break; + case ARG_DVBSRC_HIERARCHY_INF: + object->hierarchy_information = g_value_get_enum (value); + break; + case ARG_DVBSRC_INVERSION: + object->inversion = g_value_get_enum (value); + break; + case ARG_DVBSRC_TUNE: + GST_INFO ("Set Property: ARG_DVBSRC_TUNE"); + /* if we are in paused/playing state tune now, otherwise in ready to paused state change */ + if (gst_element_get_state + (GST_ELEMENT (object), NULL, NULL, + GST_CLOCK_TIME_NONE) > GST_STATE_READY) { + g_mutex_lock (object->tune_mutex); + gst_dvbsrc_tune (object); + g_mutex_unlock (object->tune_mutex); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } + +} + + +static void +gst_dvbsrc_get_property (GObject * _object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDvbSrc *object; + + g_return_if_fail (GST_IS_DVBSRC (_object)); + object = GST_DVBSRC (_object); + + switch (prop_id) { + case ARG_DVBSRC_ADAPTER_PREFIX: + g_value_set_string (value, object->adapter_prefix); + break; + case ARG_DVBSRC_FREQ: + g_value_set_int (value, object->freq); + break; + case ARG_DVBSRC_POL: + if (object->pol == DVB_POL_H) + g_value_set_string (value, "H"); + else + g_value_set_string (value, "V"); + break; + case ARG_DVBSRC_SYM_RATE: + g_value_set_int (value, object->sym_rate); + break; + case ARG_DVBSRC_DISEQC_SRC: + g_value_set_int (value, object->diseqc_src); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +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_open_frontend (GstDvbSrc * object) +{ + struct dvb_frontend_info fe_info; + char *adapter_desc = NULL; + + GST_INFO ("Using frontend: %s", object->frontend_dev); + GST_INFO ("Using dvr: %s", object->dvr_dev); + + /* open frontend */ + if ((object->fd_frontend = open (object->frontend_dev, O_RDWR)) < 0) { + close (object->fd_dvr); + g_warning ("Could not open frontend: %s, %s", object->frontend_dev, + strerror (errno)); + return FALSE; + } + + if (ioctl (object->fd_frontend, FE_GET_INFO, &fe_info) < 0) { + close (object->fd_dvr); + close (object->fd_frontend); + + g_warning ("Unable to get frontend info: %s", strerror (errno)); + return FALSE; + } + + object->adapter_type = fe_info.type; + switch (object->adapter_type) { + case FE_QPSK: + adapter_desc = "DVB-S"; + break; + case FE_QAM: + adapter_desc = "DVB-C"; + break; + case FE_OFDM: + adapter_desc = "DVB-T"; + break; + default: + g_error ("Unknown frontend type: %d", object->adapter_type); + } + + /*g_signal_emit (G_OBJECT (object), gst_dvbsrc_signals[ADAPTER_TYPE_SIGNAL], + 0, object->adapter_type); */ + + GST_INFO ("DVB card: %s ", fe_info.name); + return TRUE; +} + +static gboolean +gst_dvbsrc_open_dvr (GstDvbSrc * object) +{ + /* open DVR */ + if ((object->fd_dvr = open (object->dvr_dev, O_RDONLY | O_NONBLOCK)) < 0) { + g_warning ("Could not open dvr device: %s", object->dvr_dev); + return FALSE; + } + GST_INFO ("Setting buffer size"); + if (ioctl (object->fd_dvr, DMX_SET_BUFFER_SIZE, 1024 * 1024) < 0) { + GST_INFO ("DMX_SET_BUFFER_SIZE failed"); + return FALSE; + } + return TRUE; +} + +static void +gst_dvbsrc_dispose (GObject * _object) +{ + GstDvbSrc *object; + + GST_DEBUG ("gst_dvbsrc_dispose"); + + g_return_if_fail (GST_IS_DVBSRC (_object)); + object = GST_DVBSRC (_object); +} + +static void +gst_dvbsrc_finalize (GObject * _object) +{ + GstDvbSrc *object; + + GST_DEBUG ("gst_dvbsrc_finalize"); + + g_return_if_fail (GST_IS_DVBSRC (_object)); + object = GST_DVBSRC (_object); + + g_free (object->frontend_dev); + g_free (object->demux_dev); + + /* freeing the mutex segfaults somehow */ + g_mutex_free (object->tune_mutex); +} + + +/* + ****************************** + * * + * Plugin Realisation * + * * + ****************************** + */ + + + +/* entry point to initialize the plug-in + * initialize the plug-in itself + * register the element factories and pad templates + * register the features + */ +static gboolean +plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "dvbsrc", GST_RANK_NONE, + GST_TYPE_DVBSRC); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "dvbsrc", + "DVB Source", plugin_init, VERSION, "LGPL", "", "University of Paderborn") + + static GstBuffer *read_device (int fd, const char *fd_name, int size) +{ + int count = 0; + struct pollfd pfd[1]; + int ret_val = 0; + int attempts = 0; + const int TIMEOUT = 100; + + GstBuffer *buf = gst_buffer_new_and_alloc (size); + + g_return_val_if_fail (GST_IS_BUFFER (buf), NULL); + + if (fd < 0) { + return NULL; + } + + pfd[0].fd = fd; + pfd[0].events = POLLIN; + + while (count < size) { + ret_val = poll (pfd, 1, TIMEOUT); + if (ret_val > 0) { + if (pfd[0].revents & POLLIN) { + int tmp = 0; + + tmp = read (fd, GST_BUFFER_DATA (buf) + count, size - count); + if (tmp < 0) { + GST_WARNING ("Unable to read from device: %s (%d)", fd_name, errno); + attempts += 1; + if (attempts == MAX_ATTEMPTS) { + GST_WARNING + ("Unable to read from device after too many attempts: %s", + fd_name); + + goto fail; + } + + } else + count = count + tmp; + } else { + fprintf (stderr, "revents = %d\n", pfd[0].revents); + } + } else if (ret_val == 0) { // poll timeout + attempts += 1; + GST_INFO ("Reading from device %s timedout (%d)", fd_name, attempts); + + if (attempts == MAX_ATTEMPTS) { + GST_WARNING ("Unable to read from device: %s (%d)", fd_name, errno); + goto fail; + } + } else if (errno == -EINTR) { // poll interrupted + ; + } + + } + + GST_BUFFER_SIZE (buf) = count; + GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE; + goto end; + +fail: + gst_buffer_unref (buf); + buf = NULL; + +end: + return buf; +} + +static GstFlowReturn +gst_dvbsrc_create (GstPushSrc * element, GstBuffer ** buf) +{ + static int quality_signal_rate = 0; + gint buffer_size; + GstFlowReturn retval = GST_FLOW_ERROR; + + GstDvbSrc *object = NULL; + + g_return_val_if_fail (GST_IS_DVBSRC (element), GST_FLOW_ERROR); + g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + object = GST_DVBSRC (element); + //g_object_get(G_OBJECT(object), "blocksize", &buffer_size, NULL); + buffer_size = DEFAULT_BUFFER_SIZE; + + /* device can not be tuned during read */ + g_mutex_lock (object->tune_mutex); + + + if (object->fd_dvr > -1) { + /* --- Read TS from DVR device --- */ + GST_DEBUG ("Reading from DVR device"); + *buf = read_device (object->fd_dvr, object->dvr_dev, buffer_size); + if (*buf != NULL) { + GstCaps *caps; + + retval = GST_FLOW_OK; + + caps = gst_pad_get_caps (GST_BASE_SRC_PAD (object)); + gst_buffer_set_caps (*buf, caps); + gst_caps_unref (caps); + + /* Every now and then signal signal quality */ + if (quality_signal_rate == 100) { + guint16 strength = 0; + guint16 snr = 0; + + gst_dvbsrc_output_frontend_stats (object); + quality_signal_rate = 0; + } else { + quality_signal_rate++; + } + } else { + GST_DEBUG ("Failed to read from device"); + } + } + + g_mutex_unlock (object->tune_mutex); + return retval; + +} + +static gboolean +gst_dvbsrc_start (GstBaseSrc * bsrc) +{ + GstDvbSrc *src = GST_DVBSRC (bsrc); + + gst_dvbsrc_open_frontend (src); + gst_dvbsrc_tune (src); + if (!gst_dvbsrc_frontend_status (src)) { + return FALSE; + } + if (!gst_dvbsrc_open_dvr (src)) { + GST_ERROR ("\nNot able to open dvr_device"); + return FALSE; + } + + return TRUE; +} + +static gboolean +gst_dvbsrc_stop (GstBaseSrc * bsrc) +{ + GstDvbSrc *src = GST_DVBSRC (bsrc); + + gst_dvbsrc_close_devices (src); + return TRUE; +} + +static gboolean +gst_dvbsrc_unlock (GstBaseSrc * bsrc) +{ + return TRUE; +} + +static gboolean +gst_dvbsrc_is_seekable (GstBaseSrc * bsrc) +{ + return FALSE; +} + +static gboolean +gst_dvbsrc_get_size (GstBaseSrc * src, guint64 * size) +{ + return FALSE; +} + +static void +gst_dvbsrc_output_frontend_stats (GstDvbSrc * src) +{ + fe_status_t status; + uint16_t snr, _signal; + uint32_t ber, uncorrected_blocks; + GstMessage *message; + GstStructure *structure; + int fe_fd = src->fd_frontend; + + ioctl (fe_fd, FE_READ_STATUS, &status); + ioctl (fe_fd, FE_READ_SIGNAL_STRENGTH, &_signal); + ioctl (fe_fd, FE_READ_SNR, &snr); + ioctl (fe_fd, FE_READ_BER, &ber); + ioctl (fe_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks); + + structure = gst_structure_new ("dvb-frontend-stats", "status", G_TYPE_INT, + status, "signal", G_TYPE_INT, _signal, "snr", G_TYPE_INT, snr, + "ber", G_TYPE_INT, ber, "unc", G_TYPE_INT, uncorrected_blocks, + "lock", G_TYPE_BOOLEAN, status & FE_HAS_LOCK, NULL); + message = gst_message_new_element (GST_OBJECT (src), structure); + gst_element_post_message (GST_ELEMENT (src), message); +} + +static gboolean +gst_dvbsrc_frontend_status (GstDvbSrc * object) +{ + fe_status_t status = 0; + gint i; + + GST_INFO ("gst_dvbsrc_frontend_status\n"); + + if (object->fd_frontend < 0) { + GST_ERROR ("Trying to get frontend status from not opened device!"); + return FALSE; + } else + GST_INFO ("fd-frontend: %d", object->fd_frontend); + + for (i = 0; i < 15; i++) { + usleep (1000000); + GST_INFO ("."); + if (ioctl (object->fd_frontend, FE_READ_STATUS, &status) == -1) { + GST_ERROR ("Failed reading frontend status."); + return FALSE; + } + gst_dvbsrc_output_frontend_stats (object); + if (status & FE_HAS_LOCK) { + break; + } + } + + if (!(status & FE_HAS_LOCK)) { + GST_INFO ("Not able to lock to the signal on the given frequency.\n"); + return FALSE; + } else + return TRUE; +} + +struct diseqc_cmd +{ + struct dvb_diseqc_master_cmd cmd; + uint32_t wait; +}; + +static void +diseqc_send_msg (int fd, fe_sec_voltage_t v, struct diseqc_cmd *cmd, + fe_sec_tone_mode_t t, fe_sec_mini_cmd_t b) +{ + if (ioctl (fd, FE_SET_TONE, SEC_TONE_OFF) == -1) + perror ("FE_SET_TONE failed"); + + if (ioctl (fd, FE_SET_VOLTAGE, v) == -1) + perror ("FE_SET_VOLTAGE failed"); + + usleep (15 * 1000); + + if (ioctl (fd, FE_DISEQC_SEND_MASTER_CMD, &cmd->cmd) == -1) + perror ("FE_DISEQC_SEND_MASTER_CMD failed"); + + usleep (cmd->wait * 1000); + usleep (15 * 1000); + + if (ioctl (fd, FE_DISEQC_SEND_BURST, b) == -1) + perror ("FE_DISEQC_SEND_BURST failed"); + + usleep (15 * 1000); + + if (ioctl (fd, FE_SET_TONE, t) == -1) + perror ("FE_SET_TONE failed"); +} + + +/* digital satellite equipment control, + * specification is available from http://www.eutelsat.com/ + */ +static void +diseqc (int secfd, int sat_no, int voltage, int tone) +{ + struct diseqc_cmd cmd = { {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}, 0 }; + + /* param: high nibble: reset bits, low nibble set bits, + * bits are: option, position, polarizaion, band + */ + cmd.cmd.msg[3] = + 0xf0 | (((sat_no * 4) & 0x0f) | (tone == SEC_TONE_ON ? 1 : 0) | + (voltage == SEC_VOLTAGE_13 ? 0 : 2)); + + diseqc_send_msg (secfd, voltage, &cmd, tone, + (sat_no / 4) % 2 ? SEC_MINI_B : SEC_MINI_A); + +} + + +static gboolean +gst_dvbsrc_tune (GstDvbSrc * object) +{ + struct dvb_frontend_parameters feparams; + fe_sec_voltage_t voltage; + + 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 ("gst_dvbsrc_tune"); + + if (object->fd_frontend < 0) { + /* frontend not opened yet, tune later */ + GST_INFO ("Frontend not open: tuning later"); + return FALSE; + } + + gst_dvbsrc_unset_pes_filters (object); + + 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); + if (object->tone < 0) + object->tone = SEC_TONE_OFF; + } else { + feparams.frequency = (freq - LOF2); + if (object->tone < 0) + object->tone = SEC_TONE_ON; + } + } else { + // this is an L-Band frequency + feparams.frequency = freq; + object->tone = SEC_TONE_OFF; + } + GST_INFO ("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"); + + feparams.inversion = INVERSION_AUTO; + feparams.u.qpsk.symbol_rate = sym_rate; + feparams.u.qpsk.fec_inner = FEC_AUTO; + + 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 ("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; + 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; + feparams.inversion = object->inversion; + + GST_INFO ("tuning DVB-T to %d Hz\n", freq); + break; + case FE_QAM: + GST_INFO ("Tuning DVB-C to %d, srate=%d", freq, sym_rate); + feparams.frequency = freq; + feparams.inversion = INVERSION_OFF; + feparams.u.qam.fec_inner = FEC_AUTO; + feparams.u.qam.modulation = object->modulation; + feparams.u.qam.symbol_rate = sym_rate; + break; + default: + g_error ("Unknown frontend type: %d", object->adapter_type); + + } + usleep (100000); + + /* now tune the frontend */ + if (ioctl (object->fd_frontend, FE_SET_FRONTEND, &feparams) < 0) { + g_warning ("Error tuning channel: %s", strerror (errno)); + } + + /* set pid filters */ + gst_dvbsrc_set_pes_filter (object); + + return TRUE; +} + + +static void +gst_dvbsrc_unset_pes_filters (GstDvbSrc * object) +{ + int i = 0; + + GST_INFO ("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 void +gst_dvbsrc_set_pes_filter (GstDvbSrc * object) +{ + int *fd; + int pid, i; + struct dmx_pes_filter_params pes_filter; + + GST_INFO ("Setting PES filter"); + + for (i = 0; i < MAX_FILTERS; i++) { + if (object->pids[i] == 0) + continue; + + fd = &object->fd_filters[i]; + pid = object->pids[i]; + + close (*fd); + if ((*fd = open (object->demux_dev, O_RDWR)) < 0) + g_error ("Error opening demuxer: %s (%s)", strerror (errno), + object->demux_dev); + + g_return_if_fail (*fd != -1); + + pes_filter.pid = pid; + pes_filter.input = DMX_IN_FRONTEND; + pes_filter.output = DMX_OUT_TS_TAP; + pes_filter.pes_type = DMX_PES_OTHER; + pes_filter.flags = DMX_IMMEDIATE_START; + + GST_INFO ("Setting pes-filter, pid = %d, type = %d", pes_filter.pid, + pes_filter.pes_type); + + if (ioctl (*fd, DMX_SET_PES_FILTER, &pes_filter) < 0) + g_warning ("Error setting PES filter on %s: %s", object->demux_dev, + strerror (errno)); + } +} diff --git a/sys/dvb/gstdvbsrc.h b/sys/dvb/gstdvbsrc.h new file mode 100644 index 0000000000..8bfa0e574f --- /dev/null +++ b/sys/dvb/gstdvbsrc.h @@ -0,0 +1,103 @@ + +#ifndef __GST_DVBSRC_H__ +#define __GST_DVBSRC_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + + typedef enum + { + DVB_POL_H, + DVB_POL_V, + DVB_POL_ZERO + } GstDvbSrcPol; + + +#define IPACKS 2048 +#define TS_SIZE 188 +#define IN_SIZE TS_SIZE*10 +#define MAX_ATTEMPTS 10 // limit timeouts for poll + +#define DEFAULT_ADAPTER_PREFIX "/dev/dvb/adapter0" +#define DEFAULT_SYMBOL_RATE 0 +#define DEFAULT_BUFFER_SIZE 8192 +#define DEFAULT_DISEQC_SRC -1 /* disabled */ + +#define MAX_FILTERS 8 + +/* #define's don't like whitespacey bits */ +#define GST_TYPE_DVBSRC \ + (gst_dvbsrc_get_type()) +#define GST_DVBSRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DVBSRC,GstDvbSrc)) +#define GST_DVBSRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DVBSRC,GstDvbSrc)) +#define GST_IS_DVBSRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DVBSRC)) +#define GST_IS_DVBSRC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DVBSRC)) + + typedef struct _GstDvbSrc GstDvbSrc; + typedef struct _GstDvbSrcClass GstDvbSrcClass; + typedef struct _GstDvbSrcParam GstDvbSrcParam; + + struct _GstDvbSrc + { + GstPushSrc element; + GstPad *srcpad; + + GMutex *tune_mutex; + gboolean need_tune; + + int adapter_type; + + char *adapter_prefix; + char *frontend_dev; + char *dvr_dev; + char *demux_dev; + + int fd_frontend; + int fd_dvr; + int fd_filters[MAX_FILTERS]; + + guint16 pids[MAX_FILTERS]; + unsigned int freq; + unsigned int sym_rate; + int tone; + int diseqc_src; + gboolean send_diseqc; + + int bandwidth; + int code_rate_hp; + int code_rate_lp; + int modulation; + int guard_interval; + int transmission_mode; + int hierarchy_information; + int inversion; + + GstDvbSrcPol pol; + }; + + struct _GstDvbSrcClass + { + GstPushSrcClass parent_class; + + void (*adapter_type) (GstElement * element, gint type); + void (*signal_quality) (GstElement * element, gint strength, gint snr); + }; + + + GType gst_dvbsrc_get_type (void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GST_DVBSRC_H__ */