aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-03-16 20:13:28 +0000
committerGravatar arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-03-16 20:13:28 +0000
commit5c49cd8e07ca0f676f759bfb8e1e4a94636e2af6 (patch)
treed8d453ffd3502d82418494650e44a6dae9ff5359
parent79102684ed09aef64829bb0ef67469dfccf5afe3 (diff)
this is a combo patch that:
1) adds an experimental TS demuxer to mplayer 2) adds an input (streaming) interface from DVB cards. It compiles and runs with the following versions of the drivers: dvb-kernel (HEAD) (with stock kernel 2.4.20) and 0.9.4 (with kernel 2.4.18) patch by Nico <nsabbi@libero.it> some cleanups, ts demuxer fixes by me git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@9611 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r--cfg-common.h16
-rwxr-xr-xconfigure4
-rw-r--r--libmpdemux/Makefile11
-rw-r--r--libmpdemux/demux_ts.c903
-rw-r--r--libmpdemux/demuxer.c25
-rw-r--r--libmpdemux/demuxer.h3
-rw-r--r--libmpdemux/dvb_defaults.h89
-rw-r--r--libmpdemux/dvb_tune.c803
-rw-r--r--libmpdemux/dvbin.c684
-rw-r--r--libmpdemux/dvbin.h102
-rw-r--r--libmpdemux/open.c24
-rw-r--r--libmpdemux/stream.c15
-rw-r--r--libmpdemux/stream.h1
-rw-r--r--libmpdemux/video.c4
-rw-r--r--mencoder.c2
-rw-r--r--mplayer.c38
16 files changed, 2714 insertions, 10 deletions
diff --git a/cfg-common.h b/cfg-common.h
index ac222efd6f..7f5c0ce8f7 100644
--- a/cfg-common.h
+++ b/cfg-common.h
@@ -64,8 +64,8 @@
{"forceidx", &index_mode, CONF_TYPE_FLAG, 0, -1, 2, NULL},
// select audio/videosubtitle stream
- {"aid", &audio_id, CONF_TYPE_INT, CONF_RANGE, 0, 255, NULL},
- {"vid", &video_id, CONF_TYPE_INT, CONF_RANGE, 0, 255, NULL},
+ {"aid", &audio_id, CONF_TYPE_INT, CONF_RANGE, 0, 8192, NULL},
+ {"vid", &video_id, CONF_TYPE_INT, CONF_RANGE, 0, 8192, NULL},
{"sid", &dvdsub_id, CONF_TYPE_INT, CONF_RANGE, 0, 31, NULL},
{ "hr-mp3-seek", &hr_mp3_seek, CONF_TYPE_FLAG, 0, 0, 1, NULL },
@@ -94,6 +94,10 @@
{"tv", "MPlayer was compiled without TV Interface support\n", CONF_TYPE_PRINT, 0, 0, 0, NULL},
#endif
{"vivo", vivoopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
+#ifdef HAS_DVBIN_SUPPORT
+ {"dvbin", dvbin_opts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
+#endif
+
// ------------------------- a-v sync options --------------------
@@ -164,6 +168,7 @@
{"flip", &flip, CONF_TYPE_FLAG, 0, -1, 1, NULL},
{"noflip", &flip, CONF_TYPE_FLAG, 0, -1, 0, NULL},
+ {"tsfastparse", &ts_fastparse, CONF_TYPE_INT, 0, 0, 0, NULL},
#ifdef USE_LIBAVCODEC
{"lavdopts", lavc_decode_opts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
@@ -243,6 +248,7 @@ extern config_t cdda_opts[];
extern char* audio_stream;
extern char* sub_stream;
extern int demuxer_type, audio_demuxer_type, sub_demuxer_type;
+extern int ts_fastparse;
#include "libmpdemux/tv.h"
@@ -290,6 +296,12 @@ struct config tvopts_conf[]={
};
#endif
+#ifdef HAS_DVBIN_SUPPORT
+#include "libmpdemux/dvbin.h"
+extern struct config dvbin_opts_conf[];
+#endif
+
+
extern int sws_chr_vshift;
extern int sws_chr_hshift;
extern float sws_chr_gblur;
diff --git a/configure b/configure
index e2621b40da..738aed2753 100755
--- a/configure
+++ b/configure
@@ -2848,6 +2848,7 @@ else
fi
if test "$_dvb" = yes ; then
_def_dvb='#define HAVE_DVB 1'
+ _def_dvb_in='#define HAS_DVBIN_SUPPORT 1'
_aomodules="mpegpes(dvb) $_aomodules"
_vomodules="mpegpes(dvb) $_vomodules"
fi
@@ -2888,12 +2889,14 @@ EOF
fi
if test "$_dvbhead" = yes ; then
_def_dvb='#define HAVE_DVB_HEAD 1'
+ _def_dvb_in='#define HAS_DVBIN_SUPPORT 1'
_aomodules="mpegpes(dvb) $_aomodules"
_vomodules="mpegpes(dvb) $_vomodules"
fi
fi
if test "$_dvbhead" = no && test "$_dvb" = no ; then
_def_dvb='#undef HAVE_DVB'
+ _def_dvb_in='#undef HAS_DVBIN_SUPPORT '
_aomodules="mpegpes(file) $_aomodules"
_vomodules="mpegpes(file) $_vomodules"
fi
@@ -5497,6 +5500,7 @@ $_def_fbdev_nocopy
$_def_dxr2
$_def_dxr3
$_def_dvb
+$_def_dvb_in
$_def_svga
$_def_vesa
$_def_xdpms
diff --git a/libmpdemux/Makefile b/libmpdemux/Makefile
index 42d2ca21cf..a1ce08ffe7 100644
--- a/libmpdemux/Makefile
+++ b/libmpdemux/Makefile
@@ -3,7 +3,7 @@ LIBNAME = libmpdemux.a
include ../config.mak
-SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c muxer.c muxer_avi.c muxer_mpeg.c demux_asf.c demux_avi.c demux_mov.c parse_mp4.c demux_mpg.c demux_pva.c demux_viv.c demuxer.c dvdauth.c dvdnav_stream.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c tvi_bsdbt848.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c demux_ogg.c demux_bmp.c cdda.c demux_rawaudio.c demux_rawvideo.c cddb.c cdinfo.c demux_rawdv.c ai_alsa.c ai_oss.c audio_in.c demux_smjpeg.c cue_read.c extension.c demux_gif.c
+SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c muxer.c muxer_avi.c muxer_mpeg.c demux_asf.c demux_avi.c demux_mov.c parse_mp4.c demux_mpg.c demux_pva.c demux_viv.c demuxer.c dvdauth.c dvdnav_stream.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c tvi_bsdbt848.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c demux_ogg.c demux_bmp.c cdda.c demux_rawaudio.c demux_rawvideo.c cddb.c cdinfo.c demux_rawdv.c ai_alsa.c ai_oss.c audio_in.c demux_smjpeg.c cue_read.c extension.c demux_gif.c demux_ts.c
ifeq ($(XMMS_PLUGINS),yes)
SRCS += demux_xmms.c
endif
@@ -20,6 +20,15 @@ SRCS += rtp.c
endif
endif
+DVBIN = yes
+ifeq ($(DVBIN),yes)
+SRCS += dvbin.c
+SRCS += dvb_tune.c
+endif
+
+
+
+
OBJS = $(SRCS:.c=.o)
OBJS += $(CPLUSPLUSSRCS:.cpp=.o)
INCLUDE = -I../loader $(CSS_INC) $(EXTRA_INC)
diff --git a/libmpdemux/demux_ts.c b/libmpdemux/demux_ts.c
new file mode 100644
index 0000000000..a718a17da7
--- /dev/null
+++ b/libmpdemux/demux_ts.c
@@ -0,0 +1,903 @@
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine 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 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
+ *
+ * $Id$
+ *
+ * Demultiplexer for MPEG2 Transport Streams.
+ *
+ * For the purposes of playing video, we make some assumptions about the
+ * kinds of TS we have to process. The most important simplification is to
+ * assume that the TS contains a single program (SPTS) because this then
+ * allows significant simplifications to be made in processing PATs.
+
+
+
+ /*
+ * WARNING: Quite a hack was required in order to get files by MultiDec played back correctly.
+ * If it breaks anything else, just comment out the "#define DEMUX_PVA_MULTIDEC_HACK" below
+ * and it will not be compiled in.
+ *
+ * Feedback is appreciated.
+ *
+ * written by Matteo Giani
+ */
+
+
+/*
+ * MPEG2 transport stream (aka DVB) demux
+ * Copyright (c) 2002 Fabrice Bellard.
+ *
+ * This library 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 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "stream.h"
+#include "demuxer.h"
+#include "stheader.h"
+
+#include "bswap.h"
+
+
+typedef struct {
+ off_t offset;
+ long size;
+ uint8_t type;
+ uint8_t is_packet_start;
+ float pts;
+ uint8_t packet_size;
+} ts_payload_t;
+
+
+typedef struct {
+ float last_audio_pts;
+ float last_video_pts;
+ uint8_t just_synced;
+ uint8_t synced_stream_id;
+ char *buffer;
+ int buffer_size;
+ int buffer_offset;
+ int packet_size;
+} ts_priv_t;
+
+#define TS_FEC_PACKET_SIZE 204
+#define TS_PACKET_SIZE 188
+#define NB_PID_MAX 8192
+
+#define MAX_HEADER_SIZE 6 /* enough for PES header + length */
+#define MAX_PROBE_SIZE 1000000
+#define NUM_CONSECUTIVE_TS_PACKETS 5
+
+
+enum MpegTSState {
+ MPEGTS_HEADER = 0,
+ MPEGTS_PESHEADER_FILL,
+ MPEGTS_PESHEADER_FLAGS,
+ MPEGTS_PESHEADER_SIZE,
+ MPEGTS_PESHEADER_READ,
+ MPEGTS_PAYLOAD,
+ MPEGTS_SKIP,
+};
+
+
+int ts_fastparse = 0;
+
+typedef enum
+{
+ UNKNOWN = -1,
+ VIDEO_MPEG2 = 0x10000002,
+ AUDIO_MP2 = 0x50,
+ AUDIO_A52 = 0x2000,
+ AUDIO_LPCM_BE = 0x2000000,
+ SPU_DVD = 0x3000000,
+ SPU_DVB = 0x3000001,
+} es_stream_type_t;
+
+typedef struct MpegTSStream // IT'S AN ES
+{
+ int pid;
+ enum MpegTSState state;
+ int last_cc; /* last cc code (-1 if first packet) */
+ /* used to get the format */
+ int header_size;
+ int payload_size;
+ int pes_header_size;
+ //AVStream *st;
+ es_stream_type_t type;
+ unsigned char header[MAX_HEADER_SIZE];
+ char *pes_buffer;
+ int offset;
+ float pts;
+ float last_pts;
+} MpegTSStream;
+
+
+typedef struct MpegTSContext {
+ int raw_packet_size; /* raw packet size, including FEC if present */
+ MpegTSStream *pids[NB_PID_MAX];
+ demuxer_t *demuxer;
+} MpegTSContext;
+
+
+typedef struct {
+ int size;
+ unsigned char *start;
+ es_stream_type_t type;
+ float pts;
+ int pid;
+} ES_info_t;
+
+MpegTSContext ts;
+
+//FILE *outfile;
+
+
+static uint8_t get_packet_size(const unsigned char *buf, int size)
+{
+ int i;
+
+ if (size < (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS))
+ return 0;
+
+ for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++)
+ {
+ if (buf[i * TS_PACKET_SIZE] != 0x47)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "GET_PACKET_SIZE, pos %d, char: %2x\n", i, buf[i * TS_PACKET_SIZE]);
+ goto try_fec;
+ }
+ }
+ return TS_PACKET_SIZE;
+
+ try_fec:
+ for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++)
+ {
+ if (buf[i * TS_FEC_PACKET_SIZE] != 0x47)
+ return 0;
+ }
+ return TS_FEC_PACKET_SIZE;
+}
+
+
+
+
+int ts_check_file(demuxer_t * demuxer)
+{
+ const int buf_size = (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS);
+ char buf[buf_size], c, done = 0;
+ uint32_t _read, i=1;
+ uint8_t size = 0;
+ off_t pos = 0;
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "************Checking for TS************\n");
+
+ while(! done)
+ {
+ while(((c=stream_read_char(demuxer->stream)) != 0x47)
+ && (i < MAX_PROBE_SIZE)
+ && ! demuxer->stream->eof
+ ) i++;
+
+ if(c != 0x47)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "NOT A TS FILE1\n");
+ done = 1;
+ continue;
+ }
+
+ pos = stream_tell(demuxer->stream) - 1;
+ buf[0] = c;
+ _read = stream_read(demuxer->stream, &buf[1], buf_size-1);
+
+ if(_read < buf_size-1)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "COULDN'T READ ENOUGH DATA, EXITING TS_CHECK\n");
+ stream_reset(demuxer->stream);
+ return 0;
+ }
+
+ size = get_packet_size(buf, buf_size);
+ if(size)
+ done = 1;
+ }
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "TRIED UP TO POSITION %u, FUOND %x, packet_size= %d\n", i, c, size);
+ stream_seek(demuxer->stream, pos);
+ return size;
+}
+
+
+
+
+
+demuxer_t *demux_open_ts(demuxer_t * demuxer)
+{
+ uint8_t packet_size;
+ //demuxer_t *vd, *ad;
+ //stream_t *s;
+ sh_video_t *sh_video;
+ sh_audio_t *sh_audio;
+ ts_priv_t * priv;
+ int i;
+
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "DEMUX OPEN, AUDIO_ID: %d, VIDEO_ID: %d, SUBTITLE_ID: %d,\n",
+ demuxer->audio->id, demuxer->video->id, demuxer->sub->id);
+
+ for(i=0; i < 8192; i++)
+ ts.pids[i] = NULL;
+
+ demuxer->type= DEMUXER_TYPE_MPEG_TS;
+
+ stream_reset(demuxer->stream);
+ stream_seek(demuxer->stream, 0);
+
+ packet_size = ts_check_file(demuxer);
+ if(!packet_size)
+ return NULL;
+
+ priv = malloc(sizeof(ts_priv_t));
+ priv->last_video_pts=-1;
+ priv->last_audio_pts=-1;
+ priv->packet_size = packet_size;
+ demuxer->priv = priv;
+
+ if(demuxer->stream->type != STREAMTYPE_FILE) demuxer->seekable=0;
+ else demuxer->seekable = 1;
+
+
+ sh_video = new_sh_video(demuxer, 0);
+ sh_video->ds = demuxer->video;
+ demuxer->video->sh = sh_video;
+
+
+
+ sh_audio = new_sh_audio(demuxer, 0);
+ sh_audio->ds = demuxer->audio;
+ demuxer->audio->sh = sh_audio;
+
+
+ mp_msg(MSGT_DEMUXER,MSGL_INFO, "Opened TS demuxer...");
+
+ if(! ts_fastparse)
+ ts_detect_streams(demuxer);
+
+
+ /*
+ demuxer->movi_start = 0;
+ demuxer->movi_end = demuxer->stream->end_pos;
+ */
+
+
+ /*
+ s= new_ds_stream(demuxer->video);
+ return demux_open_stream(s, DEMUXER_TYPE_MPEG_ES, demuxer->audio->id, demuxer->video->id, demuxer->sub->id, NULL);
+ */
+
+ stream_seek(demuxer->stream, 0); //IF IT'S FROM A PIPE IT WILL FAIL, BUT WHO CARES?
+ return demuxer;
+}
+
+
+
+void ts_detect_streams(demuxer_t *demuxer)
+{
+ int video_found = 0, audio_found = 0;
+ off_t pos=0;
+ ES_info_t es;
+ int *apid, *vpid, *spid;
+ unsigned char tmp[TS_FEC_PACKET_SIZE];
+ sh_video_t *sh_video = demuxer->video->sh;
+ sh_audio_t *sh_audio = demuxer->audio->sh;
+
+ apid = &(demuxer->audio->id);
+ vpid = &(demuxer->video->id);
+ spid = &(demuxer->sub->id);
+
+
+ mp_msg(MSGT_DEMUXER, MSGL_INFO, "PROBING UP TO %u\n", MAX_PROBE_SIZE);
+ while(pos <= MAX_PROBE_SIZE)
+ {
+ if(ts_parse(demuxer, &es, tmp))
+ {
+ mp_msg(MSGT_DEMUXER, MSGL_V, "TYPE: %x, PID: %d\n", es.type, es.pid);
+ if(es.type == VIDEO_MPEG2)
+ {
+ sh_video->format = VIDEO_MPEG2; //MPEG2 video
+ if(*vpid == -1)
+ *vpid = es.pid;
+ video_found = 1;
+ }
+
+ if(es.type == AUDIO_MP2)
+ {
+ sh_audio->format = AUDIO_MP2; //MPEG1L2 audio
+ if(*apid == -1)
+ *apid = es.pid;
+ audio_found = 1;
+ }
+
+ if(es.type == AUDIO_A52)
+ {
+ sh_audio->format = AUDIO_MP2; //MPEG1L2 audio
+ if(*apid == -1)
+ *apid = es.pid;
+ audio_found = 1;
+ }
+
+ pos = stream_tell(demuxer->stream);
+ if(video_found && audio_found)
+ break;
+ }
+ }
+
+ if(video_found)
+ mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG2...");
+ else
+ {
+ *vpid = -2; //WE DIDN'T MATCH ANY VIDEO STREAM, SO WE FORCE THE DEMUXER TO IGNORE VIDEO
+ mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO VIDEO!\n");
+ }
+
+ if(sh_audio->format == AUDIO_MP2)
+ mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO MP2\n");
+ else if(sh_audio->format == AUDIO_A52)
+ mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO A52\n");
+ else
+ {
+ *apid = -2; //WE DIDN'T MATCH ANY AUDIO STREAM, SO WE FORCE THE DEMUXER TO IGNORE AUDIO
+ mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO AUDIO!\n");
+ }
+}
+
+
+void demux_close_ts(demuxer_t * demuxer)
+{
+ if(demuxer->priv)
+ {
+ free(demuxer->priv);
+ demuxer->priv=NULL;
+ }
+}
+
+
+
+
+//MpegTSStream *tss, const unsigned char *buf, int buf_size, int is_start, ES_info_t *es
+static int pes_parse2(MpegTSStream *tss, unsigned char *buf, uint16_t packet_len, int is_start, ES_info_t *es)
+{
+ unsigned char *p;
+ uint32_t header_len;
+ int64_t pts;
+ uint32_t stream_id;
+ uint32_t pkt_len;
+
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2(%X, %X, %d, %d, ): \n", tss, buf, packet_len, is_start);
+
+ if(packet_len == 0)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2(,PACKET_LEN = 0, EXIT\n");
+ return 0;
+ }
+
+ if(packet_len > 184)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2, BUFFER LEN IS TOO BIG: %d, EXIT\n", packet_len);
+ return 0;
+ }
+
+
+ p = buf;
+ pkt_len = packet_len;
+
+ if(! is_start)
+ {
+ tss->pts = tss->last_pts;
+ es->start = p;
+ es->size = packet_len;
+ return es->size;
+ }
+
+ /* we should have a PES packet here */
+
+ if (p[0] || p[1] || (p[2] != 1))
+ {
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: error HEADER %02x %02x %02x (should be 0x000001) \n", p[0], p[1], p[2]);
+ return 0 ;
+ }
+
+ packet_len -= 6;
+
+ tss->payload_size = p[4] << 8 | p[5];
+ if (tss->payload_size == 0)
+ tss->payload_size = 65536;
+
+ stream_id = p[3];
+
+ if(packet_len==0)
+ return 0;
+
+ //mp_msg(MSGT_DEMUX, MSGL_V, "pes_parse2: packet stream id: %.2X (%d) len: %d (%x)\n", stream_id, stream_id, packet_len, packet_len);
+
+ if (p[7] & 0x80)
+ { /* pts avail */
+ pts = (int64_t)(p[9] & 0x0E) << 29 ;
+ pts |= p[10] << 22 ;
+ pts |= (p[11] & 0xFE) << 14 ;
+ pts |= p[12] << 7 ;
+ pts |= (p[13] & 0xFE) >> 1 ;
+
+ tss->pts = tss->last_pts = pts / 90000.0f;
+ }
+ else
+ tss->pts = tss->last_pts;
+
+ header_len = p[8];
+
+ /* sometimes corruption on header_len causes segfault in memcpy below */
+ if (header_len + 9 > pkt_len)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "demux_ts: illegal value for PES_header_data_length (0x%02x)\n", header_len);
+ return 0;
+ }
+
+ p += header_len + 9;
+ packet_len -= header_len + 3;
+
+ if (stream_id == 0xbd)
+ {
+ int track, spu_id;
+
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: audio buf = %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+
+ track = p[0] & 0x0F; /* hack : ac3 track */
+ /*
+ * we check the descriptor tag first because some stations
+ * do not include any of the ac3 header info in their audio tracks
+ * these "raw" streams may begin with a byte that looks like a stream type.
+ */
+ if( //(m->descriptor_tag == 0x81) || /* ac3 - raw */
+ (p[0] == 0x0B && p[1] == 0x77)) /* ac3 - syncword */
+ {
+ es->start = p;
+ es->size = packet_len;
+ tss->type = AUDIO_A52;
+ return es->size;
+ }
+ else if (//m->descriptor_tag == 0x06 &&
+ p[0] == 0x20 && p[1] == 0x00)
+ {
+ /* DVBSUB */
+ long payload_len = ((buf[4] << 8) | buf[5]) - header_len - 3;
+ es->start = p;
+ es->size = packet_len;
+ tss->type = SPU_DVB + payload_len;
+
+ return es->size;
+ }
+ else if ((p[0] & 0xE0) == 0x20)
+ {
+ spu_id = (p[0] & 0x1f);
+ es->start = p+1;
+ es->size = packet_len-1;
+ tss->type = SPU_DVD + spu_id;
+ return es->size;
+ }
+ else if ((p[0] & 0xF0) == 0x80)
+ {
+ es->start = p+4;
+ es->size = packet_len - 4;
+ tss->type = AUDIO_A52; // + track;
+ return es->size;
+ }
+ else if ((p[0]&0xf0) == 0xa0)
+ {
+ int pcm_offset;
+
+ for (pcm_offset=0; ++pcm_offset < packet_len-1 ; )
+ {
+ if (p[pcm_offset] == 0x01 && p[pcm_offset+1] == 0x80)
+ { /* START */
+ pcm_offset += 2;
+ break;
+ }
+ }
+
+ es->start = p + pcm_offset;
+ es->size = packet_len - pcm_offset;
+ tss->type = AUDIO_LPCM_BE; // + track;
+ return es->size;
+ }
+ }
+ else if ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0))
+ {
+ es->start = p;
+ es->size = packet_len;
+ tss->type = VIDEO_MPEG2;
+ return es->size;
+ }
+ else if ((stream_id & 0xe0) == 0xc0)
+ {
+ int track;
+ track = stream_id & 0x1f;
+ es->start = p;
+ es->size = packet_len;
+ tss->type = AUDIO_MP2; // + track;
+ return es->size;
+ }
+ else
+ {
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: unknown packet, id: %x\n", stream_id);
+ }
+
+ return 0;
+}
+
+
+
+
+int ts_sync(demuxer_t *demuxer)
+{
+ uint8_t c=0;
+
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "TS_SYNC \n");
+
+ while(((c=stream_read_char(demuxer->stream)) != 0x47) && ! demuxer->stream->eof);
+
+ if(c == 0x47)
+ return c;
+ else
+ return 0;
+}
+
+
+
+
+
+
+// 0 = EOF or no stream found
+// 1 = successfully read a packet
+int ts_parse(demuxer_t * demuxer , ES_info_t *es, unsigned char *packet)
+{
+ MpegTSStream *tss;
+ uint8_t done = 0;
+ ts_priv_t *priv = demuxer->priv;
+ uint16_t buf_size, is_start;
+ int len, pid, cc, cc_ok, afc;
+ unsigned char *p;
+
+ while(! done)
+ {
+ if(! ts_sync(demuxer))
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "TS_FILL_BUFFER: COULDN'T SYNC\n");
+ return 0;
+ }
+
+ len = stream_read(demuxer->stream, &packet[1], priv->packet_size-1);
+ if (len != priv->packet_size-1)
+ return 0;
+
+
+
+ pid = ((packet[1] & 0x1f) << 8) | packet[2];
+ tss = ts.pids[pid]; //an ES stream
+ if(tss == NULL)
+ {
+ /* if no pid found, then add a pid context */
+ tss = malloc(sizeof(MpegTSStream));
+ if (!tss)
+ continue;
+ memset(tss, 0, sizeof(MpegTSStream));
+ ts.pids[pid] = tss;
+ tss->pid = pid;
+ tss->last_cc = -1;
+ tss->type = UNKNOWN;
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "new TS pid=%u\n", pid);
+ }
+
+ cc = (packet[3] & 0xf);
+ cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc));
+ if(! cc_ok)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "ts_parse: CCCheck NOT OK: %d -> %d\n", tss->last_cc, cc);
+ }
+ tss->last_cc = cc;
+
+
+
+ /* skip adaptation field */
+ afc = (packet[3] >> 4) & 3;
+ p = packet + 4;
+ if (afc == 0) /* reserved value */
+ continue;
+ if (afc == 2) /* adaptation field only */
+ continue;
+ if (afc == 3)
+ {
+ /* skip adapation field */
+ p += p[0] + 1;
+ }
+ /* if past the end of packet, ignore */
+ if (p >= packet + TS_PACKET_SIZE)
+ continue;
+
+ // PES CONTENT STARTS HERE
+
+ buf_size = TS_PACKET_SIZE - (p - packet);
+
+ is_start = packet[1] & 0x40;
+ if((len = pes_parse2(tss, p, buf_size, is_start, es)))
+ {
+ tss->offset += es->size;
+ es->pid = tss->pid;
+ es->pts = tss->pts;
+ es->type = tss->type;
+
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "ts_parse, type=%X, start=%X, len=%d\n", tss->type, es->start, es->size);
+
+ return len;
+ }
+ }
+
+ return 0;
+}
+
+
+int demux_ts_fill_buffer(demuxer_t * demuxer)
+{
+ ES_info_t es;
+ demux_packet_t *dp;
+ int len;
+ unsigned char packet[TS_FEC_PACKET_SIZE];
+ int *apid, *vpid, *spid;
+
+ apid = &(demuxer->audio->id);
+ vpid = &(demuxer->video->id);
+ spid = &(demuxer->sub->id);
+
+ while(len = ts_parse(demuxer, &es, packet))
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "NEW_FILL_BUFFER, NEW_ADD_PACKET(%x, %d) type: %x, PTS: %f\n", es.start, es.size, es.type, es.pts);
+
+ if(es.type == VIDEO_MPEG2)
+ {
+ if(ts_fastparse)
+ {
+ if(*vpid == -2)
+ continue;
+
+ if(*vpid == -1)
+ *vpid = es.pid;
+ }
+
+ if(*vpid != es.pid)
+ continue;
+
+ dp = new_demux_packet(es.size);
+ if(! dp || ! dp->buffer)
+ {
+ fprintf(stderr, "fill_buffer, NEW_ADD_PACKET(%d) FAILED\n", es.size);
+ continue;
+ }
+ memcpy(dp->buffer, es.start, es.size);
+ dp->pts = es.pts;
+ dp->flags = 0;
+ dp->pos = stream_tell(demuxer->stream);
+ ds_add_packet(demuxer->video, dp);
+ mp_msg(MSGT_DEMUX, MSGL_V, "VIDEO pts=%f\n", es.pts);
+ return len;
+ }
+
+ if((es.type == AUDIO_MP2) || (es.type == AUDIO_A52))
+ {
+ if(ts_fastparse)
+ {
+ if(*apid == -2)
+ continue;
+
+ if(*apid == -1)
+ *apid = es.pid;
+ }
+
+ if(*apid != es.pid)
+ continue;
+
+ dp = new_demux_packet(es.size);
+ if(! dp || ! dp->buffer)
+ {
+ fprintf(stderr, "fill_buffer, NEW_ADD_PACKET(%d) FAILED\n", es.size);
+ continue;
+ }
+ memcpy(dp->buffer, es.start, es.size);
+ dp->flags = 0;
+ dp->pts = es.pts;
+ dp->pos = stream_tell(demuxer->stream);
+ ds_add_packet(demuxer->audio, dp);
+ mp_msg(MSGT_DEMUX, MSGL_V, "AUDIO pts=%f\r\n", es.pts);
+ return len;
+ }
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "SKIP--------\n");
+ }
+}
+
+
+
+
+int stringent_ts_sync(demuxer_t *demuxer)
+{
+ ts_priv_t *priv = demuxer->priv;
+ uint8_t c = 0, done = 0, i, buf[TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS];
+ off_t pos;
+
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "STRINGENT_TS_SYNC packet_size: %d\n", priv->packet_size);
+
+
+ if(! demuxer->seekable)
+ return 0;
+
+
+ while(! done)
+ {
+ while(((c=stream_read_char(demuxer->stream)) != 0x47) && !demuxer->stream->eof);
+
+ if(c != 0x47)
+ {
+ stream_reset(demuxer->stream);
+ return 0;
+ }
+
+ pos = stream_tell(demuxer->stream);
+ if(pos < 1)
+ pos = 1;
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "dopo il while, pos=%u\n", pos);
+
+ done = 1;
+ buf[0] = c;
+ stream_read(demuxer->stream, &buf[1], (priv->packet_size * NUM_CONSECUTIVE_TS_PACKETS) - 1);
+ for(i = 0; i < 5; i++)
+ {
+ if (buf[i * priv->packet_size] != 0x47)
+ done = 0;
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "i: %d, char: %x\n", i, buf[i * priv->packet_size]);
+ }
+
+ if(done)
+ stream_seek(demuxer->stream, pos);
+ else
+ stream_seek(demuxer->stream, pos);
+ }
+ //stream_seek(demuxer->stream, pos+1);
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "STRINGENT_TS_SYNC, STREAM_POS: %lu\n", stream_tell(demuxer->stream));
+ return 0x47;
+}
+
+
+extern void resync_audio_stream(sh_audio_t *);
+
+
+int demux_seek_ts(demuxer_t * demuxer, float rel_seek_secs, int flags)
+{
+ int total_bitrate=0;
+ off_t dest_offset;
+ ts_priv_t * priv = demuxer->priv;
+ int a_bps, v_bps;
+ demux_stream_t *d_audio=demuxer->audio;
+ demux_stream_t *d_video=demuxer->video;
+ sh_audio_t *sh_audio=d_audio->sh;
+ sh_video_t *sh_video=d_video->sh;
+
+
+ /*
+ * Compute absolute offset inside the stream. Approximate total bitrate with sum of bitrates
+ * reported by the audio and video codecs. The seek is not accurate because, just like
+ * with MPEG streams, the bitrate is not constant. Moreover, we do not take into account
+ * the overhead caused by PVA and PES headers.
+ * If the calculated absolute offset is negative, seek to the beginning of the file.
+ */
+
+
+ if(demuxer->audio->id != -2)
+ {
+ a_bps = ((sh_audio_t *)demuxer->audio->sh)->i_bps;
+ total_bitrate += a_bps;
+ }
+
+ if(demuxer->video->id != -2)
+ {
+ v_bps = ((sh_video_t *)demuxer->video->sh)->i_bps;
+ total_bitrate += v_bps;
+ }
+
+ if(! total_bitrate)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEEK_TS, couldn't determine bitrate, no seek\n");
+ return 0;
+ }
+
+ dest_offset = stream_tell(demuxer->stream) + rel_seek_secs*total_bitrate;
+ if(dest_offset < 0) dest_offset = 0;
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEEK TO: %f, BITRATE: %lu, FINAL_POS: %u \n", rel_seek_secs, total_bitrate, dest_offset);
+
+ stream_seek(demuxer->stream, dest_offset);
+
+ /*if(!ts_sync(demuxer))
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "demux_ts: Couldn't seek!\n");
+ return 0;
+ }
+ */
+
+ ds_fill_buffer(d_video);
+ if(sh_audio)
+ {
+ ds_fill_buffer(d_audio);
+ resync_audio_stream(sh_audio);
+ }
+
+
+ /*
+ * Reset the PTS info inside the ts_priv_t structure. This way we don't deliver
+ * data with the wrong PTSs (the ones we had before seeking).
+ *
+ */
+
+
+ priv->last_video_pts=-1;
+ priv->last_audio_pts=-1;
+
+ return 1;
+}
+
+
+
+
+
+static int mpegts_read_close(MpegTSContext *ts)
+{
+ int i;
+ for(i=0;i<NB_PID_MAX;i++)
+ free(ts->pids[i]);
+ return 0;
+}
+
+
+
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
index 49aaf92692..65fd2df5a6 100644
--- a/libmpdemux/demuxer.c
+++ b/libmpdemux/demuxer.c
@@ -134,6 +134,7 @@ extern void demux_close_pva(demuxer_t* demuxer);
extern void demux_close_smjpeg(demuxer_t* demuxer);
extern void demux_close_xmms(demuxer_t* demuxer);
extern void demux_close_gif(demuxer_t* demuxer);
+extern void demux_close_ts(demuxer_t* demuxer);
#ifdef USE_TV
#include "tv.h"
@@ -204,6 +205,8 @@ void free_demuxer(demuxer_t *demuxer){
case DEMUXER_TYPE_GIF:
demux_close_gif(demuxer); break;
#endif
+ case DEMUXER_TYPE_MPEG_TS:
+ demux_close_ts(demuxer); break;
}
// free streams:
@@ -282,6 +285,7 @@ int demux_audio_fill_buffer(demux_stream_t *ds);
int demux_pva_fill_buffer(demuxer_t *demux);
int demux_xmms_fill_buffer(demuxer_t *demux,demux_stream_t *ds);
int demux_gif_fill_buffer(demuxer_t *demux);
+int demux_ts_fill_buffer(demuxer_t *demux);
extern int demux_demuxers_fill_buffer(demuxer_t *demux,demux_stream_t *ds);
extern int demux_ogg_fill_buffer(demuxer_t *d);
@@ -334,6 +338,7 @@ int demux_fill_buffer(demuxer_t *demux,demux_stream_t *ds){
#ifdef HAVE_GIF
case DEMUXER_TYPE_GIF: return demux_gif_fill_buffer(demux);
#endif
+ case DEMUXER_TYPE_MPEG_TS: return demux_ts_fill_buffer(demux);
}
return 0;
}
@@ -560,6 +565,7 @@ extern int bmp_check_file(demuxer_t *demuxer);
extern int demux_xmms_open(demuxer_t* demuxer);
extern int gif_check_file(demuxer_t *demuxer);
extern int demux_open_gif(demuxer_t* demuxer);
+extern int ts_check_file(demuxer_t * demuxer);
extern demuxer_t* init_avi_with_ogg(demuxer_t* demuxer);
@@ -817,6 +823,17 @@ if(file_format == DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_PVA){
demuxer=NULL;
}
}
+//=============== Try to open as MPEG-TS file: =================
+if(file_format == DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MPEG_TS){
+ demuxer=new_demuxer(stream,DEMUXER_TYPE_MPEG_TS,audio_id,video_id,dvdsub_id);
+ if(ts_check_file(demuxer)) {
+ mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_Detected_XXX_FileFormat,"TS");
+ file_format=DEMUXER_TYPE_MPEG_TS;
+ } else {
+ free_demuxer(demuxer);
+ demuxer=NULL;
+ }
+}
//=============== Try to open as MPEG-PS file: =================
if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MPEG_PS){
int pes=1;
@@ -1127,6 +1144,10 @@ switch(file_format){
break;
}
#endif
+ case DEMUXER_TYPE_MPEG_TS: {
+ demux_open_ts(demuxer);
+ break;
+ }
} // switch(file_format)
pts_from_bps=0; // !!!
return demuxer;
@@ -1195,6 +1216,7 @@ int demux_seek_nuv(demuxer_t *demuxer,float rel_seek_secs,int flags);
void demux_seek_mov(demuxer_t *demuxer,float pts,int flags);
int demux_seek_real(demuxer_t *demuxer,float rel_seek_secs,int flags);
int demux_seek_pva(demuxer_t *demuxer,float rel_seek_secs,int flags);
+int demux_seek_ts(demuxer_t *demuxer,float rel_seek_secs,int flags);
#ifdef HAVE_LIBDV095
int demux_seek_rawdv(demuxer_t *demuxer, float pts, int flags);
@@ -1294,7 +1316,8 @@ switch(demuxer->file_format){
case DEMUXER_TYPE_XMMS:
demux_xmms_seek(demuxer,rel_seek_secs,flags); break;
#endif
-
+ case DEMUXER_TYPE_MPEG_TS:
+ demux_seek_ts(demuxer,rel_seek_secs,flags); break;
} // switch(demuxer->file_format)
diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h
index 0b211f30d5..2138e68a8d 100644
--- a/libmpdemux/demuxer.h
+++ b/libmpdemux/demuxer.h
@@ -37,11 +37,12 @@
#define DEMUXER_TYPE_RAWVIDEO 26
#define DEMUXER_TYPE_MPEG4_ES 27
#define DEMUXER_TYPE_GIF 28
+#define DEMUXER_TYPE_MPEG_TS 29
// This should always match the higest demuxer type number.
// Unless you want to disallow users to force the demuxer to some types
#define DEMUXER_TYPE_MIN 0
-#define DEMUXER_TYPE_MAX 28
+#define DEMUXER_TYPE_MAX 29
#define DEMUXER_TYPE_DEMUXERS (1<<16)
// A virtual demuxer type for the network code
diff --git a/libmpdemux/dvb_defaults.h b/libmpdemux/dvb_defaults.h
new file mode 100644
index 0000000000..0f56c1e8e5
--- /dev/null
+++ b/libmpdemux/dvb_defaults.h
@@ -0,0 +1,89 @@
+/* dvb_defaults.h
+
+ Provided by Tomi Ollila
+
+ Copyright (C) Dave Chapman 2002
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ 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 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.
+ Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+
+*/
+
+#ifndef _DVB_DEFAULTS_H
+#define _DVB_DEFAULTS_H
+
+/* DVB-S */
+
+// With a diseqc system you may need different values per LNB. I hope
+// no-one ever asks for that :-)
+
+#define SLOF (11700*1000UL)
+#define LOF1 (9750*1000UL)
+#define LOF2 (10600*1000UL)
+
+
+
+#ifdef FINLAND
+ /* FINLAND settings 1 */
+ #define DVB_T_LOCATION "Suomessa"
+ #define BANDWIDTH_DEFAULT BANDWIDTH_8_MHZ
+ #define HP_CODERATE_DEFAULT FEC_2_3
+ #define CONSTELLATION_DEFAULT QAM_64
+ #define TRANSMISSION_MODE_DEFAULT TRANSMISSION_MODE_8K
+ #define GUARD_INTERVAL_DEFAULT GUARD_INTERVAL_1_8
+ #define HIERARCHY_DEFAULT HIERARCHY_NONE
+#endif
+
+
+#ifdef FINLAND2
+ /* FINLAND settings 2 (someone verify there is such environment) */
+ #define DVB_T_LOCATION "Suomessa II"
+ #define BANDWIDTH_DEFAULT BANDWIDTH_8_MHZ
+ #define HP_CODERATE_DEFAULT FEC_1_2
+ #define CONSTELLATION_DEFAULT QAM_64
+ #define TRANSMISSION_MODE_DEFAULT TRANSMISSION_MODE_2K
+ #define GUARD_INTERVAL_DEFAULT GUARD_INTERVAL_1_8
+ #define HIERARCHY_DEFAULT HIERARCHY_NONE
+#endif
+
+#if defined (UK) && defined (HP_CODERATE_DEFAULT)
+ #error Multible countries defined
+#endif
+
+
+
+#ifndef DVB_T_LOCATION
+ #ifndef UK
+ #warning No DVB-T country defined in dvb_defaults.h
+ #warning defaulting to UK
+ #warning Ignore this if using Satellite or Cable
+ #endif
+
+ /* UNITED KINGDOM settings */
+ #define DVB_T_LOCATION "in United Kingdom"
+ #define BANDWIDTH_DEFAULT BANDWIDTH_8_MHZ
+ #define HP_CODERATE_DEFAULT FEC_2_3
+ #define CONSTELLATION_DEFAULT QAM_64
+ #define TRANSMISSION_MODE_DEFAULT TRANSMISSION_MODE_2K
+ #define GUARD_INTERVAL_DEFAULT GUARD_INTERVAL_1_32
+ #define HIERARCHY_DEFAULT HIERARCHY_NONE
+#endif
+
+
+#if HIERARCHY_DEFAULT == HIERARCHY_NONE && !defined (LP_CODERATE_DEFAULT)
+ #define LP_CODERATE_DEFAULT (0) /* unused if HIERARCHY_NONE */
+#endif
+
+#endif
diff --git a/libmpdemux/dvb_tune.c b/libmpdemux/dvb_tune.c
new file mode 100644
index 0000000000..147976c22f
--- /dev/null
+++ b/libmpdemux/dvb_tune.c
@@ -0,0 +1,803 @@
+/* dvbtune - tune.c
+
+ Copyright (C) Dave Chapman 2001,2002
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ 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 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.
+ Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <error.h>
+#include "config.h"
+
+#ifdef HAVE_DVB_HEAD
+ #include <linux/dvb/dmx.h>
+ #include <linux/dvb/frontend.h>
+ char* frontenddev[4]={"/dev/dvb/adapter0/frontend0","/dev/dvb/adapter1/frontend0","/dev/dvb/adapter2/frontend0","/dev/dvb/adapter3/frontend0"};
+ char* dvrdev[4]={"/dev/dvb/adapter0/dvr0","/dev/dvb/adapter1/dvr0","/dev/dvb/adapter2/dvr0","/dev/dvb/adapter3/dvr0"};
+ char* demuxdev[4]={"/dev/dvb/adapter0/demux0","/dev/dvb/adapter1/demux0","/dev/dvb/adapter2/demux0","/dev/dvb/adapter3/demux0"};
+ char* secdev[4]={"","","",""}; //UNUSED, ONLY FOR UNIFORMITY
+#else
+ #include <ost/dmx.h>
+ #include <ost/sec.h>
+ #include <ost/frontend.h>
+ char* frontenddev[4]={"/dev/ost/frontend0","/dev/ost/frontend1","/dev/ost/frontend2","/dev/ost/frontend3"};
+ char* dvrdev[4]={"/dev/ost/dvr0","/dev/ost/dvr1","/dev/ost/dvr2","/dev/ost/dvr3"};
+ char* secdev[4]={"/dev/ost/sec0","/dev/ost/sec1","/dev/ost/sec2","/dev/ost/sec3"};
+ char* demuxdev[4]={"/dev/ost/demux0","/dev/ost/demux1","/dev/ost/demux2","/dev/ost/demux3"};
+#endif
+
+#include "dvbin.h"
+#include "dvb_defaults.h"
+#include "../mp_msg.h"
+
+
+extern int card;
+
+int open_fe(int* fd_frontend, int* fd_sec)
+{
+ if((*fd_frontend = open(frontenddev[card], O_RDWR)) < 0)
+ {
+ perror("ERROR IN OPENING FRONTEND DEVICE: ");
+ return -1;
+ }
+#ifdef HAVE_DVB_HEAD
+ fd_sec=0;
+#else
+ if (fd_sec != 0)
+ {
+ if((*fd_sec = open(secdev[card], O_RDWR)) < 0)
+ {
+ perror("ERROR IN OPENING SEC DEVICE: ");
+ return -1;
+ }
+ }
+#endif
+ return 1;
+}
+
+
+
+int set_ts_filt(int fd, uint16_t pid, dmx_pes_type_t pestype)
+{
+ int i;
+ struct dmx_pes_filter_params pesFilterParams;
+
+ pesFilterParams.pid = pid;
+ pesFilterParams.input = DMX_IN_FRONTEND;
+ pesFilterParams.output = DMX_OUT_TS_TAP;
+#ifdef HAVE_DVB_HEAD
+ pesFilterParams.pes_type = pestype;
+#else
+ pesFilterParams.pesType = pestype;
+#endif
+
+ //pesFilterParams.pesType = pestype;
+
+ pesFilterParams.flags = DMX_IMMEDIATE_START;
+
+ if ((i = ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams)) < 0)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "ERROR IN SETTING DMX_FILTER %i: ", pid);
+ }
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "SET PES FILTER ON PID %d, RESULT: %d\n", pid, i );
+ return 1;
+}
+
+
+int demux_stop(int fd)
+{
+ int i;
+ i = ioctl(fd, DMX_STOP);
+
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "STOPPING FD: %d, RESULT: %d\n", fd, i);
+
+ return (i==0);
+}
+
+
+
+void make_nonblock(int f)
+{
+ int oldflags;
+
+ if ((oldflags=fcntl(f, F_GETFL, 0)) < 0)
+ {
+ perror("ERROR IN F_GETFL");
+ }
+
+ oldflags|=O_NONBLOCK;
+ if (fcntl(f, F_SETFL, oldflags) < 0)
+ {
+ perror("F_SETFL");
+ }
+}
+
+
+static int tune_it(int fd_frontend, int fd_sec, unsigned int freq, unsigned int srate, char pol, int tone,
+ fe_spectral_inversion_t specInv, unsigned int diseqc, fe_modulation_t modulation, fe_code_rate_t HP_CodeRate,
+ fe_transmit_mode_t TransmissionMode, fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth);
+
+
+//int dvb_tune(dvb_priv_t *priv, int freq, char pol, int srate, int diseqc, int tone)
+dvb_tune(dvb_priv_t *priv, int freq, char pol, int srate, int diseqc, int tone,
+ fe_spectral_inversion_t specInv, fe_modulation_t modulation, fe_guard_interval_t guardInterval,
+ fe_transmit_mode_t TransmissionMode, fe_bandwidth_t bandWidth, fe_code_rate_t HP_CodeRate)
+{
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "dvb_tune con Freq: %lu, pol: %c, srate: %lu, diseqc %d, tone %d\n", freq, pol, srate, diseqc, tone);
+ /* INPUT: frequency, polarization, srate */
+ if(freq > 100000000)
+ {
+ if(open_fe(&(priv->fe_fd), 0))
+ {
+ //tune_it(fd_frontend, 0, freq, 0, 0, tone, specInv, diseqc,modulation,HP_CodeRate,TransmissionMode,guardInterval,bandWidth);
+ tune_it(priv->fe_fd, 0, freq, 0, 0, tone, specInv, diseqc, modulation, HP_CodeRate, TransmissionMode, guardInterval, bandWidth);
+
+ close(priv->fe_fd);
+ }
+ else
+ return 0;
+ }
+ else if ((freq != 0) && (pol != 0) && (srate != 0))
+ {
+ if (open_fe(&(priv->fe_fd), &(priv->sec_fd)))
+ {
+ tune_it(priv->fe_fd, priv->sec_fd, freq, srate, pol, tone, specInv, diseqc, modulation, HP_CodeRate, TransmissionMode, guardInterval, bandWidth);
+ close(priv->fe_fd);
+ close(priv->sec_fd);
+ }
+ else
+ return 0;
+ }
+
+ priv->channel.freq = freq;
+ priv->channel.srate = srate;
+ priv->channel.pol = pol;
+ priv->channel.diseqc = diseqc;
+ priv->channel.tone = tone;
+ priv->channel.inv = specInv;
+ priv->channel.mod = modulation;
+ priv->channel.gi = guardInterval;
+ priv->channel.trans = TransmissionMode;
+ priv->channel.bw = bandWidth;
+ priv->channel.cr = HP_CodeRate;
+
+ return 1;
+}
+
+
+
+
+
+#ifndef HAVE_DVB_HEAD
+static int OSTSelftest(int fd)
+{
+ int ans;
+
+ if ((ans = ioctl(fd, FE_SELFTEST,0) < 0))
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "FE SELF TEST: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int OSTSetPowerState(int fd, uint32_t state)
+{
+ int ans;
+
+ if ((ans = ioctl(fd,FE_SET_POWER_STATE,state) < 0))
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "OST SET POWER STATE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int OSTGetPowerState(int fd, uint32_t *state)
+{
+ int ans;
+
+ if ((ans = ioctl(fd,FE_GET_POWER_STATE,state) < 0))
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "OST GET POWER STATE: ");
+ return -1;
+ }
+
+ switch(*state)
+ {
+ case FE_POWER_ON:
+ mp_msg(MSGT_DEMUX, MSGL_V, "POWER ON (%d)\n",*state);
+ break;
+ case FE_POWER_STANDBY:
+ mp_msg(MSGT_DEMUX, MSGL_V, "POWER STANDBY (%d)\n",*state);
+ break;
+ case FE_POWER_SUSPEND:
+ mp_msg(MSGT_DEMUX, MSGL_V, "POWER SUSPEND (%d)\n",*state);
+ break;
+ case FE_POWER_OFF:
+ mp_msg(MSGT_DEMUX, MSGL_V, "POWER OFF (%d)\n",*state);
+ break;
+ default:
+ mp_msg(MSGT_DEMUX, MSGL_V, "unknown (%d)\n",*state);
+ break;
+ }
+
+ return 0;
+}
+
+
+static int SecGetStatus (int fd, struct secStatus *state)
+{
+ int ans;
+
+ if ((ans = ioctl(fd, SEC_GET_STATUS, state) < 0))
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, ("SEC GET STATUS: "));
+ return -1;
+ }
+
+ switch (state->busMode)
+ {
+ case SEC_BUS_IDLE:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE: IDLE (%d)\n",state->busMode);
+ break;
+ case SEC_BUS_BUSY:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE: BUSY (%d)\n",state->busMode);
+ break;
+ case SEC_BUS_OFF:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE: OFF (%d)\n",state->busMode);
+ break;
+ case SEC_BUS_OVERLOAD:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE: OVERLOAD (%d)\n",state->busMode);
+ break;
+ default:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC BUS MODE: unknown (%d)\n",state->busMode);
+ break;
+ }
+
+ switch (state->selVolt)
+ {
+ case SEC_VOLTAGE_OFF:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE: OFF (%d)\n",state->selVolt);
+ break;
+ case SEC_VOLTAGE_LT:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE: LT (%d)\n",state->selVolt);
+ break;
+ case SEC_VOLTAGE_13:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE: 13 (%d)\n",state->selVolt);
+ break;
+ case SEC_VOLTAGE_13_5:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE: 13.5 (%d)\n",state->selVolt);
+ break;
+ case SEC_VOLTAGE_18:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE: 18 (%d)\n",state->selVolt);
+ break;
+ case SEC_VOLTAGE_18_5:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE: 18.5 (%d)\n",state->selVolt);
+ break;
+ default:
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC VOLTAGE: unknown (%d)\n",state->selVolt);
+ break;
+ }
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "SEC CONT TONE: %s\n", (state->contTone == SEC_TONE_ON ? "ON" : "OFF"));
+ return 0;
+}
+
+#endif
+
+static void print_status(fe_status_t festatus)
+{
+ mp_msg(MSGT_DEMUX, MSGL_V, "FE_STATUS:");
+ if (festatus & FE_HAS_SIGNAL) mp_msg(MSGT_DEMUX, MSGL_V," FE_HAS_SIGNAL");
+#ifdef HAVE_DVB_HEAD
+ if (festatus & FE_TIMEDOUT) mp_msg(MSGT_DEMUX, MSGL_V, " FE_TIMEDOUT");
+#else
+ if (festatus & FE_HAS_POWER) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_POWER");
+ if (festatus & FE_SPECTRUM_INV) mp_msg(MSGT_DEMUX, MSGL_V, " FE_SPECTRUM_INV");
+ if (festatus & FE_TUNER_HAS_LOCK) mp_msg(MSGT_DEMUX, MSGL_V, " FE_TUNER_HAS_LOCK");
+#endif
+ if (festatus & FE_HAS_LOCK) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_LOCK");
+ if (festatus & FE_HAS_CARRIER) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_CARRIER");
+ if (festatus & FE_HAS_VITERBI) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_VITERBI");
+ if (festatus & FE_HAS_SYNC) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_SYNC");
+ mp_msg(MSGT_DEMUX, MSGL_V, "\n");
+}
+
+
+#ifdef HAVE_DVB_HEAD
+static int check_status(int fd_frontend,struct dvb_frontend_parameters* feparams,int tone)
+{
+ int i,res;
+ int32_t strength;
+ fe_status_t festatus;
+ struct dvb_frontend_event event;
+ struct dvb_frontend_info fe_info;
+ struct pollfd pfd[1];
+
+ if (ioctl(fd_frontend,FE_SET_FRONTEND,feparams) < 0)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR tuning channel\n");
+ return -1;
+ }
+
+ pfd[0].fd = fd_frontend;
+ pfd[0].events = POLLIN;
+
+ event.status=0;
+ while (((event.status & FE_TIMEDOUT)==0) && ((event.status & FE_HAS_LOCK)==0))
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "polling....\n");
+ if (poll(pfd,1,10000))
+ {
+ if (pfd[0].revents & POLLIN)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "Getting frontend event\n");
+ if ( ioctl(fd_frontend, FE_GET_EVENT, &event) < 0)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "FE_GET_EVENT");
+ return -1;
+ }
+ }
+ print_status(event.status);
+ }
+ }
+
+ if (event.status & FE_HAS_LOCK)
+ {
+ switch(fe_info.type)
+ {
+ case FE_OFDM:
+ mp_msg(MSGT_DEMUX, MSGL_V, "Event: Frequency: %d\n",event.parameters.frequency);
+ break;
+ case FE_QPSK:
+ mp_msg(MSGT_DEMUX, MSGL_V, "Event: Frequency: %d\n",(unsigned int)((event.parameters.frequency)+(tone==SEC_TONE_OFF ? LOF1 : LOF2)));
+ mp_msg(MSGT_DEMUX, MSGL_V, " SymbolRate: %d\n",event.parameters.u.qpsk.symbol_rate);
+ mp_msg(MSGT_DEMUX, MSGL_V, " FEC_inner: %d\n",event.parameters.u.qpsk.fec_inner);
+ mp_msg(MSGT_DEMUX, MSGL_V, "\n");
+ break;
+ case FE_QAM:
+ mp_msg(MSGT_DEMUX, MSGL_V, "Event: Frequency: %d\n",event.parameters.frequency);
+ mp_msg(MSGT_DEMUX, MSGL_V, " SymbolRate: %d\n",event.parameters.u.qpsk.symbol_rate);
+ mp_msg(MSGT_DEMUX, MSGL_V, " FEC_inner: %d\n",event.parameters.u.qpsk.fec_inner);
+ break;
+ default:
+ break;
+ }
+
+ strength=0;
+ ioctl(fd_frontend,FE_READ_BER,&strength);
+ mp_msg(MSGT_DEMUX, MSGL_V, "Bit error rate: %d\n",strength);
+
+ strength=0;
+ ioctl(fd_frontend,FE_READ_SIGNAL_STRENGTH,&strength);
+ mp_msg(MSGT_DEMUX, MSGL_V, "Signal strength: %d\n",strength);
+
+ strength=0;
+ ioctl(fd_frontend,FE_READ_SNR,&strength);
+ mp_msg(MSGT_DEMUX, MSGL_V, "SNR: %d\n",strength);
+
+ festatus=0;
+ ioctl(fd_frontend,FE_READ_STATUS,&festatus);
+ print_status(festatus);
+ }
+ else
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "Not able to lock to the signal on the given frequency\n");
+ return -1;
+ }
+ return 0;
+}
+
+#else
+
+static int check_status(int fd_frontend,FrontendParameters* feparams,int tone)
+{
+ int i,res;
+ int32_t strength;
+ fe_status_t festatus;
+ FrontendEvent event;
+ FrontendInfo fe_info;
+ struct pollfd pfd[1];
+
+ i = 0; res = -1;
+ while ((i < 3) && (res < 0))
+ {
+ if (ioctl(fd_frontend,FE_SET_FRONTEND,feparams) < 0)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR tuning channel\n");
+ return -1;
+ }
+
+ pfd[0].fd = fd_frontend;
+ pfd[0].events = POLLIN;
+
+ if (poll(pfd,1,10000))
+ {
+ if (pfd[0].revents & POLLIN)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "Getting frontend event\n");
+ if ( ioctl(fd_frontend, FE_GET_EVENT, &event) < 0)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "FE_GET_EVENT");
+ return -1;
+ }
+ mp_msg(MSGT_DEMUX, MSGL_V, "Received ");
+ switch(event.type)
+ {
+ case FE_UNEXPECTED_EV:
+ mp_msg(MSGT_DEMUX, MSGL_V, "unexpected event\n");
+ res = -1;
+ break;
+
+ case FE_FAILURE_EV:
+ mp_msg(MSGT_DEMUX, MSGL_V, "failure event\n");
+ res = -1;
+ break;
+
+ case FE_COMPLETION_EV:
+ mp_msg(MSGT_DEMUX, MSGL_V, "completion event\n");
+ res = 0;
+ break;
+ }
+ }
+ i++;
+ }
+ }
+
+ if (res > 0)
+ switch (event.type)
+ {
+ case FE_UNEXPECTED_EV: mp_msg(MSGT_DEMUX, MSGL_V, "FE_UNEXPECTED_EV\n");
+ break;
+ case FE_COMPLETION_EV: mp_msg(MSGT_DEMUX, MSGL_V, "FE_COMPLETION_EV\n");
+ break;
+ case FE_FAILURE_EV: mp_msg(MSGT_DEMUX, MSGL_V, "FE_FAILURE_EV\n");
+ break;
+ }
+
+ if (event.type == FE_COMPLETION_EV)
+ {
+ switch(fe_info.type)
+ {
+ case FE_OFDM:
+ mp_msg(MSGT_DEMUX, MSGL_V, "Event: Frequency: %d\n",event.u.completionEvent.Frequency);
+ break;
+
+ case FE_QPSK:
+ mp_msg(MSGT_DEMUX, MSGL_V, "Event: Frequency: %d\n",(unsigned int)((event.u.completionEvent.Frequency)+(tone==SEC_TONE_OFF ? LOF1 : LOF2)));
+ mp_msg(MSGT_DEMUX, MSGL_V, " SymbolRate: %d\n",event.u.completionEvent.u.qpsk.SymbolRate);
+ mp_msg(MSGT_DEMUX, MSGL_V, " FEC_inner: %d\n",event.u.completionEvent.u.qpsk.FEC_inner);
+ mp_msg(MSGT_DEMUX, MSGL_V, "\n");
+ break;
+
+ case FE_QAM:
+ mp_msg(MSGT_DEMUX, MSGL_V, "Event: Frequency: %d\n",event.u.completionEvent.Frequency);
+ mp_msg(MSGT_DEMUX, MSGL_V, " SymbolRate: %d\n",event.u.completionEvent.u.qpsk.SymbolRate);
+ mp_msg(MSGT_DEMUX, MSGL_V, " FEC_inner: %d\n",event.u.completionEvent.u.qpsk.FEC_inner);
+ break;
+
+ default:
+ break;
+ }
+
+ strength=0;
+ ioctl(fd_frontend,FE_READ_BER,&strength);
+ mp_msg(MSGT_DEMUX, MSGL_V, "Bit error rate: %d\n",strength);
+
+ strength=0;
+ ioctl(fd_frontend,FE_READ_SIGNAL_STRENGTH,&strength);
+ mp_msg(MSGT_DEMUX, MSGL_V, "Signal strength: %d\n",strength);
+
+ strength=0;
+ ioctl(fd_frontend,FE_READ_SNR,&strength);
+ mp_msg(MSGT_DEMUX, MSGL_V, "SNR: %d\n",strength);
+
+ festatus=0;
+ ioctl(fd_frontend,FE_READ_STATUS,&festatus);
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "FE_STATUS:");
+ if (festatus & FE_HAS_POWER) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_POWER");
+ if (festatus & FE_HAS_SIGNAL) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_SIGNAL");
+ if (festatus & FE_SPECTRUM_INV) mp_msg(MSGT_DEMUX, MSGL_V, " FE_SPECTRUM_INV");
+ if (festatus & FE_HAS_LOCK) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_LOCK");
+ if (festatus & FE_HAS_CARRIER) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_CARRIER");
+ if (festatus & FE_HAS_VITERBI) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_VITERBI");
+ if (festatus & FE_HAS_SYNC) mp_msg(MSGT_DEMUX, MSGL_V, " FE_HAS_SYNC");
+ if (festatus & FE_TUNER_HAS_LOCK) mp_msg(MSGT_DEMUX, MSGL_V, " FE_TUNER_HAS_LOCK");
+ mp_msg(MSGT_DEMUX, MSGL_V, "\n");
+ }
+ else
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "Not able to lock to the signal on the given frequency\n");
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+#ifdef HAVE_DVB_HEAD
+
+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)
+{
+ ioctl(fd, FE_SET_TONE, SEC_TONE_OFF);
+ ioctl(fd, FE_SET_VOLTAGE, v);
+ usleep(15 * 1000);
+ ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &cmd->cmd);
+ usleep(cmd->wait * 1000);
+ usleep(15 * 1000);
+ ioctl(fd, FE_DISEQC_SEND_BURST, b);
+ usleep(15 * 1000);
+ ioctl(fd, FE_SET_TONE, t);
+}
+
+
+
+
+/* digital satellite equipment control,
+ * specification is available from http://www.eutelsat.com/
+ */
+static int head_diseqc(int secfd, int sat_no, int pol, int hi_lo)
+{
+ 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) | (hi_lo ? 1 : 0) | (pol ? 0 : 2));
+
+ diseqc_send_msg(secfd, pol ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18,
+ &cmd, hi_lo ? SEC_TONE_ON : SEC_TONE_OFF,
+ (sat_no / 4) % 2 ? SEC_MINI_B : SEC_MINI_A);
+
+ return 1;
+}
+
+#endif
+
+
+static int tune_it(int fd_frontend, int fd_sec, unsigned int freq, unsigned int srate, char pol, int tone,
+ fe_spectral_inversion_t specInv, unsigned int diseqc, fe_modulation_t modulation, fe_code_rate_t HP_CodeRate,
+ fe_transmit_mode_t TransmissionMode, fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth)
+{
+ int res;
+#ifdef HAVE_DVB_HEAD
+ struct dvb_frontend_parameters feparams;
+ struct dvb_frontend_info fe_info;
+ fe_sec_voltage_t voltage;
+#else
+ FrontendParameters feparams;
+ FrontendInfo fe_info;
+ secVoltage voltage;
+ struct secStatus sec_state;
+#endif
+
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "TUNE_IT, fd_frontend %d, fd_sec %d, freq %lu, srate %lu, pol %c, tone %i, specInv, diseqc %u, fe_modulation_t modulation,fe_code_rate_t HP_CodeRate, fe_transmit_mode_t TransmissionMode,fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth\n",
+ fd_frontend, fd_sec, freq, srate, pol, tone, diseqc);
+
+
+ if ( (res = ioctl(fd_frontend,FE_GET_INFO, &fe_info) < 0))
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "FE_GET_INFO: ");
+ return -1;
+ }
+
+
+#ifdef HAVE_DVB_HEAD
+ mp_msg(MSGT_DEMUX, MSGL_V, "Using DVB card \"%s\"\n",fe_info.name);
+#endif
+
+ switch(fe_info.type)
+ {
+ case FE_OFDM:
+#ifdef HAVE_DVB_HEAD
+ if (freq < 1000000) freq*=1000UL;
+ feparams.frequency=freq;
+ feparams.inversion=INVERSION_OFF;
+ feparams.u.ofdm.bandwidth=bandwidth;
+ feparams.u.ofdm.code_rate_HP=HP_CodeRate;
+ feparams.u.ofdm.code_rate_LP=LP_CODERATE_DEFAULT;
+ feparams.u.ofdm.constellation=modulation;
+ feparams.u.ofdm.transmission_mode=TransmissionMode;
+ feparams.u.ofdm.guard_interval=guardInterval;
+ feparams.u.ofdm.hierarchy_information=HIERARCHY_DEFAULT;
+#else
+ if (freq < 1000000) freq*=1000UL;
+ feparams.Frequency=freq;
+ feparams.Inversion=INVERSION_OFF;
+ feparams.u.ofdm.bandWidth=bandwidth;
+ feparams.u.ofdm.HP_CodeRate=HP_CodeRate;
+ feparams.u.ofdm.LP_CodeRate=LP_CODERATE_DEFAULT;
+ feparams.u.ofdm.Constellation=modulation;
+ feparams.u.ofdm.TransmissionMode=TransmissionMode;
+ feparams.u.ofdm.guardInterval=guardInterval;
+ feparams.u.ofdm.HierarchyInformation=HIERARCHY_DEFAULT;
+#endif
+ mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-T (%s) to %d Hz\n",DVB_T_LOCATION,freq);
+ break;
+ case FE_QPSK:
+#ifdef HAVE_DVB_HEAD
+ mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-S to L-Band:%d, Pol:%c Srate=%d, 22kHz=%s\n",feparams.frequency,pol,srate,tone == SEC_TONE_ON ? "on" : "off");
+#else
+ mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-S to L-Band:%d, Pol:%c Srate=%d, 22kHz=%s\n",feparams.Frequency,pol,srate,tone == SEC_TONE_ON ? "on" : "off");
+#endif
+ if ((pol=='h') || (pol=='H'))
+ {
+ voltage = SEC_VOLTAGE_18;
+ }
+ else
+ {
+ voltage = SEC_VOLTAGE_13;
+ }
+#ifdef HAVE_DVB_HEAD
+ if (ioctl(fd_frontend,FE_SET_VOLTAGE,voltage) < 0)
+ {
+#else
+ if (ioctl(fd_sec,SEC_SET_VOLTAGE,voltage) < 0)
+ {
+#endif
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR setting voltage\n");
+ }
+
+ if (freq > 2200000)
+ {
+ // this must be an absolute frequency
+ if (freq < SLOF)
+ {
+#ifdef HAVE_DVB_HEAD
+ feparams.frequency=(freq-LOF1);
+#else
+ feparams.Frequency=(freq-LOF1);
+#endif
+ if (tone < 0) tone = SEC_TONE_OFF;
+ }
+ else
+ {
+#ifdef HAVE_DVB_HEAD
+ feparams.frequency=(freq-LOF2);
+#else
+ feparams.Frequency=(freq-LOF2);
+#endif
+ if (tone < 0) tone = SEC_TONE_ON;
+ }
+ }
+ else
+ {
+ // this is an L-Band frequency
+#ifdef HAVE_DVB_HEAD
+ feparams.frequency=freq;
+#else
+ feparams.Frequency=freq;
+#endif
+ }
+
+#ifdef HAVE_DVB_HEAD
+ feparams.inversion=specInv;
+ feparams.u.qpsk.symbol_rate=srate;
+ feparams.u.qpsk.fec_inner=FEC_AUTO;
+#else
+ feparams.Inversion=specInv;
+ feparams.u.qpsk.SymbolRate=srate;
+ feparams.u.qpsk.FEC_inner=FEC_AUTO;
+#endif
+
+#ifdef HAVE_DVB_HEAD
+ if (ioctl(fd_frontend, FE_SET_TONE,tone) < 0)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR setting tone\n");
+ }
+#else
+ if (ioctl(fd_sec, SEC_SET_TONE,tone) < 0)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR setting tone\n");
+ }
+#endif
+
+#ifdef HAVE_DVB_HEAD
+ //#warning DISEQC is unimplemented for HAVE_DVB_HEAD
+ if(diseqc > 0)
+ {
+ int ipol = (pol == 'V' ? 1 : 0);
+ int hiband = (freq >= SLOF);
+
+ if(head_diseqc(fd_frontend, diseqc-1, ipol, hiband))
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "DISEQC SETTING SUCCEDED\n");
+ }
+ else
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "DISEQC SETTING FAILED\n");
+ }
+ }
+#else
+ if (diseqc > 0)
+ {
+ struct secCommand scmd;
+ struct secCmdSequence scmds;
+
+ scmds.continuousTone = tone;
+ scmds.voltage = voltage;
+ /*
+ scmds.miniCommand = toneBurst ? SEC_MINI_B : SEC_MINI_A;
+ */
+ scmds.miniCommand = SEC_MINI_NONE;
+
+ scmd.type = 0;
+ scmds.numCommands = 1;
+ scmds.commands = &scmd;
+
+ scmd.u.diseqc.addr = 0x10;
+ scmd.u.diseqc.cmd = 0x38;
+ scmd.u.diseqc.numParams = 1;
+ scmd.u.diseqc.params[0] = 0xf0 |
+ (((diseqc - 1) << 2) & 0x0c) |
+ (voltage==SEC_VOLTAGE_18 ? 0x02 : 0) |
+ (tone==SEC_TONE_ON ? 0x01 : 0);
+
+ if (ioctl(fd_sec,SEC_SEND_SEQUENCE,&scmds) < 0)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "Error sending DisEqC");
+ return -1;
+ }
+ }
+#endif
+ break;
+ case FE_QAM:
+ mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-C to %d, srate=%d\n",freq,srate);
+#ifdef HAVE_DVB_HEAD
+ feparams.frequency=freq;
+ feparams.inversion=INVERSION_OFF;
+ feparams.u.qam.symbol_rate = srate;
+ feparams.u.qam.fec_inner = FEC_AUTO;
+ feparams.u.qam.modulation = QAM_64;
+#else
+ feparams.Frequency=freq;
+ feparams.Inversion=INVERSION_OFF;
+ feparams.u.qam.SymbolRate = srate;
+ feparams.u.qam.FEC_inner = FEC_AUTO;
+ feparams.u.qam.QAM = QAM_64;
+#endif
+ break;
+ default:
+ mp_msg(MSGT_DEMUX, MSGL_V, "Unknown FE type. Aborting\n");
+ exit(-1);
+ }
+ usleep(100000);
+
+#ifndef HAVE_DVB_HEAD
+ if (fd_sec) SecGetStatus(fd_sec, &sec_state);
+#endif
+
+ return(check_status(fd_frontend,&feparams,tone));
+}
diff --git a/libmpdemux/dvbin.c b/libmpdemux/dvbin.c
new file mode 100644
index 0000000000..d845b64e32
--- /dev/null
+++ b/libmpdemux/dvbin.c
@@ -0,0 +1,684 @@
+/*
+
+dvbstream
+(C) Dave Chapman <dave@dchapman.com> 2001, 2002.
+
+The latest version can be found at http://www.linuxstb.org/dvbstream
+
+Copyright notice:
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 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 General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+// Linux includes:
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <resolv.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <values.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "config.h"
+
+// DVB includes:
+
+#include "stream.h"
+#include "demuxer.h"
+
+#include "../cfgparser.h"
+
+#include "dvbin.h"
+#include "dvb_defaults.h"
+
+extern int video_id, audio_id, demuxer_type;
+
+
+#define MAX_CHANNELS 8
+
+
+#define min(a, b) ((a) <= (b) ? (a) : (b))
+
+int dvbin_param_card, dvbin_param_freq, dvbin_param_srate, dvbin_param_diseqc = 0,
+ dvbin_param_tone = -1, dvbin_param_vid, dvbin_param_aid, dvbin_is_active = 0;
+int dvbin_param_mod, dvbin_param_gi, dvbin_param_tm, dvbin_param_bw, dvbin_param_cr;
+char *dvbin_param_pol = "", *dvbin_param_inv="INVERSION_AUTO",
+ *dvbin_param_type="SAT ",
+ *dvbin_param_prog = " ";
+dvb_history_t dvb_prev_next;
+
+struct config dvbin_opts_conf[] = {
+ {"on", &dvbin_param_on, CONF_TYPE_INT, 0, 0, 1, NULL},
+ {"type", &dvbin_param_type, CONF_TYPE_STRING, 0, 0, 1, NULL},
+ {"card", &dvbin_param_card, CONF_TYPE_INT, CONF_RANGE, 1, 4, NULL},
+ {"freq", &dvbin_param_freq, CONF_TYPE_INT, 0, 0, 1, NULL},
+ {"pol", &dvbin_param_pol, CONF_TYPE_STRING, 0, 0, 0, NULL},
+ {"srate", &dvbin_param_srate, CONF_TYPE_INT, 0, 0, 1, NULL},
+ {"diseqc", &dvbin_param_diseqc, CONF_TYPE_INT, CONF_RANGE, 1, 4, NULL},
+ {"tone", &dvbin_param_tone, CONF_TYPE_INT, 0, 0, 1, NULL},
+ {"vid", &dvbin_param_vid, CONF_TYPE_INT, 0, 0, 1, NULL},
+ {"aid", &dvbin_param_aid, CONF_TYPE_INT, 0, 0, 1, NULL},
+ {"prog", &dvbin_param_prog, CONF_TYPE_STRING, 0, 0, 0, NULL},
+ {"inv", &dvbin_param_inv, CONF_TYPE_STRING, 0, 0, 0, NULL},
+ {"mod", &dvbin_param_mod, CONF_TYPE_INT, 0, 0, 1, NULL},
+ {"gi", &dvbin_param_gi, CONF_TYPE_INT, 0, 0, 1, NULL},
+ {"tm", &dvbin_param_tm, CONF_TYPE_INT, 0, 0, 1, NULL},
+ {"bw", &dvbin_param_bw, CONF_TYPE_INT, 0, 0, 1, NULL},
+ {"cr", &dvbin_param_cr, CONF_TYPE_INT, 0, 0, 1, NULL},
+ {NULL, NULL, 0, 0, 0, 0, NULL}
+};
+
+
+int card=0;
+
+extern int open_fe(int* fd_frontend, int* fd_sec);
+extern int set_ts_filt(int fd, uint16_t pid, dmx_pes_type_t pestype);
+extern int demux_stop(int fd);
+extern void make_nonblock(int f);
+extern int dvb_tune(dvb_priv_t *priv, int freq, char pol, int srate, int diseqc, int tone,
+ fe_spectral_inversion_t specInv, fe_modulation_t modulation, fe_guard_interval_t guardInterval,
+ fe_transmit_mode_t TransmissionMode, fe_bandwidth_t bandWidth, fe_code_rate_t HP_CodeRate);
+extern char *frontenddev[4], *dvrdev[4], *secdev[4], *demuxdev[4];
+
+
+dvb_channels_list *dvb_get_channels(char *filename, const char *type)
+{
+ dvb_channels_list *list;
+ FILE *f;
+ uint8_t line[128];
+ int fields, row_count;
+ dvb_channel_t *ptr;
+ char *tmp_lcr, *tmp_hier, *inv, *bw, *cr, *mod, *transm, *gi;
+ //const char *cbl_conf = "%a[^:]:%d:%c:%d:%a[^:]:%a[^:]:%d:%d\n";
+ const char *sat_conf = "%a[^:]:%d:%c:%d:%d:%d:%d:%d:%d:%d\n";
+ const char *ter_conf = "%a[^:]:%d:%a[^:]:%a[^:]:%a[^:]:%a[^:]:%a[^:]:%a[^:]:%a[^:]:%a[^:]:%d:%d\n";
+
+ list = malloc(sizeof(dvb_channels_list));
+ if(list == NULL)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_V, "DVB_GET_CHANNELS: couldn't malloc enough memory\n");
+ return NULL;
+ }
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "CONFIG_READ FILE: %s, type: %s\n", filename, type);
+ if((f=fopen(filename, "r"))==NULL)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_FATAL, "CAN'T READ CONFIG FILE %s\n", filename);
+ return NULL;
+ }
+
+ list->NUM_CHANNELS = 0;
+ row_count = 0;
+ while(! feof(f) && row_count < 512)
+ {
+ if( fgets(line, 128, f) == NULL ) continue;
+
+ if(line[0] == '#')
+ continue; //comment line
+
+ ptr = &(list->channels[ list->NUM_CHANNELS ]);
+
+ if(! strcmp(type, "TER"))
+ {
+ fields = sscanf(line, ter_conf,
+ &ptr->name, &ptr->freq, &inv, &bw, &cr, tmp_lcr, &mod,
+ &transm, &gi, &tmp_hier, &ptr->vpid, &ptr->apid1);
+
+ if(! strcmp(inv, "INVERSION_ON"))
+ ptr->inv = INVERSION_ON;
+ else if(! strcmp(inv, "INVERSION_OFF"))
+ ptr->inv = INVERSION_OFF;
+ else
+ ptr->inv = INVERSION_AUTO;
+
+ if(! strcmp(bw, "BANDWIDTH_6_MHZ"))
+ ptr->bw = BANDWIDTH_6_MHZ;
+ else if(! strcmp(bw, "BANDWIDTH_7_MHZ"))
+ ptr->bw = BANDWIDTH_7_MHZ;
+ else if(! strcmp(bw, "BANDWIDTH_8_MHZ"))
+ ptr->bw = BANDWIDTH_8_MHZ;
+
+
+ if(! strcmp(cr, "FEC_1_2"))
+ ptr->cr =FEC_1_2;
+ else if(! strcmp(cr, "FEC_2_3"))
+ ptr->cr =FEC_2_3;
+ else if(! strcmp(cr, "FEC_3_4"))
+ ptr->cr =FEC_3_4;
+#ifdef HAVE_DVB_HEAD
+ else if(! strcmp(cr, "FEC_4_5"))
+ ptr->cr =FEC_4_5;
+ else if(! strcmp(cr, "FEC_6_7"))
+ ptr->cr =FEC_6_7;
+ else if(! strcmp(cr, "FEC_8_9"))
+ ptr->cr =FEC_8_9;
+#endif
+ else if(! strcmp(cr, "FEC_5_6"))
+ ptr->cr =FEC_5_6;
+ else if(! strcmp(cr, "FEC_7_8"))
+ ptr->cr =FEC_7_8;
+ else if(! strcmp(cr, "FEC_NONE"))
+ ptr->cr =FEC_NONE;
+ else ptr->cr =FEC_AUTO;
+
+ if(! strcmp(mod, "QAM_128"))
+ ptr->mod = QAM_128;
+ else if(! strcmp(mod, "QAM_256"))
+ ptr->mod = QAM_256;
+ else if(! strcmp(mod, "QAM_64"))
+ ptr->mod = QAM_64;
+ else if(! strcmp(mod, "QAM_32"))
+ ptr->mod = QAM_32;
+ else if(! strcmp(mod, "QAM_16"))
+ ptr->mod = QAM_16;
+ else ptr->mod = QPSK;
+
+
+ if(! strcmp(transm, "TRANSMISSION_MODE_2K"))
+ ptr->trans = TRANSMISSION_MODE_2K;
+ else if(! strcmp(transm, "TRANSMISSION_MODE_8K"))
+ ptr->trans = TRANSMISSION_MODE_8K;
+
+ if(! strcmp(gi, "GUARD_INTERVAL_1_32"))
+ ptr->gi = GUARD_INTERVAL_1_32;
+ else if(! strcmp(gi, "GUARD_INTERVAL_1_16"))
+ ptr->gi = GUARD_INTERVAL_1_16;
+ else if(! strcmp(gi, "GUARD_INTERVAL_1_8"))
+ ptr->gi = GUARD_INTERVAL_1_8;
+ else ptr->gi = GUARD_INTERVAL_1_4;
+
+
+ }
+ /*
+ else if(! strcmp(type, "CBL"))
+ {
+ fields = sscanf(line, cbl_conf,
+ &ptr->name, &ptr->freq, &ptr->inv, &ptr->qam,
+ &ptr->fec, &ptr->mod, &ptr->vpid, &ptr->apid1);
+
+
+ }
+ */
+ else //SATELLITE
+ {
+ fields = sscanf(line, sat_conf,
+ &ptr->name, &ptr->freq, &ptr->pol, &ptr->diseqc, &ptr->srate, &ptr->vpid, &ptr->apid1,
+ &ptr->tpid, &ptr->ca, &ptr->progid);
+ ptr->pol = toupper(ptr->pol);
+ ptr->freq *= 1000UL;
+ ptr->srate *= 1000UL;
+ ptr->tone = -1;
+ mp_msg(MSGT_DEMUX, MSGL_V,
+ "NUM_FIELDS: %d, NAME: %s, FREQ: %d, SRATE: %d, POL: %c, DISEQC: %d, TONE: %d, VPID: %d, APID1: %d, APID2: %d, TPID: %d, PROGID: %d, NUM: %d\n",
+ fields, ptr->name, ptr->freq, ptr->srate, ptr->pol, ptr->diseqc, ptr->tone, ptr->vpid, ptr->apid1, ptr->apid2, ptr->tpid, ptr->progid, list->NUM_CHANNELS);
+ }
+
+ list->NUM_CHANNELS++;
+ row_count++;
+ }
+
+ fclose(f);
+ return list;
+}
+
+
+static long getmsec()
+{
+ struct timeval tv;
+ gettimeofday(&tv, (struct timezone*) NULL);
+ return(tv.tv_sec%1000000)*1000 + tv.tv_usec/1000;
+}
+
+
+
+int dvb_streaming_read(int fd, char *buffer, unsigned int size, dvb_priv_t *priv)
+{
+ struct pollfd pfds[1];
+ uint32_t ok = 0, pos = 0, tot = 0, rk, d, r, m;
+
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "dvb_streaming_read(%u)\n", fd);
+
+ while(pos < size)
+ {
+ ok = 0;
+ tot = 0;
+ //int m = min((size-pos), 188);
+ m = size - pos;
+ d = (int) (m / 188);
+ r = m % 188;
+
+ m = d * 188;
+ m = (m ? m : r);
+
+ pfds[0].fd = fd;
+ pfds[0].events = POLLIN | POLLPRI;
+
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "DEVICE: %d, DVR: %d, PIPE: %d <-> %d\n", fd, priv->dvr_fd, priv->input, priv->output);
+
+ poll(pfds, 1, 500);
+ if((rk = read(fd, &buffer[pos], m)) > 0)
+ pos += rk;
+ }
+
+ return pos;
+}
+
+
+
+dvb_history_t *dvb_step_channel(dvb_priv_t *priv, int dir, dvb_history_t *h)
+{
+ //int new_freq, new_srate, new_diseqc, new_tone, new_vpid, new_apid;
+ //char new_pol;
+ int new_current;
+ dvb_channel_t *next;
+ dvb_channels_list *list;
+
+ if(priv == NULL)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_step_channel: PRIV NULL PTR, quit\n");
+ return 0;
+ }
+
+ list = priv->list;
+ if(list == NULL)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "dvb_step_channel: LIST NULL PTR, quit\n");
+ return 0;
+ }
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "DVB_STEP_CHANNEL dir %d\n", dir);
+
+ if(dir == DVB_CHANNEL_HIGHER)
+ {
+ if(list->current == list->NUM_CHANNELS)
+ return 0;
+
+ new_current = list->current + 1;
+ next = &(list->channels[new_current]);
+ }
+ else
+ {
+ if(list->current == 0)
+ return 0;
+
+ new_current = list->current - 1;
+ next = &(list->channels[new_current]);
+
+ }
+
+ demux_stop(priv->demux_fd[0]);
+ demux_stop(priv->demux_fd[1]);
+
+ h->prev = list->current;
+ h->next = new_current;
+
+ list->current = new_current;
+
+ return h;
+}
+
+
+extern char *get_path(char *);
+
+dvb_channels_list *list_ptr = NULL;
+
+int dvb_streaming_start(stream_t *stream)
+{
+ int pids[MAX_CHANNELS];
+ int pestypes[MAX_CHANNELS];
+ int npids, i;
+ char *filename, type[80];
+ unsigned long freq = 0;
+ char pol = 0;
+ unsigned long srate = 0;
+ int diseqc = 0, old_diseqc = 0;
+ int tone = -1;
+
+ dvb_priv_t *priv;
+ dvb_channel_t *channel = NULL;
+ fe_spectral_inversion_t specInv = INVERSION_AUTO;
+ fe_modulation_t modulation = CONSTELLATION_DEFAULT;
+ fe_transmit_mode_t TransmissionMode = TRANSMISSION_MODE_DEFAULT;
+ fe_bandwidth_t bandWidth = BANDWIDTH_DEFAULT;
+ fe_guard_interval_t guardInterval = GUARD_INTERVAL_DEFAULT;
+ fe_code_rate_t HP_CodeRate = HP_CODERATE_DEFAULT;
+
+
+ stream->priv = (dvb_priv_t*) malloc(sizeof(dvb_priv_t));
+ if(stream->priv == NULL)
+ return 0;
+ priv = (dvb_priv_t*) stream->priv;
+
+ if(!strncmp(dvbin_param_type, "CBL", 3))
+ strncpy(type, "CBL", 3);
+ else if(!strncmp(dvbin_param_type, "TER", 3))
+ strncpy(type, "TER", 3);
+ else
+ strncpy(type, "SAT", 3);
+
+
+ filename = get_path("channels.conf");
+
+ if(list_ptr == NULL)
+ {
+ if(filename)
+ {
+ if((list_ptr = dvb_get_channels(filename, type)) == NULL)
+ mp_msg(MSGT_DEMUX, MSGL_WARN, "EMPTY CHANNELS LIST!\n");
+ else
+ {
+ priv->list = list_ptr;
+ priv->list->current = 0;
+ }
+ }
+ else
+ {
+ list_ptr = NULL;
+ mp_msg(MSGT_DEMUX, MSGL_WARN, "NO CHANNELS FILE FOUND!\n");
+ }
+ }
+
+
+ mp_msg(MSGT_DEMUX, MSGL_INFO, "code taken from dvbstream for mplayer v0.4pre1 - (C) Dave Chapman 2001\n");
+ mp_msg(MSGT_DEMUX, MSGL_INFO, "Released under the GPL.\n");
+ mp_msg(MSGT_DEMUX, MSGL_INFO, "Latest version available from http://www.linuxstb.org/\n");
+ mp_msg(MSGT_DEMUX, MSGL_V, "ON: %d, CARD: %d, FREQ: %d, SRATE: %d, POL: %s, VID: %d, AID: %d\n", dvbin_param_on,
+ dvbin_param_card, dvbin_param_freq, dvbin_param_srate, dvbin_param_pol, dvbin_param_vid, dvbin_param_aid);
+
+ npids = 0;
+
+ if((dvb_prev_next.next > -1) && (dvb_prev_next.prev > -1) && (list_ptr != NULL)) //We are after a channel stepping
+ {
+ list_ptr->current = dvb_prev_next.next;
+ channel = &(list_ptr->channels[dvb_prev_next.next]);
+ mp_msg(MSGT_DEMUX, MSGL_V, "PROGRAM NUMBER %d: name=%s, vid=%d, aid=%d, freq=%lu, srate=%lu, pol=%c, diseqc: %d, tone: %d\n", dvb_prev_next.next,
+ channel->name, channel->vpid, channel->apid1,
+ channel->freq, channel->srate, channel->pol, channel->diseqc, channel->tone);
+
+
+ if((dvb_prev_next.prev >= 0) && (dvb_prev_next.prev < list_ptr->NUM_CHANNELS))
+ {
+ dvb_channel_t *tmp = &(list_ptr->channels[dvb_prev_next.prev]);
+ old_diseqc = tmp->diseqc;
+ }
+ }
+ else if(list_ptr != NULL && strlen(dvbin_param_prog))
+ {
+ i = 0;
+ while((channel == NULL) && i < list_ptr->NUM_CHANNELS)
+ {
+ if(! strcmp(list_ptr->channels[i].name, dvbin_param_prog))
+ channel = &(list_ptr->channels[i]);
+
+ i++;
+ }
+ if(channel != NULL)
+ {
+ list_ptr->current = i-1;
+ mp_msg(MSGT_DEMUX, MSGL_V, "PROGRAM NUMBER %d: name=%s, vid=%d, aid=%d, freq=%lu, srate=%lu, pol=%c, diseqc: %d, tone: %d\n", i-1,
+ channel->name, channel->vpid, channel->apid1,
+ channel->freq, channel->srate, channel->pol, channel->diseqc, channel->tone);
+
+ }
+ }
+
+
+ if(dvbin_param_vid > 0)
+ {
+ pids[npids] = priv->channel.vpid = dvbin_param_vid;
+ }
+ else if(channel != NULL)
+ {
+ pids[npids] = priv->channel.vpid = channel->vpid;
+ }
+ pestypes[npids] = DMX_PES_VIDEO;
+ npids++;
+
+ if(dvbin_param_aid > 0)
+ {
+ pids[npids] = priv->channel.apid1 = dvbin_param_aid;
+ }
+ else if(channel != NULL)
+ {
+ pids[npids] = priv->channel.vpid = channel->apid1;
+ }
+ pestypes[npids] = DMX_PES_AUDIO;
+ npids++;
+
+
+
+ if(dvbin_param_freq)
+ freq = dvbin_param_freq * 1000UL;
+ else if(channel != NULL)
+ freq = channel->freq;
+
+
+ if(dvbin_param_srate)
+ srate = dvbin_param_srate * 1000UL;
+ else if(channel != NULL)
+ srate = channel->srate;
+
+ if((1<= dvbin_param_diseqc) && (dvbin_param_diseqc <= 4))
+ diseqc = dvbin_param_diseqc;
+ else
+ if(channel != NULL)
+ if(channel->diseqc != old_diseqc)
+ diseqc = channel->diseqc;
+ else
+ diseqc = 0;
+ else
+ diseqc = 0;
+ mp_msg(MSGT_DEMUX, MSGL_INFO, "DISEQC: %d\n", diseqc);
+
+ if((dvbin_param_tone == 0) || (dvbin_param_tone == 1))
+ tone = dvbin_param_tone;
+ else
+ if(channel != NULL)
+ tone = channel->tone;
+ else
+ tone = -1;
+
+ if(! strcmp(dvbin_param_pol, "V")) pol = 'V';
+ else if(! strcmp(dvbin_param_pol, "H")) pol = 'H';
+ else if(channel != NULL) pol = channel->pol;
+ else pol='V';
+ pol = toupper(pol);
+
+
+ if(!strcmp(dvbin_param_inv, "INVERSION_ON"))
+ specInv = INVERSION_ON;
+ else if(!strcmp(dvbin_param_inv, "INVERSION_OFF"))
+ specInv = INVERSION_OFF;
+ else if(!strcmp(dvbin_param_inv, "INVERSION_AUTO"))
+ specInv = INVERSION_AUTO;
+ else if(channel != NULL)
+ specInv = channel->inv;
+ else
+ specInv = INVERSION_AUTO;
+
+
+ if(dvbin_param_mod)
+ {
+ switch(dvbin_param_mod)
+ {
+ case 16: modulation=QAM_16; break;
+ case 32: modulation=QAM_32; break;
+ case 64: modulation=QAM_64; break;
+ case 128: modulation=QAM_128; break;
+ case 256: modulation=QAM_256; break;
+ default:
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "Invalid QAM rate: %s\n", dvbin_param_mod);
+ modulation=CONSTELLATION_DEFAULT;
+ }
+ }
+ else if(channel != NULL)
+ modulation = channel->mod;
+ else
+ modulation=CONSTELLATION_DEFAULT;
+
+
+ if(dvbin_param_gi)
+ {
+ switch(dvbin_param_gi)
+ {
+ case 32: guardInterval=GUARD_INTERVAL_1_32; break;
+ case 16: guardInterval=GUARD_INTERVAL_1_16; break;
+ case 8: guardInterval=GUARD_INTERVAL_1_8; break;
+ case 4: guardInterval=GUARD_INTERVAL_1_4; break;
+ default:
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "Invalid Guard Interval: %s\n", dvbin_param_gi);
+ guardInterval=GUARD_INTERVAL_DEFAULT;
+ }
+ }
+ else if(channel != NULL)
+ guardInterval = channel->gi;
+ else
+ guardInterval=GUARD_INTERVAL_DEFAULT;
+
+ if(dvbin_param_tm)
+ {
+ switch(dvbin_param_tm)
+ {
+ case 8: TransmissionMode=TRANSMISSION_MODE_8K; break;
+ case 2: TransmissionMode=TRANSMISSION_MODE_2K; break;
+ default:
+ TransmissionMode=TRANSMISSION_MODE_DEFAULT;
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "Invalid Transmission Mode: %s\n", dvbin_param_tm);
+ }
+ }
+ else if(channel != NULL)
+ TransmissionMode = channel->trans;
+ else
+ TransmissionMode=TRANSMISSION_MODE_DEFAULT;
+
+
+ if(dvbin_param_bw)
+ {
+ switch(dvbin_param_bw)
+ {
+ case 8: bandWidth=BANDWIDTH_8_MHZ; break;
+ case 7: bandWidth=BANDWIDTH_7_MHZ; break;
+ case 6: bandWidth=BANDWIDTH_6_MHZ; break;
+ default:
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "Invalid DVB-T bandwidth: %s\n", dvbin_param_bw);
+ bandWidth=BANDWIDTH_DEFAULT;
+ }
+ }
+ else if(channel != NULL)
+ bandWidth = channel->bw;
+ else
+ bandWidth=BANDWIDTH_DEFAULT;
+
+
+ if(dvbin_param_cr)
+ {
+ switch(dvbin_param_cr)
+ {
+ case -1: HP_CodeRate=FEC_AUTO; break;
+ case 12: HP_CodeRate=FEC_1_2; break;
+ case 23: HP_CodeRate=FEC_2_3; break;
+ case 34: HP_CodeRate=FEC_3_4; break;
+ case 56: HP_CodeRate=FEC_5_6; break;
+ case 78: HP_CodeRate=FEC_7_8; break;
+ default:
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "Invalid Code Rate: %s\n", dvbin_param_cr);
+ HP_CodeRate=HP_CODERATE_DEFAULT;
+ }
+ }
+ else if(channel != NULL)
+ HP_CodeRate = channel->cr;
+ else
+ HP_CodeRate=HP_CODERATE_DEFAULT;
+
+
+
+ card = dvbin_param_card - 1;
+ if((card < 0) || (card > 4))
+ card = 0;
+
+
+ dvbin_param_on = 1;
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "CARD: %d, FREQ: %d, POL: %c, SRATE: %d, DISEQC: %d, TONE: %d, VPID: %d, APID: %d\n", card, freq, pol, srate, diseqc, tone, pids[0], pids[1]);
+
+ priv->channel.freq = freq;
+ priv->channel.srate = srate;
+ priv->channel.diseqc = diseqc;
+ priv->channel.pol = pol;
+ priv->channel.tone = tone;
+ priv->channel.inv = specInv;
+ priv->channel.mod = modulation;
+ priv->channel.gi = guardInterval;
+ priv->channel.trans = TransmissionMode;
+ priv->channel.bw = bandWidth;
+ priv->channel.cr = HP_CodeRate;
+
+ if(freq && pol && srate)
+ if (! dvb_tune(priv, freq, pol, srate, diseqc, tone, specInv, modulation, guardInterval, TransmissionMode, bandWidth, HP_CodeRate))
+ return 0;
+
+ for (i=0; i < npids; i++)
+ {
+ if((priv->demux_fd[i] = open(demuxdev[card], O_RDWR)) < 0)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR OPENING DEMUX %i: ", i);
+ return -1;
+ }
+ }
+
+ if((priv->dvr_fd = open(dvrdev[card], O_RDONLY| O_NONBLOCK)) < 0)
+ {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "DVR DEVICE: ");
+ return -1;
+ }
+
+
+ /* Now we set the filters */
+ for (i=0; i< npids; i++)
+ {
+ set_ts_filt(priv->demux_fd[i], pids[i], pestypes[i]);
+ //make_nonblock(fd[i]);
+ }
+
+
+ stream->fd = priv->dvr_fd;
+
+ dvbin_is_active = 1;
+
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "ESCO da dvb_streaming_start(s)\n");
+
+ return 1;
+}
+
+
+int dvbin_close(dvb_priv_t *priv)
+{
+ //close(priv->dvr_fd);
+ close(priv->demux_fd[0]);
+ close(priv->demux_fd[1]);
+}
diff --git a/libmpdemux/dvbin.h b/libmpdemux/dvbin.h
new file mode 100644
index 0000000000..1fea471b9c
--- /dev/null
+++ b/libmpdemux/dvbin.h
@@ -0,0 +1,102 @@
+
+#ifndef DVBIN_H
+#define DVBIN_H
+
+extern int dvbin_param_on;
+
+#ifdef HAVE_DVB_HEAD
+ #include <linux/dvb/dmx.h>
+ #include <linux/dvb/frontend.h>
+#else
+ #include <ost/dmx.h>
+ #include <ost/sec.h>
+ #include <ost/frontend.h>
+ #define fe_status_t FrontendStatus
+ #define fe_spectral_inversion_t SpectralInversion
+ #define fe_modulation_t Modulation
+ #define fe_code_rate_t CodeRate
+ #define fe_transmit_mode_t TransmitMode
+ #define fe_guard_interval_t GuardInterval
+ #define fe_bandwidth_t BandWidth
+ #define fe_sec_voltage_t SecVoltage
+ #define dmx_pes_filter_params dmxPesFilterParams
+ #define dmx_sct_filter_params dmxSctFilterParams
+ #define dmx_pes_type_t dmxPesType_t
+#endif
+
+
+
+#define DVB_CHANNEL_LOWER -1
+#define DVB_CHANNEL_HIGHER 1
+
+
+typedef struct
+{
+ int next, prev;
+} dvb_history_t;
+
+typedef struct {
+ char *name;
+ int freq, srate, diseqc, tone;
+ char pol;
+ int vpid, apid1, apid2, tpid, dpid1, dpid2, progid, ca;
+ fe_spectral_inversion_t inv;
+ fe_modulation_t mod;
+ fe_transmit_mode_t trans;
+ fe_bandwidth_t bw;
+ fe_guard_interval_t gi;
+ fe_code_rate_t cr;
+} dvb_channel_t;
+
+
+typedef struct {
+ uint16_t NUM_CHANNELS;
+ uint16_t current;
+ dvb_channel_t channels[512];
+} dvb_channels_list;
+
+
+
+typedef struct {
+ int fe_fd;
+ int sec_fd;
+ int demux_fd[3];
+ int dvr_fd;
+ int input;
+ int output;
+ int discard;
+
+ dvb_channel_t channel;
+ dvb_channels_list *list;
+} dvb_priv_t;
+
+
+extern dvb_history_t *dvb_step_channel(dvb_priv_t*, int, dvb_history_t*);
+
+extern dvb_channels_list *dvb_get_channels(char *, const char *);
+extern dvb_history_t dvb_prev_next;
+
+
+
+
+#ifndef DVB_T_LOCATION
+ #ifndef UK
+ #warning No DVB-T country defined in dvb_defaults.h, defaulting to UK
+ #endif
+
+ /* UNITED KINGDOM settings */
+ #define DVB_T_LOCATION "in United Kingdom"
+ #define BANDWIDTH_DEFAULT BANDWIDTH_8_MHZ
+ #define HP_CODERATE_DEFAULT FEC_2_3
+ #define CONSTELLATION_DEFAULT QAM_64
+ #define TRANSMISSION_MODE_DEFAULT TRANSMISSION_MODE_2K
+ #define GUARD_INTERVAL_DEFAULT GUARD_INTERVAL_1_32
+ #define HIERARCHY_DEFAULT HIERARCHY_NONE
+#endif
+
+#define HIERARCHY_DEFAULT HIERARCHY_NONE
+#define LP_CODERATE_DEFAULT (0)
+
+
+
+#endif
diff --git a/libmpdemux/open.c b/libmpdemux/open.c
index add424d8cf..111e256b67 100644
--- a/libmpdemux/open.c
+++ b/libmpdemux/open.c
@@ -30,6 +30,8 @@ int isSDPFile = 0;
static URL_t* url;
#endif
+int dvbin_param_on=0;
+
int dvd_title=0;
int dvd_chapter=1;
int dvd_last_chapter=0;
@@ -76,6 +78,12 @@ extern int vcd_get_track_end(int fd,int track);
extern int stream_open_tv(stream_t *stream, tvi_handle_t *tvh);
#endif
+#ifdef HAS_DVBIN_SUPPORT
+#include "dvbin.h"
+#endif
+
+
+
#ifdef HAVE_CDDA
stream_t* open_cdda(char* dev,char* track);
#ifdef STREAMING
@@ -478,6 +486,22 @@ if(dvd_title){
}
#endif
+#ifdef HAS_DVBIN_SUPPORT
+if(dvbin_param_on == 1)
+{
+ stream = new_stream(-1, STREAMTYPE_DVB);
+ if (!stream)
+ return(NULL);
+ if (!dvb_streaming_start(stream))
+ return NULL;
+
+ return stream;
+}
+#endif
+
+
+
+
//============ Check for TV-input or multi-file input ====
if( (mf_support == 1)
#ifdef USE_TV
diff --git a/libmpdemux/stream.c b/libmpdemux/stream.c
index 18b45c56e4..ac1fb49d75 100644
--- a/libmpdemux/stream.c
+++ b/libmpdemux/stream.c
@@ -106,6 +106,15 @@ int stream_fill_buffer(stream_t *s){
case STREAMTYPE_DS:
len = demux_read_data((demux_stream_t*)s->priv,s->buffer,STREAM_BUFFER_SIZE);
break;
+
+#ifdef HAS_DVBIN_SUPPORT
+ case STREAMTYPE_DVB:
+ len = dvb_streaming_read(s->fd, s->buffer, STREAM_BUFFER_SIZE, s->priv);
+ break;
+#endif
+
+
+
default: len=0;
}
if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; }
@@ -309,6 +318,12 @@ void free_stream(stream_t *s){
close_cdda(s);
break;
#endif
+#ifdef HAS_DVBIN_SUPPORT
+ case STREAMTYPE_DVB:
+ dvbin_close(s->priv);
+ break;
+#endif
+
#ifdef USE_DVDREAD
case STREAMTYPE_DVD:
dvd_close(s->priv);
diff --git a/libmpdemux/stream.h b/libmpdemux/stream.h
index 9ba790acb7..aabadd2658 100644
--- a/libmpdemux/stream.h
+++ b/libmpdemux/stream.h
@@ -18,6 +18,7 @@
#define STREAMTYPE_CDDA 10 // raw audio CD reader
#define STREAMTYPE_SMB 11 // smb:// url, using libsmbclient (samba)
#define STREAMTYPE_VCDBINCUE 12 // vcd directly from bin/cue files
+#define STREAMTYPE_DVB 13
#define STREAM_BUFFER_SIZE 2048
diff --git a/libmpdemux/video.c b/libmpdemux/video.c
index 3049638afa..5fee28e57b 100644
--- a/libmpdemux/video.c
+++ b/libmpdemux/video.c
@@ -134,6 +134,7 @@ switch(d_video->demuxer->file_format){
// otherwise fall through to...
#endif
case DEMUXER_TYPE_PVA:
+ case DEMUXER_TYPE_MPEG_TS:
case DEMUXER_TYPE_MPEG_ES:
case DEMUXER_TYPE_MPEG_PS: {
//mpeg_header_parser:
@@ -270,7 +271,7 @@ int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char**
*start=NULL;
if(demuxer->file_format==DEMUXER_TYPE_MPEG_ES || demuxer->file_format==DEMUXER_TYPE_MPEG_PS
- || demuxer->file_format==DEMUXER_TYPE_PVA
+ || demuxer->file_format==DEMUXER_TYPE_PVA || demuxer->file_format==DEMUXER_TYPE_MPEG_TS
#ifdef STREAMING_LIVE_DOT_COM
|| (demuxer->file_format==DEMUXER_TYPE_RTP && demux_is_mpeg_rtp_stream(demuxer))
#endif
@@ -422,6 +423,7 @@ int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char**
}
if(demuxer->file_format==DEMUXER_TYPE_MPEG_PS ||
+ demuxer->file_format==DEMUXER_TYPE_MPEG_TS ||
demuxer->file_format==DEMUXER_TYPE_MPEG_ES){
// if(pts>0.0001) printf("\r!!! pts: %5.3f [%d] (%5.3f) \n",pts,picture_coding_type,i_pts);
diff --git a/mencoder.c b/mencoder.c
index 01ef13ba66..5f685b565a 100644
--- a/mencoder.c
+++ b/mencoder.c
@@ -422,7 +422,7 @@ if(!parse_codec_cfg(get_path("codecs.conf"))){
}
#endif
- if(!filename && !vcd_track && !dvd_title && !tv_param_on){
+ if(!filename && !vcd_track && !dvd_title && !tv_param_on && !dvbin_param_on){
printf(MSGTR_MissingFilename);
mencoder_exit(1,NULL);
}
diff --git a/mplayer.c b/mplayer.c
index 8d5210ed0b..741536de50 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -92,6 +92,13 @@ static int quiet=0;
extern int tv_param_on;
#endif
+#ifdef HAS_DVBIN_SUPPORT
+#include "libmpdemux/dvbin.h"
+extern dvb_history_t dvb_prev_next;
+dvb_history_t *dvb_history;
+#endif
+
+
//**************************************************************************//
// Playtree
//**************************************************************************//
@@ -661,6 +668,13 @@ int i;
int gui_no_filename=0;
+#ifdef HAS_DVBIN_SUPPORT
+ dvb_prev_next.prev = dvb_prev_next.next = -1;
+ dvb_history = &dvb_prev_next;
+#endif
+
+
+
srand((int) time(NULL));
mp_msg_init();
@@ -928,7 +942,7 @@ if(!parse_codec_cfg(get_path("codecs.conf"))){
}
#endif
- if(!filename && !vcd_track && !dvd_title && !dvd_nav && !tv_param_on){
+ if(!filename && !vcd_track && !dvd_title && !dvd_nav && !tv_param_on && !dvbin_param_on){
if(!use_gui){
// no file/vcd/dvd -> show HELP:
mp_msg(MSGT_CPLAYER, MSGL_INFO, help_text);
@@ -2641,7 +2655,21 @@ if (stream->type==STREAMTYPE_DVDNAV && dvd_nav_still)
#endif
}
}
- } break;
+ }
+#ifdef HAS_DVBIN_SUPPORT
+ if(dvbin_param_on == 1)
+ {
+ int v = cmd->args[0].v.i;
+ if(v > 0)
+ dvb_history = dvb_step_channel((dvb_priv_t*)(demuxer->stream->priv), DVB_CHANNEL_HIGHER, dvb_history);
+ else
+ dvb_history = dvb_step_channel((dvb_priv_t*)(demuxer->stream->priv), DVB_CHANNEL_LOWER, dvb_history);
+ uninit_player(INITED_ALL);
+ goto goto_next_file;
+ }
+#endif
+
+ break;
case MP_CMD_TV_SET_CHANNEL : {
if (tv_param_on == 1) {
tv_set_channel((tvi_handle_t*)(demuxer->priv), cmd->args[0].v.s);
@@ -3363,7 +3391,11 @@ while(playtree_iter != NULL) {
}
#endif
-if(use_gui || playtree_iter != NULL){
+if(use_gui || playtree_iter != NULL
+#ifdef HAS_DVBIN_SUPPORT
+ || dvbin_param_on
+#endif
+ ){
eof = 0;
goto play_next_file;