summaryrefslogtreecommitdiff
path: root/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'device.c')
-rw-r--r--device.c1653
1 files changed, 0 insertions, 1653 deletions
diff --git a/device.c b/device.c
deleted file mode 100644
index d317738f..00000000
--- a/device.c
+++ /dev/null
@@ -1,1653 +0,0 @@
-/*
- * device.c: xine-lib output device for the Video Disk Recorder
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: device.c,v 1.90 2009-08-19 17:08:08 phintuka Exp $
- *
- */
-
-#define __STDC_FORMAT_MACROS
-#define __STDC_CONSTANT_MACROS
-#include <inttypes.h>
-
-#include <vdr/config.h>
-#include <vdr/thread.h>
-#include <vdr/dvbspu.h>
-#include <vdr/channels.h>
-#include <vdr/skins.h>
-#include <vdr/status.h>
-#include <vdr/remote.h>
-
-//#define XINELIBOUTPUT_DEBUG
-//#define XINELIBOUTPUT_DEBUG_STDERR
-//#define TRACK_EXEC_TIME
-//#define FORWARD_DVD_SPUS
-//#define DEBUG_SWITCHING_TIME
-//#define LOG_TRICKSPEED
-
-#include "logdefs.h"
-#include "config.h"
-#include "osd.h"
-
-#include "tools/listiter.h"
-#include "tools/mpeg.h"
-#include "tools/pes.h"
-#include "tools/ts.h"
-#include "tools/functor.h"
-
-#include "frontend_local.h"
-#include "frontend_svr.h"
-
-#include "device.h"
-
-#define STILLPICTURE_REPEAT_COUNT 3
-#define LOCAL_INIT_TIMEOUT 20 // seconds
-#define SERVER_INIT_TIMEOUT 5 // seconds
-
-#ifdef LOG_TRICKSPEED
-# define LOGTRICKSPEED(x...) LOGMSG("trs: " x)
-#else
-# define LOGTRICKSPEED(x...)
-#endif
-
-//---------------------------- status monitor -------------------------------
-
-class cXinelibStatusMonitor : public cStatus
-{
- private:
- cXinelibStatusMonitor();
- cXinelibStatusMonitor(cXinelibStatusMonitor&);
-
- public:
- cXinelibStatusMonitor(cXinelibDevice& device, int cardIndex) :
- m_Device(device), m_cardIndex(cardIndex)
- {
-#ifdef DEBUG_SWITCHING_TIME
- switchtimeOff = 0LL;
- switchtimeOn = 0LL;
- switchingIframe = false;
-#endif
- };
-
- protected:
- virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber);
- virtual void Replaying(const cControl *Control, const char *Name,
- const char *FileName, bool On);
-
- cXinelibDevice& m_Device;
- int m_cardIndex;
-
-#ifdef DEBUG_SWITCHING_TIME
- public:
- int64_t switchtimeOff;
- int64_t switchtimeOn;
- bool switchingIframe;
-
- void IFrame(void)
- {
- if(!switchingIframe) {
- int64_t now = cTimeMs::Now();
- switchingIframe = true;
- LOGMSG("Channel switch: off -> on %" PRId64 " ms, "
- "on -> 1. I-frame %" PRId64 " ms",
- switchtimeOn-switchtimeOff, now-switchtimeOn);
- } else {
- int64_t now = cTimeMs::Now();
- LOGMSG("Channel switch: on -> 2. I-frame %" PRId64 " ms, "
- "Total %" PRId64 " ms",
- now-switchtimeOn, now-switchtimeOff);
- switchtimeOff = 0LL;
- switchtimeOn = 0LL;
- switchingIframe = false;
- }
- }
-#endif
-};
-
-void cXinelibStatusMonitor::ChannelSwitch(const cDevice *Device,
- int ChannelNumber)
-{
- TRACEF("cXinelibStatusMonitor::ChannelSwitch");
- TRACK_TIME(200);
-
- if (ChannelNumber) {
- if (Device->CardIndex() == m_cardIndex) {
-#ifdef DEBUG_SWITCHING_TIME
- switchtimeOn = cTimeMs::Now();
-#endif
- m_Device.SetTvMode(Channels.GetByNumber(ChannelNumber));
- TRACE("cXinelibStatusMonitor: Set to TvMode");
- }
- } else {
- if (Device->CardIndex() == m_cardIndex) {
-#ifdef DEBUG_SWITCHING_TIME
- switchtimeOff = cTimeMs::Now();
-#endif
- m_Device.StopOutput();
- TRACE("cXinelibStatusMonitor: received stop");
- }
- }
-}
-
-void cXinelibStatusMonitor::Replaying(const cControl *Control,
- const char *Name,
- const char *FileName, bool On)
-{
- TRACEF("cXinelibStatusMonitor::Replaying");
-
- if (On /*&& Name != NULL*/) {
- TRACE("cXinelibStatusMonitor: Replaying " << Name << "(" << FileName << ")");
- m_Device.SetReplayMode();
- }
-}
-
-//----------------------------- device ----------------------------------------
-
-//
-// Singleton
-//
-
-cXinelibDevice* cXinelibDevice::m_pInstance = NULL;
-
-cXinelibDevice& cXinelibDevice::Instance(void)
-{
- TRACEF("cXinelibDevice::Instance");
- if (!m_pInstance) {
- m_pInstance = new cXinelibDevice();
- TRACE("cXinelibDevice::Instance(): create, cardindex = "
- << m_pInstance->CardIndex());
- }
-
- return *m_pInstance;
-}
-
-void cXinelibDevice::Dispose(void)
-{
- TRACEF("cXinelibDevice::Dispose");
- delete m_pInstance;
- m_pInstance = NULL;
-}
-
-//
-// init and shutdown
-//
-
-cXinelibDevice::cXinelibDevice()
-{
- TRACEF("cXinelibDevice::cXinelibDevice");
-
- m_statusMonitor = NULL;
- m_spuDecoder = NULL;
-
- m_local = NULL;
- m_server = NULL;
-
- m_OriginalPrimaryDevice = 0;
- m_ForcePrimaryDeviceCnt = 0;
-
- if(*xc.local_frontend && strncmp(xc.local_frontend, "none", 4))
- m_clients.Add(m_local = new cXinelibLocal(xc.local_frontend));
- if(xc.remote_mode && xc.listen_port>0)
- m_clients.Add(m_server = new cXinelibServer(xc.listen_port));
-
- m_ac3Present = false;
- m_spuPresent = false;
-
- memset(m_MetaInfo, 0, sizeof(m_MetaInfo));
-
- m_PlayMode = pmNone;
- m_AudioChannel = 0;
-
- m_liveMode = true;
- m_TrickSpeed = -1;
- m_TrickSpeedPts = 0;
- m_TrickSpeedMode = 0;
- m_TrickSpeedDelay = 0;
- m_SkipAudio = false;
- m_PlayingFile = pmNone;
- m_StreamStart = true;
- m_RadioStream = false;
- m_AudioCount = 0;
- m_FreeBufs = 0;
- m_h264 = false;
-
- m_VideoSize = (video_size_t*)calloc(1, sizeof(video_size_t));
-
- TsBufferClear();
-}
-
-cXinelibDevice::~cXinelibDevice()
-{
- TRACEF("cXinelibDevice::~cXinelibDevice");
-
- StopDevice();
-
- m_pInstance = NULL;
-
- free (m_VideoSize);
-}
-
-bool cXinelibDevice::StartDevice()
-{
- TRACEF("cXinelibDevice::StartDevice");
-
- if(m_local)
- m_local->Start();
- if(m_server)
- m_server->Start();
-
- // if(dynamic_cast<cXinelibLocal*>(it))
- if(m_local) {
- int timer = 0;
- while (!m_local->IsReady()) {
- cCondWait::SleepMs(100);
- if (!m_local->Active()) {
- LOGMSG("cXinelibDevice::Start(): Local frontend init failed");
- return false;
- }
- if (++timer >= LOCAL_INIT_TIMEOUT*10) {
- LOGMSG("cXinelibDevice::Start(): Local frontend init timeout");
- return false;
- }
- }
- if(xc.force_primary_device)
- ForcePrimaryDevice(true);
- }
-
- if(m_server) {
- int timer = 0;
- while(!m_server->IsReady()) {
- cCondWait::SleepMs(100);
- if (!m_server->Active()) {
- LOGMSG("cXinelibDevice::Start(): Server init failed");
- return false;
- }
- if(++timer >= SERVER_INIT_TIMEOUT*10) {
- LOGMSG("cXinelibDevice::Start(): Server init timeout");
- return false;
- }
- }
- }
-
- ASSERT(m_statusMonitor == NULL, false);
- m_statusMonitor = new cXinelibStatusMonitor(*this, CardIndex());
-
- LOGDBG("cXinelibDevice::StartDevice(): Device started");
- return true;
-}
-
-void cXinelibDevice::StopDevice(void)
-{
- TRACEF("cXinelibDevice::StopDevice");
- LOGDBG("cXinelibDevice::StopDevice(): Stopping device ...");
-
- if(m_statusMonitor) {
- delete m_statusMonitor;
- m_statusMonitor = NULL;
- }
- if (m_spuDecoder) {
- delete m_spuDecoder;
- m_spuDecoder = NULL;
- }
-
- cXinelibThread *server = m_server;
- cXinelibThread *local = m_local;
- m_local = m_server = NULL;
-
- cControl::Shutdown();
- ForEach(m_clients, &cXinelibThread::SetLiveMode, false);
- TrickSpeed(-1);
-
- if(local) m_clients.Del(local, false);
- if(server) m_clients.Del(server, false);
-
- if(server)
- delete server;
- if(local)
- delete local;
-
- m_clients.Clear();
-}
-
-//
-// Primary device switching
-//
-
-void cXinelibDevice::MakePrimaryDevice(bool On)
-{
- TRACEF("cXinelibDevice::MakePrimaryDevice");
-
- cDevice::MakePrimaryDevice(On);
-
- if(On)
- new cXinelibOsdProvider(this);
-}
-
-void cXinelibDevice::ForcePrimaryDevice(bool On)
-{
- TRACEF("cXinelibDevice::ForcePrimaryDevice");
-
- m_MainThreadLock.Lock();
- m_MainThreadFunctors.Add(CreateFunctor(this, &cXinelibDevice::ForcePrimaryDeviceImpl, On));
- m_MainThreadLock.Unlock();
-}
-
-void cXinelibDevice::ForcePrimaryDeviceImpl(bool On)
-{
- TRACEF("cXinelibDevice::ForcePrimaryDeviceImpl");
- ASSERT(cThread::IsMainThread(), false);
-
- if(On) {
- m_ForcePrimaryDeviceCnt++;
-
- if(xc.force_primary_device) {
- if(cDevice::PrimaryDevice() && this != cDevice::PrimaryDevice()) {
- m_OriginalPrimaryDevice = cDevice::PrimaryDevice()->DeviceNumber() + 1;
- cControl::Shutdown();
- LOGMSG("Forcing primary device, original index = %d", m_OriginalPrimaryDevice);
- if(cOsd::IsOpen()) {
- LOGMSG("Forcing primary device, old OSD still open !");
- xc.main_menu_mode = CloseOsd;
- cRemote::CallPlugin("xineliboutput");
- }
- SetPrimaryDevice(DeviceNumber() + 1);
- }
- }
-
- } else /* Off */ {
- m_ForcePrimaryDeviceCnt--;
-
- if(m_ForcePrimaryDeviceCnt < 0)
- LOGMSG("ForcePrimaryDevice: Internal error (ForcePrimaryDevice < 0)");
- else if(m_ForcePrimaryDeviceCnt == 0) {
- if(m_OriginalPrimaryDevice) {
- LOGMSG("Restoring original primary device %d", m_OriginalPrimaryDevice);
- cControl::Shutdown();
- if(cOsd::IsOpen()) {
- LOGMSG("Restoring primary device, xineliboutput OSD still open !");
- xc.main_menu_mode = CloseOsd; /* will be executed in future by vdr main thread */
- cRemote::CallPlugin("xineliboutput");
- }
- cChannel *channel = Channels.GetByNumber(CurrentChannel());
- cDevice::SetPrimaryDevice(m_OriginalPrimaryDevice);
- PrimaryDevice()->SwitchChannel(channel, true);
- m_OriginalPrimaryDevice = 0;
- }
- }
- }
-}
-
-//
-// Execute functors in main thread context
-//
-
-void cXinelibDevice::MainThreadHook(void)
-{
- TRACEF("cXinelibDevice::MainThreadHook");
-
- if(m_MainThreadFunctors.First()) {
- cFunctor *f = NULL;
- do {
- m_MainThreadLock.Lock();
- if(f)
- m_MainThreadFunctors.Del(f);
- f = m_MainThreadFunctors.First();
- m_MainThreadLock.Unlock();
-
- if(f) {
- /*LOGDBG("cXinelibDevice::MainThreadHook: executing functor 0x%lx",(long)f);*/
- f->Execute();
- }
-
- } while(f);
- }
-}
-
-//
-// Configuration
-//
-
-void cXinelibDevice::ConfigurePostprocessing(const char *deinterlace_method,
- int audio_delay,
- int audio_compression,
- const int *audio_equalizer,
- int audio_surround,
- int speaker_type)
-{
- TRACEF("cXinelibDevice::ConfigurePostprocessing");
-
- if(m_local)
- m_local->ConfigurePostprocessing(deinterlace_method, audio_delay,
- audio_compression, audio_equalizer,
- audio_surround, speaker_type);
- if(m_server)
- m_server->ConfigurePostprocessing(deinterlace_method, audio_delay,
- audio_compression, audio_equalizer,
- audio_surround, speaker_type);
-}
-
-void cXinelibDevice::ConfigurePostprocessing(const char *name, bool on,
- const char *args)
-{
- TRACEF("cXinelibDevice::ConfigurePostprocessing");
-
- if(m_local)
- m_local->ConfigurePostprocessing(name, on, args);
- if(m_server)
- m_server->ConfigurePostprocessing(name, on, args);
-}
-
-void cXinelibDevice::ConfigureVideo(int hue, int saturation, int brightness, int sharpness,
- int noise_reduction, int contrast, int overscan, int vo_aspect_ratio)
-{
- TRACEF("cXinelibDevice::ConfigureVideo");
-
- if(m_local)
- m_local->ConfigureVideo(hue, saturation, brightness, sharpness, noise_reduction, contrast, overscan, vo_aspect_ratio);
- if(m_server)
- m_server->ConfigureVideo(hue, saturation, brightness, sharpness, noise_reduction, contrast, overscan, vo_aspect_ratio);
-}
-
-void cXinelibDevice::ConfigureDecoder(int pes_buffers)
-{
- TRACEF("cXinelibDevice::ConfigureDecoder");
-
- if(m_local)
- m_local->ConfigureDecoder(pes_buffers);
- //if(m_server)
- // m_server->ConfigureDecoder(pes_buffers);
-
- cXinelibOsdProvider::RefreshOsd();
-}
-
-void cXinelibDevice::ConfigureWindow(int fullscreen, int width, int height,
- int modeswitch, const char *modeline,
- int aspect, int scale_video,
- int field_order)
-{
- TRACEF("cXinelibDevice::ConfigureWindow");
-
- if((!*xc.local_frontend || !strncmp(xc.local_frontend, "none", 4)) && m_local) {
- cXinelibThread *tmp = m_local;
- m_clients.Del(tmp, false);
- m_local = NULL;
- cCondWait::SleepMs(5);
- delete tmp;
- if(xc.force_primary_device)
- ForcePrimaryDevice(false);
- }
-
- if(m_local)
- m_local->ConfigureWindow(fullscreen, width, height, modeswitch, modeline,
- aspect, scale_video, field_order);
-
- else if(*xc.local_frontend && strncmp(xc.local_frontend, "none", 4)) {
- cXinelibThread *tmp = new cXinelibLocal(xc.local_frontend);
- tmp->Start();
- m_clients.Add(m_local = tmp);
-
- cCondWait::SleepMs(25);
- while (!m_local->IsReady() && m_local->Active())
- cCondWait::SleepMs(25);
-
- if (!m_local->Active()) {
- m_local = NULL;
- m_clients.Del(tmp, true);
- Skins.QueueMessage(mtError, tr("Frontend initialization failed"), 10);
- } else {
- if(xc.force_primary_device)
- ForcePrimaryDevice(true);
-
- m_local->ConfigureWindow(fullscreen, width, height, modeswitch, modeline,
- aspect, scale_video, field_order);
- }
- }
-}
-
-void cXinelibDevice::Listen(bool activate, int port)
-{
- TRACEF("cXinelibDevice::Listen");
-
- if(activate && port>0) {
- if(!m_server) {
- cXinelibThread *tmp = new cXinelibServer(port);
- tmp->Start();
- m_clients.Add(m_server = tmp);
-
- cCondWait::SleepMs(10);
- while (!m_server->IsReady() && m_server->Active())
- cCondWait::SleepMs(10);
-
- if (!m_server->Active()) {
- Skins.QueueMessage(mtError, tr("Server initialization failed"), 10);
- m_server = NULL;
- m_clients.Del(tmp, true);
- }
-
- } else {
- if(! m_server->Listen(port))
- Skins.QueueMessage(mtError, tr("Server initialization failed"), 10);
- }
- } else if( /*((!activate) || port<=0) && */ m_server) {
- cXinelibThread *tmp = m_server;
- m_clients.Del(tmp, false);
- m_server = NULL;
- cCondWait::SleepMs(5);
- delete tmp;
- }
-}
-
-//
-// OSD
-//
-
-void cXinelibDevice::OsdCmd(void *cmd)
-{
- TRACEF("cXinelibDevice::OsdCmd");
- TRACK_TIME(250);
-
- if(m_server) // call first server, local frontend modifies contents of the message ...
- m_server->OsdCmd(cmd);
- if(m_local)
- m_local->OsdCmd(cmd);
-}
-
-//
-// Play mode control
-//
-void cXinelibDevice::StopOutput(void)
-{
- TRACEF("cXinelibDevice::StopOutput");
- TRACK_TIME(250);
-
- m_RadioStream = false;
- m_AudioCount = 0;
- ForEach(m_clients, &cXinelibThread::SetLiveMode, false);
- Clear();
- ForEach(m_clients, &cXinelibThread::QueueBlankDisplay);
- ForEach(m_clients, &cXinelibThread::SetNoVideo, false);
-}
-
-void cXinelibDevice::SetTvMode(cChannel *Channel)
-{
- TRACEF("cXinelibDevice::SetTvMode");
- TRACK_TIME(250);
-
-#if VDRVERSNUM >= 10701
- m_PatPmtParser.Reset();
-#endif
-
- m_RadioStream = false;
- if (Channel && !Channel->Vpid() && (Channel->Apid(0) || Channel->Apid(1)))
- m_RadioStream = true;
- if(m_PlayMode == pmAudioOnlyBlack)
- m_RadioStream = true;
- TRACE("cXinelibDevice::SetTvMode - isRadio = "<<m_RadioStream);
-
- m_StreamStart = true;
- m_liveMode = true;
- m_TrickSpeed = -1;
- m_SkipAudio = false;
- m_AudioCount = 0;
- m_spuPresent = false;
-
- Clear();
- ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream);
- ForEach(m_clients, &cXinelibThread::SetLiveMode, true);
- ForEach(m_clients, &cXinelibThread::ResumeOutput);
-}
-
-void cXinelibDevice::SetReplayMode(void)
-{
- TRACEF("cXinelibDevice::SetReplayMode");
-
- m_RadioStream = true; // first seen replayed video packet resets this
- m_AudioCount = 15;
- m_StreamStart = true;
-
- ForEach(m_clients, &cXinelibThread::SetLiveMode, false);
- Clear();
- ForEach(m_clients, &cXinelibThread::SetNoVideo, false /*m_RadioStream*/);
- if(m_RadioStream && !m_liveMode)
- ForEach(m_clients, &cXinelibThread::BlankDisplay);
- ForEach(m_clients, &cXinelibThread::ResumeOutput);
-
- m_liveMode = false;
-}
-
-bool cXinelibDevice::SetPlayMode(ePlayMode PlayMode)
-{
- TRACEF("cXinelibDevice::SetPlayMode");
-
-#ifdef XINELIBOUTPUT_DEBUG
- switch (PlayMode) {
- case pmNone:
- TRACE("cXinelibDevice::SetPlayMode audio/video from decoder"); break;
- case pmAudioVideo:
- TRACE("cXinelibDevice::SetPlayMode audio/video from player"); break;
- case pmVideoOnly:
- TRACE("cXinelibDevice::SetPlayMode video from player, audio from decoder"); break;
- case pmAudioOnly:
- TRACE("cXinelibDevice::SetPlayMode audio from player, video from decoder"); break;
- case pmAudioOnlyBlack:
- TRACE("cXinelibDevice::SetPlayMode audio only from player, no video (black screen)"); break;
- case pmExtern_THIS_SHOULD_BE_AVOIDED:
- TRACE("cXinelibDevice::SetPlayMode this should be avoided"); break;
- }
-#endif
-
- m_ac3Present = false;
- m_spuPresent = false;
-
- m_PlayMode = PlayMode;
-
- TrickSpeed(-1);
- if (m_PlayMode == pmAudioOnlyBlack) {
- TRACE("pmAudioOnlyBlack --> BlankDisplay, NoVideo");
- ForEach(m_clients, &cXinelibThread::BlankDisplay);
- ForEach(m_clients, &cXinelibThread::SetNoVideo, true);
- } else {
- if(m_liveMode)
- ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream);
- else
- ForEach(m_clients, &cXinelibThread::SetNoVideo,
- m_RadioStream && (m_AudioCount<1));
- Clear();
- }
-
- return true;
-}
-
-//
-// Playback control
-//
-
-// m_TrickSpeedMode flags
-#define trs_IPB_frames 0x01 // stream has all frame types
-#define trs_I_frames 0x02 // stream has only I-frames
-#define trs_PTS_recalc 0x04 // PTS must be re-calculated
-#define trs_NoAudio 0x08 // no audio in trick speed mode
-#define trs_PTS_check 0x80 // detect in PlayVideo if PTS must be recalculated
-
-void cXinelibDevice::TrickSpeed(int Speed)
-{
- TRACEF("cXinelibDevice::TrickSpeed");
-
- if(m_TrickSpeed != Speed) {
- int RealSpeed = abs(Speed);
- LOGTRICKSPEED("TrickSpeed changed from %d to %d [%d]", m_TrickSpeed, Speed, RealSpeed);
-
- m_TrickSpeedPts = 0;
- m_TrickSpeed = Speed;
- m_TrickSpeedDelay = 0;
-
- // Possible transitions:
- // fast <-> play
- // play <-> pause
- // pause <-> slow
- // _and_ from any mode to normal play and pause
-
- if(Speed == 8 || Speed == 4 || Speed == 2) {
- LOGTRICKSPEED(" Slow forward (1/%d speed), IPB-frames", Speed);
-
- // do nothing - slow forward is just slow playback of complete stream
- m_TrickSpeedMode = trs_IPB_frames;
-
- // previous state was slow forward or pause --> no need for clear
-
- // change decoder and UDP/RTP scheduler clock rates
- ForEach(m_clients, &cXinelibThread::TrickSpeed, RealSpeed);
- }
-
- else if(Speed == 63 || Speed == 48 || Speed == 24) {
- RealSpeed = (Speed+11)/12;
- LOGTRICKSPEED(" Slow backward (1/%d speed), I-frames only", RealSpeed);
-
- // previous state was slow backwards or pause --> clear if it was pause
- //
- //if(PrevSpeed == 0 && !(m_TrickSpeedMode & trs_PTS_recalc)) {
- // LOGMSG(" -> Clear");
- // ForEach(m_clients, &cXinelibThread::Clear);
- //}
-
- // only I-frames, backwards, pts must be re-generated
- m_TrickSpeedMode = trs_I_frames | trs_PTS_recalc | trs_NoAudio;
-
- // change decoder and UDP/RTP scheduler clock rates
- ForEach(m_clients, &cXinelibThread::TrickSpeed, RealSpeed);
- }
-
- else if(Speed == 6 || Speed == 3 || Speed == 1) {
- RealSpeed = 12/Speed;
- LOGTRICKSPEED(" Fast (%dx speed), direction unknown", RealSpeed);
-
- if(RealSpeed > xc.max_trickspeed) {
- RealSpeed = xc.max_trickspeed;
- LOGTRICKSPEED(" Trick speed limited to %dx speed", RealSpeed);
- }
-
- /* only I-frames, backwards, pts must be re-generated if playing backwards */
- m_TrickSpeedMode |= trs_PTS_check;
-
- /* backward/forward state is unknown until first PTS is seen
- so, clear() must be done in PlayVideo. */
- /* previous trick speed state is not overwritten yet ... ! */
-
- // change decoder and UDP/RTP scheduler clock rates
- ForEach(m_clients, &cXinelibThread::TrickSpeed, -RealSpeed);
- }
-
- else if(Speed==-1 || Speed == 0) {
- LOGTRICKSPEED(" Play/Pause");
-
- // change decoder and UDP/RTP scheduler clock rates
- ForEach(m_clients, &cXinelibThread::TrickSpeed, RealSpeed);
-
- // returning from backward mode needs Clear
- //
- //if(Speed==-1 && (m_TrickSpeedMode & trs_PTS_recalc)) {
- // LOGMSG(" -> Clear");
- // ForEach(m_clients, &cXinelibThread::Clear);
- // m_TrickSpeedMode = 0;
- //}
- // returning from fast forward mode needs Clear
- // because of DvbPlayer jumps few seconds back at mode change ...
- //
- //if(Speed==-1 && (m_TrickSpeedMode & trs_I_frames)) {
- // LOGMSG(" -> Clear");
- // ForEach(m_clients, &cXinelibThread::Clear);
- //}
- m_TrickSpeedMode = 0;
- }
-
- else {
- LOGTRICKSPEED(" Unknown trickspeed %d !", Speed);
- m_TrickSpeedMode = 0;
- m_TrickSpeed = -1;
- ForEach(m_clients, &cXinelibThread::TrickSpeed, -1);
- }
- }
-}
-
-void cXinelibDevice::Clear(void)
-{
- TRACEF("cXinelibDevice::Clear");
- TRACK_TIME(100);
-
- TsBufferClear();
-
- m_StreamStart = true;
- m_h264 = false;
- m_FreeBufs = 0;
- TrickSpeed(-1);
- ForEach(m_clients, &cXinelibThread::Clear);
- ForEach(m_clients, &cXinelibThread::SetStillMode, false);
-}
-
-void cXinelibDevice::Play(void)
-{
- TRACEF("cXinelibDevice::Play");
-
- m_SkipAudio = false;
-
- ForEach(m_clients, &cXinelibThread::SetLiveMode, false);
- TrickSpeed(-1);
-}
-
-void cXinelibDevice::Freeze(void)
-{
- TRACEF("cXinelibDevice::Freeze");
-
- TsBufferFlush();
- TrickSpeed(0);
-}
-
-int64_t cXinelibDevice::GetSTC(void)
-{
- TRACEF("cXinelibDevice::GetSTC");
-
- if(m_local)
- return m_local->GetSTC();
- if(m_server)
- return m_server->GetSTC();
- return cDevice::GetSTC();
-}
-
-bool cXinelibDevice::Flush(int TimeoutMs)
-{
- TRACEF("cXinelibDevice::Flush");
- TRACK_TIME(500);
-
- TsBufferFlush();
-
- if(m_TrickSpeed == 0) {
- ForEach(m_clients, &cXinelibThread::SetLiveMode, false);
- TrickSpeed(-1);
- }
-
- bool r = ForEach(m_clients, &cXinelibThread::Flush, TimeoutMs,
- &mand<bool>, true);
-
- return r;
-}
-
-
-//
-// Playback of files and images
-//
-
-int cXinelibDevice::PlayFileCtrl(const char *Cmd, int TimeoutMs)
-{
- TRACEF("cXinelibDevice::PlayFile");
- int result = -1;
-
- /*if(m_PlayingFile != pmNone)*/ {
- if(m_server)
- result = m_server->PlayFileCtrl(Cmd, TimeoutMs);
- if(m_local)
- result = m_local->PlayFileCtrl(Cmd, TimeoutMs);
- }
- return result;
-}
-
-bool cXinelibDevice::EndOfStreamReached(void)
-{
- if(m_local && !m_local->EndOfStreamReached())
- return false;
- if(m_server && !m_server->EndOfStreamReached())
- return false;
- return true;
-}
-
-bool cXinelibDevice::PlayFile(const char *FileName, int Position,
- bool LoopPlay, ePlayMode PlayMode,
- int TimeoutMs)
-{
- TRACEF("cXinelibDevice::PlayFile");
- TRACE("cXinelibDevice::PlayFile(\"" << FileName << "\")");
-
- bool result = true;
-
- if(FileName) {
- if(m_PlayingFile == pmNone) {
- m_PlayingFile = PlayMode;
- if (!xc.IsImageFile(FileName))
- StopOutput();
- }
- for(int i = 0; i < mi_Count; i++)
- m_MetaInfo[i][0] = 0;
- if(m_server)
- result = m_server->PlayFile(FileName, Position, LoopPlay, PlayMode, TimeoutMs);
- if(m_local)
- result = m_local->PlayFile(FileName, Position, LoopPlay, PlayMode, TimeoutMs);
- } else if(/*!FileName &&*/m_PlayingFile != pmNone) {
- if(m_server)
- result = m_server->PlayFile(NULL, 0, 0, pmNone, TimeoutMs);
- if(m_local)
- result = m_local->PlayFile(NULL, 0, 0, pmNone, TimeoutMs);
- if(!m_liveMode)
- SetReplayMode();
- else
- SetTvMode(Channels.GetByNumber(cDevice::CurrentChannel()));
- m_PlayingFile = pmNone;
- }
-
- return result;
-}
-
-//
-// Data stream handling
-//
-
-int cXinelibDevice::PlayTrickSpeed(const uchar *buf, int length)
-{
-#if VDRVERSNUM >= 10705
- return 0;
-#endif
- if(abs(m_TrickSpeed) > 1 && (m_TrickSpeedMode & trs_I_frames)) {
- uint8_t PictureType = pes_get_picture_type(buf, length);
-#ifdef LOG_TRICKSPEED
- if(PictureType != NO_PICTURE && PES_HAS_PTS(buf)) {
- int64_t pts = pes_get_pts(buf, length);
- LOGMSG(" TrickSpeed: frame %s pts %"PRId64, picture_type_str[PictureType], pts);
- }
-#endif
-
-#if 1
- // limit I-frame rate
- if(PictureType == I_FRAME) {
- static int64_t t0 = 0;
- int64_t t1 = cTimeMs::Now();
- if((t1 - t0) < 1000) {
- int fdelay = 40*12; // = 480 ms, time of one GOP in normal speed
- switch(m_TrickSpeed) {
- case 6: /* 2x ff */ fdelay /= min( 2, xc.max_trickspeed); break;
- case 3: /* 4x ff */ fdelay /= min( 4, xc.max_trickspeed); break;
- case 1: /* 12x ff */ fdelay /= min(12, xc.max_trickspeed); break;
- case 63: /* 1/6x rew */ fdelay *= 6; break;
- case 48: /* 1/4x rew */ fdelay *= 4; break;
- case 24: /* 1/2x rew */ fdelay *= 2; break;
- default: break;
- }
- /* wait if data is coming in too fast */
- if(fdelay - (t1-t0) >= 40) {
- m_TrickSpeedDelay = 40;
- return -1;
- }
-
- t0 += fdelay;
-
- pes_change_pts((uchar*)buf, length, INT64_C(0));
- } else {
- t0 = t1;
- }
- }
-#endif
- }
-
- //
- // detecting trick speed mode ?
- //
- if( m_TrickSpeed > 0 && (m_TrickSpeedMode & trs_PTS_check) && IS_VIDEO_PACKET(buf)) {
- int64_t pts;
- if (PES_HAS_PTS(buf) && (pts = pes_get_pts(buf, length)) > 0) {
- uint8_t PictureType = pes_get_picture_type(buf, length);
- if(PictureType != I_FRAME && PictureType != NO_PICTURE) {
- // --> must be fast worward with IBP frames.
- // --> PTS check does not work (frames are sent in decoder order) ! */
- m_TrickSpeedPts = pts - 1;
- LOGTRICKSPEED(" Detected fast forward mode, using IBP frames");
- }
- if(m_TrickSpeedPts == 0) {
- m_TrickSpeedMode |= trs_NoAudio;
- m_TrickSpeedPts = pts;
- LOGTRICKSPEED(" Seen video pts = %"PRId64, pts);
- } else {
- if(pts < m_TrickSpeedPts) {
- /* -> playing fast backwards */
- LOGTRICKSPEED(" Detected fast backward mode. last %"PRId64" now %"PRId64,
- m_TrickSpeedPts, pts);
- //if(!(m_TrickSpeedMode & trs_PTS_recalc))
- // ForEach(m_clients, &cXinelibThread::Clear);
- m_TrickSpeedMode = trs_I_frames | trs_PTS_recalc | trs_NoAudio;
- } else {
- LOGTRICKSPEED(" Detected fast forward mode");
- if(xc.ibp_trickspeed)
- m_TrickSpeedMode = trs_IPB_frames;
- else
- m_TrickSpeedMode = trs_I_frames;
- }
- }
- }
- }
-
- //
- // Trick speed mode with PTS re-calc
- //
- if( m_TrickSpeed > 0 && (m_TrickSpeedMode & trs_PTS_recalc) &&
- IS_VIDEO_PACKET(buf) && PES_HAS_PTS(buf)) {
- int64_t pts = pes_get_pts(buf, length);
- if (pts > 0) {
-
- /* m_TrickSpeedPts could be 0 in case of slow backwards */
- if(m_TrickSpeedPts == 0)
- m_TrickSpeedPts = pts;
-
- LOGTRICKSPEED(" pts %"PRId64" -> %"PRId64" (diff %"PRId64") %"PRId64"", pts,
- m_TrickSpeedPts + 40*12*90, m_TrickSpeedPts + 40*12*90 - pts,
- (m_TrickSpeedPts + 40*12*90)^0x80000000);
- pts = m_TrickSpeedPts = m_TrickSpeedPts + 40*12*90; /* 12 frames * 40ms -> pts units */
- pts ^= 0x80000000; /* discontinuity (when mode changes) forces re-syncing of all clocks */
- pes_change_pts((uchar*)buf, length, pts);
- }
- }
-
-#if 1
- else if (m_TrickSpeedMode & trs_I_frames) {
- if (IS_VIDEO_PACKET(buf) && PES_HAS_PTS(buf)) {
- int64_t pts = pes_get_pts(buf, length);
- if (pts > 0) {
- pts ^= 0x80000000; /* discontinuity (when mode changes) forces re-syncing of all clocks */
- pes_change_pts((uchar*)buf, length, pts);
- }
- }
- }
-#endif
-
- return 0;
-}
-
-int cXinelibDevice::PlayAny(const uchar *buf, int length)
-{
- TRACEF("cXinelibDevice::PlayAny");
- TRACK_TIME(100);
-
-#if 0
- if(m_PlayingFile)
- return length;
-#endif
-
- if (!buf || length <= 0)
- return length;
-
- //
- // Need to be sure Poll has been called for every frame:
- // - cDevice can feed multiple frames after each poll from player/transfer.
- // - If only part of frames are consumed, rest are fed again after next Poll.
- // - If there are multiple clients it is possible first client(s)
- // can queue more frames than last client(s).
- // -> frame(s) are either lost immediately (last client(s))
- // or duplicated after next poll (first client(s))
- //
- if(m_FreeBufs < 1) {
- cPoller Poller;
- if(!Poll(Poller,0)) {
- errno = EAGAIN;
- return 0;
- }
- }
-
- bool isMpeg1 = false;
- if (DATA_IS_PES(buf)) {
- isMpeg1 = pes_is_mpeg1(buf);
- int len = pes_packet_len(buf, length);
- if (len>0 && len != length)
- LOGMSG("cXinelibDevice::PlayAny: invalid data !");
- }
-
- if(m_TrickSpeed > 0) {
- if(PlayTrickSpeed(buf, length) < 0)
- return 0; /* wait if data is coming in too fast */
- } else if(m_SkipAudio) {
- /* needed for still images when moving cutting marks */
- if (DATA_IS_PES(buf))
- pes_change_pts((uchar*)buf, length, INT64_C(0));
- }
- m_FreeBufs --;
-
- if(m_local) {
- length = (isMpeg1 ? m_local->Play_Mpeg1_PES(buf,length) :
- m_local->Play_PES(buf,length));
- }
- if(m_server && length > 0) {
- int length2 = isMpeg1 ? m_server->Play_Mpeg1_PES(buf, length) :
- m_server->Play_PES(buf, length);
- if(!m_local)
- return length2;
- }
-
- return length;
-}
-
-#if VDRVERSNUM >= 10701
-/*
- * hook to PlayTs() to get PAT and PMT
- */
-int cXinelibDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly)
-{
- if (Length > TS_SIZE) Length = TS_SIZE;
-
- if (Length == TS_SIZE && TsHasPayload(Data)) {
- int PayloadOffset = TsPayloadOffset(Data);
- if (PayloadOffset < Length) {
- int Pid = TsPid(Data);
- if (Pid == 0) {
-#if VDRVERSNUM >= 10708
- m_PatPmtParser.Reset();
-#endif
-#if VDRVERSNUM >= 10704
- m_PatPmtParser.ParsePat(Data, Length);
-#else
- m_PatPmtParser.ParsePat(Data + PayloadOffset, Length - PayloadOffset);
-#endif
- //LOGDBG("Got PAT: PMT pid = %d", m_PatPmtParser.PmtPid());
- if (m_server)
- m_server->SetHeader(Data, Length, true);
- PlayTsAny(Data, Length);
- } else if (Pid == m_PatPmtParser.PmtPid()) {
-#if VDRVERSNUM >= 10704
- m_PatPmtParser.ParsePmt(Data, Length);
-#else
- m_PatPmtParser.ParsePmt(Data + PayloadOffset, Length - PayloadOffset);
-#endif
- m_h264 = (m_PatPmtParser.Vtype() == 0x1b); /* ISO_14496_PART10_VIDEO */
- //LOGDBG("Got PMT packet, h264 = %d", m_h264?1:0);
- if (m_server)
- m_server->SetHeader(Data, Length);
-#ifndef NO_HACKS
- ForEach(m_clients, &cXinelibThread::SetHDMode, m_h264);
-#endif
- PlayTsAny(Data, Length);
- TsBufferFlush();
- }
- }
- } else if (!Data) {
- TsBufferFlush();
- }
-
- return cDevice::PlayTs(Data, Length, VideoOnly);
-}
-
-int cXinelibDevice::TsBufferFlush(void)
-{
- if (m_TsBufSize) {
- int n;
- if ((n = PlayAny(m_TsBuf, m_TsBufSize)) == (int)m_TsBufSize) {
- m_TsBufSize = 0;
- return n;
- }
- if (n)
- LOGMSG("cXinelibDevice::TsBufferFlush: error: cache not flushed (%d %d)", n, m_TsBufSize);
- errno = EAGAIN;
- }
- return 0;
-}
-
-int cXinelibDevice::PlayTsAny(const uchar *buf, int length)
-{
- if (!DATA_IS_TS(buf))
- LOGMSG("PlayTsAny(): TS SYNC byte missing !");
- if (length != TS_SIZE)
- LOGMSG("PlayTsAny(): length == %d !", length);
-
- // cache full ? try to flush it
- if (m_TsBufSize >= 2048)
- if (!TsBufferFlush())
- return 0;
-
- // add packet to cache
- memcpy(m_TsBuf + m_TsBufSize, buf, length);
- m_TsBufSize += length;
-
- // time to flush ?
- if (m_TsBufSize >= 2048-TS_SIZE-1)
- TsBufferFlush();
-
- return length;
-}
-
-int cXinelibDevice::PlayTsSubtitle(const uchar *Data, int Length)
-{
- if (!xc.dvb_subtitles)
- return cDevice::PlayTsSubtitle(Data, Length);
-
- return PlayTsAny(Data, Length);
-}
-
-int cXinelibDevice::PlayTsAudio(const uchar *Data, int Length)
-{
- return PlayTsAny(Data, Length);
-}
-
-int cXinelibDevice::PlayTsVideo(const uchar *Data, int Length)
-{
- return PlayTsAny(Data, Length);
-}
-#endif // VDRVERSNUM >= 10701
-
-int cXinelibDevice::PlayVideo(const uchar *buf, int length)
-{
- TRACEF("cXinelibDevice::PlayVideo");
- TRACK_TIME(100);
-
- if(m_PlayMode == pmAudioOnlyBlack)
- return length;
-
- if (!DATA_IS_PES(buf)) {
- LOGMSG("PlayVideo: data is not PES !");
- return length;
- }
-
- if(m_RadioStream) {
- m_RadioStream = false;
- m_AudioCount = 0;
- ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream);
- }
-
- if(m_StreamStart) {
-#ifdef START_IFRAME
- // Start with I-frame if stream has video
- // wait for first I-frame
- if (pes_get_picture_type(buf, length) == I_FRAME) {
- m_StreamStart = false;
- } else {
- return length;
- }
-#endif
-
- if (!m_h264 && pes_is_frame_h264(buf, length)) {
- LOGMSG("cXinelibDevice::PlayVideo: Detected H.264 video");
- m_h264 = true;
- }
-
- if (pes_get_video_size(buf, length, m_VideoSize, m_h264 ? 1:0)) {
- m_StreamStart = false;
- LOGDBG("Detected video size %dx%d", m_VideoSize->width, m_VideoSize->height);
- ForEach(m_clients, &cXinelibThread::SetHDMode, (m_VideoSize->width > 800));
- }
- }
-
-#ifdef DEBUG_SWITCHING_TIME
- if(m_statusMonitor->switchtimeOff && m_statusMonitor->switchtimeOn) {
- if (pes_get_picture_type(buf, length) == I_FRAME)
- m_statusMonitor->IFrame();
- }
-#endif
-
- if(m_PlayingFile && (m_PlayingFile == pmAudioVideo || m_PlayingFile == pmVideoOnly))
- return length;
-
- return PlayAny(buf, length);
-}
-
-void cXinelibDevice::StillPicture(const uchar *Data, int Length)
-{
- TRACEF("cXinelibDevice::StillPicture");
-
- // skip still images coming in too fast (ex. when moving cutting marks)
- if(cRemote::HasKeys()) {
- static int skipped = 0;
- static uint64_t lastshow = 0;
- uint64_t now = cTimeMs::Now();
- if(now - lastshow < 500) {
- skipped++;
- //LOGMSG("Skipping still image (coming in too fast)");
- return;
- }
- LOGDBG("Forcing still image - skipped %d images", skipped);
- lastshow = now;
- skipped = 0;
- }
-
- bool isPes = DATA_IS_PES(Data) && ((Data[3] & 0xF0) == 0xE0);
- bool isMpeg1 = isPes && ((Data[6] & 0xC0) != 0x80);
- bool isH264 = isPes && pes_is_frame_h264(Data, Length);
-#if VDRVERSNUM >= 10701
- bool isTs = DATA_IS_TS(Data);
-#endif
-
- int i;
-
- if(m_PlayingFile && (m_PlayingFile == pmAudioVideo || m_PlayingFile == pmVideoOnly))
- return;
-
- TsBufferFlush();
-
- ForEach(m_clients, &cXinelibThread::Clear);
- ForEach(m_clients, &cXinelibThread::SetNoVideo, false);
- ForEach(m_clients, &cXinelibThread::SetLiveMode, false);
- ForEach(m_clients, &cXinelibThread::SetStillMode, true);
- ForEach(m_clients, &cXinelibThread::TrickSpeed, 1);
-
- m_TrickSpeed = -1; // to make Poll work ...
- m_SkipAudio = 1; // enables audio and pts stripping
-
- for(i=0; i<STILLPICTURE_REPEAT_COUNT; i++)
- if(isMpeg1) {
- ForEach(m_clients, &cXinelibThread::Play_Mpeg1_PES, Data, Length,
- &mmin<int>, Length);
- } else if(isPes) {
- /*cDevice::*/PlayPes(Data, Length, m_SkipAudio);
-#if VDRVERSNUM >= 10701
- } else if(isTs) {
- /*cDevice::*/PlayTs(Data, Length, m_SkipAudio);
-#endif
- } else {
- ForEach(m_clients, &cXinelibThread::Play_Mpeg2_ES,
- Data, Length, VIDEO_STREAM,
- &mand<bool>, true);
- }
-
- if(!isH264) {
- // creates empty video PES with pseudo-pts
- ForEach(m_clients, &cXinelibThread::Play_Mpeg2_ES,
- Data, 0, VIDEO_STREAM,
- &mand<bool>, true);
- }
-
- TsBufferFlush();
-
- ForEach(m_clients, &cXinelibThread::Flush, 60,
- &mand<bool>, true);
-
- m_TrickSpeed = 0;
- m_SkipAudio = 0;
-}
-
-int cXinelibDevice::PlayAudio(const uchar *buf, int length, uchar Id)
-{
- TRACEF("cXinelibDevice::PlayAudio");
- TRACK_TIME(100);
-
- if(!buf || length < 6)
- return length;
-
-#ifdef SKIP_AC3_AUDIO
- // skip AC3 audio
- if(((unsigned char *)buf)[3] == PRIVATE_STREAM1) {
- TRACE("cXinelibDevice::PlayVideo: PRIVATE_STREAM1 discarded");
- return length;
- }
-#endif
-
- // strip audio in trick speed modes and when displaying still images
- if(m_SkipAudio /*|| m_TrickSpeed > 0*/)
- return length;
- if(m_TrickSpeedMode & trs_NoAudio)
- return length;
-
- if(m_RadioStream) {
- if(m_AudioCount) {
- m_AudioCount--;
- if(!m_AudioCount) {
- LOGDBG("PlayAudio detected radio stream");
- ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream);
- }
- }
- }
-
- if(m_PlayingFile && (m_PlayingFile == pmAudioVideo || m_PlayingFile == pmAudioOnly))
- return length;
-
- return PlayAny(buf, length);
-}
-
-int cXinelibDevice::PlaySubtitle(const uchar *Data, int Length)
-{
- if(!xc.dvb_subtitles)
- return cDevice::PlaySubtitle(Data, Length);
- return PlayAny(Data, Length);
-}
-
-bool cXinelibDevice::Poll(cPoller &Poller, int TimeoutMs)
-{
- TRACEF("cXinelibDevice::Poll");
- TRACK_TIME(400);
-
- if(m_PlayingFile == pmAudioVideo)
- return true;
-
- if(m_TrickSpeed == 0) {
- cCondWait::SleepMs(min(TimeoutMs, 20));
- return Poller.Poll(0);
- }
-
- if(!m_local && !m_server) {
- /* nothing to do... why do I exist ... ? */
- //cCondWait::SleepMs(TimeoutMs);
- //return Poller.Poll(0);
- return true;
- }
-
- if(m_TrickSpeed > 1 && m_TrickSpeedDelay > 20) {
- LOGTRICKSPEED(" Poll: m_TrickSpeedDelay=%d.", m_TrickSpeedDelay);
- cCondWait::SleepMs(20);
- m_TrickSpeedDelay -= 20;
- return false;
- }
-
- if(m_FreeBufs < 1) {
- int result = DEFAULT_POLL_SIZE;
-
- if(m_local)
- result = min(result, m_local->Poll(Poller, TimeoutMs));
- if(m_server)
- result = min(result, m_server->Poll(Poller, TimeoutMs));
-
- m_FreeBufs = max(result, 0);
- }
-
- return m_FreeBufs > 0 /*|| Poller.Poll(0)*/;
-}
-
-//
-// Audio facilities
-//
-
-void cXinelibDevice::SetVolumeDevice(int Volume)
-{
- TRACEF("cXinelibDevice::SetVolumeDevice");
-
- ForEach(m_clients, &cXinelibThread::SetVolume, Volume);
-}
-
-void cXinelibDevice::SetAudioTrackDevice(eTrackType Type)
-{
- TRACEF("cXinelibDevice::SetAudioTrackDevice");
-
- // track changes are autodetected at xine side
-}
-
-void cXinelibDevice::SetAudioChannelDevice(int AudioChannel)
-{
- TRACEF("cXinelibDevice::SetAudioChannelDevice");
-
- if(m_AudioChannel != AudioChannel) {
- m_AudioChannel = AudioChannel;
- //LOGDBG("cXinelibDevice::SetAudioChannelDevice --> %d", AudioChannel);
-#if 0
- switch(AudioChannel) {
- default:
- //case 0: ConfigurePostprocessing("upmix_mono", false, NULL);
- case 0: ConfigurePostprocessing("upmix_mono", true, "channel=-1");
- break;
- case 1: ConfigurePostprocessing("upmix_mono", true, "channel=0");
- break;
- case 2: ConfigurePostprocessing("upmix_mono", true, "channel=1");
- break;
- }
-#else
- switch(AudioChannel) {
- default:
- case 0: ConfigurePostprocessing("audiochannel", false, NULL);
- break;
- case 1: ConfigurePostprocessing("audiochannel", true, "channel=0");
- break;
- case 2: ConfigurePostprocessing("audiochannel", true, "channel=1");
- break;
- }
-#endif
- }
-}
-
-void cXinelibDevice::SetDigitalAudioDevice(bool On)
-{
- TRACEF("cXinelibDevice::SetDigitalAudioDevice");
-
- // track changes are autodetected at xine side
-}
-
-//
-// Video format facilities
-//
-
-void cXinelibDevice::SetVideoFormat(bool VideoFormat16_9)
-{
- TRACEF("cXinelibDevice::SetVideoFormat");
- cDevice::SetVideoFormat(VideoFormat16_9);
-
-#if 0
- //
- // TODO
- //
- if(xc.aspect != ASPECT_AUTO &&
- xc.aspect != ASPECT_DEFAULT) {
- if(VideoFormat16_9)
- xc.aspect = ASPECT_16_9;
- else if(xc.aspect == ASPECT_16_9)
- xc.aspect = ASPECT_4_3;
- ConfigureDecoder(,,,xc.aspect,,,);
- }
-#endif
-}
-
-void cXinelibDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
-{
- TRACEF("cXinelibDevice::SetVideoDisplayFormat");
- cDevice::SetVideoDisplayFormat(VideoDisplayFormat);
-
-#if 0
- //
- // TODO
- //
- // - set normal, pan&scan, letterbox (only for 4:3?)
- //
- if(xc.aspect != ASPECT_AUTO &&
- xc.aspect != ASPECT_DEFAULT) {
- switch(VideoDisplayFormat) {
- case vdfPanAndScan:
- xc.aspect = ASPECT_PAN_SCAN;
- break;
- case vdfLetterBox:
- xc.aspect = ASPECT_4_3; /* borders are added automatically if needed */
- break;
- case vdfCenterCutOut:
- xc.aspect = ASPECT_CENTER_CUT_OUT;
- break;
- }
- ConfigureDecoder(,,,xc.aspect,,,);
- }
-#endif
-}
-
-eVideoSystem cXinelibDevice::GetVideoSystem(void)
-{
- TRACEF("cXinelibDevice::GetVideoSystem");
- return cDevice::GetVideoSystem();
-}
-
-#if VDRVERSNUM >= 10708
-void cXinelibDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect)
-{
- Width = m_VideoSize->width;
- Height = m_VideoSize->height;
- VideoAspect = 1.0;
- if (m_VideoSize->pixel_aspect.den) {
- VideoAspect = (double)m_VideoSize->pixel_aspect.num / (double)m_VideoSize->pixel_aspect.den;
- VideoAspect *= (double)Width / (double)Height;
- }
-}
-#endif
-
-void cXinelibDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect)
-{
- switch (xc.osd_size) {
- case OSD_SIZE_720x576:
- Width = 720;
- Height = 576;
- break;
- case OSD_SIZE_1280x720:
- Width = 1280;
- Height = 720;
- break;
- case OSD_SIZE_1920x1080:
- Width = 1920;
- Height = 1080;
- break;
- case OSD_SIZE_auto:
- if (xc.osd_width_auto > 0 && xc.osd_height_auto > 0) {
- Width = xc.osd_width_auto;
- Height = xc.osd_height_auto;
- break;
- }
- case OSD_SIZE_custom:
- default:
- Width = xc.osd_width;
- Height = xc.osd_height;
- break;
- }
- PixelAspect = 16.0 / 9.0 / (double)Width * (double)Height;
-}
-
-//
-// SPU decoder
-//
-
-#ifdef FORWARD_DVD_SPUS
-# include "spu_decoder.h"
-#endif
-
-cSpuDecoder *cXinelibDevice::GetSpuDecoder(void)
-{
- TRACEF("cXinelibDevice::GetSpuDecoder");
- if (!m_spuDecoder && IsPrimaryDevice()) {
- //
- // TODO
- //
- // - use own derived SpuDecoder with special cXinelibOsd
- // -> always visible
- //
-
-#ifdef FORWARD_DVD_SPUS
- // forward DVD SPUs to xine without decoding
- m_spuDecoder = new cFwdSpuDecoder(this);
-#else
- m_spuDecoder = new cDvbSpuDecoder();
-#endif
- }
- return m_spuDecoder;
-}
-
-//
-// Image Grabbing
-//
-
-uchar *cXinelibDevice::GrabImage(int &Size, bool Jpeg,
- int Quality, int SizeX, int SizeY)
-{
- TRACEF("cXinelibDevice::GrabImage");
-
- if(m_local)
- return m_local->GrabImage(Size, Jpeg, Quality, SizeX, SizeY);
- if(m_server)
- return m_server->GrabImage(Size, Jpeg, Quality, SizeX, SizeY);
-
- return NULL;
-}
-
-
-//
-// Available DVD SPU tracks
-//
-
-void cXinelibDevice::SetSubtitleTrackDevice(eTrackType Type)
-{
- if (m_PlayingFile == pmAudioVideo || m_PlayingFile == pmVideoOnly)
- ForEach(m_clients, &cXinelibThread::SetSubtitleTrack, Type);
-}
-
-//
-// Metainfo
-//
-
-const char *cXinelibDevice::GetMetaInfo(eMetainfoType Type)
-{
- if(Type >= 0 && Type < mi_Count) {
- if ((Type == miTitle) ||
- (Type == miTracknumber && xc.playlist_tracknumber == 1) ||
- (Type == miArtist && xc.playlist_artist == 1) ||
- (Type == miAlbum && xc.playlist_album == 1) ||
- (Type > miAlbum)) {
- return m_MetaInfo[Type];
- }
- return "";
- }
-
- LOGMSG("cXinelibDevice::GetMetaInfo: unknown metainfo type");
- return "";
-}
-
-void cXinelibDevice::SetMetaInfo(eMetainfoType Type, const char *Value)
-{
- if(Type >= 0 && Type < mi_Count) {
- /* set to 0 first, so if player is accessing string in middle of
- copying it will always be 0-terminated (but truncated) */
- memset(m_MetaInfo[Type], 0, sizeof(m_MetaInfo[Type]));
- strn0cpy(m_MetaInfo[Type], Value, MAX_METAINFO_LEN);
- } else {
- LOGMSG("cXinelibDevice::SetMetaInfo: unknown metainfo type");
- }
-}
-