diff options
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; } |