~oah-dev/oah/gst-plugins-bad

« back to all changes in this revision

Viewing changes to sys/dvb/gstdvbsrc.c

  • Committer: Haakon Sporsheim
  • Date: 2009-03-12 13:52:03 UTC
  • Revision ID: haakon.sporsheim@tandberg.com-20090312135203-i5k294hgkushb0mt
Initial import of git repository: git://anongit.freedesktop.org/gstreamer/gst-plugins-bad (tag: RELEASE-0_10_10)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GStreamer DVB source
 
2
 * Copyright (C) 2006 Zaheer Abbas Merali <zaheerabbas at merali
 
3
 *                                         dot org>
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Library General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Library General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Library General Public
 
16
 * License along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
/**
 
21
 * SECTION:element-dvbsrc
 
22
 *
 
23
 * dvbsrc can be used to capture video from DVB cards, DVB-T, DVB-S or DVB-T.
 
24
 * 
 
25
 * <refsect2>
 
26
 * <title>Example launch line</title>
 
27
 * |[
 
28
 * gst-launch dvbsrc modulation="QAM 64" trans-mode=8k bandwidth=8MHz frequency=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 demux. ! queue max-size-buffers=0 max-size-time=0 ! flump3dec ! alsasink sync
 
29
 * ]| 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 
 
30
 * pipeline and outputs the first tv program on the transport stream.
 
31
 * |[
 
32
 * gst-launch dvbsrc modulation="QAM 64" trans-mode=8k bandwidth=8 frequency=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 demux. ! queue max-size-buffers=0 max-size-time=0 ! flump3dec ! alsasink
 
33
 * ]| 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.  
 
34
 * |[
 
35
 * gst-launch dvbsrc polarity="h" frequency=11302000 srate=27500 diseqc-src=0 pids=102:103 ! queue max-size-buffers=0 max-size-time=0 ! flumpeg2vdec ! xvimagesink demux. ! queue max-size-buffers=0 max-size-time=0 ! flump3dec ! alsasink
 
36
 * ]| 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.
 
37
 * </refsect2>
 
38
 */
 
39
 
 
40
#ifdef HAVE_CONFIG_H
 
41
#include "config.h"
 
42
#endif
 
43
 
 
44
#include "gstdvbsrc.h"
 
45
#include <gst/gst.h>
 
46
#include <sys/ioctl.h>
 
47
#include <sys/poll.h>
 
48
#include <fcntl.h>
 
49
#include <error.h>
 
50
#include <errno.h>
 
51
#include <stdlib.h>
 
52
#include <string.h>
 
53
#include "_stdint.h"
 
54
 
 
55
#define _XOPEN_SOURCE 500
 
56
#include <unistd.h>
 
57
 
 
58
#include <linux/dvb/version.h>
 
59
#include <linux/dvb/frontend.h>
 
60
#include <linux/dvb/dmx.h>
 
61
 
 
62
#include <gst/gst-i18n-plugin.h>
 
63
 
 
64
GST_DEBUG_CATEGORY_STATIC (gstdvbsrc_debug);
 
65
#define GST_CAT_DEFAULT (gstdvbsrc_debug)
 
66
 
 
67
#define SLOF (11700*1000UL)
 
68
#define LOF1 (9750*1000UL)
 
69
#define LOF2 (10600*1000UL)
 
70
 
 
71
 
 
72
static GstElementDetails dvbsrc_details = {
 
73
  "DVB Source",
 
74
  "Source/Video",
 
75
  "Digital Video Broadcast Source",
 
76
  "P2P-VCR, C-Lab, University of Paderborn\n"
 
77
      "Zaheer Abbas Merali <zaheerabbas at merali dot org>"
 
78
};
 
79
 
 
80
/* Arguments */
 
81
enum
 
82
{
 
83
  ARG_0,
 
84
  ARG_DVBSRC_ADAPTER,
 
85
  ARG_DVBSRC_FRONTEND,
 
86
  ARG_DVBSRC_DISEQC_SRC,
 
87
  ARG_DVBSRC_FREQUENCY,
 
88
  ARG_DVBSRC_POLARITY,
 
89
  ARG_DVBSRC_PIDS,
 
90
  ARG_DVBSRC_SYM_RATE,
 
91
  ARG_DVBSRC_BANDWIDTH,
 
92
  ARG_DVBSRC_CODE_RATE_HP,
 
93
  ARG_DVBSRC_CODE_RATE_LP,
 
94
  ARG_DVBSRC_GUARD,
 
95
  ARG_DVBSRC_MODULATION,
 
96
  ARG_DVBSRC_TRANSMISSION_MODE,
 
97
  ARG_DVBSRC_HIERARCHY_INF,
 
98
  ARG_DVBSRC_TUNE,
 
99
  ARG_DVBSRC_INVERSION,
 
100
  ARG_DVBSRC_STATS_REPORTING_INTERVAL
 
101
};
 
102
 
 
103
static void gst_dvbsrc_output_frontend_stats (GstDvbSrc * src);
 
104
 
 
105
#define GST_TYPE_DVBSRC_CODE_RATE (gst_dvbsrc_code_rate_get_type ())
 
106
static GType
 
107
gst_dvbsrc_code_rate_get_type (void)
 
108
{
 
109
  static GType dvbsrc_code_rate_type = 0;
 
110
  static GEnumValue code_rate_types[] = {
 
111
    {FEC_NONE, "NONE", "NONE"},
 
112
    {FEC_1_2, "1/2", "1/2"},
 
113
    {FEC_2_3, "2/3", "2/3"},
 
114
    {FEC_3_4, "3/4", "3/4"},
 
115
    {FEC_4_5, "4/5", "4/5"},
 
116
    {FEC_5_6, "5/6", "5/6"},
 
117
    {FEC_6_7, "6/7", "6/7"},
 
118
    {FEC_7_8, "7/8", "7/8"},
 
119
    {FEC_8_9, "8/9", "8/9"},
 
120
    {FEC_AUTO, "AUTO", ""},
 
121
    {0, NULL, NULL},
 
122
  };
 
123
 
 
124
  if (!dvbsrc_code_rate_type) {
 
125
    dvbsrc_code_rate_type =
 
126
        g_enum_register_static ("GstDvbSrcCode_Rate", code_rate_types);
 
127
  }
 
128
  return dvbsrc_code_rate_type;
 
129
}
 
130
 
 
131
#define GST_TYPE_DVBSRC_MODULATION (gst_dvbsrc_modulation_get_type ())
 
132
static GType
 
133
gst_dvbsrc_modulation_get_type (void)
 
134
{
 
135
  static GType dvbsrc_modulation_type = 0;
 
136
  static GEnumValue modulation_types[] = {
 
137
    {QPSK, "QPSK", "QPSK"},
 
138
    {QAM_16, "QAM 16", "QAM 16"},
 
139
    {QAM_32, "QAM 32", "QAM 32"},
 
140
    {QAM_64, "QAM 64", "QAM 64"},
 
141
    {QAM_128, "QAM 128", "QAM 128"},
 
142
    {QAM_256, "QAM 256", "QAM 256"},
 
143
    {QAM_AUTO, "AUTO", "AUTO"},
 
144
    {VSB_8, "8VSB", "8VSB"},
 
145
    {VSB_16, "16VSB", "16VSB"},
 
146
    {0, NULL, NULL},
 
147
  };
 
148
 
 
149
  if (!dvbsrc_modulation_type) {
 
150
    dvbsrc_modulation_type =
 
151
        g_enum_register_static ("GstDvbSrcModulation", modulation_types);
 
152
  }
 
153
  return dvbsrc_modulation_type;
 
154
}
 
155
 
 
156
#define GST_TYPE_DVBSRC_TRANSMISSION_MODE (gst_dvbsrc_transmission_mode_get_type ())
 
157
static GType
 
158
gst_dvbsrc_transmission_mode_get_type (void)
 
159
{
 
160
  static GType dvbsrc_transmission_mode_type = 0;
 
161
  static GEnumValue transmission_mode_types[] = {
 
162
    {TRANSMISSION_MODE_2K, "2k", "2k"},
 
163
    {TRANSMISSION_MODE_8K, "8k", "8k"},
 
164
    {TRANSMISSION_MODE_AUTO, "AUTO", "AUTO"},
 
165
    {0, NULL, NULL},
 
166
  };
 
167
 
 
168
  if (!dvbsrc_transmission_mode_type) {
 
169
    dvbsrc_transmission_mode_type =
 
170
        g_enum_register_static ("GstDvbSrcTransmission_Mode",
 
171
        transmission_mode_types);
 
172
  }
 
173
  return dvbsrc_transmission_mode_type;
 
174
}
 
175
 
 
176
#define GST_TYPE_DVBSRC_BANDWIDTH (gst_dvbsrc_bandwidth_get_type ())
 
177
static GType
 
178
gst_dvbsrc_bandwidth_get_type (void)
 
179
{
 
180
  static GType dvbsrc_bandwidth_type = 0;
 
181
  static GEnumValue bandwidth_types[] = {
 
182
    {BANDWIDTH_8_MHZ, "8", "8"},
 
183
    {BANDWIDTH_7_MHZ, "7", "7"},
 
184
    {BANDWIDTH_6_MHZ, "6", "6"},
 
185
    {BANDWIDTH_AUTO, "AUTO", "AUTO"},
 
186
    {0, NULL, NULL},
 
187
  };
 
188
 
 
189
  if (!dvbsrc_bandwidth_type) {
 
190
    dvbsrc_bandwidth_type =
 
191
        g_enum_register_static ("GstDvbSrcBandwidth", bandwidth_types);
 
192
  }
 
193
  return dvbsrc_bandwidth_type;
 
194
}
 
195
 
 
196
#define GST_TYPE_DVBSRC_GUARD (gst_dvbsrc_guard_get_type ())
 
197
static GType
 
198
gst_dvbsrc_guard_get_type (void)
 
199
{
 
200
  static GType dvbsrc_guard_type = 0;
 
201
  static GEnumValue guard_types[] = {
 
202
    {GUARD_INTERVAL_1_32, "32", "32"},
 
203
    {GUARD_INTERVAL_1_16, "16", "16"},
 
204
    {GUARD_INTERVAL_1_8, "8", "8"},
 
205
    {GUARD_INTERVAL_1_4, "4", "4"},
 
206
    {GUARD_INTERVAL_AUTO, "AUTO", "AUTO"},
 
207
    {0, NULL, NULL},
 
208
  };
 
209
 
 
210
  if (!dvbsrc_guard_type) {
 
211
    dvbsrc_guard_type = g_enum_register_static ("GstDvbSrcGuard", guard_types);
 
212
  }
 
213
  return dvbsrc_guard_type;
 
214
}
 
215
 
 
216
#define GST_TYPE_DVBSRC_HIERARCHY (gst_dvbsrc_hierarchy_get_type ())
 
217
static GType
 
218
gst_dvbsrc_hierarchy_get_type (void)
 
219
{
 
220
  static GType dvbsrc_hierarchy_type = 0;
 
221
  static GEnumValue hierarchy_types[] = {
 
222
    {HIERARCHY_NONE, "NONE", "NONE"},
 
223
    {HIERARCHY_1, "1", "1"},
 
224
    {HIERARCHY_2, "2", "2"},
 
225
    {HIERARCHY_4, "4", "4"},
 
226
    {HIERARCHY_AUTO, "AUTO", "AUTO"},
 
227
    {0, NULL, NULL},
 
228
  };
 
229
 
 
230
  if (!dvbsrc_hierarchy_type) {
 
231
    dvbsrc_hierarchy_type =
 
232
        g_enum_register_static ("GstDvbSrcHierarchy", hierarchy_types);
 
233
  }
 
234
  return dvbsrc_hierarchy_type;
 
235
}
 
236
 
 
237
#define GST_TYPE_DVBSRC_INVERSION (gst_dvbsrc_inversion_get_type ())
 
238
static GType
 
239
gst_dvbsrc_inversion_get_type (void)
 
240
{
 
241
  static GType dvbsrc_inversion_type = 0;
 
242
  static GEnumValue inversion_types[] = {
 
243
    {INVERSION_OFF, "OFF", "OFF"},
 
244
    {INVERSION_ON, "ON", "ON"},
 
245
    {INVERSION_AUTO, "AUTO", "AUTO"},
 
246
    {0, NULL, NULL},
 
247
  };
 
248
 
 
249
  if (!dvbsrc_inversion_type) {
 
250
    dvbsrc_inversion_type =
 
251
        g_enum_register_static ("GstDvbSrcInversion", inversion_types);
 
252
  }
 
253
  return dvbsrc_inversion_type;
 
254
}
 
255
 
 
256
static void gst_dvbsrc_finalize (GObject * object);
 
257
static void gst_dvbsrc_set_property (GObject * object, guint prop_id,
 
258
    const GValue * value, GParamSpec * pspec);
 
259
static void gst_dvbsrc_get_property (GObject * object, guint prop_id,
 
260
    GValue * value, GParamSpec * pspec);
 
261
 
 
262
static GstFlowReturn gst_dvbsrc_create (GstPushSrc * element,
 
263
    GstBuffer ** buffer);
 
264
 
 
265
static gboolean gst_dvbsrc_start (GstBaseSrc * bsrc);
 
266
static gboolean gst_dvbsrc_stop (GstBaseSrc * bsrc);
 
267
static GstStateChangeReturn gst_dvbsrc_change_state (GstElement * element,
 
268
    GstStateChange transition);
 
269
 
 
270
static gboolean gst_dvbsrc_unlock (GstBaseSrc * bsrc);
 
271
static gboolean gst_dvbsrc_is_seekable (GstBaseSrc * bsrc);
 
272
static gboolean gst_dvbsrc_get_size (GstBaseSrc * src, guint64 * size);
 
273
 
 
274
static gboolean gst_dvbsrc_tune (GstDvbSrc * object);
 
275
static void gst_dvbsrc_set_pes_filters (GstDvbSrc * object);
 
276
static void gst_dvbsrc_unset_pes_filters (GstDvbSrc * object);
 
277
 
 
278
static gboolean gst_dvbsrc_frontend_status (GstDvbSrc * object);
 
279
 
 
280
static GstStaticPadTemplate ts_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
 
281
    GST_PAD_SRC,
 
282
    GST_PAD_ALWAYS,
 
283
    GST_STATIC_CAPS
 
284
    ("video/mpegts, "
 
285
        "mpegversion = (int) 2," "systemstream = (boolean) TRUE"));
 
286
 
 
287
/*
 
288
 ******************************
 
289
 *                            *
 
290
 *      GObject Related       *
 
291
 *                            *
 
292
 *                            *
 
293
 ******************************
 
294
 */
 
295
 
 
296
GST_BOILERPLATE (GstDvbSrc, gst_dvbsrc, GstPushSrc, GST_TYPE_PUSH_SRC);
 
297
 
 
298
static void
 
299
gst_dvbsrc_base_init (gpointer gclass)
 
300
{
 
301
  GstDvbSrcClass *klass = (GstDvbSrcClass *) gclass;
 
302
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 
303
 
 
304
  gst_element_class_add_pad_template (element_class,
 
305
      gst_static_pad_template_get (&ts_src_factory));
 
306
 
 
307
  gst_element_class_set_details (element_class, &dvbsrc_details);
 
308
}
 
309
 
 
310
 
 
311
/* initialize the plugin's class */
 
312
static void
 
313
gst_dvbsrc_class_init (GstDvbSrcClass * klass)
 
314
{
 
315
  GObjectClass *gobject_class;
 
316
  GstElementClass *gstelement_class;
 
317
  GstBaseSrcClass *gstbasesrc_class;
 
318
  GstPushSrcClass *gstpushsrc_class;
 
319
 
 
320
  gobject_class = (GObjectClass *) klass;
 
321
  gstelement_class = (GstElementClass *) klass;
 
322
  gstbasesrc_class = (GstBaseSrcClass *) klass;
 
323
  gstpushsrc_class = (GstPushSrcClass *) klass;
 
324
 
 
325
  gobject_class->set_property = gst_dvbsrc_set_property;
 
326
  gobject_class->get_property = gst_dvbsrc_get_property;
 
327
  gobject_class->finalize = gst_dvbsrc_finalize;
 
328
 
 
329
  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dvbsrc_change_state);
 
330
  gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_dvbsrc_start);
 
331
  gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_dvbsrc_stop);
 
332
  gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_dvbsrc_unlock);
 
333
  gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_dvbsrc_is_seekable);
 
334
  gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_dvbsrc_get_size);
 
335
 
 
336
  gstpushsrc_class->create = gst_dvbsrc_create;
 
337
  g_object_class_install_property (gobject_class, ARG_DVBSRC_ADAPTER,
 
338
      g_param_spec_int ("adapter",
 
339
          "The adapter device number",
 
340
          "The adapter device number (eg. 0 for adapter0)", 0, 16, 0,
 
341
          G_PARAM_READWRITE));
 
342
 
 
343
  g_object_class_install_property (gobject_class, ARG_DVBSRC_FRONTEND,
 
344
      g_param_spec_int ("frontend",
 
345
          "The frontend device number",
 
346
          "The frontend device number (eg. 0 for frontend0)", 0, 16, 0,
 
347
          G_PARAM_READWRITE));
 
348
 
 
349
  g_object_class_install_property (gobject_class, ARG_DVBSRC_FREQUENCY,
 
350
      g_param_spec_int ("frequency",
 
351
          "frequency", "Frequency", 0, G_MAXINT, 0, G_PARAM_READWRITE));
 
352
 
 
353
  g_object_class_install_property (gobject_class, ARG_DVBSRC_POLARITY,
 
354
      g_param_spec_string ("polarity",
 
355
          "polarity", "Polarity [vhHV] (DVB-S)", "h", G_PARAM_READWRITE));
 
356
 
 
357
 
 
358
  g_object_class_install_property (gobject_class, ARG_DVBSRC_PIDS,
 
359
      g_param_spec_string ("pids",
 
360
          "pids",
 
361
          "Colon seperated list of pids (eg. 110:120)",
 
362
          "8192", G_PARAM_WRITABLE));
 
363
 
 
364
  g_object_class_install_property (gobject_class, ARG_DVBSRC_SYM_RATE,
 
365
      g_param_spec_int ("symbol-rate",
 
366
          "symbol rate",
 
367
          "Symbol Rate (DVB-S, DVB-C)",
 
368
          0, G_MAXINT, DEFAULT_SYMBOL_RATE, G_PARAM_READWRITE));
 
369
 
 
370
  g_object_class_install_property (gobject_class, ARG_DVBSRC_TUNE,
 
371
      g_param_spec_pointer ("tune",
 
372
          "tune", "Atomically tune to channel. (For Apps)", G_PARAM_WRITABLE));
 
373
 
 
374
  g_object_class_install_property (gobject_class, ARG_DVBSRC_DISEQC_SRC,
 
375
      g_param_spec_int ("diseqc-source",
 
376
          "diseqc source",
 
377
          "DISEqC selected source (-1 disabled) (DVB-S)",
 
378
          -1, 7, DEFAULT_DISEQC_SRC, G_PARAM_READWRITE));
 
379
 
 
380
  /* DVB-T, additional properties */
 
381
 
 
382
  g_object_class_install_property (gobject_class, ARG_DVBSRC_BANDWIDTH,
 
383
      g_param_spec_enum ("bandwidth",
 
384
          "bandwidth",
 
385
          "Bandwidth (DVB-T)", GST_TYPE_DVBSRC_BANDWIDTH, 1,
 
386
          G_PARAM_READWRITE));
 
387
 
 
388
  g_object_class_install_property (gobject_class, ARG_DVBSRC_CODE_RATE_HP,
 
389
      g_param_spec_enum ("code-rate-hp",
 
390
          "code-rate-hp",
 
391
          "High Priority Code Rate (DVB-T, DVB-S and DVB-C)",
 
392
          GST_TYPE_DVBSRC_CODE_RATE, FEC_AUTO, G_PARAM_READWRITE));
 
393
 
 
394
  g_object_class_install_property (gobject_class, ARG_DVBSRC_CODE_RATE_LP,
 
395
      g_param_spec_enum ("code-rate-lp",
 
396
          "code-rate-lp",
 
397
          "Low Priority Code Rate (DVB-T)",
 
398
          GST_TYPE_DVBSRC_CODE_RATE, 1, G_PARAM_READWRITE));
 
399
 
 
400
  g_object_class_install_property (gobject_class, ARG_DVBSRC_GUARD,
 
401
      g_param_spec_enum ("guard",
 
402
          "guard",
 
403
          "Guard Interval (DVB-T)",
 
404
          GST_TYPE_DVBSRC_GUARD, 1, G_PARAM_READWRITE));
 
405
 
 
406
  g_object_class_install_property (gobject_class, ARG_DVBSRC_MODULATION,
 
407
      g_param_spec_enum ("modulation",
 
408
          "modulation",
 
409
          "Modulation (DVB-T and DVB-C)",
 
410
          GST_TYPE_DVBSRC_MODULATION, 1, G_PARAM_READWRITE));
 
411
 
 
412
  g_object_class_install_property (gobject_class,
 
413
      ARG_DVBSRC_TRANSMISSION_MODE,
 
414
      g_param_spec_enum ("trans-mode",
 
415
          "trans-mode",
 
416
          "Transmission Mode (DVB-T)",
 
417
          GST_TYPE_DVBSRC_TRANSMISSION_MODE, 1, G_PARAM_READWRITE));
 
418
 
 
419
  g_object_class_install_property (gobject_class, ARG_DVBSRC_HIERARCHY_INF,
 
420
      g_param_spec_enum ("hierarchy",
 
421
          "hierarchy",
 
422
          "Hierarchy Information (DVB-T)",
 
423
          GST_TYPE_DVBSRC_HIERARCHY, 1, G_PARAM_READWRITE));
 
424
  g_object_class_install_property (gobject_class, ARG_DVBSRC_INVERSION,
 
425
      g_param_spec_enum ("inversion",
 
426
          "inversion",
 
427
          "Inversion Information (DVB-T and DVB-C)",
 
428
          GST_TYPE_DVBSRC_INVERSION, 1, G_PARAM_READWRITE));
 
429
 
 
430
  g_object_class_install_property (gobject_class,
 
431
      ARG_DVBSRC_STATS_REPORTING_INTERVAL,
 
432
      g_param_spec_uint ("stats-reporting-interval",
 
433
          "stats-reporting-interval",
 
434
          "The number of reads before reporting frontend stats",
 
435
          0, G_MAXUINT, 100, G_PARAM_READWRITE));
 
436
}
 
437
 
 
438
/* initialize the new element
 
439
 * instantiate pads and add them to element
 
440
 * set functions
 
441
 * initialize structure
 
442
 */
 
443
static void
 
444
gst_dvbsrc_init (GstDvbSrc * object, GstDvbSrcClass * klass)
 
445
{
 
446
  int i = 0;
 
447
 
 
448
  GST_INFO_OBJECT (object, "gst_dvbsrc_init");
 
449
 
 
450
  /* We are a live source */
 
451
  gst_base_src_set_live (GST_BASE_SRC (object), TRUE);
 
452
 
 
453
  object->fd_frontend = -1;
 
454
  object->fd_dvr = -1;
 
455
 
 
456
  for (i = 0; i < MAX_FILTERS; i++) {
 
457
    object->pids[i] = G_MAXUINT16;
 
458
    object->fd_filters[i] = -1;
 
459
  }
 
460
  /* Pid 8192 on DVB gets the whole transport stream */
 
461
  object->pids[0] = 8192;
 
462
 
 
463
  object->adapter_number = 0;
 
464
  object->frontend_number = 0;
 
465
  object->sym_rate = DEFAULT_SYMBOL_RATE;
 
466
  object->diseqc_src = DEFAULT_DISEQC_SRC;
 
467
  object->send_diseqc = FALSE;
 
468
  object->code_rate_hp = FEC_AUTO;
 
469
  object->tune_mutex = g_mutex_new ();
 
470
}
 
471
 
 
472
 
 
473
static void
 
474
gst_dvbsrc_set_property (GObject * _object, guint prop_id,
 
475
    const GValue * value, GParamSpec * pspec)
 
476
{
 
477
  GstDvbSrc *object;
 
478
 
 
479
  g_return_if_fail (GST_IS_DVBSRC (_object));
 
480
  object = GST_DVBSRC (_object);
 
481
 
 
482
  switch (prop_id) {
 
483
    case ARG_DVBSRC_ADAPTER:
 
484
      object->adapter_number = g_value_get_int (value);
 
485
      break;
 
486
    case ARG_DVBSRC_FRONTEND:
 
487
      object->frontend_number = g_value_get_int (value);
 
488
      break;
 
489
    case ARG_DVBSRC_DISEQC_SRC:
 
490
      if (object->diseqc_src != g_value_get_int (value)) {
 
491
        object->diseqc_src = g_value_get_int (value);
 
492
        object->send_diseqc = TRUE;
 
493
      }
 
494
      GST_INFO_OBJECT (object, "Set Property: ARG_DVBSRC_DISEQC_ID");
 
495
      break;
 
496
    case ARG_DVBSRC_FREQUENCY:
 
497
      object->freq = g_value_get_int (value);
 
498
      GST_INFO_OBJECT (object, "Set Property: ARG_DVBSRC_FREQUENCY");
 
499
      break;
 
500
    case ARG_DVBSRC_POLARITY:
 
501
    {
 
502
      const char *s = NULL;
 
503
 
 
504
      s = g_value_get_string (value);
 
505
      if (s != NULL)
 
506
        object->pol = (s[0] == 'h' || s[0] == 'H') ? DVB_POL_H : DVB_POL_V;
 
507
    }
 
508
      GST_INFO_OBJECT (object, "Set Property: ARG_DVBSRC_POLARITY");
 
509
      break;
 
510
    case ARG_DVBSRC_PIDS:
 
511
    {
 
512
      gchar *pid_string;
 
513
 
 
514
      GST_INFO_OBJECT (object, "Set Property: ARG_DVBSRC_PIDS");
 
515
      pid_string = g_value_dup_string (value);
 
516
      if (!strcmp (pid_string, "8192")) {
 
517
        /* get the whole ts */
 
518
        object->pids[0] = 8192;
 
519
      } else {
 
520
        int pid = 0;
 
521
        int pid_count;
 
522
        gchar **pids;
 
523
        char **tmp;
 
524
 
 
525
        tmp = pids = g_strsplit (pid_string, ":", MAX_FILTERS);
 
526
        if (pid_string)
 
527
          g_free (pid_string);
 
528
 
 
529
        /* always add the PAT and CAT pids */
 
530
        object->pids[0] = 0;
 
531
        object->pids[1] = 1;
 
532
 
 
533
        pid_count = 2;
 
534
        while (*pids != NULL && pid_count < MAX_FILTERS) {
 
535
          pid = strtol (*pids, NULL, 0);
 
536
          if (pid > 1 && pid <= 8192) {
 
537
            GST_INFO_OBJECT (object, "Parsed Pid: %d\n", pid);
 
538
            object->pids[pid_count] = pid;
 
539
            pid_count++;
 
540
          }
 
541
          pids++;
 
542
        }
 
543
 
 
544
        g_strfreev (tmp);
 
545
      }
 
546
      /* if we are in playing or paused, then set filters now */
 
547
      GST_INFO_OBJECT (object, "checking if playing for setting pes filters");
 
548
      if (GST_ELEMENT (object)->current_state == GST_STATE_PLAYING ||
 
549
          GST_ELEMENT (object)->current_state == GST_STATE_PAUSED) {
 
550
        GST_INFO_OBJECT (object, "Setting pes filters now");
 
551
        gst_dvbsrc_set_pes_filters (object);
 
552
      }
 
553
    }
 
554
      break;
 
555
    case ARG_DVBSRC_SYM_RATE:
 
556
      object->sym_rate = g_value_get_int (value);
 
557
      GST_INFO_OBJECT (object, "Set Property: ARG_DVBSRC_SYM_RATE to value %d",
 
558
          g_value_get_int (value));
 
559
      break;
 
560
 
 
561
    case ARG_DVBSRC_BANDWIDTH:
 
562
      object->bandwidth = g_value_get_enum (value);
 
563
      break;
 
564
    case ARG_DVBSRC_CODE_RATE_HP:
 
565
      object->code_rate_hp = g_value_get_enum (value);
 
566
      break;
 
567
    case ARG_DVBSRC_CODE_RATE_LP:
 
568
      object->code_rate_lp = g_value_get_enum (value);
 
569
      break;
 
570
    case ARG_DVBSRC_GUARD:
 
571
      object->guard_interval = g_value_get_enum (value);
 
572
      break;
 
573
    case ARG_DVBSRC_MODULATION:
 
574
      object->modulation = g_value_get_enum (value);
 
575
      break;
 
576
    case ARG_DVBSRC_TRANSMISSION_MODE:
 
577
      object->transmission_mode = g_value_get_enum (value);
 
578
      break;
 
579
    case ARG_DVBSRC_HIERARCHY_INF:
 
580
      object->hierarchy_information = g_value_get_enum (value);
 
581
      break;
 
582
    case ARG_DVBSRC_INVERSION:
 
583
      object->inversion = g_value_get_enum (value);
 
584
      break;
 
585
    case ARG_DVBSRC_TUNE:
 
586
      GST_INFO_OBJECT (object, "Set Property: ARG_DVBSRC_TUNE");
 
587
      /* if we are in paused/playing state tune now, otherwise in ready to paused state change */
 
588
      if (gst_element_get_state
 
589
          (GST_ELEMENT (object), NULL, NULL,
 
590
              GST_CLOCK_TIME_NONE) > GST_STATE_READY) {
 
591
        g_mutex_lock (object->tune_mutex);
 
592
        gst_dvbsrc_tune (object);
 
593
        g_mutex_unlock (object->tune_mutex);
 
594
      }
 
595
      break;
 
596
    case ARG_DVBSRC_STATS_REPORTING_INTERVAL:
 
597
      object->stats_interval = g_value_get_uint (value);
 
598
      object->stats_counter = 0;
 
599
      break;
 
600
    default:
 
601
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
602
  }
 
603
 
 
604
}
 
605
 
 
606
static void
 
607
gst_dvbsrc_get_property (GObject * _object, guint prop_id,
 
608
    GValue * value, GParamSpec * pspec)
 
609
{
 
610
  GstDvbSrc *object;
 
611
 
 
612
  g_return_if_fail (GST_IS_DVBSRC (_object));
 
613
  object = GST_DVBSRC (_object);
 
614
 
 
615
  switch (prop_id) {
 
616
    case ARG_DVBSRC_ADAPTER:
 
617
      g_value_set_int (value, object->adapter_number);
 
618
      break;
 
619
    case ARG_DVBSRC_FRONTEND:
 
620
      g_value_set_int (value, object->frontend_number);
 
621
      break;
 
622
    case ARG_DVBSRC_FREQUENCY:
 
623
      g_value_set_int (value, object->freq);
 
624
      break;
 
625
    case ARG_DVBSRC_POLARITY:
 
626
      if (object->pol == DVB_POL_H)
 
627
        g_value_set_string (value, "H");
 
628
      else
 
629
        g_value_set_string (value, "V");
 
630
      break;
 
631
    case ARG_DVBSRC_SYM_RATE:
 
632
      g_value_set_int (value, object->sym_rate);
 
633
      break;
 
634
    case ARG_DVBSRC_DISEQC_SRC:
 
635
      g_value_set_int (value, object->diseqc_src);
 
636
      break;
 
637
    case ARG_DVBSRC_BANDWIDTH:
 
638
      g_value_set_enum (value, object->bandwidth);
 
639
      break;
 
640
    case ARG_DVBSRC_CODE_RATE_HP:
 
641
      g_value_set_enum (value, object->code_rate_hp);
 
642
      break;
 
643
    case ARG_DVBSRC_CODE_RATE_LP:
 
644
      g_value_set_enum (value, object->code_rate_lp);
 
645
      break;
 
646
    case ARG_DVBSRC_GUARD:
 
647
      g_value_set_enum (value, object->guard_interval);
 
648
      break;
 
649
    case ARG_DVBSRC_MODULATION:
 
650
      g_value_set_enum (value, object->modulation);
 
651
      break;
 
652
    case ARG_DVBSRC_TRANSMISSION_MODE:
 
653
      g_value_set_enum (value, object->transmission_mode);
 
654
      break;
 
655
    case ARG_DVBSRC_HIERARCHY_INF:
 
656
      g_value_set_enum (value, object->hierarchy_information);
 
657
      break;
 
658
    case ARG_DVBSRC_INVERSION:
 
659
      g_value_set_enum (value, object->inversion);
 
660
      break;
 
661
    case ARG_DVBSRC_STATS_REPORTING_INTERVAL:
 
662
      g_value_set_uint (value, object->stats_interval);
 
663
      break;
 
664
    default:
 
665
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
666
  }
 
667
}
 
668
 
 
669
static gboolean
 
670
gst_dvbsrc_close_devices (GstDvbSrc * object)
 
671
{
 
672
  gst_dvbsrc_unset_pes_filters (object);
 
673
 
 
674
  close (object->fd_dvr);
 
675
  object->fd_dvr = -1;
 
676
  close (object->fd_frontend);
 
677
  object->fd_frontend = -1;
 
678
 
 
679
  return TRUE;
 
680
}
 
681
 
 
682
static gboolean
 
683
gst_dvbsrc_open_frontend (GstDvbSrc * object)
 
684
{
 
685
  struct dvb_frontend_info fe_info;
 
686
  char *adapter_desc = NULL;
 
687
  gchar *frontend_dev;
 
688
  GstStructure *adapter_structure;
 
689
  char *adapter_name = NULL;
 
690
 
 
691
  frontend_dev = g_strdup_printf ("/dev/dvb/adapter%d/frontend%d",
 
692
      object->adapter_number, object->frontend_number);
 
693
  GST_INFO_OBJECT (object, "Using frontend device: %s", frontend_dev);
 
694
 
 
695
  /* open frontend */
 
696
  if ((object->fd_frontend = open (frontend_dev, O_RDWR)) < 0) {
 
697
    switch (errno) {
 
698
      case ENOENT:
 
699
        GST_ELEMENT_ERROR (object, RESOURCE, NOT_FOUND,
 
700
            (_("Device \"%s\" does not exist."), frontend_dev), (NULL));
 
701
        break;
 
702
      default:
 
703
        GST_ELEMENT_ERROR (object, RESOURCE, OPEN_READ_WRITE,
 
704
            (_("Could not open frontend device \"%s\"."), frontend_dev),
 
705
            GST_ERROR_SYSTEM);
 
706
        break;
 
707
    }
 
708
 
 
709
    close (object->fd_frontend);
 
710
    g_free (frontend_dev);
 
711
    return FALSE;
 
712
  }
 
713
 
 
714
  if (ioctl (object->fd_frontend, FE_GET_INFO, &fe_info) < 0) {
 
715
    GST_ELEMENT_ERROR (object, RESOURCE, SETTINGS,
 
716
        (_("Could not get settings from frontend device \"%s\"."),
 
717
            frontend_dev), GST_ERROR_SYSTEM);
 
718
 
 
719
    close (object->fd_frontend);
 
720
    g_free (frontend_dev);
 
721
    return FALSE;
 
722
  }
 
723
 
 
724
  adapter_name = g_strdup (fe_info.name);
 
725
 
 
726
  object->adapter_type = fe_info.type;
 
727
  switch (object->adapter_type) {
 
728
    case FE_QPSK:
 
729
      adapter_desc = "DVB-S";
 
730
      adapter_structure = gst_structure_new ("dvb-adapter",
 
731
          "type", G_TYPE_STRING, adapter_desc,
 
732
          "name", G_TYPE_STRING, adapter_name,
 
733
          "auto-fec", G_TYPE_BOOLEAN, fe_info.caps & FE_CAN_FEC_AUTO, NULL);
 
734
      break;
 
735
    case FE_QAM:
 
736
      adapter_desc = "DVB-C";
 
737
      adapter_structure = gst_structure_new ("dvb-adapter",
 
738
          "type", G_TYPE_STRING, adapter_desc,
 
739
          "name", G_TYPE_STRING, adapter_name,
 
740
          "auto-inversion", G_TYPE_BOOLEAN,
 
741
          fe_info.caps & FE_CAN_INVERSION_AUTO, "auto-qam", G_TYPE_BOOLEAN,
 
742
          fe_info.caps & FE_CAN_QAM_AUTO, "auto-fec", G_TYPE_BOOLEAN,
 
743
          fe_info.caps & FE_CAN_FEC_AUTO, NULL);
 
744
      break;
 
745
    case FE_OFDM:
 
746
      adapter_desc = "DVB-T";
 
747
      adapter_structure = gst_structure_new ("dvb-adapter",
 
748
          "type", G_TYPE_STRING, adapter_desc,
 
749
          "name", G_TYPE_STRING, adapter_name,
 
750
          "auto-inversion", G_TYPE_BOOLEAN,
 
751
          fe_info.caps & FE_CAN_INVERSION_AUTO, "auto-qam", G_TYPE_BOOLEAN,
 
752
          fe_info.caps & FE_CAN_QAM_AUTO, "auto-transmission-mode",
 
753
          G_TYPE_BOOLEAN, fe_info.caps & FE_CAN_TRANSMISSION_MODE_AUTO,
 
754
          "auto-guard-interval", G_TYPE_BOOLEAN,
 
755
          fe_info.caps & FE_CAN_GUARD_INTERVAL_AUTO, "auto-hierarchy",
 
756
          G_TYPE_BOOLEAN, fe_info.caps % FE_CAN_HIERARCHY_AUTO, "auto-fec",
 
757
          G_TYPE_BOOLEAN, fe_info.caps & FE_CAN_FEC_AUTO, NULL);
 
758
      break;
 
759
    case FE_ATSC:
 
760
      adapter_desc = "ATSC";
 
761
      adapter_structure = gst_structure_new ("dvb-adapter",
 
762
          "type", G_TYPE_STRING, adapter_desc,
 
763
          "name", G_TYPE_STRING, adapter_name, NULL);
 
764
      break;
 
765
    default:
 
766
      g_error ("Unknown frontend type: %d", object->adapter_type);
 
767
      adapter_structure = gst_structure_new ("dvb-adapter",
 
768
          "type", G_TYPE_STRING, "unknown", NULL);
 
769
  }
 
770
 
 
771
  GST_INFO_OBJECT (object, "DVB card: %s ", adapter_name);
 
772
  gst_element_post_message (GST_ELEMENT_CAST (object), gst_message_new_element
 
773
      (GST_OBJECT (object), adapter_structure));
 
774
  g_free (frontend_dev);
 
775
  g_free (adapter_name);
 
776
  return TRUE;
 
777
}
 
778
 
 
779
static gboolean
 
780
gst_dvbsrc_open_dvr (GstDvbSrc * object)
 
781
{
 
782
  gchar *dvr_dev;
 
783
 
 
784
  dvr_dev = g_strdup_printf ("/dev/dvb/adapter%d/dvr%d",
 
785
      object->adapter_number, object->frontend_number);
 
786
  GST_INFO_OBJECT (object, "Using dvr device: %s", dvr_dev);
 
787
 
 
788
  /* open DVR */
 
789
  if ((object->fd_dvr = open (dvr_dev, O_RDONLY | O_NONBLOCK)) < 0) {
 
790
    switch (errno) {
 
791
      case ENOENT:
 
792
        GST_ELEMENT_ERROR (object, RESOURCE, NOT_FOUND,
 
793
            (_("Device \"%s\" does not exist."), dvr_dev), (NULL));
 
794
        break;
 
795
      default:
 
796
        GST_ELEMENT_ERROR (object, RESOURCE, OPEN_READ,
 
797
            (_("Could not open file \"%s\" for reading."), dvr_dev),
 
798
            GST_ERROR_SYSTEM);
 
799
        break;
 
800
    }
 
801
    g_free (dvr_dev);
 
802
    return FALSE;
 
803
  }
 
804
  g_free (dvr_dev);
 
805
  GST_INFO_OBJECT (object, "Setting buffer size");
 
806
  if (ioctl (object->fd_dvr, DMX_SET_BUFFER_SIZE, 1024 * 1024) < 0) {
 
807
    GST_INFO_OBJECT (object, "DMX_SET_BUFFER_SIZE failed");
 
808
    return FALSE;
 
809
  }
 
810
  return TRUE;
 
811
}
 
812
 
 
813
static void
 
814
gst_dvbsrc_finalize (GObject * _object)
 
815
{
 
816
  GstDvbSrc *object;
 
817
 
 
818
  GST_DEBUG_OBJECT (_object, "gst_dvbsrc_finalize");
 
819
 
 
820
  g_return_if_fail (GST_IS_DVBSRC (_object));
 
821
  object = GST_DVBSRC (_object);
 
822
 
 
823
  /* freeing the mutex segfaults somehow */
 
824
  g_mutex_free (object->tune_mutex);
 
825
 
 
826
  if (G_OBJECT_CLASS (parent_class)->finalize)
 
827
    G_OBJECT_CLASS (parent_class)->finalize (_object);
 
828
}
 
829
 
 
830
 
 
831
/*
 
832
 ******************************
 
833
 *                            *
 
834
 *      Plugin Realisation    *
 
835
 *                            *
 
836
 ******************************
 
837
 */
 
838
 
 
839
 
 
840
 
 
841
/* entry point to initialize the plug-in
 
842
 * initialize the plug-in itself
 
843
 * register the element factories and pad templates
 
844
 * register the features
 
845
 */
 
846
gboolean
 
847
gst_dvbsrc_plugin_init (GstPlugin * plugin)
 
848
{
 
849
  GST_DEBUG_CATEGORY_INIT (gstdvbsrc_debug, "dvbsrc", 0, "DVB Source Element");
 
850
 
 
851
#ifdef ENABLE_NLS
 
852
  GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
 
853
      LOCALEDIR);
 
854
  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
 
855
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
856
#endif /* ENABLE_NLS */
 
857
 
 
858
  return gst_element_register (plugin, "dvbsrc", GST_RANK_NONE,
 
859
      GST_TYPE_DVBSRC);
 
860
}
 
861
 
 
862
static GstBuffer *
 
863
read_device (int fd, int adapter_number, int frontend_number, int size,
 
864
    GstDvbSrc * object)
 
865
{
 
866
  int count = 0;
 
867
  struct pollfd pfd[1];
 
868
  int ret_val = 0;
 
869
  guint attempts = 0;
 
870
  const int TIMEOUT = 100;
 
871
 
 
872
  GstBuffer *buf = gst_buffer_new_and_alloc (size);
 
873
 
 
874
  g_return_val_if_fail (GST_IS_BUFFER (buf), NULL);
 
875
 
 
876
  if (fd < 0) {
 
877
    return NULL;
 
878
  }
 
879
 
 
880
  pfd[0].fd = fd;
 
881
  pfd[0].events = POLLIN;
 
882
 
 
883
  while (count < size) {
 
884
    ret_val = poll (pfd, 1, TIMEOUT);
 
885
    if (ret_val > 0) {
 
886
      if (pfd[0].revents & POLLIN) {
 
887
        int tmp = 0;
 
888
 
 
889
        tmp = read (fd, GST_BUFFER_DATA (buf) + count, size - count);
 
890
        if (tmp < 0) {
 
891
          GST_WARNING
 
892
              ("Unable to read from device: /dev/dvb/adapter%d/dvr%d (%d)",
 
893
              adapter_number, frontend_number, errno);
 
894
          attempts += 1;
 
895
          if (attempts % 10 == 0) {
 
896
            GST_WARNING
 
897
                ("Unable to read from device after %u attempts: /dev/dvb/adapter%d/dvr%d",
 
898
                attempts, adapter_number, frontend_number);
 
899
          }
 
900
 
 
901
        } else
 
902
          count = count + tmp;
 
903
      } else {
 
904
        GST_LOG ("revents = %d\n", pfd[0].revents);
 
905
      }
 
906
    } else if (ret_val == 0) {  // poll timeout
 
907
      attempts += 1;
 
908
      GST_INFO ("Reading from device /dev/dvb/adapter%d/dvr%d timedout (%d)",
 
909
          adapter_number, frontend_number, attempts);
 
910
 
 
911
      if (attempts % 10 == 0) {
 
912
        GST_WARNING
 
913
            ("Unable to read after %u attempts from device: /dev/dvb/adapter%d/dvr%d (%d)",
 
914
            attempts, adapter_number, frontend_number, errno);
 
915
        gst_element_post_message (GST_ELEMENT_CAST (object),
 
916
            gst_message_new_element (GST_OBJECT (object),
 
917
                gst_structure_empty_new ("dvb-read-failure")));
 
918
 
 
919
      }
 
920
    } else if (errno == -EINTR) {       // poll interrupted
 
921
      if (attempts % 50 == 0) {
 
922
        gst_buffer_unref (buf);
 
923
        return NULL;
 
924
      };
 
925
    }
 
926
 
 
927
  }
 
928
 
 
929
  GST_BUFFER_SIZE (buf) = count;
 
930
  GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
 
931
  return buf;
 
932
}
 
933
 
 
934
static GstFlowReturn
 
935
gst_dvbsrc_create (GstPushSrc * element, GstBuffer ** buf)
 
936
{
 
937
  gint buffer_size;
 
938
  GstFlowReturn retval = GST_FLOW_ERROR;
 
939
  GstDvbSrc *object;
 
940
 
 
941
  object = GST_DVBSRC (element);
 
942
  GST_LOG ("fd_dvr: %d", object->fd_dvr);
 
943
 
 
944
  //g_object_get(G_OBJECT(object), "blocksize", &buffer_size, NULL);
 
945
  buffer_size = DEFAULT_BUFFER_SIZE;
 
946
 
 
947
  /* device can not be tuned during read */
 
948
  g_mutex_lock (object->tune_mutex);
 
949
 
 
950
 
 
951
  if (object->fd_dvr > -1) {
 
952
    /* --- Read TS from DVR device --- */
 
953
    GST_DEBUG_OBJECT (object, "Reading from DVR device");
 
954
    *buf = read_device (object->fd_dvr, object->adapter_number,
 
955
        object->frontend_number, buffer_size, object);
 
956
    if (*buf != NULL) {
 
957
      GstCaps *caps;
 
958
 
 
959
      retval = GST_FLOW_OK;
 
960
 
 
961
      caps = gst_pad_get_caps (GST_BASE_SRC_PAD (object));
 
962
      gst_buffer_set_caps (*buf, caps);
 
963
      gst_caps_unref (caps);
 
964
    } else {
 
965
      GST_DEBUG_OBJECT (object, "Failed to read from device");
 
966
      gst_element_post_message (GST_ELEMENT_CAST (object),
 
967
          gst_message_new_element (GST_OBJECT (object),
 
968
              gst_structure_empty_new ("dvb-read-failure")));
 
969
    }
 
970
 
 
971
    if (object->stats_interval != 0 &&
 
972
        ++object->stats_counter == object->stats_interval) {
 
973
      gst_dvbsrc_output_frontend_stats (object);
 
974
      object->stats_counter = 0;
 
975
    }
 
976
  }
 
977
 
 
978
  g_mutex_unlock (object->tune_mutex);
 
979
  return retval;
 
980
 
 
981
}
 
982
 
 
983
static GstStateChangeReturn
 
984
gst_dvbsrc_change_state (GstElement * element, GstStateChange transition)
 
985
{
 
986
  GstDvbSrc *src;
 
987
  GstStateChangeReturn ret;
 
988
 
 
989
  src = GST_DVBSRC (element);
 
990
  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 
991
 
 
992
  switch (transition) {
 
993
    case GST_STATE_CHANGE_NULL_TO_READY:
 
994
      /* open frontend then close it again, just so caps sent */
 
995
      gst_dvbsrc_open_frontend (src);
 
996
      if (src->fd_frontend) {
 
997
        close (src->fd_frontend);
 
998
      }
 
999
      break;
 
1000
    default:
 
1001
      break;
 
1002
  }
 
1003
 
 
1004
  return ret;
 
1005
}
 
1006
 
 
1007
 
 
1008
static gboolean
 
1009
gst_dvbsrc_start (GstBaseSrc * bsrc)
 
1010
{
 
1011
  GstDvbSrc *src = GST_DVBSRC (bsrc);
 
1012
 
 
1013
  gst_dvbsrc_open_frontend (src);
 
1014
  if (!gst_dvbsrc_tune (src)) {
 
1015
    GST_ERROR_OBJECT (src, "Not able to lock on to the dvb channel");
 
1016
    close (src->fd_frontend);
 
1017
    return FALSE;
 
1018
  }
 
1019
  if (!gst_dvbsrc_frontend_status (src)) {
 
1020
    /* unset filters also */
 
1021
    gst_dvbsrc_unset_pes_filters (src);
 
1022
    close (src->fd_frontend);
 
1023
    return FALSE;
 
1024
  }
 
1025
  if (!gst_dvbsrc_open_dvr (src)) {
 
1026
    GST_ERROR_OBJECT (src, "Not able to open dvr_device");
 
1027
    /* unset filters also */
 
1028
    gst_dvbsrc_unset_pes_filters (src);
 
1029
    close (src->fd_frontend);
 
1030
    return FALSE;
 
1031
  }
 
1032
 
 
1033
  return TRUE;
 
1034
}
 
1035
 
 
1036
static gboolean
 
1037
gst_dvbsrc_stop (GstBaseSrc * bsrc)
 
1038
{
 
1039
  GstDvbSrc *src = GST_DVBSRC (bsrc);
 
1040
 
 
1041
  gst_dvbsrc_close_devices (src);
 
1042
  return TRUE;
 
1043
}
 
1044
 
 
1045
static gboolean
 
1046
gst_dvbsrc_unlock (GstBaseSrc * bsrc)
 
1047
{
 
1048
  return TRUE;
 
1049
}
 
1050
 
 
1051
static gboolean
 
1052
gst_dvbsrc_is_seekable (GstBaseSrc * bsrc)
 
1053
{
 
1054
  return FALSE;
 
1055
}
 
1056
 
 
1057
static gboolean
 
1058
gst_dvbsrc_get_size (GstBaseSrc * src, guint64 * size)
 
1059
{
 
1060
  return FALSE;
 
1061
}
 
1062
 
 
1063
static void
 
1064
gst_dvbsrc_output_frontend_stats (GstDvbSrc * src)
 
1065
{
 
1066
  fe_status_t status;
 
1067
  uint16_t snr, _signal;
 
1068
  uint32_t ber, uncorrected_blocks;
 
1069
  GstMessage *message;
 
1070
  GstStructure *structure;
 
1071
  int fe_fd = src->fd_frontend;
 
1072
 
 
1073
  ioctl (fe_fd, FE_READ_STATUS, &status);
 
1074
  ioctl (fe_fd, FE_READ_SIGNAL_STRENGTH, &_signal);
 
1075
  ioctl (fe_fd, FE_READ_SNR, &snr);
 
1076
  ioctl (fe_fd, FE_READ_BER, &ber);
 
1077
  ioctl (fe_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks);
 
1078
 
 
1079
  structure = gst_structure_new ("dvb-frontend-stats", "status", G_TYPE_INT,
 
1080
      status, "signal", G_TYPE_INT, _signal, "snr", G_TYPE_INT, snr,
 
1081
      "ber", G_TYPE_INT, ber, "unc", G_TYPE_INT, uncorrected_blocks,
 
1082
      "lock", G_TYPE_BOOLEAN, status & FE_HAS_LOCK, NULL);
 
1083
  message = gst_message_new_element (GST_OBJECT (src), structure);
 
1084
  gst_element_post_message (GST_ELEMENT (src), message);
 
1085
}
 
1086
 
 
1087
static gboolean
 
1088
gst_dvbsrc_frontend_status (GstDvbSrc * object)
 
1089
{
 
1090
  fe_status_t status = 0;
 
1091
  gint i;
 
1092
 
 
1093
  GST_INFO_OBJECT (object, "gst_dvbsrc_frontend_status\n");
 
1094
 
 
1095
  if (object->fd_frontend < 0) {
 
1096
    GST_ERROR_OBJECT (object,
 
1097
        "Trying to get frontend status from not opened device!");
 
1098
    return FALSE;
 
1099
  } else
 
1100
    GST_INFO_OBJECT (object, "fd-frontend: %d", object->fd_frontend);
 
1101
 
 
1102
  for (i = 0; i < 15; i++) {
 
1103
    usleep (1000000);
 
1104
    GST_INFO_OBJECT (object, ".");
 
1105
    if (ioctl (object->fd_frontend, FE_READ_STATUS, &status) == -1) {
 
1106
      GST_ERROR_OBJECT (object, "Failed reading frontend status.");
 
1107
      return FALSE;
 
1108
    }
 
1109
    gst_dvbsrc_output_frontend_stats (object);
 
1110
    if (status & FE_HAS_LOCK) {
 
1111
      break;
 
1112
    }
 
1113
  }
 
1114
 
 
1115
  if (!(status & FE_HAS_LOCK)) {
 
1116
    GST_INFO_OBJECT (object,
 
1117
        "Not able to lock to the signal on the given frequency.\n");
 
1118
    return FALSE;
 
1119
  } else
 
1120
    return TRUE;
 
1121
}
 
1122
 
 
1123
struct diseqc_cmd
 
1124
{
 
1125
  struct dvb_diseqc_master_cmd cmd;
 
1126
  uint32_t wait;
 
1127
};
 
1128
 
 
1129
static void
 
1130
diseqc_send_msg (int fd, fe_sec_voltage_t v, struct diseqc_cmd *cmd,
 
1131
    fe_sec_tone_mode_t t, fe_sec_mini_cmd_t b)
 
1132
{
 
1133
  if (ioctl (fd, FE_SET_TONE, SEC_TONE_OFF) == -1) {
 
1134
    GST_ERROR ("Setting tone to off failed");
 
1135
    return;
 
1136
  }
 
1137
 
 
1138
  if (ioctl (fd, FE_SET_VOLTAGE, v) == -1) {
 
1139
    GST_ERROR ("Setting voltage failed");
 
1140
    return;
 
1141
  }
 
1142
 
 
1143
  usleep (15 * 1000);
 
1144
  GST_LOG ("diseqc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", cmd->cmd.msg[0],
 
1145
      cmd->cmd.msg[1], cmd->cmd.msg[2], cmd->cmd.msg[3], cmd->cmd.msg[4],
 
1146
      cmd->cmd.msg[5]);
 
1147
  if (ioctl (fd, FE_DISEQC_SEND_MASTER_CMD, &cmd->cmd) == -1) {
 
1148
    GST_ERROR ("Sending diseqc command failed");
 
1149
    return;
 
1150
  }
 
1151
 
 
1152
  usleep (cmd->wait * 1000);
 
1153
  usleep (15 * 1000);
 
1154
 
 
1155
  if (ioctl (fd, FE_DISEQC_SEND_BURST, b) == -1) {
 
1156
    GST_ERROR ("Sending burst failed");
 
1157
    return;
 
1158
  }
 
1159
 
 
1160
  usleep (15 * 1000);
 
1161
 
 
1162
  if (ioctl (fd, FE_SET_TONE, t) == -1) {
 
1163
    GST_ERROR ("Setting tone failed");
 
1164
    return;
 
1165
  }
 
1166
}
 
1167
 
 
1168
 
 
1169
/* digital satellite equipment control,
 
1170
 * specification is available from http://www.eutelsat.com/
 
1171
 */
 
1172
static void
 
1173
diseqc (int secfd, int sat_no, int voltage, int tone)
 
1174
{
 
1175
  struct diseqc_cmd cmd = { {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}, 0 };
 
1176
 
 
1177
  /* param: high nibble: reset bits, low nibble set bits,
 
1178
   * bits are: option, position, polarizaion, band
 
1179
   */
 
1180
  cmd.cmd.msg[3] =
 
1181
      0xf0 | (((sat_no * 4) & 0x0f) | (tone == SEC_TONE_ON ? 1 : 0) |
 
1182
      (voltage == SEC_VOLTAGE_13 ? 0 : 2));
 
1183
  /* send twice because some diseqc switches do not respond correctly the
 
1184
   * first time */
 
1185
  diseqc_send_msg (secfd, voltage, &cmd, tone,
 
1186
      sat_no % 2 ? SEC_MINI_B : SEC_MINI_A);
 
1187
  diseqc_send_msg (secfd, voltage, &cmd, tone,
 
1188
      sat_no % 2 ? SEC_MINI_B : SEC_MINI_A);
 
1189
 
 
1190
}
 
1191
 
 
1192
 
 
1193
static gboolean
 
1194
gst_dvbsrc_tune (GstDvbSrc * object)
 
1195
{
 
1196
#if DVB_API_VERSION == 3 && DVB_API_VERSION_MINOR == 3
 
1197
  struct dvbfe_params feparams;
 
1198
#else
 
1199
  struct dvb_frontend_parameters feparams;
 
1200
#endif
 
1201
  fe_sec_voltage_t voltage;
 
1202
  fe_status_t status;
 
1203
  int i;
 
1204
  int j;
 
1205
  unsigned int freq = object->freq;
 
1206
  unsigned int sym_rate = object->sym_rate * 1000;
 
1207
 
 
1208
  /* found in mail archive on linuxtv.org
 
1209
   * What works well for us is:
 
1210
   * - first establish a TS feed (i.e. tune the frontend and check for success)
 
1211
   * - then set filters (PES/sections)
 
1212
   * - then tell the MPEG decoder to start
 
1213
   * - before tuning: first stop the MPEG decoder, then stop all filters  
 
1214
   */
 
1215
  GST_INFO_OBJECT (object, "gst_dvbsrc_tune");
 
1216
 
 
1217
  if (object->fd_frontend < 0) {
 
1218
    /* frontend not opened yet, tune later */
 
1219
    GST_INFO_OBJECT (object, "Frontend not open: tuning later");
 
1220
    return FALSE;
 
1221
  }
 
1222
 
 
1223
  gst_dvbsrc_unset_pes_filters (object);
 
1224
  for (j = 0; j < 5; j++) {
 
1225
    switch (object->adapter_type) {
 
1226
      case FE_QPSK:
 
1227
        object->tone = SEC_TONE_OFF;
 
1228
        if (freq > 2200000) {
 
1229
          // this must be an absolute frequency
 
1230
          if (freq < SLOF) {
 
1231
            feparams.frequency = (freq - LOF1);
 
1232
          } else {
 
1233
            feparams.frequency = (freq - LOF2);
 
1234
            object->tone = SEC_TONE_ON;
 
1235
          }
 
1236
        } else {
 
1237
          // this is an L-Band frequency
 
1238
          feparams.frequency = freq;
 
1239
        }
 
1240
        feparams.inversion = INVERSION_AUTO;
 
1241
        GST_DEBUG_OBJECT (object, "api version %d.%d", DVB_API_VERSION,
 
1242
            DVB_API_VERSION_MINOR);
 
1243
#if DVB_API_VERSION == 3 && DVB_API_VERSION_MINOR == 3
 
1244
        GST_DEBUG_OBJECT (object, "using multiproto driver");
 
1245
        feparams.delsys.dvbs.symbol_rate = sym_rate;
 
1246
        feparams.delsys.dvbs.fec = object->code_rate_hp;
 
1247
#else
 
1248
        feparams.u.qpsk.symbol_rate = sym_rate;
 
1249
        feparams.u.qpsk.fec_inner = object->code_rate_hp;
 
1250
#endif
 
1251
        GST_INFO_OBJECT (object,
 
1252
            "tuning DVB-S to L-Band:%u, Pol:%d, srate=%u, 22kHz=%s",
 
1253
            feparams.frequency, object->pol, sym_rate,
 
1254
            object->tone == SEC_TONE_ON ? "on" : "off");
 
1255
 
 
1256
        if (object->pol == DVB_POL_H)
 
1257
          voltage = SEC_VOLTAGE_18;
 
1258
        else
 
1259
          voltage = SEC_VOLTAGE_13;
 
1260
 
 
1261
        if (object->diseqc_src == -1 || object->send_diseqc == FALSE) {
 
1262
          if (ioctl (object->fd_frontend, FE_SET_VOLTAGE, voltage) < 0) {
 
1263
            g_warning ("Unable to set voltage on dvb frontend device");
 
1264
          }
 
1265
 
 
1266
          if (ioctl (object->fd_frontend, FE_SET_TONE, object->tone) < 0) {
 
1267
            g_warning ("Error setting tone: %s", strerror (errno));
 
1268
          }
 
1269
        } else {
 
1270
          GST_DEBUG_OBJECT (object, "Sending DISEqC");
 
1271
          diseqc (object->fd_frontend, object->diseqc_src, voltage,
 
1272
              object->tone);
 
1273
          /* Once diseqc source is set, do not set it again until
 
1274
           * app decides to change it */
 
1275
          //object->send_diseqc = FALSE;
 
1276
        }
 
1277
 
 
1278
        break;
 
1279
      case FE_OFDM:
 
1280
 
 
1281
        feparams.frequency = freq;
 
1282
#if DVB_API_VERSION == 3 && DVB_API_VERSION_MINOR == 3
 
1283
#else
 
1284
        feparams.u.ofdm.bandwidth = object->bandwidth;
 
1285
        feparams.u.ofdm.code_rate_HP = object->code_rate_hp;
 
1286
        feparams.u.ofdm.code_rate_LP = object->code_rate_lp;
 
1287
        feparams.u.ofdm.constellation = object->modulation;
 
1288
        feparams.u.ofdm.transmission_mode = object->transmission_mode;
 
1289
        feparams.u.ofdm.guard_interval = object->guard_interval;
 
1290
        feparams.u.ofdm.hierarchy_information = object->hierarchy_information;
 
1291
#endif
 
1292
        feparams.inversion = object->inversion;
 
1293
 
 
1294
        GST_INFO_OBJECT (object, "tuning DVB-T to %d Hz\n", freq);
 
1295
        break;
 
1296
      case FE_QAM:
 
1297
        GST_INFO_OBJECT (object, "Tuning DVB-C to %d, srate=%d", freq,
 
1298
            sym_rate);
 
1299
        feparams.frequency = freq;
 
1300
        feparams.inversion = object->inversion;
 
1301
        feparams.u.qam.fec_inner = object->code_rate_hp;
 
1302
        feparams.u.qam.modulation = object->modulation;
 
1303
        feparams.u.qam.symbol_rate = sym_rate;
 
1304
        break;
 
1305
      case FE_ATSC:
 
1306
        GST_INFO_OBJECT (object, "Tuning ATSC to %d", freq);
 
1307
        feparams.frequency = freq;
 
1308
        feparams.u.vsb.modulation = object->modulation;
 
1309
        break;
 
1310
      default:
 
1311
        g_error ("Unknown frontend type: %d", object->adapter_type);
 
1312
 
 
1313
    }
 
1314
    usleep (100000);
 
1315
    /* now tune the frontend */
 
1316
#if DVB_API_VERSION == 3 && DVB_API_VERSION_MINOR == 3
 
1317
    if (ioctl (object->fd_frontend, DVBFE_SET_PARAMS, &feparams) < 0) {
 
1318
#else
 
1319
    if (ioctl (object->fd_frontend, FE_SET_FRONTEND, &feparams) < 0) {
 
1320
#endif
 
1321
      g_warning ("Error tuning channel: %s", strerror (errno));
 
1322
    }
 
1323
    for (i = 0; i < 5; i++) {
 
1324
      usleep (100000);
 
1325
      if (ioctl (object->fd_frontend, FE_READ_STATUS, &status) == -1) {
 
1326
        perror ("FE_READ_STATUS");
 
1327
        break;
 
1328
      }
 
1329
      GST_LOG_OBJECT (object, "status == 0x%02x", status);
 
1330
    }
 
1331
    if (status & FE_HAS_LOCK)
 
1332
      break;
 
1333
  }
 
1334
  if (!(status & FE_HAS_LOCK))
 
1335
    return FALSE;
 
1336
  /* set pid filters */
 
1337
  gst_dvbsrc_set_pes_filters (object);
 
1338
 
 
1339
  return TRUE;
 
1340
}
 
1341
 
 
1342
 
 
1343
static void
 
1344
gst_dvbsrc_unset_pes_filters (GstDvbSrc * object)
 
1345
{
 
1346
  int i = 0;
 
1347
 
 
1348
  GST_INFO_OBJECT (object, "clearing PES filter");
 
1349
 
 
1350
  for (i = 0; i < MAX_FILTERS; i++) {
 
1351
    if (object->fd_filters[i] == -1)
 
1352
      continue;
 
1353
    close (object->fd_filters[i]);
 
1354
    object->fd_filters[i] = -1;
 
1355
  }
 
1356
}
 
1357
 
 
1358
static void
 
1359
gst_dvbsrc_set_pes_filters (GstDvbSrc * object)
 
1360
{
 
1361
  int *fd;
 
1362
  int pid, i;
 
1363
  struct dmx_pes_filter_params pes_filter;
 
1364
  gchar *demux_dev = g_strdup_printf ("/dev/dvb/adapter%d/demux%d",
 
1365
      object->adapter_number, object->frontend_number);
 
1366
 
 
1367
  GST_INFO_OBJECT (object, "Setting PES filter");
 
1368
 
 
1369
  for (i = 0; i < MAX_FILTERS; i++) {
 
1370
    if (object->pids[i] == G_MAXUINT16)
 
1371
      break;
 
1372
 
 
1373
    fd = &object->fd_filters[i];
 
1374
    pid = object->pids[i];
 
1375
 
 
1376
    close (*fd);
 
1377
    if ((*fd = open (demux_dev, O_RDWR)) < 0) {
 
1378
      g_error ("Error opening demuxer: %s (%s)", strerror (errno), demux_dev);
 
1379
      g_free (demux_dev);
 
1380
    }
 
1381
    g_return_if_fail (*fd != -1);
 
1382
 
 
1383
    pes_filter.pid = pid;
 
1384
    pes_filter.input = DMX_IN_FRONTEND;
 
1385
    pes_filter.output = DMX_OUT_TS_TAP;
 
1386
    pes_filter.pes_type = DMX_PES_OTHER;
 
1387
    pes_filter.flags = DMX_IMMEDIATE_START;
 
1388
 
 
1389
    GST_INFO_OBJECT (object, "Setting pes-filter, pid = %d, type = %d",
 
1390
        pes_filter.pid, pes_filter.pes_type);
 
1391
 
 
1392
    if (ioctl (*fd, DMX_SET_PES_FILTER, &pes_filter) < 0)
 
1393
      GST_WARNING_OBJECT (object, "Error setting PES filter on %s: %s",
 
1394
          demux_dev, strerror (errno));
 
1395
  }
 
1396
 
 
1397
  g_free (demux_dev);
 
1398
}