From eadff9a874810b5963dd483a044a481c291a6199 Mon Sep 17 00:00:00 2001 From: Guenter Bartsch Date: Fri, 27 Dec 2002 00:53:49 +0000 Subject: finally - dvb support in xine :) CVS patchset: 3687 CVS date: 2002/12/27 00:53:49 --- src/demuxers/demux_ts.c | 50 ++- src/input/Makefile.am | 9 +- src/input/input_dvb.c | 865 ++++++++++++++++++++++++++++++++++++++++ src/input/ost/Makefile.am | 22 + src/input/ost/README | 9 + src/input/ost/ca.h | 84 ++++ src/input/ost/demux.h | 346 ++++++++++++++++ src/input/ost/dmx.h | 141 +++++++ src/input/ost/frontend.h | 208 ++++++++++ src/input/ost/sec.h | 118 ++++++ src/xine-engine/audio_decoder.c | 18 +- src/xine-engine/xine.c | 4 +- 12 files changed, 1860 insertions(+), 14 deletions(-) create mode 100644 src/input/input_dvb.c create mode 100644 src/input/ost/Makefile.am create mode 100644 src/input/ost/README create mode 100644 src/input/ost/ca.h create mode 100644 src/input/ost/demux.h create mode 100644 src/input/ost/dmx.h create mode 100644 src/input/ost/frontend.h create mode 100644 src/input/ost/sec.h (limited to 'src') diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index e4ef198ef..9cc331830 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_ts.c,v 1.71 2002/12/21 12:56:46 miguelfreitas Exp $ + * $Id: demux_ts.c,v 1.72 2002/12/27 00:53:49 guenter Exp $ * * Demultiplexer for MPEG2 Transport Streams. * @@ -139,8 +139,7 @@ #include "xine_internal.h" #include "xineutils.h" #include "demux.h" - -#define VALID_MRLS "fifo,stdin,dvb,tcp" +#include "events.h" /* #define TS_LOG @@ -285,6 +284,9 @@ typedef struct { demux_ts_spu_lang spu_langs[MAX_NO_SPU_LANGS]; int no_spu_langs; int current_spu_channel; + + /* dvb */ + xine_event_queue_t *event_queue; } demux_ts_t; typedef struct { @@ -1597,6 +1599,33 @@ static void demux_ts_parse_packet (demux_ts_t*this) { } } +/* + * check for pids change events + */ + +static void demux_ts_event_handler (demux_ts_t *this) { + + xine_event_t *event; + + while ((event = xine_event_get (this->event_queue))) { + + + switch (event->type) { + + case XINE_EVENT_PIDS_CHANGE: + + this->videoPid = INVALID_PID; + this->audioPid = INVALID_PID; + this->media_num = 0; + this->send_newpts = 1; + + break; + + } + + xine_event_free (event); + } +} /* * send a piece of data down the fifos @@ -1606,14 +1635,15 @@ static int demux_ts_send_chunk (demux_plugin_t *this_gen) { demux_ts_t*this = (demux_ts_t*)this_gen; + demux_ts_event_handler (this); + demux_ts_parse_packet(this); /* DVBSUB: check if channel has changed. Dunno if I should, or * even could, lock the xine object. */ - if (this->stream->spu_channel != this->current_spu_channel) - { - demux_ts_update_spu_channel(this); - } + if (this->stream->spu_channel != this->current_spu_channel) { + demux_ts_update_spu_channel(this); + } return this->status; } @@ -1629,6 +1659,9 @@ static void demux_ts_dispose (demux_plugin_t *this_gen) { if (this->media[i].buf != NULL) this->media[i].buf->free_buffer(this->media[i].buf); } + + xine_event_dispose_queue (this->event_queue); + free(this_gen); } @@ -1953,6 +1986,9 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, this->spu_pid = INVALID_PID; this->no_spu_langs = 0; this->current_spu_channel = this->stream->spu_channel; + + /* dvb */ + this->event_queue = xine_event_new_queue (this->stream); return &this->demux_plugin; } diff --git a/src/input/Makefile.am b/src/input/Makefile.am index d19cf63e5..1304163ab 100644 --- a/src/input/Makefile.am +++ b/src/input/Makefile.am @@ -3,9 +3,9 @@ ## if HAVE_DVDNAV -SUBDIRS = libreal librtsp libdvdread +SUBDIRS = ost libreal librtsp libdvdread else -SUBDIRS = libreal librtsp libdvdread libdvdnav +SUBDIRS = ost libreal librtsp libdvdread libdvdnav endif LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic @@ -48,6 +48,7 @@ lib_LTLIBRARIES = \ $(in_vcd) \ xineplug_inp_mms.la \ xineplug_inp_stdin_fifo.la \ + xineplug_inp_dvb.la \ xineplug_inp_pnm.la \ xineplug_inp_rtsp.la \ xineplug_inp_net.la @@ -104,6 +105,10 @@ xineplug_inp_pnm_la_SOURCES = input_pnm.c net_buf_ctrl.c pnm.c xineplug_inp_pnm_la_LIBADD = $(XINE_LIB) xineplug_inp_pnm_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ +xineplug_inp_dvb_la_SOURCES = input_dvb.c net_buf_ctrl.c +xineplug_inp_dvb_la_LIBADD = $(XINE_LIB) +xineplug_inp_dvb_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ + xineplug_inp_rtsp_la_SOURCES = input_rtsp.c net_buf_ctrl.c xineplug_inp_rtsp_la_LIBADD = $(XINE_LIB) libreal/libreal.la librtsp/librtsp.la xineplug_inp_rtsp_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ diff --git a/src/input/input_dvb.c b/src/input/input_dvb.c new file mode 100644 index 000000000..12ad6dd09 --- /dev/null +++ b/src/input/input_dvb.c @@ -0,0 +1,865 @@ +/* + * 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 + * + * + * input plugin for Digital TV (Digital Video Broadcast - DVB) devices + * e.g. Hauppauge WinTV Nova supported by DVB drivers from Convergence + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ost/dmx.h" +#include "ost/sec.h" +#include "ost/frontend.h" + +#include "xine_internal.h" +#include "xineutils.h" +#include "events.h" +#include "input_plugin.h" +#include "net_buf_ctrl.h" + +/* +#define LOG +*/ + +extern int errno; + +#define FRONTEND_DEVICE "/dev/ost/frontend" +#define SEC_DEVICE "/dev/ost/sec" +#define DEMUX_DEVICE "/dev/ost/demux" +#define DVR_DEVICE "/dev/ost/dvr" + +#define BUFSIZE 4096 + +#define NOPID 0xffff + +typedef struct { + int fd_frontend; + int fd_sec; + int fd_demuxa, fd_demuxv, fd_demuxtt; + + FrontendInfo feinfo; + FrontendParameters front_param; + + struct secCommand scmd; + struct secCmdSequence scmds; + struct dmxPesFilterParams pesFilterParamsV; + struct dmxPesFilterParams pesFilterParamsA; + struct dmxPesFilterParams pesFilterParamsTT; + +} tuner_t; + +typedef struct { + + char *name; + int freq; /* freq - lof */ + int tone; /* SEC_TONE_ON/OFF */ + int volt; /* SC_VOLTAGE_13/18 */ + int diseqcnr; + int srate; + int fec; + int vpid; + int apid; + +} channel_t; + +typedef struct { + + input_class_t input_class; + + xine_t *xine; + + char *mrls[2]; + +} dvb_input_class_t; + +typedef struct { + input_plugin_t input_plugin; + + dvb_input_class_t *cls; + + xine_stream_t *stream; + + char *mrl; + + off_t curpos; + + nbc_t *nbc; + + tuner_t *tuner; + channel_t *channels; + int fd; + int num_channels; + int channel; + pthread_mutex_t mutex; + + osd_object_t *osd; + + xine_event_queue_t *event_queue; + + /* scratch buffer for forward seeking */ + char seek_buf[BUFSIZE]; + + int out_fd; /* recording function */ + +} dvb_input_plugin_t; + + +static tuner_t *tuner_init () { + + tuner_t *this; + + this = malloc (sizeof (tuner_t)); + + if ((this->fd_frontend = open(FRONTEND_DEVICE, O_RDWR)) < 0){ + perror("FRONTEND DEVICE: "); + free (this); + return NULL; + } + + ioctl (this->fd_frontend, FE_GET_INFO, &this->feinfo); + if (this->feinfo.type==FE_QPSK) { + + if ((this->fd_sec = open (SEC_DEVICE, O_RDWR)) < 0) { + perror ("SEC DEVICE: "); + free (this); + return NULL; + } + } + + this->fd_demuxtt = open (DEMUX_DEVICE, O_RDWR); + if (this->fd_demuxtt < 0) { + perror ("DEMUX DEVICE tt: "); + free (this); + return NULL; + } + + this->fd_demuxa = open (DEMUX_DEVICE, O_RDWR); + if (this->fd_demuxa < 0) { + perror ("DEMUX DEVICE audio: "); + free (this); + return NULL; + } + + this->fd_demuxv=open (DEMUX_DEVICE, O_RDWR); + if (this->fd_demuxv < 0) { + perror ("DEMUX DEVICE video: "); + free (this); + return NULL; + } + + return this; +} + +static void tuner_dispose (tuner_t *this) { + + close (this->fd_frontend); + close (this->fd_sec); + close (this->fd_demuxa); + close (this->fd_demuxv); + close (this->fd_demuxtt); + + free (this); +} + +static void tuner_set_vpid (tuner_t *this, ushort vpid) { + + if (vpid==0 || vpid==NOPID || vpid==0x1fff) { + ioctl (this->fd_demuxv, DMX_STOP, 0); + return; + } + + this->pesFilterParamsV.pid = vpid; + this->pesFilterParamsV.input = DMX_IN_FRONTEND; + this->pesFilterParamsV.output = DMX_OUT_TS_TAP; + this->pesFilterParamsV.pesType = DMX_PES_VIDEO; + this->pesFilterParamsV.flags = DMX_IMMEDIATE_START; + if (ioctl(this->fd_demuxv, DMX_SET_PES_FILTER, + &this->pesFilterParamsV) < 0) + perror("set_vpid"); +} + +static void tuner_set_apid (tuner_t *this, ushort apid) { + if (apid==0 || apid==NOPID || apid==0x1fff) { + ioctl (this->fd_demuxa, DMX_STOP, apid); + return; + } + + this->pesFilterParamsA.pid = apid; + this->pesFilterParamsA.input = DMX_IN_FRONTEND; + this->pesFilterParamsA.output = DMX_OUT_TS_TAP; + this->pesFilterParamsA.pesType = DMX_PES_AUDIO; + this->pesFilterParamsA.flags = DMX_IMMEDIATE_START; + if (ioctl (this->fd_demuxa, DMX_SET_PES_FILTER, + &this->pesFilterParamsA) < 0) + perror("set_apid"); +} + +static void tuner_set_ttpid (tuner_t *this, ushort ttpid) { + + if (ttpid==0 || ttpid== NOPID || ttpid==0x1fff) { + ioctl (this->fd_demuxtt, DMX_STOP, 0); + return; + } + this->pesFilterParamsTT.pid = ttpid; + this->pesFilterParamsTT.input = DMX_IN_FRONTEND; + this->pesFilterParamsTT.output = DMX_OUT_DECODER; + this->pesFilterParamsTT.pesType = DMX_PES_TELETEXT; + this->pesFilterParamsTT.flags = DMX_IMMEDIATE_START; + if (ioctl(this->fd_demuxtt, DMX_SET_PES_FILTER, + &this->pesFilterParamsTT) < 0) { + /* printf("PID=%04x\n", ttpid); */ + perror("set_ttpid"); + } +} + +static void tuner_get_front (tuner_t *this) { + tuner_set_vpid (this, 0); + tuner_set_apid (this, 0); + tuner_set_ttpid(this, 0); + this->scmds.voltage = SEC_VOLTAGE_13; + this->scmds.miniCommand = SEC_MINI_NONE; + this->scmds.continuousTone = SEC_TONE_OFF; + this->scmds.numCommands = 1; + this->scmds.commands = &this->scmd; +} + +static void tuner_set_diseqc_nr (tuner_t *this, int nr) { + + this->scmd.type=0; + this->scmd.u.diseqc.addr = 0x10; + this->scmd.u.diseqc.cmd = 0x38; + this->scmd.u.diseqc.numParams = 1; + this->scmd.u.diseqc.params[0] = 0xF0 | ((nr * 4) & 0x0F) | + (this->scmds.continuousTone == SEC_TONE_ON ? 1 : 0) | + (this->scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0); +} + +static void tuner_set_tp (tuner_t *this, int freq, int tone, + int volt, int diseqcnr, + int srate, int fec) { + + static const uint8_t rfectab[9] = {1,2,3,0,4,0,5,0,0}; + + this->front_param.Frequency = freq; + this->scmds.continuousTone = tone; + this->scmds.voltage = volt; + tuner_set_diseqc_nr (this, diseqcnr); + this->front_param.u.qpsk.SymbolRate = srate; + this->front_param.u.qpsk.FEC_inner = (CodeRate)rfectab[fec]; + this->front_param.Inversion = INVERSION_AUTO; +} + +static int tuner_tune_it (tuner_t *this, FrontendParameters *front_param) { + FrontendEvent event; + struct pollfd pfd[1]; + + if (ioctl(this->fd_frontend, FE_SET_FRONTEND, front_param) <0) + perror("setfront front"); + + pfd[0].fd=this->fd_frontend; + pfd[0].events=POLLIN; + if (poll(pfd,1,2000)) { + if (pfd[0].revents & POLLIN){ + if (ioctl(this->fd_frontend, FE_GET_EVENT, &event) + == -EBUFFEROVERFLOW){ + perror("fe get event"); + return 0; + } + switch(event.type){ + case FE_UNEXPECTED_EV: + perror("unexpected event\n"); + return 0; + case FE_FAILURE_EV: + perror("failure event\n"); + return 0; + + case FE_COMPLETION_EV: + fprintf(stderr, "completion event\n"); + return 1; + } + } + } + return 0; +} + + +static int tuner_set_front (tuner_t *this) { + this->scmds.miniCommand = SEC_MINI_NONE; + this->scmds.numCommands=1; + this->scmds.commands=&this->scmd; + + tuner_set_vpid (this, 0); + tuner_set_apid (this, 0); + tuner_set_ttpid(this,0); + + if (this->feinfo.type==FE_QPSK) { + if (ioctl(this->fd_sec, SEC_SEND_SEQUENCE, &this->scmds) < 0) + perror("setfront sec"); + usleep(70000); + } + return tuner_tune_it(this, &this->front_param); +} + +static void print_channel (channel_t *channel) { + + printf ("input_dvb: channel '%s' diseqc %d freq %d volt %d srate %d fec %d vpid %d apid %d\n", + channel->name, + channel->diseqcnr, + channel->freq, + channel->volt, + channel->srate, + channel->fec, + channel->vpid, + channel->apid); + +} + + +static int tuner_set_channel (tuner_t *this, + channel_t *c) { + + print_channel (c); + + tuner_get_front (this); + tuner_set_tp (this, c->freq, c->tone, c->volt, c->diseqcnr, c->srate, c->fec); + if (!tuner_set_front (this)) + return 0; + + tuner_set_vpid (this, c->vpid); + tuner_set_apid (this, c->apid); + tuner_set_ttpid (this, 0); + + return 1; /* fixme: error handling */ +} + +static void osd_show_channel (dvb_input_plugin_t *this) { + + printf ("input_dvb: channel=%d\n", this->channel); + +#if 0 /* FIXME */ + int i, channel ; + + if (!this->osd) { + this->osd = this->stream->osd_renderer->new_object (this->stream->osd_renderer, + 410, 410); + this->stream->osd_renderer->set_position (this->osd, 20, 20); + this->stream->osd_renderer->set_font (this->osd, "cetus", 32); + this->stream->osd_renderer->set_text_palette (this->osd, + TEXTPALETTE_WHITE_NONE_TRANSLUCID, + OSD_TEXT3); + } + + this->stream->osd_renderer->filled_rect (this->osd, 0, 0, 395, 400, 2); + + channel = this->channel - 5; + + for (i=0; i<11; i++) { + + if ( (channel >= 0) && (channel < this->num_channels) ) + this->stream->osd_renderer->render_text (this->osd, 10, 10+i*35, + this->channels[channel].name, + OSD_TEXT3); + channel ++; + } + + this->stream->osd_renderer->line (this->osd, 5, 183, 390, 183, 10); + this->stream->osd_renderer->line (this->osd, 5, 183, 5, 219, 10); + this->stream->osd_renderer->line (this->osd, 5, 219, 390, 219, 10); + this->stream->osd_renderer->line (this->osd, 390, 183, 390, 219, 10); + + this->stream->osd_renderer->show (this->osd, 0); +#endif + +} + +static void switch_channel (dvb_input_plugin_t *this) { + + xine_event_t event; + xine_pids_data_t data; + + pthread_mutex_lock (&this->mutex); + + close (this->fd); + + if (!tuner_set_channel (this->tuner, &this->channels[this->channel])) { + printf ("input_dvb: tuner_set_channel failed\n"); + pthread_mutex_unlock (&this->mutex); + return; + } + + event.type = XINE_EVENT_PIDS_CHANGE; + data.vpid = this->channels[this->channel].vpid; + data.apid = this->channels[this->channel].apid; + event.data = &data; + event.data_length = sizeof (xine_pids_data_t); + + printf ("input_dvb: sending event\n"); + + xine_event_send (this->stream, &event); + + this->fd = open (DVR_DEVICE, O_RDONLY); + + pthread_mutex_unlock (&this->mutex); + +#if 0 /* FIXME */ + this->stream->osd_renderer->hide (this->osd, 0); +#endif +} + +static void dvb_event_handler (dvb_input_plugin_t *this) { + + xine_event_t *event; + + while ((event = xine_event_get (this->event_queue))) { + + if (this->fd<0) { + xine_event_free (event); + return; + } + + switch (event->type) { + + case XINE_EVENT_INPUT_NEXT: + if (this->channel < (this->num_channels-1)) + this->channel++; + osd_show_channel (this); + break; + + case XINE_EVENT_INPUT_PREVIOUS: + if (this->channel>0) + this->channel--; + osd_show_channel (this); + break; + + case XINE_EVENT_INPUT_DOWN: + if (this->channel < (this->num_channels-1)) { + this->channel++; + switch_channel (this); + } + break; + + case XINE_EVENT_INPUT_UP: + if (this->channel>0) { + this->channel--; + switch_channel (this); + } + break; + + case XINE_EVENT_INPUT_SELECT: + switch_channel (this); + break; + + case XINE_EVENT_INPUT_MENU3: + this->stream->osd_renderer->hide (this->osd, 0); + break; + +#if 0 + default: + printf ("input_dvb: got an event, type 0x%08x\n", event->type); +#endif + } + + xine_event_free (event); + } +} + +static off_t dvb_plugin_read (input_plugin_t *this_gen, + char *buf, off_t len) { + dvb_input_plugin_t *this = (dvb_input_plugin_t *) this_gen; + off_t n, total; + + dvb_event_handler (this); + +#ifdef LOG + printf ("input_dvb: reading %lld bytes...\n", len); +#endif + + nbc_check_buffers (this->nbc); + + pthread_mutex_lock( &this->mutex ); /* protect agains channel changes */ + total=0; + while (totalfd, &buf[total], len-total); + +#ifdef LOG + printf ("input_dvb: got %lld bytes (%lld/%lld bytes read)\n", + n,total,len); +#endif + + if (n > 0){ + this->curpos += n; + total += n; + } else if (n<0 && errno!=EAGAIN) { + pthread_mutex_unlock( &this->mutex ); + return total; + } + } + + if (this->out_fd>0) + write (this->out_fd, buf, total); + + pthread_mutex_unlock( &this->mutex ); + return total; +} + +static buf_element_t *dvb_plugin_read_block (input_plugin_t *this_gen, + fifo_buffer_t *fifo, off_t todo) { + /* dvb_input_plugin_t *this = (dvb_input_plugin_t *) this_gen; */ + buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + int total_bytes; + + +#if 0 + if (this->report_pids) { + + printf ("input_dvb: reporting pids %d (video), %d (audio)\n", + this->channels[this->channel].vpid, + this->channels[this->channel].apid); + + this->report_pids = 0; + + } +#endif + + buf->content = buf->mem; + buf->type = BUF_DEMUX_BLOCK; + + total_bytes = dvb_plugin_read (this_gen, buf->content, todo); + + if (total_bytes != todo) { + buf->free_buffer (buf); + return NULL; + } + + buf->size = total_bytes; + + return buf; +} + +static off_t dvb_plugin_seek (input_plugin_t *this_gen, off_t offset, + int origin) { + + dvb_input_plugin_t *this = (dvb_input_plugin_t *) this_gen; + +#ifdef LOG + printf ("input_dvb: seek %lld bytes, origin %d\n", + offset, origin); +#endif + + /* only relative forward-seeking is implemented */ + + if ((origin == SEEK_CUR) && (offset >= 0)) { + + for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { + this->curpos += dvb_plugin_read (this_gen, this->seek_buf, BUFSIZE); + } + + this->curpos += dvb_plugin_read (this_gen, this->seek_buf, offset); + } + + return this->curpos; +} + +static off_t dvb_plugin_get_length (input_plugin_t *this_gen) { + return 0; +} + +static uint32_t dvb_plugin_get_capabilities (input_plugin_t *this_gen) { + return 0; /* where did INPUT_CAP_AUTOPLAY go ?!? */ +} + +static uint32_t dvb_plugin_get_blocksize (input_plugin_t *this_gen) { + return 0; +} + +static off_t dvb_plugin_get_current_pos (input_plugin_t *this_gen){ + dvb_input_plugin_t *this = (dvb_input_plugin_t *) this_gen; + + return this->curpos; +} + +static void dvb_plugin_dispose (input_plugin_t *this_gen) { + dvb_input_plugin_t *this = (dvb_input_plugin_t *) this_gen; + + close(this->fd); + this->fd = -1; + + if (this->nbc) { + nbc_close (this->nbc); + this->nbc = NULL; + } + + if (this->out_fd>0) + close (this->out_fd); + + xine_event_dispose_queue (this->event_queue); + + free (this->mrl); + free (this); +} + +static char* dvb_plugin_get_mrl (input_plugin_t *this_gen) { + dvb_input_plugin_t *this = (dvb_input_plugin_t *) this_gen; + + return this->mrl; +} + +static int dvb_plugin_get_optional_data (input_plugin_t *this_gen, + void *data, int data_type) { + + return INPUT_OPTIONAL_UNSUPPORTED; +} + +static channel_t *load_channels (int *num_ch) { + + FILE *f; + unsigned char str[BUFSIZE]; + unsigned char filename[BUFSIZE]; + channel_t *channels; + int num_channels; + + snprintf (filename, BUFSIZE, "%s/.xine/dvb_channels", xine_get_homedir()); + + f = fopen (filename, "rb"); + if (!f) { + printf ("input_dvb: failed to open dvb channel file '%s'\n", filename); + return NULL; + } + + /* + * count and alloc channels + */ + num_channels = 0; + while ( fgets (str, BUFSIZE, f)) { + fgets (str, BUFSIZE, f); + num_channels++; + } + fclose (f); + printf ("input_dvb: %d channels found.\n", num_channels); + + channels = malloc (sizeof (channel_t) * num_channels); + + /* + * load channel list + */ + + f = fopen (filename, "rb"); + num_channels = 0; + while ( fgets (str, BUFSIZE, f)) { + + int freq; + + channels[num_channels].name = strdup (str); + + fgets (str, BUFSIZE, f); + + sscanf (str, "%d %d %d %d %d %d %d\n", + &channels[num_channels].diseqcnr, + &freq, + &channels[num_channels].volt, + &channels[num_channels].srate, + &channels[num_channels].fec, + &channels[num_channels].vpid, + &channels[num_channels].apid); + + if (freq > 11700000) { + channels[num_channels].freq = freq - 10600000; + channels[num_channels].tone = SEC_TONE_ON; + } else { + channels[num_channels].freq = freq - 9750000; + channels[num_channels].tone = SEC_TONE_OFF; + } + +#ifdef LOG + printf ("input: dvb channel %s loaded\n", channels[num_channels].name); +#endif + + num_channels++; + } + + *num_ch = num_channels; + return channels; +} + +static input_plugin_t *open_plugin (input_class_t *cls_gen, + xine_stream_t *stream, + const char *data) { + + dvb_input_class_t *cls = (dvb_input_class_t *) cls_gen; + dvb_input_plugin_t *this; + tuner_t *tuner; + channel_t *channels; + int num_channels; + char *mrl = (char *) data; + + if (strncasecmp (mrl, "dvb:/",5)) + return NULL; + + if ( !(tuner = tuner_init()) ) { + printf ("input_dvb: cannot open dvb device\n"); + return NULL; + } + + if ( !(channels = load_channels(&num_channels)) ) { + tuner_dispose (tuner); + return NULL; + } + + this = (dvb_input_plugin_t *) xine_xmalloc (sizeof(dvb_input_plugin_t)); + + this->tuner = tuner; + this->channels = channels; + + if ( sscanf (mrl, "dvb://%d", &this->channel) != 1) + this->channel = 0; + + if (!tuner_set_channel (this->tuner, &this->channels[this->channel])) { + printf ("input_dvb: tuner_set_channel failed\n"); + free (this); + return NULL; + } + + if ((this->fd = open (DVR_DEVICE, O_RDONLY)) < 0){ + printf ("input_dvb: cannot open dvr device '%s'\n", DVR_DEVICE); + free (this); + return NULL; + } + + this->mrl = strdup(mrl); + + this->curpos = 0; + this->nbc = nbc_init (stream); + this->stream = stream; + this->tuner = tuner; + this->channels = channels; + this->num_channels = num_channels; + this->osd = NULL; + + this->input_plugin.get_capabilities = dvb_plugin_get_capabilities; + this->input_plugin.read = dvb_plugin_read; + this->input_plugin.read_block = dvb_plugin_read_block; + this->input_plugin.seek = dvb_plugin_seek; + this->input_plugin.get_current_pos = dvb_plugin_get_current_pos; + this->input_plugin.get_length = dvb_plugin_get_length; + this->input_plugin.get_blocksize = dvb_plugin_get_blocksize; + this->input_plugin.get_mrl = dvb_plugin_get_mrl; + this->input_plugin.get_optional_data = dvb_plugin_get_optional_data; + this->input_plugin.dispose = dvb_plugin_dispose; + this->input_plugin.input_class = cls_gen; + this->cls = cls; + + /* + xine_register_event_listener (this->stream, dvb_event_listener, this); + */ + + pthread_mutex_init (&this->mutex, NULL); + +#if 0 + this->out_fd = open ("foo.ts", O_CREAT | O_WRONLY | O_TRUNC, 0644); +#else + this->out_fd = 0; +#endif + + this->event_queue = xine_event_new_queue (this->stream); + + return (input_plugin_t *) this; +} + +/* + * dvb input plugin class stuff + */ + +static char *dvb_class_get_description (input_class_t *this_gen) { + return _("DVB (Digital TV) input plugin"); +} + +static char *dvb_class_get_identifier (input_class_t *this_gen) { + return "dvb"; +} + +static void dvb_class_dispose (input_class_t *this_gen) { + + dvb_input_class_t *cls = (dvb_input_class_t *) this_gen; + + free (cls->mrls[0]); + + free (cls); +} + +static int dvb_class_eject_media (input_class_t *this_gen) { + return 1; +} + +static char ** dvb_class_get_autoplay_list (input_class_t *this_gen, + int *num_files) { + dvb_input_class_t *cls = (dvb_input_class_t *) this_gen; + + *num_files = 1; + return cls->mrls; +} + +static void *init_class (xine_t *xine, void *data) { + + dvb_input_class_t *this; + + this = (dvb_input_class_t *) xine_xmalloc (sizeof (dvb_input_class_t)); + + this->xine = xine; + + this->input_class.open_plugin = open_plugin; + this->input_class.get_identifier = dvb_class_get_identifier; + this->input_class.get_description = dvb_class_get_description; + this->input_class.get_dir = NULL; + this->input_class.get_autoplay_list = dvb_class_get_autoplay_list; + this->input_class.dispose = dvb_class_dispose; + this->input_class.eject_media = dvb_class_eject_media; + + this->mrls[0] = "dvb://"; + this->mrls[1] = 0; + + printf ("input_dvb: init class succeeded\n"); + + return this; +} + + +/* + * exported plugin catalog entry + */ + +plugin_info_t xine_plugin_info[] = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_INPUT, 11, "DVB", XINE_VERSION_CODE, NULL, init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; diff --git a/src/input/ost/Makefile.am b/src/input/ost/Makefile.am new file mode 100644 index 000000000..7c179a4af --- /dev/null +++ b/src/input/ost/Makefile.am @@ -0,0 +1,22 @@ +noinst_HEADERS = \ + demux.h \ + dmx.h \ + frontend.h \ + sec.h + +debug: + @list='$(SUBDIRS)'; for subdir in $$list; do \ + (cd $$subdir && $(MAKE) $@) || exit;\ + done; + @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)" + +install-debug: debug + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +mostlyclean-generic: + -rm -f *~ \#* .*~ .\#* + +maintainer-clean-generic: + -@echo "This command is intended for maintainers to use;" + -@echo "it deletes files that may require special tools to rebuild." + -rm -f Makefile.in diff --git a/src/input/ost/README b/src/input/ost/README new file mode 100644 index 000000000..5fc680215 --- /dev/null +++ b/src/input/ost/README @@ -0,0 +1,9 @@ +This directories contains header files for the Linux DVB drivers +from convergence integrated media GmbH + + Copyright (C) 2000 Ralph Metzler + & Marcus Metzler + for convergence integrated media GmbH + +released under the LGPL license. For details see the individual +header files. diff --git a/src/input/ost/ca.h b/src/input/ost/ca.h new file mode 100644 index 000000000..226ef5c09 --- /dev/null +++ b/src/input/ost/ca.h @@ -0,0 +1,84 @@ +/* + * ca.h + * + * Copyright (C) 2000 Ralph Metzler + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Lesser Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _OST_CA_H_ +#define _OST_CA_H_ + +/* slot interface types and info */ + +typedef struct ca_slot_info_s { + int num; /* slot number */ + + int type; /* CA interface this slot supports */ +#define CA_CI 1 /* CI high level interface */ +#define CA_CI_LINK 2 /* CI link layer level interface */ +#define CA_CI_PHYS 4 /* CI physical layer level interface */ +#define CA_SC 128 /* simple smart card interface */ + + unsigned int flags; +#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */ +#define CA_CI_MODULE_READY 2 +} ca_slot_info_t; + + +/* descrambler types and info */ + +typedef struct ca_descr_info_s { + unsigned int num; /* number of available descramblers (keys) */ + unsigned int type; /* type of supported scrambling system */ +#define CA_ECD 1 +#define CA_NDS 2 +#define CA_DSS 4 +} ca_descr_info_t; + +typedef struct ca_cap_s { + unsigned int slot_num; /* total number of CA card and module slots */ + unsigned int slot_type; /* OR of all supported types */ + unsigned int descr_num; /* total number of descrambler slots (keys) */ + unsigned int descr_type; /* OR of all supported types */ +} ca_cap_t; + +/* a message to/from a CI-CAM */ +typedef struct ca_msg_s { + unsigned int index; + unsigned int type; + unsigned int length; + unsigned char msg[256]; +} ca_msg_t; + +typedef struct ca_descr_s { + unsigned int index; + unsigned int parity; + unsigned char cw[8]; +} ca_descr_t; + +#define CA_RESET _IOW('o', 128, int) +#define CA_GET_CAP _IOR('o', 129, ca_cap_t *) +#define CA_GET_SLOT_INFO _IOR('o', 130, ca_slot_info_t *) +#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t *) +#define CA_GET_MSG _IOR('o', 132, ca_msg_t *) +#define CA_SEND_MSG _IOW('o', 133, ca_msg_t *) +#define CA_SET_DESCR _IOW('o', 134, ca_descr_t *) + +#endif + diff --git a/src/input/ost/demux.h b/src/input/ost/demux.h new file mode 100644 index 000000000..758e921b6 --- /dev/null +++ b/src/input/ost/demux.h @@ -0,0 +1,346 @@ +/* * demux.h * * Copyright (c) 2000 Nokia Research Center + * Tampere, FINLAND + * + * Project: + * Universal Broadcast Access + * + * Contains: + * Type definitions of a Linux kernel-level API for filtering MPEG-2 TS + * packets and MPEG-2 sections. Support for PES packet filtering will be + * added later. + * + * History: + * 12.01.2000/JPL File created - Initial version. + * 18.02.2000/JPL Minor corrections. + * 21.02.2000/JPL DMX_NAME_SIZE and dmx_in_use() removed, typos fixed, + * some names changed. + * 23.02.2000/JPL Added a parameter indicating the callback source in + * the callback functions. + * 10.03.2000/JPL Added the macros DMX_DIR_ENTRY() and DMX_FE_ENTRY(). + * 15.03.2000/JPL Added the capabilities field to dmx_demux_t. + * 22.03.2000/JPL Corrected the callback parameter in the + * allocate_x_feed() functions. + * 03.04.2000/JPL Added support for optional resource conflict resolution + * and scarce resource handling. + * 05.04.2000/JPL Changed the dmx_resolve_conflict() to use resource + * type as a parameter. + * 12.04.2000/JPL Added a second buffer parameter for dmx_x_callback() + * functions to better handle buffer wrapping. + * 26.04.2000/JPL Added functions for section-level descrambling. + * 03.09.2000/JPL Removed support for conflict resolution and scarce + * resource handling. Otherwise only minor changes to + * data structures and function prototypes. + * + * + * Author: + * Juha-Pekka Luoma (JPL) + * Nokia Research Center + * + * Notes: + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ +/* $Id: demux.h,v 1.1 2002/12/27 00:53:50 guenter Exp $ */ + +#ifndef __DEMUX_H +#define __DEMUX_H + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + +#include /* __u8, __u16, ... */ +#include /* list_entry(), struct list_head */ +#include /* struct timespec */ +#include /* Function return values */ + +/*--------------------------------------------------------------------------*/ +/* Common definitions */ +/*--------------------------------------------------------------------------*/ + +/* + * DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter. + */ + +#ifndef DMX_MAX_FILTER_SIZE +#define DMX_MAX_FILTER_SIZE 18 +#endif +/* + * dmx_success_t: Success codes for the Demux Callback API. + */ + +typedef enum { + DMX_OK = 0, /* Received Ok */ + DMX_LENGTH_ERROR, /* Incorrect length */ + DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */ + DMX_CRC_ERROR, /* Incorrect CRC */ + DMX_FRAME_ERROR, /* Frame alignment error */ + DMX_FIFO_ERROR, /* Receiver FIFO overrun */ + DMX_MISSED_ERROR /* Receiver missed packet */ +} dmx_success_t; + +/*--------------------------------------------------------------------------*/ +/* TS packet reception */ +/*--------------------------------------------------------------------------*/ + +/* TS filter type for set_type() */ + +#define TS_PACKET 1 /* send TS packets (188 bytes) to callback (default) */ +#define TS_PAYLOAD_ONLY 2 /* in case TS_PACKET is set, only send the TS + payload (<=184 bytes per packet) to callback */ +#define TS_DECODER 4 /* send stream to built-in decoder (if present) */ + +/* PES type for filters which write to built-in decoder */ +/* these should be kept identical to the types in dmx.h */ + +typedef enum +{ + DMX_TS_PES_AUDIO, /* also send packets to audio decoder (if it exists) */ + DMX_TS_PES_VIDEO, /* ... */ + DMX_TS_PES_TELETEXT, + DMX_TS_PES_SUBTITLE, + DMX_TS_PES_PCR, + DMX_TS_PES_OTHER, +} dmx_ts_pes_t; + + +struct dmx_ts_feed_s { + int is_filtering; /* Set to non-zero when filtering in progress */ + struct dmx_demux_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ + int (*set) (struct dmx_ts_feed_s* feed, + __u16 pid, + size_t callback_length, + size_t circular_buffer_size, + int descramble, + struct timespec timeout); + int (*start_filtering) (struct dmx_ts_feed_s* feed); + int (*stop_filtering) (struct dmx_ts_feed_s* feed); + int (*set_type) (struct dmx_ts_feed_s* feed, + int type, + dmx_ts_pes_t pes_type); +}; + +typedef struct dmx_ts_feed_s dmx_ts_feed_t; + +/*--------------------------------------------------------------------------*/ +/* PES packet reception (not supported yet) */ +/*--------------------------------------------------------------------------*/ + +typedef struct dmx_pes_filter_s { + struct dmx_pes_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ +} dmx_pes_filter_t; + +typedef struct dmx_pes_feed_s { + int is_filtering; /* Set to non-zero when filtering in progress */ + struct dmx_demux_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ + int (*set) (struct dmx_pes_feed_s* feed, + __u16 pid, + size_t circular_buffer_size, + int descramble, + struct timespec timeout); + int (*start_filtering) (struct dmx_pes_feed_s* feed); + int (*stop_filtering) (struct dmx_pes_feed_s* feed); + int (*allocate_filter) (struct dmx_pes_feed_s* feed, + dmx_pes_filter_t** filter); + int (*release_filter) (struct dmx_pes_feed_s* feed, + dmx_pes_filter_t* filter); +} dmx_pes_feed_t; + +/*--------------------------------------------------------------------------*/ +/* Section reception */ +/*--------------------------------------------------------------------------*/ + +typedef struct { + __u8 filter_value [DMX_MAX_FILTER_SIZE]; + __u8 filter_mask [DMX_MAX_FILTER_SIZE]; + struct dmx_section_feed_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ +} dmx_section_filter_t; + +struct dmx_section_feed_s { + int is_filtering; /* Set to non-zero when filtering in progress */ + struct dmx_demux_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ + int (*set) (struct dmx_section_feed_s* feed, + __u16 pid, + size_t circular_buffer_size, + int descramble, + int check_crc); + int (*allocate_filter) (struct dmx_section_feed_s* feed, + dmx_section_filter_t** filter); + int (*release_filter) (struct dmx_section_feed_s* feed, + dmx_section_filter_t* filter); + int (*start_filtering) (struct dmx_section_feed_s* feed); + int (*stop_filtering) (struct dmx_section_feed_s* feed); +}; +typedef struct dmx_section_feed_s dmx_section_feed_t; + +/*--------------------------------------------------------------------------*/ +/* Callback functions */ +/*--------------------------------------------------------------------------*/ + +typedef int (*dmx_ts_cb) ( __u8 * buffer1, + size_t buffer1_length, + __u8 * buffer2, + size_t buffer2_length, + dmx_ts_feed_t* source, + dmx_success_t success); + +typedef int (*dmx_section_cb) ( __u8 * buffer1, + size_t buffer1_len, + __u8 * buffer2, + size_t buffer2_len, + dmx_section_filter_t * source, + dmx_success_t success); + +typedef int (*dmx_pes_cb) ( __u8 * buffer1, + size_t buffer1_len, + __u8 * buffer2, + size_t buffer2_len, + dmx_pes_filter_t* source, + dmx_success_t success); + +/*--------------------------------------------------------------------------*/ +/* DVB Front-End */ +/*--------------------------------------------------------------------------*/ + +typedef enum { + DMX_OTHER_FE = 0, + DMX_SATELLITE_FE, + DMX_CABLE_FE, + DMX_TERRESTRIAL_FE, + DMX_LVDS_FE, + DMX_ASI_FE, /* DVB-ASI interface */ + DMX_MEMORY_FE +} dmx_frontend_source_t; + +typedef struct { + /* The following char* fields point to NULL terminated strings */ + char* id; /* Unique front-end identifier */ + char* vendor; /* Name of the front-end vendor */ + char* model; /* Name of the front-end model */ + struct list_head connectivity_list; /* List of front-ends that can + be connected to a particular + demux */ + void* priv; /* Pointer to private data of the API client */ + dmx_frontend_source_t source; +} dmx_frontend_t; + +/*--------------------------------------------------------------------------*/ +/* MPEG-2 TS Demux */ +/*--------------------------------------------------------------------------*/ + +/* + * Flags OR'ed in the capabilites field of struct dmx_demux_s. + */ + +#define DMX_TS_FILTERING 1 +#define DMX_PES_FILTERING 2 +#define DMX_SECTION_FILTERING 4 +#define DMX_MEMORY_BASED_FILTERING 8 /* write() available */ +#define DMX_CRC_CHECKING 16 +#define DMX_TS_DESCRAMBLING 32 +#define DMX_SECTION_PAYLOAD_DESCRAMBLING 64 +#define DMX_MAC_ADDRESS_DESCRAMBLING 128 + +/* + * Demux resource type identifier. +*/ + +/* + * DMX_FE_ENTRY(): Casts elements in the list of registered + * front-ends from the generic type struct list_head + * to the type * dmx_frontend_t + *. +*/ + +#define DMX_FE_ENTRY(list) list_entry(list, dmx_frontend_t, connectivity_list) + +struct dmx_demux_s { + /* The following char* fields point to NULL terminated strings */ + char* id; /* Unique demux identifier */ + char* vendor; /* Name of the demux vendor */ + char* model; /* Name of the demux model */ + __u32 capabilities; /* Bitfield of capability flags */ + dmx_frontend_t* frontend; /* Front-end connected to the demux */ + struct list_head reg_list; /* List of registered demuxes */ + void* priv; /* Pointer to private data of the API client */ + int users; /* Number of users */ + int (*open) (struct dmx_demux_s* demux); + int (*close) (struct dmx_demux_s* demux); + int (*write) (struct dmx_demux_s* demux, const char* buf, size_t count); + int (*allocate_ts_feed) (struct dmx_demux_s* demux, + dmx_ts_feed_t** feed, + dmx_ts_cb callback); + int (*release_ts_feed) (struct dmx_demux_s* demux, + dmx_ts_feed_t* feed); + int (*allocate_pes_feed) (struct dmx_demux_s* demux, + dmx_pes_feed_t** feed, + dmx_pes_cb callback); + int (*release_pes_feed) (struct dmx_demux_s* demux, + dmx_pes_feed_t* feed); + int (*allocate_section_feed) (struct dmx_demux_s* demux, + dmx_section_feed_t** feed, + dmx_section_cb callback); + int (*release_section_feed) (struct dmx_demux_s* demux, + dmx_section_feed_t* feed); + int (*descramble_mac_address) (struct dmx_demux_s* demux, + __u8* buffer1, + size_t buffer1_length, + __u8* buffer2, + size_t buffer2_length, + __u16 pid); + int (*descramble_section_payload) (struct dmx_demux_s* demux, + __u8* buffer1, + size_t buffer1_length, + __u8* buffer2, size_t buffer2_length, + __u16 pid); + int (*add_frontend) (struct dmx_demux_s* demux, + dmx_frontend_t* frontend); + int (*remove_frontend) (struct dmx_demux_s* demux, + dmx_frontend_t* frontend); + struct list_head* (*get_frontends) (struct dmx_demux_s* demux); + int (*connect_frontend) (struct dmx_demux_s* demux, + dmx_frontend_t* frontend); + int (*disconnect_frontend) (struct dmx_demux_s* demux); + + + /* added because js cannot keep track of these himself */ + int (*get_pes_pids) (struct dmx_demux_s* demux, __u16 *pids); +}; +typedef struct dmx_demux_s dmx_demux_t; + +/*--------------------------------------------------------------------------*/ +/* Demux directory */ +/*--------------------------------------------------------------------------*/ + +/* + * DMX_DIR_ENTRY(): Casts elements in the list of registered + * demuxes from the generic type struct list_head* to the type dmx_demux_t + *. + */ + +#define DMX_DIR_ENTRY(list) list_entry(list, dmx_demux_t, reg_list) + +int dmx_register_demux (dmx_demux_t* demux); +int dmx_unregister_demux (dmx_demux_t* demux); +struct list_head* dmx_get_demuxes (void); + +#endif /* #ifndef __DEMUX_H */ + diff --git a/src/input/ost/dmx.h b/src/input/ost/dmx.h new file mode 100644 index 000000000..9c4bb6b6d --- /dev/null +++ b/src/input/ost/dmx.h @@ -0,0 +1,141 @@ +/* + * dmx.h + * + * Copyright (C) 2000 Marcus Metzler + * & Ralph Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _OST_DMX_H_ +#define _OST_DMX_H_ + +#ifdef __KERNEL__ +#include +#else +#include +#endif + +#ifndef EBUFFEROVERFLOW +#define EBUFFEROVERFLOW 769 +#endif + +/* pid_t conflicts with linux/include/linux/types.h !!!*/ + +typedef uint16_t dvb_pid_t; + +#define DMX_FILTER_SIZE 16 + +typedef enum +{ + DMX_OUT_DECODER, /* Streaming directly to decoder. */ + DMX_OUT_TAP, /* Output going to a memory buffer */ + /* (to be retrieved via the read command).*/ + DMX_OUT_TS_TAP /* Output multiplexed into a new TS */ + /* (to be retrieved by reading from the */ + /* logical DVR device). */ +} dmxOutput_t; + + +typedef enum +{ + DMX_IN_FRONTEND, /* Input from a front-end device. */ + DMX_IN_DVR /* Input from the logical DVR device. */ +} dmxInput_t; + + +typedef enum +{ + DMX_PES_AUDIO, + DMX_PES_VIDEO, + DMX_PES_TELETEXT, + DMX_PES_SUBTITLE, + DMX_PES_PCR, + DMX_PES_OTHER +} dmxPesType_t; + + +typedef enum +{ + DMX_SCRAMBLING_EV, + DMX_FRONTEND_EV +} dmxEvent_t; + + +typedef enum +{ + DMX_SCRAMBLING_OFF, + DMX_SCRAMBLING_ON +} dmxScramblingStatus_t; + + +typedef struct dmxFilter +{ + uint8_t filter[DMX_FILTER_SIZE]; + uint8_t mask[DMX_FILTER_SIZE]; +} dmxFilter_t; + + +struct dmxFrontEnd +{ + /*TBD tbd; */ +}; + + +struct dmxSctFilterParams +{ + dvb_pid_t pid; + dmxFilter_t filter; + uint32_t timeout; + uint32_t flags; +#define DMX_CHECK_CRC 1 +#define DMX_ONESHOT 2 +#define DMX_IMMEDIATE_START 4 +#define DMX_KERNEL_CLIENT 0x8000 +}; + + +struct dmxPesFilterParams +{ + dvb_pid_t pid; + dmxInput_t input; + dmxOutput_t output; + dmxPesType_t pesType; + uint32_t flags; +}; + + +struct dmxEvent +{ + dmxEvent_t event; + time_t timeStamp; + union + { + dmxScramblingStatus_t scrambling; + } u; +}; + + +#define DMX_START _IOW('o',41,int) +#define DMX_STOP _IOW('o',42,int) +#define DMX_SET_FILTER _IOW('o',43,struct dmxSctFilterParams *) +#define DMX_SET_PES_FILTER _IOW('o',44,struct dmxPesFilterParams *) +#define DMX_SET_BUFFER_SIZE _IOW('o',45,unsigned long) +#define DMX_GET_EVENT _IOR('o',46,struct dmxEvent *) +#define DMX_GET_PES_PIDS _IOR('o',47,dvb_pid_t *) + +#endif /*_OST_DMX_H_*/ diff --git a/src/input/ost/frontend.h b/src/input/ost/frontend.h new file mode 100644 index 000000000..57fb69e83 --- /dev/null +++ b/src/input/ost/frontend.h @@ -0,0 +1,208 @@ +/* + * frontend.h + * + * Copyright (C) 2000 Marcus Metzler + * & Ralph Metzler + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _FRONTEND_H_ +#define _FRONTEND_H_ + +#include + + +#define ENOSIGNAL 768 +#ifndef EBUFFEROVERFLOW +#define EBUFFEROVERFLOW 769 +#endif + + +typedef __u32 FrontendStatus; + +/* bit definitions for FrontendStatus */ +#define FE_HAS_POWER 1 +#define FE_HAS_SIGNAL 2 +#define FE_SPECTRUM_INV 4 +#define FE_HAS_LOCK 8 +#define FE_HAS_CARRIER 16 +#define FE_HAS_VITERBI 32 +#define FE_HAS_SYNC 64 +#define FE_TUNER_HAS_LOCK 128 + + +/* possible values for spectral inversion */ +typedef enum { + INVERSION_OFF, + INVERSION_ON, + INVERSION_AUTO +} SpectralInversion; + +/* possible values for FEC_inner/FEC_outer */ +typedef enum { + FEC_AUTO, + FEC_1_2, + FEC_2_3, + FEC_3_4, + FEC_5_6, + FEC_7_8, + FEC_NONE +} CodeRate; + + +typedef enum { + QPSK, + QAM_16, + QAM_32, + QAM_64, + QAM_128, + QAM_256 +} Modulation; + + +typedef enum { + TRANSMISSION_MODE_2K, + TRANSMISSION_MODE_8K +} TransmitMode; + +typedef enum { + BANDWIDTH_8_MHZ, + BANDWIDTH_7_MHZ, + BANDWIDTH_6_MHZ +} BandWidth; + + +typedef enum { + GUARD_INTERVAL_1_32, + GUARD_INTERVAL_1_16, + GUARD_INTERVAL_1_8, + GUARD_INTERVAL_1_4 +} GuardInterval; + + +typedef enum { + HIERARCHY_NONE, + HIERARCHY_1, + HIERARCHY_2, + HIERARCHY_4 +} Hierarchy; + + +typedef struct { + __u32 SymbolRate; /* symbol rate in Symbols per second */ + CodeRate FEC_inner; /* forward error correction (see above) */ +} QPSKParameters; + + +typedef struct { + __u32 SymbolRate; /* symbol rate in Symbols per second */ + CodeRate FEC_inner; /* forward error correction (see above) */ + Modulation QAM; /* modulation type (see above) */ +} QAMParameters; + + +typedef struct { + BandWidth bandWidth; + CodeRate HP_CodeRate; /* high priority stream code rate */ + CodeRate LP_CodeRate; /* low priority stream code rate */ + Modulation Constellation; /* modulation type (see above) */ + TransmitMode TransmissionMode; + GuardInterval guardInterval; + Hierarchy HierarchyInformation; +} OFDMParameters; + + +typedef enum { + FE_QPSK, + FE_QAM, + FE_OFDM +} FrontendType; + + +typedef struct { + __u32 Frequency; /* (absolute) frequency in Hz for QAM/OFDM */ + /* intermediate frequency in kHz for QPSK */ + SpectralInversion Inversion; /* spectral inversion */ + union { + QPSKParameters qpsk; + QAMParameters qam; + OFDMParameters ofdm; + } u; +} FrontendParameters; + + +typedef enum { + FE_UNEXPECTED_EV, /* unexpected event (e.g. loss of lock) */ + FE_COMPLETION_EV, /* completion event, tuning succeeded */ + FE_FAILURE_EV /* failure event, we couldn't tune */ +} EventType; + + +typedef struct { + EventType type; /* type of event, FE_UNEXPECTED_EV, ... */ + + long timestamp; /* time in seconds since 1970-01-01 */ + + union { + struct { + FrontendStatus previousStatus; /* status before event */ + FrontendStatus currentStatus; /* status during event */ + } unexpectedEvent; + FrontendParameters completionEvent; /* parameters for which the + tuning succeeded */ + FrontendStatus failureEvent; /* status at failure (e.g. no lock) */ + } u; +} FrontendEvent; + +typedef struct { + FrontendType type; + __u32 minFrequency; + __u32 maxFrequency; + __u32 maxSymbolRate; + __u32 minSymbolRate; + __u32 hwType; + __u32 hwVersion; +} FrontendInfo; + + +typedef enum { + FE_POWER_ON, + FE_POWER_STANDBY, + FE_POWER_SUSPEND, + FE_POWER_OFF +} FrontendPowerState; + + +#define FE_SELFTEST _IO('o', 61) +#define FE_SET_POWER_STATE _IOW('o', 62, FrontendPowerState) +#define FE_GET_POWER_STATE _IOR('o', 63, FrontendPowerState*) +#define FE_READ_STATUS _IOR('o', 64, FrontendStatus*) +#define FE_READ_BER _IOW('o', 65, __u32*) +#define FE_READ_SIGNAL_STRENGTH _IOR('o', 66, __s32*) +#define FE_READ_SNR _IOR('o', 67, __s32*) +#define FE_READ_UNCORRECTED_BLOCKS _IOW('o', 68, __u32*) +#define FE_GET_NEXT_FREQUENCY _IOW('o', 69, __u32*) +#define FE_GET_NEXT_SYMBOL_RATE _IOW('o', 70, __u32*) + +#define FE_SET_FRONTEND _IOW('o', 71, FrontendParameters*) +#define FE_GET_FRONTEND _IOR('o', 72, FrontendParameters*) +#define FE_GET_INFO _IOR('o', 73, FrontendInfo*) +#define FE_GET_EVENT _IOR('o', 74, FrontendEvent*) + +#endif /*_FRONTEND_H_*/ + diff --git a/src/input/ost/sec.h b/src/input/ost/sec.h new file mode 100644 index 000000000..8863df268 --- /dev/null +++ b/src/input/ost/sec.h @@ -0,0 +1,118 @@ +/* + * sec.h + * + * Copyright (C) 2000 Ralph Metzler + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _OST_SEC_H_ +#define _OST_SEC_H_ + +#define SEC_MAX_DISEQC_PARAMS 3 + +struct secDiseqcCmd { + uint8_t addr; + uint8_t cmd; + uint8_t numParams; + uint8_t params[SEC_MAX_DISEQC_PARAMS]; +}; + +typedef uint32_t secVoltage; + +enum { + SEC_VOLTAGE_OFF, + SEC_VOLTAGE_LT, + SEC_VOLTAGE_13, + SEC_VOLTAGE_13_5, + SEC_VOLTAGE_18, + SEC_VOLTAGE_18_5 +}; + +#define SEC_VOLTAGE_HORIZONTAL SEC_VOLTAGE_18 +#define SEC_VOLTAGE_VERTICAL SEC_VOLTAGE_13 + +typedef uint32_t secToneMode; + +typedef enum { + SEC_TONE_ON, + SEC_TONE_OFF +} secToneMode_t; + + +typedef uint32_t secMiniCmd; + +typedef enum { + SEC_MINI_NONE, + SEC_MINI_A, + SEC_MINI_B +} secMiniCmd_t; + +struct secStatus { + int32_t busMode; + secVoltage selVolt; + secToneMode contTone; +}; + +enum { + SEC_BUS_IDLE, + SEC_BUS_BUSY, + SEC_BUS_OFF, + SEC_BUS_OVERLOAD +}; + +struct secCommand { + int32_t type; + union { + struct secDiseqcCmd diseqc; + uint8_t vsec; + uint32_t pause; + } u; +}; + +struct secCmdSequence { + secVoltage voltage; + secMiniCmd miniCommand; + secToneMode continuousTone; + + uint32_t numCommands; + struct secCommand* commands; +}; + +enum { + SEC_CMDTYPE_DISEQC, + SEC_CMDTYPE_VSEC, + SEC_CMDTYPE_PAUSE +}; + + +#define SEC_GET_STATUS _IOR('o',91,struct secStatus *) +#define SEC_RESET_OVERLOAD _IOW('o',92,void) +#define SEC_SEND_SEQUENCE _IOW('o',93,struct secCmdSequence *) +#define SEC_SET_TONE _IOW('o',94,secToneMode) +#define SEC_SET_VOLTAGE _IOW('o',95,secVoltage) + +typedef enum { + SEC_DISEQC_SENT, + SEC_VSEC_SENT, + SEC_PAUSE_COMPLETE, + SEC_CALLBACK_ERROR +} secCallback_t; + + +#endif /*_OST_SEC_H_*/ diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index b5c8bf79c..104539871 100644 --- a/src/xine-engine/audio_decoder.c +++ b/src/xine-engine/audio_decoder.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: audio_decoder.c,v 1.95 2002/12/26 21:53:42 miguelfreitas Exp $ + * $Id: audio_decoder.c,v 1.96 2002/12/27 00:53:50 guenter Exp $ * * * functions that implement audio decoding @@ -195,7 +195,8 @@ void *audio_decoder_loop (void *stream_gen) { while ( (iaudio_track_map_entries) && (stream->audio_track_map[i]type) ) i++; - if ( (i==stream->audio_track_map_entries) || (stream->audio_track_map[i] != buf->type) ) { + if ( (i==stream->audio_track_map_entries) + || (stream->audio_track_map[i] != buf->type) ) { j = stream->audio_track_map_entries; while (j>i) { @@ -208,12 +209,23 @@ void *audio_decoder_loop (void *stream_gen) { /* find out which audio type to decode */ +#ifdef LOG + printf ("audio_decoder: audio_channel_user = %d, map[0]=%08x\n", + stream->audio_channel_user, + stream->audio_track_map[0]); +#endif + if (stream->audio_channel_user > -2) { if (stream->audio_channel_user == -1) { /* auto */ +#ifdef LOG + printf ("audio_decoder: audio_channel_auto = %d\n", + stream->audio_channel_auto); +#endif + if (stream->audio_channel_auto>=0) { if ((buf->type & 0xFF) == stream->audio_channel_auto) { @@ -311,7 +323,7 @@ void audio_decoder_init (xine_stream_t *stream) { */ stream->audio_fifo = fifo_buffer_new (230, 8192); stream->audio_channel_user = -1; - stream->audio_channel_auto = 0; + stream->audio_channel_auto = -1; stream->audio_track_map_entries = 0; stream->audio_type = 0; diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 1d1816eb4..063333178 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine.c,v 1.203 2002/12/26 21:53:42 miguelfreitas Exp $ + * $Id: xine.c,v 1.204 2002/12/27 00:53:50 guenter Exp $ * * top-level xine functions * @@ -309,7 +309,7 @@ xine_stream_t *xine_stream_new (xine_t *this, stream->spu_decoder_streamtype = -1; stream->audio_out = ao; stream->audio_channel_user = -1; - stream->audio_channel_auto = 0; + stream->audio_channel_auto = -1; stream->audio_decoder_plugin = NULL; stream->audio_decoder_streamtype = -1; stream->spu_channel_auto = -1; -- cgit v1.2.3