diff options
author | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2002-09-08 18:00:00 +0200 |
---|---|---|
committer | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2002-09-08 18:00:00 +0200 |
commit | 523c4a07aa9112841743fca2ebcce957fde03bc8 (patch) | |
tree | 6980f2c5644d926410c359574fa11732860d7eac /dvbdevice.c | |
parent | a2a215d5e12ad35df8d0731dd00b6e41d5dd77fa (diff) | |
download | vdr-patch-lnbsharing-523c4a07aa9112841743fca2ebcce957fde03bc8.tar.gz vdr-patch-lnbsharing-523c4a07aa9112841743fca2ebcce957fde03bc8.tar.bz2 |
Version 1.1.9vdr-1.1.9
- Fixed the 'newplugin' script to make it name the target for creating the
distribution package 'dist', as stated in the PLUGINS.html documentation.
If you have already created a plugin source directory and Makefile you may
want to check it and replace the 'package' target with 'dist' if necessary.
- Changed device handling for being able to do simultaneous recording and
replay on the same device (Time Shifting). In order for this to work you need
to use a driver with a firmware version that has this feature implemented.
- cDevice::ProvidesCa() is no longer virtual. The new function
cDevice::ProvidesChannel() is now used to determine whether a device can
receive a given channel, and by default this function returns false. So a
device that is a pure replaying device doesn't need to do anything here.
- Increased the recorder buffer size to 5MB in order to be able to better handle
multiple recordings.
- Implemented cTSBuffer for better handling TS packet buffering in derived
cDevice classes.
- Changed the interface if cDevice::GetTSPacket() to avoid unnecessary copying
of data.
- Removed cDevice::Channel(), since this makes no more sense with devices
receiving multiple channels.
- Switching through channels with the 'Up' and 'Down' keys now skips channels
that are currently not available (for instance because all devices are
recording and these channels are on different transponders).
- Implemented an SPU decoder (thanks to Andreas Schultz).
- Fixed a crash when entering an integer value outside the limits (thanks to
Stefan Huelswitt for reporting this one).
- Added play mode pmAudioOnlyBlack (thanks to Stefan Huelswitt).
Diffstat (limited to 'dvbdevice.c')
-rw-r--r-- | dvbdevice.c | 460 |
1 files changed, 268 insertions, 192 deletions
diff --git a/dvbdevice.c b/dvbdevice.c index 52c7c3b..a130112 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.c 1.8 2002/08/25 09:20:53 kls Exp $ + * $Id: dvbdevice.c 1.13 2002/09/08 15:00:46 kls Exp $ */ #include "dvbdevice.h" @@ -20,10 +20,12 @@ extern "C" { #include <linux/videodev.h> #ifdef NEWSTRUCT #include <linux/dvb/audio.h> +#include <linux/dvb/dmx.h> #include <linux/dvb/frontend.h> #include <linux/dvb/video.h> #else #include <ost/audio.h> +#include <ost/dmx.h> #include <ost/sec.h> #include <ost/video.h> #endif @@ -35,8 +37,6 @@ extern "C" { #include "status.h" #include "transfer.h" -#define MAXDVBDEVICES 4 - #define DEV_VIDEO "/dev/video" #ifdef NEWSTRUCT #define DEV_DVB_ADAPTER "/dev/dvb/adapter" @@ -80,6 +80,7 @@ cDvbDevice::cDvbDevice(int n) { frontendType = FrontendType(-1); // don't know how else to initialize this - there is no FE_UNKNOWN siProcessor = NULL; + spuDecoder = NULL; playMode = pmNone; // Devices that are present on all card types: @@ -91,10 +92,10 @@ cDvbDevice::cDvbDevice(int n) fd_osd = DvbOpen(DEV_DVB_OSD, n, O_RDWR); fd_video = DvbOpen(DEV_DVB_VIDEO, n, O_RDWR | O_NONBLOCK); fd_audio = DvbOpen(DEV_DVB_AUDIO, n, O_RDWR | O_NONBLOCK); - + #ifndef NEWSTRUCT // Devices that are only present on DVB-S cards: - + fd_sec = DvbOpen(DEV_DVB_SEC, n, O_RDWR); #endif @@ -128,6 +129,7 @@ cDvbDevice::cDvbDevice(int n) cDvbDevice::~cDvbDevice() { + delete spuDecoder; delete siProcessor; // We're not explicitly closing any device files here, since this sometimes // caused segfaults. Besides, the program is about to terminate anyway... @@ -179,15 +181,6 @@ void cDvbDevice::MakePrimaryDevice(bool On) cDvbOsd::SetDvbDevice(On ? this : NULL); } -bool cDvbDevice::CanBeReUsed(int Frequency, int Vpid) -{ - return Receiving() // to be reused the DVB device must already be receiving... - && frequency == Frequency // ...and tuned to the requested frequency... - && (!HasDecoder() // ...and either be a "budget card" which can receive multiple channels... - || pidHandles[ptVideo].pid == Vpid // ...or be a "full featured card" that's already tuned to the requested video PID - ); -} - bool cDvbDevice::HasDecoder(void) const { return fd_video >= 0 && fd_audio >= 0; @@ -198,6 +191,13 @@ cOsdBase *cDvbDevice::NewOsd(int x, int y) return new cDvbOsd(x, y); } +cSpuDecoder *cDvbDevice::GetSpuDecoder(void) +{ + if (!spuDecoder && IsPrimaryDevice()) + spuDecoder = new cDvbSpuDecoder(); + return spuDecoder; +} + bool cDvbDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY) { int videoDev = DvbOpen(DEV_VIDEO, CardIndex(), O_RDWR, true); @@ -235,10 +235,10 @@ bool cDvbDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int Siz mem1[0] = tmp; mem1 += 3; } - + if (Quality < 0) Quality = 255; //XXX is this 'best'??? - + isyslog("grabbing to %s (%s %d %d %d)", FileName, Jpeg ? "JPEG" : "PNM", Quality, vm.width, vm.height); FILE *f = fopen(FileName, "wb"); if (f) { @@ -253,11 +253,11 @@ bool cDvbDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int Siz cinfo.image_height = vm.height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; - + jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, Quality, true); jpeg_start_compress(&cinfo, true); - + int rs = vm.width * 3; JSAMPROW rp[vm.height]; for (int k = 0; k < vm.height; k++) @@ -313,6 +313,14 @@ bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On) else { CHECK(ioctl(Handle->handle, DMX_STOP)); if (Handle->used == 0) { + dmxPesFilterParams pesFilterParams; + memset(&pesFilterParams, 0, sizeof(pesFilterParams)); + pesFilterParams.pid = 0x1FFF; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_DECODER; + pesFilterParams.pesType = PesTypes[Type < ptOther ? Type : ptOther]; + pesFilterParams.flags = DMX_IMMEDIATE_START; + CHECK(ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams)); close(Handle->handle); Handle->handle = -1; return true; @@ -339,8 +347,56 @@ bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On) return true; } -bool cDvbDevice::SetChannelDevice(const cChannel *Channel) +bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) { + bool result = false; + bool hasPriority = Priority < 0 || Priority > this->Priority(); + bool needsDetachReceivers = true; + + if (ProvidesCa(Channel->ca)) { + if (Receiving()) { + if (frequency == Channel->frequency) { + needsDetachReceivers = false; + if (!HasPid(Channel->vpid)) { + if (Channel->ca > CACONFBASE) { + needsDetachReceivers = true; + result = hasPriority; + } + else if (!HasDecoder()) + result = true; // if it has no decoder it can't be the primary device + else { +#define DVB_DRIVER_VERSION 2002090101 //XXX+ +#define MIN_DVB_DRIVER_VERSION_FOR_TIMESHIFT 2002090101 +#ifdef DVB_DRIVER_VERSION +#if (DVB_DRIVER_VERSION >= MIN_DVB_DRIVER_VERSION_FOR_TIMESHIFT) + result = !IsPrimaryDevice() || Priority >= Setup.PrimaryLimit; +#endif +#else +#warning "DVB_DRIVER_VERSION not defined - time shift with only one DVB device disabled!" +#endif + } + } + else + result = !IsPrimaryDevice() || Priority >= Setup.PrimaryLimit; + } + else + result = hasPriority; + } + else + result = hasPriority; + } + if (NeedsDetachReceivers) + *NeedsDetachReceivers = needsDetachReceivers; + return result; +} + +bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) +{ +#if (DVB_DRIVER_VERSION < MIN_DVB_DRIVER_VERSION_FOR_TIMESHIFT) + if (HasDecoder()) + LiveView = true; +#endif + // Avoid noise while switching: if (HasDecoder()) { @@ -357,204 +413,209 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel) // Turn off current PIDs: - if (HasDecoder()) { + if (HasDecoder() && (LiveView || pidHandles[ptVideo].pid == Channel->vpid)) { DelPid(pidHandles[ptVideo].pid); DelPid(pidHandles[ptAudio].pid); DelPid(pidHandles[ptTeletext].pid); DelPid(pidHandles[ptDolby].pid); } + if (frequency != Channel->frequency || Channel->ca > CACONFBASE) { // CA channels can only be decrypted in "live" mode + #ifdef NEWSTRUCT - dvb_frontend_parameters Frontend; + dvb_frontend_parameters Frontend; #else - FrontendParameters Frontend; + FrontendParameters Frontend; #endif - memset(&Frontend, 0, sizeof(Frontend)); + memset(&Frontend, 0, sizeof(Frontend)); - switch (frontendType) { - case FE_QPSK: { // DVB-S + switch (frontendType) { + case FE_QPSK: { // DVB-S - // Frequency offsets: + // Frequency offsets: - unsigned int freq = Channel->frequency; - int tone = SEC_TONE_OFF; + unsigned int freq = Channel->frequency; + int tone = SEC_TONE_OFF; - if (freq < (unsigned int)Setup.LnbSLOF) { - freq -= Setup.LnbFrequLo; - tone = SEC_TONE_OFF; - } - else { - freq -= Setup.LnbFrequHi; - tone = SEC_TONE_ON; - } + if (freq < (unsigned int)Setup.LnbSLOF) { + freq -= Setup.LnbFrequLo; + tone = SEC_TONE_OFF; + } + else { + freq -= Setup.LnbFrequHi; + tone = SEC_TONE_ON; + } #ifdef NEWSTRUCT - Frontend.frequency = freq * 1000UL; - Frontend.inversion = INVERSION_AUTO; - Frontend.u.qpsk.symbol_rate = Channel->srate * 1000UL; - Frontend.u.qpsk.fec_inner = FEC_AUTO; + Frontend.frequency = freq * 1000UL; + Frontend.inversion = INVERSION_AUTO; + Frontend.u.qpsk.symbol_rate = Channel->srate * 1000UL; + Frontend.u.qpsk.fec_inner = FEC_AUTO; #else - Frontend.Frequency = freq * 1000UL; - Frontend.Inversion = INVERSION_AUTO; - Frontend.u.qpsk.SymbolRate = Channel->srate * 1000UL; - Frontend.u.qpsk.FEC_inner = FEC_AUTO; + Frontend.Frequency = freq * 1000UL; + Frontend.Inversion = INVERSION_AUTO; + Frontend.u.qpsk.SymbolRate = Channel->srate * 1000UL; + Frontend.u.qpsk.FEC_inner = FEC_AUTO; #endif - int volt = (Channel->polarization == 'v' || Channel->polarization == 'V') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18; + int volt = (Channel->polarization == 'v' || Channel->polarization == 'V') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18; - // DiSEqC: + // DiSEqC: #ifdef NEWSTRUCT - struct dvb_diseqc_master_cmd cmd = { {0xE0, 0x10, 0x38, 0xF0, 0x00, 0x00}, 4}; - cmd.msg[3] = 0xF0 | (((Channel->diseqc * 4) & 0x0F) | (tone == SEC_TONE_ON ? 1 : 0) | (volt == SEC_VOLTAGE_18 ? 2 : 0)); - - if (Setup.DiSEqC) - CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); - CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt)); - if (Setup.DiSEqC) { - usleep(15 * 1000); - CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); - usleep(15 * 1000); - CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, (Channel->diseqc / 4) % 2 ? SEC_MINI_B : SEC_MINI_A)); - usleep(15 * 1000); - } - CHECK(ioctl(fd_frontend, FE_SET_TONE, tone)); + struct dvb_diseqc_master_cmd cmd = { {0xE0, 0x10, 0x38, 0xF0, 0x00, 0x00}, 4}; + cmd.msg[3] = 0xF0 | (((Channel->diseqc * 4) & 0x0F) | (tone == SEC_TONE_ON ? 1 : 0) | (volt == SEC_VOLTAGE_18 ? 2 : 0)); + + if (Setup.DiSEqC) + CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); + CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt)); + if (Setup.DiSEqC) { + usleep(15 * 1000); + CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); + usleep(15 * 1000); + CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, (Channel->diseqc / 4) % 2 ? SEC_MINI_B : SEC_MINI_A)); + usleep(15 * 1000); + } + CHECK(ioctl(fd_frontend, FE_SET_TONE, tone)); #else - secCommand scmd; - scmd.type = 0; - scmd.u.diseqc.addr = 0x10; - scmd.u.diseqc.cmd = 0x38; - scmd.u.diseqc.numParams = 1; - scmd.u.diseqc.params[0] = 0xF0 | ((Channel->diseqc * 4) & 0x0F) | (tone == SEC_TONE_ON ? 1 : 0) | (volt == SEC_VOLTAGE_18 ? 2 : 0); - - secCmdSequence scmds; - scmds.voltage = volt; - scmds.miniCommand = SEC_MINI_NONE; - scmds.continuousTone = tone; - scmds.numCommands = Setup.DiSEqC ? 1 : 0; - scmds.commands = &scmd; - - CHECK(ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds)); + secCommand scmd; + scmd.type = 0; + scmd.u.diseqc.addr = 0x10; + scmd.u.diseqc.cmd = 0x38; + scmd.u.diseqc.numParams = 1; + scmd.u.diseqc.params[0] = 0xF0 | ((Channel->diseqc * 4) & 0x0F) | (tone == SEC_TONE_ON ? 1 : 0) | (volt == SEC_VOLTAGE_18 ? 2 : 0); + + secCmdSequence scmds; + scmds.voltage = volt; + scmds.miniCommand = SEC_MINI_NONE; + scmds.continuousTone = tone; + scmds.numCommands = Setup.DiSEqC ? 1 : 0; + scmds.commands = &scmd; + + CHECK(ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds)); #endif - } - break; - case FE_QAM: { // DVB-C + } + break; + case FE_QAM: { // DVB-C - // Frequency and symbol rate: + // Frequency and symbol rate: #ifdef NEWSTRUCT - Frontend.frequency = Channel->frequency * 1000000UL; - Frontend.inversion = INVERSION_AUTO; - Frontend.u.qam.symbol_rate = Channel->srate * 1000UL; - Frontend.u.qam.fec_inner = FEC_AUTO; - Frontend.u.qam.modulation = QAM_64; + Frontend.frequency = Channel->frequency * 1000000UL; + Frontend.inversion = INVERSION_AUTO; + Frontend.u.qam.symbol_rate = Channel->srate * 1000UL; + Frontend.u.qam.fec_inner = FEC_AUTO; + Frontend.u.qam.modulation = QAM_64; #else - Frontend.Frequency = Channel->frequency * 1000000UL; - Frontend.Inversion = INVERSION_AUTO; - Frontend.u.qam.SymbolRate = Channel->srate * 1000UL; - Frontend.u.qam.FEC_inner = FEC_AUTO; - Frontend.u.qam.QAM = QAM_64; + Frontend.Frequency = Channel->frequency * 1000000UL; + Frontend.Inversion = INVERSION_AUTO; + Frontend.u.qam.SymbolRate = Channel->srate * 1000UL; + Frontend.u.qam.FEC_inner = FEC_AUTO; + Frontend.u.qam.QAM = QAM_64; #endif - } - break; - case FE_OFDM: { // DVB-T + } + break; + case FE_OFDM: { // DVB-T - // Frequency and OFDM paramaters: + // Frequency and OFDM paramaters: #ifdef NEWSTRUCT - Frontend.frequency = Channel->frequency * 1000UL; - Frontend.inversion = INVERSION_AUTO; - Frontend.u.ofdm.bandwidth=BANDWIDTH_8_MHZ; - Frontend.u.ofdm.code_rate_HP = FEC_2_3; - Frontend.u.ofdm.code_rate_LP = FEC_1_2; - Frontend.u.ofdm.constellation = QAM_64; - Frontend.u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; - Frontend.u.ofdm.guard_interval = GUARD_INTERVAL_1_32; - Frontend.u.ofdm.hierarchy_information = HIERARCHY_NONE; + Frontend.frequency = Channel->frequency * 1000UL; + Frontend.inversion = INVERSION_AUTO; + Frontend.u.ofdm.bandwidth=BANDWIDTH_8_MHZ; + Frontend.u.ofdm.code_rate_HP = FEC_2_3; + Frontend.u.ofdm.code_rate_LP = FEC_1_2; + Frontend.u.ofdm.constellation = QAM_64; + Frontend.u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; + Frontend.u.ofdm.guard_interval = GUARD_INTERVAL_1_32; + Frontend.u.ofdm.hierarchy_information = HIERARCHY_NONE; #else - Frontend.Frequency = Channel->frequency * 1000UL; - Frontend.Inversion = INVERSION_AUTO; - Frontend.u.ofdm.bandWidth=BANDWIDTH_8_MHZ; - Frontend.u.ofdm.HP_CodeRate=FEC_2_3; - Frontend.u.ofdm.LP_CodeRate=FEC_1_2; - Frontend.u.ofdm.Constellation=QAM_64; - Frontend.u.ofdm.TransmissionMode=TRANSMISSION_MODE_2K; - Frontend.u.ofdm.guardInterval=GUARD_INTERVAL_1_32; - Frontend.u.ofdm.HierarchyInformation=HIERARCHY_NONE; + Frontend.Frequency = Channel->frequency * 1000UL; + Frontend.Inversion = INVERSION_AUTO; + Frontend.u.ofdm.bandWidth=BANDWIDTH_8_MHZ; + Frontend.u.ofdm.HP_CodeRate=FEC_2_3; + Frontend.u.ofdm.LP_CodeRate=FEC_1_2; + Frontend.u.ofdm.Constellation=QAM_64; + Frontend.u.ofdm.TransmissionMode=TRANSMISSION_MODE_2K; + Frontend.u.ofdm.guardInterval=GUARD_INTERVAL_1_32; + Frontend.u.ofdm.HierarchyInformation=HIERARCHY_NONE; #endif - } - break; - default: - esyslog("ERROR: attempt to set channel with unknown DVB frontend type"); - return false; - } + } + break; + default: + esyslog("ERROR: attempt to set channel with unknown DVB frontend type"); + return false; + } #ifdef NEWSTRUCT - // Discard stale events: + // Discard stale events: - for (;;) { - dvb_frontend_event event; - if (ioctl(fd_frontend, FE_GET_EVENT, &event) < 0) - break; - } + for (;;) { + dvb_frontend_event event; + if (ioctl(fd_frontend, FE_GET_EVENT, &event) < 0) + break; + } #endif - // Tuning: + // Tuning: - CHECK(ioctl(fd_frontend, FE_SET_FRONTEND, &Frontend)); + CHECK(ioctl(fd_frontend, FE_SET_FRONTEND, &Frontend)); - // Wait for channel lock: + // Wait for channel lock: #ifdef NEWSTRUCT - FrontendStatus status = FrontendStatus(0); - for (int i = 0; i < 100; i++) { - CHECK(ioctl(fd_frontend, FE_READ_STATUS, &status)); - if (status & FE_HAS_LOCK) - break; - usleep(10 * 1000); - } - if (!(status & FE_HAS_LOCK)) { - esyslog("ERROR: channel %d not locked on DVB card %d!", Channel->number, CardIndex() + 1); - if (IsPrimaryDevice()) - cThread::RaisePanic(); - return false; - } + FrontendStatus status = FrontendStatus(0); + for (int i = 0; i < 100; i++) { + CHECK(ioctl(fd_frontend, FE_READ_STATUS, &status)); + if (status & FE_HAS_LOCK) + break; + usleep(10 * 1000); + } + if (!(status & FE_HAS_LOCK)) { + esyslog("ERROR: channel %d not locked on DVB card %d!", Channel->number, CardIndex() + 1); + if (IsPrimaryDevice()) + cThread::RaisePanic(); + return false; + } #else - if (cFile::FileReady(fd_frontend, 5000)) { - FrontendEvent event; - if (ioctl(fd_frontend, FE_GET_EVENT, &event) >= 0) { - if (event.type != FE_COMPLETION_EV) { - esyslog("ERROR: channel %d not sync'ed on DVB card %d!", Channel->number, CardIndex() + 1); - if (IsPrimaryDevice()) - cThread::RaisePanic(); - return false; + if (cFile::FileReady(fd_frontend, 5000)) { + FrontendEvent event; + if (ioctl(fd_frontend, FE_GET_EVENT, &event) >= 0) { + if (event.type != FE_COMPLETION_EV) { + esyslog("ERROR: channel %d not sync'ed on DVB card %d!", Channel->number, CardIndex() + 1); + if (IsPrimaryDevice()) + cThread::RaisePanic(); + return false; + } } + else + esyslog("ERROR in frontend get event (channel %d, card %d): %m", Channel->number, CardIndex() + 1); } else - esyslog("ERROR in frontend get event (channel %d, card %d): %m", Channel->number, CardIndex() + 1); - } - else - esyslog("ERROR: timeout while tuning on DVB card %d", CardIndex() + 1); + esyslog("ERROR: timeout while tuning on DVB card %d", CardIndex() + 1); #endif - frequency = Channel->frequency; + frequency = Channel->frequency; + + } // PID settings: - if (HasDecoder()) { - if (!(AddPid(Channel->vpid, ptVideo) && AddPid(Channel->apid1, ptAudio))) {//XXX+ dolby dpid1!!! (if audio plugins are attached) - esyslog("ERROR: failed to set PIDs for channel %d", Channel->number); - return false; + if (HasDecoder() && (LiveView || Channel->ca > CACONFBASE)) { // CA channels can only be decrypted in "live" mode + if (!HasPid(Channel->vpid)) { + if (!(AddPid(Channel->vpid, ptVideo) && AddPid(Channel->apid1, ptAudio))) {//XXX+ dolby dpid1!!! (if audio plugins are attached) + esyslog("ERROR: failed to set PIDs for channel %d", Channel->number); + return false; + } + if (IsPrimaryDevice()) + AddPid(Channel->tpid, ptTeletext); + CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); + CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false)); + CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false)); } - if (IsPrimaryDevice()) - AddPid(Channel->tpid, ptTeletext); - CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); - } - - if (HasDecoder()) { - CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false)); - CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false)); + else + cControl::Launch(new cTransferControl(this, Channel->vpid, Channel->apid1, 0, 0, 0)); } // Start setting system time: @@ -602,11 +663,12 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode) siProcessor->SetStatus(true); break; case pmAudioVideo: + case pmAudioOnlyBlack: if (siProcessor) siProcessor->SetStatus(false); CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY)); - CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); + CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, PlayMode == pmAudioVideo)); CHECK(ioctl(fd_audio, AUDIO_PLAY)); CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY)); CHECK(ioctl(fd_video, VIDEO_PLAY)); @@ -650,18 +712,30 @@ void cDvbDevice::Clear(void) void cDvbDevice::Play(void) { - if (fd_audio >= 0) - CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); - if (fd_video >= 0) - CHECK(ioctl(fd_video, VIDEO_CONTINUE)); + if (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) { + if (fd_audio >= 0) + CHECK(ioctl(fd_audio, AUDIO_CONTINUE)); + } + else { + if (fd_audio >= 0) + CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); + if (fd_video >= 0) + CHECK(ioctl(fd_video, VIDEO_CONTINUE)); + } } void cDvbDevice::Freeze(void) { - if (fd_audio >= 0) - CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false)); - if (fd_video >= 0) - CHECK(ioctl(fd_video, VIDEO_FREEZE)); + if (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) { + if (fd_audio >= 0) + CHECK(ioctl(fd_audio, AUDIO_PAUSE)); + } + else { + if (fd_audio >= 0) + CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false)); + if (fd_video >= 0) + CHECK(ioctl(fd_video, VIDEO_FREEZE)); + } } void cDvbDevice::Mute(void) @@ -699,13 +773,13 @@ void cDvbDevice::StillPicture(const uchar *Data, int Length) bool cDvbDevice::Poll(cPoller &Poller, int TimeoutMs) { - Poller.Add(playMode == pmAudioOnly ? fd_audio : fd_video, true); + Poller.Add((playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) ? fd_audio : fd_video, true); return Poller.Poll(TimeoutMs); } int cDvbDevice::PlayVideo(const uchar *Data, int Length) { - int fd = playMode == pmAudioOnly ? fd_audio : fd_video; + int fd = (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) ? fd_audio : fd_video; if (fd >= 0) return write(fd, Data, Length); return -1; @@ -721,6 +795,8 @@ bool cDvbDevice::OpenDvr(void) { CloseDvr(); fd_dvr = DvbOpen(DEV_DVB_DVR, CardIndex(), O_RDONLY | O_NONBLOCK, true); + if (fd_dvr >= 0) + tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(2), CardIndex() + 1); return fd_dvr >= 0; } @@ -729,28 +805,28 @@ void cDvbDevice::CloseDvr(void) if (fd_dvr >= 0) { close(fd_dvr); fd_dvr = -1; + delete tsBuffer; + tsBuffer = NULL; } } -int cDvbDevice::GetTSPacket(uchar *Data) +bool cDvbDevice::GetTSPacket(uchar *&Data) { - if (fd_dvr >= 0) { - cPoller Poller(fd_dvr, false); - if (Poller.Poll(100)) { - int r = read(fd_dvr, Data, TS_SIZE); - if (r >= 0) - return r; - else if (FATALERRNO) { - if (errno == EBUFFEROVERFLOW) // this error code is not defined in the library - esyslog("ERROR: DVB driver buffer overflow on device %d", CardIndex() + 1); - else { - LOG_ERROR; - return -1; - } + if (tsBuffer) { + int r = tsBuffer->Read(); + if (r >= 0) { + Data = tsBuffer->Get(); + return true; + } + else if (FATALERRNO) { + if (errno == EBUFFEROVERFLOW) // this error code is not defined in the library + esyslog("ERROR: DVB driver buffer overflow on device %d", CardIndex() + 1); + else { + LOG_ERROR; + return false; } } - return 0; + return true; } - else - return -1; + return false; } |