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
This commit is contained in:
arpi 2003-03-16 20:13:28 +00:00
parent 79102684ed
commit 5c49cd8e07
16 changed files with 2714 additions and 10 deletions

View File

@ -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;

4
configure vendored
View File

@ -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

View File

@ -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)

903
libmpdemux/demux_ts.c Normal file
View File

@ -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;
}

View File

@ -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)

View File

@ -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

89
libmpdemux/dvb_defaults.h Normal file
View File

@ -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

803
libmpdemux/dvb_tune.c Normal file
View File

@ -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));
}

684
libmpdemux/dvbin.c Normal file
View File

@ -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]);
}

102
libmpdemux/dvbin.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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;