mirror of
https://github.com/mpv-player/mpv
synced 2025-01-01 04:36:24 +01:00
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:
parent
79102684ed
commit
5c49cd8e07
16
cfg-common.h
16
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;
|
||||
|
4
configure
vendored
4
configure
vendored
@ -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
|
||||
|
@ -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
903
libmpdemux/demux_ts.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
89
libmpdemux/dvb_defaults.h
Normal 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
803
libmpdemux/dvb_tune.c
Normal 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
684
libmpdemux/dvbin.c
Normal 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
102
libmpdemux/dvbin.h
Normal 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
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
38
mplayer.c
38
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;
|
||||
|
Loading…
Reference in New Issue
Block a user