summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--device.c495
-rw-r--r--device.h211
2 files changed, 361 insertions, 345 deletions
diff --git a/device.c b/device.c
index 5de4498d..80b67c18 100644
--- a/device.c
+++ b/device.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: device.c,v 1.25 2006-10-18 20:32:22 phintuka Exp $
+ * $Id: device.c,v 1.26 2006-10-23 19:18:09 phintuka Exp $
*
*/
@@ -26,6 +26,7 @@
#define HD_MODE_TEST
//#define TEST_TRICKSPEEDS
//#define SKIP_DVDSPU
+//#define FORWARD_DVD_SPUS
#define DEBUG_SWITCHING_TIME
#include "logdefs.h"
@@ -45,12 +46,6 @@
//---------------------------- status monitor -------------------------------
-#ifdef DEBUG_SWITCHING_TIME
-int64_t switchtimeOff = 0LL;
-int64_t switchtimeOn = 0LL;
-bool switchingIframe;
-#endif
-
class cXinelibStatusMonitor : public cStatus
{
private:
@@ -59,7 +54,14 @@ class cXinelibStatusMonitor : public cStatus
public:
cXinelibStatusMonitor(cXinelibDevice& device, int cardIndex) :
- m_Device(device), m_cardIndex(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);
@@ -72,6 +74,32 @@ class cXinelibStatusMonitor : public cStatus
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,
@@ -126,7 +154,10 @@ void cXinelibStatusMonitor::Replaying(const cControl *Control,
//----------------------------- device ----------------------------------------
+//
// Singleton
+//
+
cXinelibDevice* cXinelibDevice::m_pInstance = NULL;
cXinelibDevice& cXinelibDevice::Instance(void)
@@ -162,6 +193,9 @@ cXinelibDevice::cXinelibDevice()
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)
@@ -223,6 +257,7 @@ bool cXinelibDevice::StartDevice()
}
}
+ ASSERT(m_statusMonitor == NULL, false);
m_statusMonitor = new cXinelibStatusMonitor(*this, CardIndex());
LOGDBG("cXinelibDevice::StartDevice(): Device started");
@@ -251,9 +286,14 @@ void cXinelibDevice::StopDevice(void)
m_clients.Clear();
}
+//
+// Primary device switching
+//
+
void cXinelibDevice::MakePrimaryDevice(bool On)
{
TRACEF("cXinelibDevice::MakePrimaryDevice");
+
if(On)
new cXinelibOsdProvider(this);
}
@@ -261,6 +301,7 @@ void cXinelibDevice::MakePrimaryDevice(bool On)
void cXinelibDevice::ForcePrimaryDevice(bool On)
{
TRACEF("cXinelibDevice::ForcePrimaryDevice");
+
m_MainThreadLock.Lock();
m_MainThreadFunctors.Add(CreateFunctor(this, &cXinelibDevice::ForcePrimaryDeviceImpl, On));
m_MainThreadLock.Unlock();
@@ -268,22 +309,17 @@ void cXinelibDevice::ForcePrimaryDevice(bool On)
void cXinelibDevice::ForcePrimaryDeviceImpl(bool On)
{
- static int Original = 0;
- static int Counter = 0;
-
TRACEF("cXinelibDevice::ForcePrimaryDeviceImpl");
- /*LOGDBG("cXinelibDevice::ForcePrimaryDeviceImpl(%s)",On?"On":"Off");*/
-
- /* TODO: All this stuff should really be done in VDR main thread context... */
+ ASSERT(cThread::IsMainThread(), false);
if(On) {
- Counter++;
+ m_ForcePrimaryDeviceCnt++;
+
if(xc.force_primary_device) {
if(cDevice::PrimaryDevice() && this != cDevice::PrimaryDevice()) {
- /* TODO: may need to use vdr main thread for this */
- Original = cDevice::PrimaryDevice()->DeviceNumber() + 1;
+ m_OriginalPrimaryDevice = cDevice::PrimaryDevice()->DeviceNumber() + 1;
cControl::Shutdown();
- LOGMSG("Forcing primary device, original index = %d", Original);
+ LOGMSG("Forcing primary device, original index = %d", m_OriginalPrimaryDevice);
if(cOsd::IsOpen()) {
LOGMSG("Forcing primary device, old OSD still open !");
#if VDRVERSNUM >= 10400
@@ -296,12 +332,13 @@ void cXinelibDevice::ForcePrimaryDeviceImpl(bool On)
}
} else /* Off */ {
- Counter--;
- if(Counter<0)
+ m_ForcePrimaryDeviceCnt--;
+
+ if(m_ForcePrimaryDeviceCnt < 0)
LOGMSG("ForcePrimaryDevice: Internal error (ForcePrimaryDevice < 0)");
- if(!Counter) {
- if(Original) {
- LOGMSG("Restoring original primary device %d", Original);
+ 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 !");
@@ -311,14 +348,18 @@ void cXinelibDevice::ForcePrimaryDeviceImpl(bool On)
#endif
}
cChannel *channel = Channels.GetByNumber(CurrentChannel());
- cDevice::SetPrimaryDevice(Original);
+ cDevice::SetPrimaryDevice(m_OriginalPrimaryDevice);
PrimaryDevice()->SwitchChannel(channel, true);
- Original = 0;
+ m_OriginalPrimaryDevice = 0;
}
}
}
}
+//
+// Execute functors in main thread context
+//
+
void cXinelibDevice::MainThreadHook(void)
{
TRACEF("cXinelibDevice::MainThreadHook");
@@ -424,9 +465,11 @@ void cXinelibDevice::ConfigureWindow(int fullscreen, int width, int height,
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();
@@ -442,9 +485,9 @@ void cXinelibDevice::ConfigureWindow(int fullscreen, int width, int height,
Skins.QueueMessage(mtError, tr("Frontend initialization failed"), 10);
} else {
if(xc.force_primary_device)
- ForcePrimaryDevice(true);
+ ForcePrimaryDevice(true);
- m_local->ConfigureWindow(fullscreen, width, height, modeswitch, modeline,
+ m_local->ConfigureWindow(fullscreen, width, height, modeswitch, modeline,
aspect, scale_video, field_order);
}
}
@@ -536,6 +579,7 @@ void cXinelibDevice::SetTvMode(cChannel *Channel)
m_TrickSpeed = -1;
m_SkipAudio = false;
m_AudioCount = 0;
+ m_spuPresent = false;
Clear();
ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream);
@@ -585,6 +629,7 @@ bool cXinelibDevice::SetPlayMode(ePlayMode PlayMode)
m_ac3Present = false;
m_spuPresent = false;
+
ClrAvailableDvdSpuTracks();
m_PlayMode = PlayMode;
@@ -594,7 +639,7 @@ bool cXinelibDevice::SetPlayMode(ePlayMode PlayMode)
ForEach(m_clients, &cXinelibThread::BlankDisplay);
ForEach(m_clients, &cXinelibThread::SetNoVideo, true);
} else {
- ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream);
+ ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream && (!m_liveMode || m_AudioCount<1));
ForEach(m_clients, &cXinelibThread::Clear);
}
@@ -643,6 +688,34 @@ void cXinelibDevice::Freeze(void)
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);
+
+ 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
//
@@ -724,7 +797,7 @@ int cXinelibDevice::PlayAny(const uchar *buf, int length)
if(!m_SkipAudio) {
#ifdef TEST_TRICKSPEEDS
-#warning Experimental trickspeed mode handling included !
+# warning Experimental trickspeed mode handling included !
// TODO: re-gen pts or signal pts+trickspeed for udp scheduler
bool Video = false, Audio = false;
uchar PictureType = NO_PICTURE;
@@ -784,9 +857,10 @@ int cXinelibDevice::PlayVideo(const uchar *buf, int length)
ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream);
}
-#ifdef START_IFRAME
- // Start with I-frame if stream has video
if(m_StreamStart) {
+
+#ifdef START_IFRAME
+ // Start with I-frame if stream has video
// wait for first I-frame
uchar pictureType;
if( ScanVideoPacket(buf, length, /*0,*/pictureType) > 0 &&
@@ -795,52 +869,24 @@ int cXinelibDevice::PlayVideo(const uchar *buf, int length)
} else {
return length;
}
- }
-#elif defined(HD_MODE_TEST)
- if(m_StreamStart) {
- int i = 8; // the minimum length of the video packet header
- i += buf[i] + 1; // possible additional header bytes
- for (; i < length-6; i++) {
- if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1) {
- if(buf[i + 3] == 0xb3) {
- int d = (buf[i+4] << 16) | (buf[i+5] << 8) | buf[i+6];
- int w = (d >> 12);
- int h = (d & 0xfff);
-
- m_StreamStart = false;
- LOGMSG("Detected video size %dx%d", w, h);
- ForEach(m_clients, &cXinelibThread::SetHDMode, (w>800));
- break;
- }
- }
- }
- }
-#else
- m_StreamStart = false;
#endif
+#if defined(HD_MODE_TEST)
+ int Width, Height;
+ if(GetVideoSize(buf, length, &Width, &Height)) {
+ m_StreamStart = false;
+ LOGDBG("Detected video size %dx%d", Width, Height);
+ ForEach(m_clients, &cXinelibThread::SetHDMode, (Width > 800));
+ }
+#endif
+ }
#ifdef DEBUG_SWITCHING_TIME
- if(switchtimeOff && switchtimeOn) {
+ if(m_statusMonitor->switchtimeOff && m_statusMonitor->switchtimeOn) {
uchar pictureType;
- if( ScanVideoPacket(buf, length, /*0,*/pictureType) > 0 &&
- pictureType == I_FRAME) {
- 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;
- }
- }
+ if( ScanVideoPacket(buf, length, pictureType) > 0 &&
+ pictureType == I_FRAME)
+ m_statusMonitor->IFrame();
}
#endif
@@ -869,7 +915,7 @@ void cXinelibDevice::StillPicture(const uchar *Data, int Length)
ForEach(m_clients, &cXinelibThread::TrickSpeed, 1);
m_TrickSpeed = -1; // to make Poll work ...
- m_SkipAudio = 1; // enables audio and pts stripping
+ m_SkipAudio = 1; // enables audio and pts stripping
for(i=0; i<STILLPICTURE_REPEAT_COUNT; i++)
if(isMpeg1) {
@@ -931,23 +977,52 @@ int cXinelibDevice::PlaySpu(const uchar *buf, int length, uchar Id)
TRACE("cXinelibDevice::PlaySpu first DVD SPU frame");
Skins.QueueMessage(mtInfo,"DVD Subtitles");
m_spuPresent = true;
-
+
ForEach(m_clients, &cXinelibThread::SpuStreamChanged, (int)Id);
}
+ // Strip all but selected SPU track
if(Id != m_CurrentDvdSpuTrack)
return length;
}
-printf("SPU %d\n", Id);
-
- //
- // TODO: channel must be selectable
- //
return PlayAny(buf, length);
#endif
}
+bool cXinelibDevice::Poll(cPoller &Poller, int TimeoutMs)
+{
+ TRACEF("cXinelibDevice::Poll");
+ TRACK_TIME(400);
+
+ if(m_PlayingFile)
+ return true;
+
+ if(m_TrickSpeed == 0) {
+ cCondWait::SleepMs(TimeoutMs);
+ return Poller.Poll(0);
+ }
+
+ if(!m_local && !m_server) {
+ /* nothing to do... why do I exist ... ? */
+ cCondWait::SleepMs(TimeoutMs);
+ return Poller.Poll(0);
+ }
+
+ bool result = true;
+
+ if(m_local)
+ result = result && m_local->Poll(Poller, TimeoutMs);
+ if(m_server)
+ result = result && m_server->Poll(Poller, TimeoutMs);
+
+ return result /*|| Poller.Poll(0)*/;
+}
+
+//
+// Audio facilities
+//
+
void cXinelibDevice::SetVolumeDevice(int Volume)
{
TRACEF("cXinelibDevice::SetVolumeDevice");
@@ -959,15 +1034,7 @@ void cXinelibDevice::SetAudioTrackDevice(eTrackType Type)
{
TRACEF("cXinelibDevice::SetAudioTrackDevice");
-#if 0
- LOGMSG("SetAudioTrackDevice(%d)", (int)Type);
- if(IS_DOLBY_TRACK(Type))
- ForEach(m_clients, &cXinelibThread::AudioStreamChanged,
- true, (PRIVATE_STREAM1<<8) | (int)(Type - ttDolbyFirst));
- if(IS_AUDIO_TRACK(Type))
- ForEach(m_clients, &cXinelibThread::AudioStreamChanged,
- false, (AUDIO_STREAM + (int)(Type - ttAudioFirst)) << 8);
-#endif
+ // track changes are autodetected at xine side
}
void cXinelibDevice::SetAudioChannelDevice(int AudioChannel)
@@ -977,10 +1044,13 @@ void cXinelibDevice::SetAudioChannelDevice(int AudioChannel)
m_AudioChannel = AudioChannel;
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;
+ default:
+ case 0: ConfigurePostprocessing("audiochannel", false, NULL);
+ break;
+ case 1: ConfigurePostprocessing("audiochannel", true, "channel=0");
+ break;
+ case 2: ConfigurePostprocessing("audiochannel", true, "channel=1");
+ break;
}
}
@@ -988,40 +1058,22 @@ void cXinelibDevice::SetDigitalAudioDevice(bool On)
{
TRACEF("cXinelibDevice::SetDigitalAudioDevice");
-#if 0
- LOGMSG("SetDigitalAudioDevice(%s)", On ? "on" : "off");
- /* selects wrong track if new track is not dolby track */
- eTrackType CurrTrack = GetCurrentAudioTrack();
- if(m_LastTrack != CurrTrack) {
- bool ac3 = IS_DOLBY_TRACK(CurrTrack);
- int index = CurrTrack - (ac3 ? ttDolbyFirst : ttAudioFirst);
- m_LastTrack = CurrTrack;
-#if 0
- LOGMSG(" Switching audio track -> %d (%02x:%s:%d)", m_LastTrack,
- ac3 ? PRIVATE_STREAM1 : (index+AUDIO_STREAM),
- ac3 ? "AC3" : "MPEG", index);
-#endif
- if(ac3)
- ForEach(m_clients, &cXinelibThread::AudioStreamChanged, true,
- (PRIVATE_STREAM1 << 8) | index);
- else
- ForEach(m_clients, &cXinelibThread::AudioStreamChanged, false,
- (index + AUDIO_STREAM) << 8);
- }
-#endif
+ // track changes are autodetected at xine side
}
+//
+// Video format facilities
+//
+
void cXinelibDevice::SetVideoFormat(bool VideoFormat16_9)
{
TRACEF("cXinelibDevice::SetVideoFormat");
- /*LOGDBG("SetVideoFormat(%s)", VideoFormat16_9 ? "16:9" : "4:3");*/
-
cDevice::SetVideoFormat(VideoFormat16_9);
+#if 0
//
// TODO
//
-#if 0
if(xc.aspect != ASPECT_AUTO &&
xc.aspect != ASPECT_DEFAULT) {
if(VideoFormat16_9)
@@ -1036,15 +1088,14 @@ void cXinelibDevice::SetVideoFormat(bool VideoFormat16_9)
void cXinelibDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
{
TRACEF("cXinelibDevice::SetVideoDisplayFormat");
-
- /*LOGDBG("SetVideoDisplayFormat(%d)", VideoDisplayFormat);*/
cDevice::SetVideoDisplayFormat(VideoDisplayFormat);
+
+#if 0
//
// TODO
//
// - set normal, pan&scan, letterbox (only for 4:3?)
//
-#if 0
if(xc.aspect != ASPECT_AUTO &&
xc.aspect != ASPECT_DEFAULT) {
switch(VideoDisplayFormat) {
@@ -1069,129 +1120,19 @@ eVideoSystem cXinelibDevice::GetVideoSystem(void)
return cDevice::GetVideoSystem();
}
-bool cXinelibDevice::Poll(cPoller &Poller, int TimeoutMs)
-{
- TRACEF("cXinelibDevice::Poll");
- TRACK_TIME(400);
-
- if(m_PlayingFile)
- return true;
-
- if(m_TrickSpeed == 0) {
- cCondWait::SleepMs(TimeoutMs);
- return Poller.Poll(0);
- }
-
- if(!m_local && !m_server) {
- /* nothing to do... why do I exist ... ? */
- cCondWait::SleepMs(TimeoutMs);
- return Poller.Poll(0);
- }
-
- bool result = true;
-
- if(m_local)
- result = result && m_local->Poll(Poller, TimeoutMs);
- if(m_server)
- result = result && m_server->Poll(Poller, TimeoutMs);
-
- return result /*|| Poller.Poll(0)*/;
-}
-
-bool cXinelibDevice::Flush(int TimeoutMs)
-{
- TRACEF("cXinelibDevice::Flush");
- TRACK_TIME(500);
-
- 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;
-}
-
-#if 0
//
-// TODO
-// - forward spu's directly to Xine
+// SPU decoder
//
-class cXineSpuDecoder : public cDvbSpuDecoder
-{
- private:
- cSpuDecoder::eScaleMode scaleMode;
- cXinelibDevice *m_Device;
-
- public:
- cXineSpuDecoder(cXinelibDevice *dev) {
- scaleMode = eSpuNormal;
- m_Device = dev;
- }
- virtual ~cXineSpuDecoder() {};
-
- virtual int setTime(uint32_t pts) { return 1; }
-
- cSpuDecoder::eScaleMode getScaleMode(void) { return scaleMode; }
- virtual void setScaleMode(cSpuDecoder::eScaleMode ScaleMode)
- { scaleMode = ScaleMode; }
- virtual void setPalette(uint32_t * pal) {};
- virtual void setHighlight(uint16_t sx, uint16_t sy,
- uint16_t ex, uint16_t ey,
- uint32_t palette) {};
- virtual void clearHighlight(void) {};
- virtual void Empty(void) {};
- virtual void Hide(void) {};
- virtual void Draw(void) {};
- virtual bool IsVisible(void) { return true; }
- virtual void processSPU(uint32_t pts, uint8_t * buf,
- bool AllowedShow = true);
-};
-#define CMD_SPU_MENU 0x00
-#define CMD_SPU_SHOW 0x01
-#define CMD_SPU_HIDE 0x02
-#define CMD_SPU_SET_PALETTE 0x03
-#define CMD_SPU_SET_ALPHA 0x04
-#define CMD_SPU_SET_SIZE 0x05
-#define CMD_SPU_SET_PXD_OFFSET 0x06
-#define CMD_SPU_CHG_COLCON 0x07
-#define CMD_SPU_EOF 0xff
-
-#define spuU32(i) ((spu[i] << 8) + spu[i+1])
-
-void cXineSpuDecoder::processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow)
-{
- uchar buf2[65536+8] = {0, 0, 1, PRIVATE_STREAM1, 0, 0, 0x80, 0x80, 5};
- int len = ((buf[0] << 8) | buf[1]);
-
- if(len+8 < 0xffff) {
- buf2[4] = ((len+8)<<8) & 0xFF;
- buf2[5] = ((len+8)) & 0xFF;
- } else {
- // should be able to handle this (but only internally ...)
- LOGMSG("cXineSpuDecoder: SPU bigger than PES packet !");
- buf2[4] = 0xff;
- buf2[5] = 0xff;
- }
- buf2[9] = ((pts>>29) & 0x0E) | 0x21;
- buf2[10] = (pts>>22) & 0xFF;
- buf2[11] = (pts>>14) & 0xFE;
- buf2[12] = (pts>>7) & 0xFF;
- buf2[13] = (pts<<1) & 0xFE;
-
- memcpy(buf2+14, buf, len);
-
- m_Device->PlaySpu(buf, len+14, 0);
-}
+#ifdef FORWARD_DVD_SPUS
+# include "spu_decoder.h"
#endif
cSpuDecoder *cXinelibDevice::GetSpuDecoder(void)
{
TRACEF("cXinelibDevice::GetSpuDecoder");
- if (!m_spuDecoder && IsPrimaryDevice())
+ if (!m_spuDecoder && IsPrimaryDevice()) {
//
// TODO
//
@@ -1199,26 +1140,19 @@ cSpuDecoder *cXinelibDevice::GetSpuDecoder(void)
// -> always visible
//
-#if 1
- m_spuDecoder = new cDvbSpuDecoder();
+#ifdef FORWARD_DVD_SPUS
+ // forward DVD SPUs to xine without decoding
+ m_spuDecoder = new cFwdSpuDecoder(this);
#else
-#warning NON-FUNCTIONAL SPU DECODER SELECTED !!!
- m_spuDecoder = new cXineSpuDecoder(this);
+ m_spuDecoder = new cDvbSpuDecoder();
#endif
+ }
return m_spuDecoder;
}
-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();
-}
-
+//
+// Image Grabbing
+//
#if VDRVERSNUM < 10338
@@ -1268,8 +1202,12 @@ uchar *cXinelibDevice::GrabImage(int &Size, bool Jpeg,
#endif
-#if 1
-// override cDevice to get DVD SPUs
+//
+// DVD SPU support in VDR recordings
+//
+// - override cDevice::PlayPesPacket to get DVD SPUs
+//
+
int cXinelibDevice::PlayPesPacket(const uchar *Data, int Length,
bool VideoOnly)
{
@@ -1297,12 +1235,17 @@ int cXinelibDevice::PlayPesPacket(const uchar *Data, int Length,
return cDevice::PlayPesPacket(Data, Length, VideoOnly);
}
+
+//
+// Available DVD SPU tracks
+//
+
bool cXinelibDevice::SetCurrentDvdSpuTrack(int Type)
{
if(Type == -1 ||
- (Type >= 0 &&
- Type < 64 &&
- m_DvdSpuTrack[Type])) {
+ ( Type >= 0 &&
+ Type < 64 &&
+ m_DvdSpuTrack[Type].id != 0xffff)) {
m_CurrentDvdSpuTrack = Type;
ForEach(m_clients, &cXinelibThread::SpuStreamChanged, Type);
return true;
@@ -1312,9 +1255,8 @@ bool cXinelibDevice::SetCurrentDvdSpuTrack(int Type)
void cXinelibDevice::ClrAvailableDvdSpuTracks(bool NotifyFrontend)
{
- m_DvdSpuTracks = 0;
for(int i=0; i<64; i++)
- m_DvdSpuTrack[i] = false;
+ m_DvdSpuTrack[i].id = 0xffff;
if(m_CurrentDvdSpuTrack >=0 ) {
m_CurrentDvdSpuTrack = -1;
if(NotifyFrontend)
@@ -1322,23 +1264,39 @@ void cXinelibDevice::ClrAvailableDvdSpuTracks(bool NotifyFrontend)
}
}
-const char *cXinelibDevice::GetDvdSpuLang(int Type)
+int cXinelibDevice::NumDvdSpuTracks(void) const
+{
+ int DvdSpuTracks = 0;
+ for(int i=0; i<64; i++)
+ if(m_DvdSpuTrack[i].id != 0xffff)
+ DvdSpuTracks++;
+ return DvdSpuTracks;
+}
+
+const tTrackId *cXinelibDevice::GetDvdSpuTrack(int Type) const
{
if(Type >= 0 && Type < 64 &&
- m_DvdSpuTrack[Type])
- return m_DvdSpuLang[Type][0] ? m_DvdSpuLang[Type] : NULL;
+ m_DvdSpuTrack[Type].id != 0xffff)
+ return &m_DvdSpuTrack[Type];
+ return NULL;
+}
+
+const char *cXinelibDevice::GetDvdSpuLang(int Type) const
+{
+ const tTrackId *track = GetDvdSpuTrack(Type);
+ if(track)
+ return track->language[0] ? track->language : NULL;
return NULL;
}
bool cXinelibDevice::SetAvailableDvdSpuTrack(int Type, const char *lang, bool Current)
{
- if(Type >= 0 && Type < 64 &&
- ! m_DvdSpuTrack[Type]) {
- m_DvdSpuTrack[Type] = true;
- m_DvdSpuLang[Type][0] = 0;
+ if(Type >= 0 && Type < 64) {
+ m_DvdSpuTrack[Type].id = Type;
+ m_DvdSpuTrack[Type].language[0] = '\0';
if(lang)
- strn0cpy(m_DvdSpuLang[Type], lang, 32);
- m_DvdSpuTracks++;
+ strn0cpy(m_DvdSpuTrack[Type].language, lang, MAXLANGCODE2);
+ //m_DvdSpuTracks++;
if(Current)
m_CurrentDvdSpuTrack = Type;
return true;
@@ -1346,12 +1304,3 @@ bool cXinelibDevice::SetAvailableDvdSpuTrack(int Type, const char *lang, bool Cu
return false;
}
-bool cXinelibDevice::HasDvdSpuTrack(int Type) const
-{
- if(Type >= 0 && Type < 64 &&
- m_DvdSpuTrack[Type])
- return true;
- return false;
-}
-
-#endif
diff --git a/device.h b/device.h
index 3a36a2df..dd1415a7 100644
--- a/device.h
+++ b/device.h
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: device.h,v 1.13 2006-10-18 20:32:51 phintuka Exp $
+ * $Id: device.h,v 1.14 2006-10-23 19:18:09 phintuka Exp $
*
*/
@@ -22,60 +22,124 @@ class cFunctor;
class cXinelibDevice : public cDevice
{
- public:
- static cXinelibDevice& Instance(void); // singleton
- static void Dispose(void);
+
+ // Singleton
private:
static cXinelibDevice* m_pInstance; // singleton
cXinelibDevice(); //
cXinelibDevice(cXinelibDevice&); // no copy constructor
- // function calls waiting to be executed in VDR main thread context
+ public:
+ static cXinelibDevice& Instance(void); // singleton
+ static void Dispose(void);
+
+ virtual ~cXinelibDevice();
+
+
+ // device start/stop (from cPlugin)
+
+ public:
+ bool StartDevice(void);
+ void StopDevice(void);
+
+
+ // function calls waiting to be executed in VDR main thread context
+
+ private:
cList<cFunctor> m_MainThreadFunctors;
cMutex m_MainThreadLock;
+ public:
+ void MainThreadHook(void);
+
+
+ // Primary device switching
+
+ private:
+ int m_OriginalPrimaryDevice;
+ int m_ForcePrimaryDeviceCnt;
+
void ForcePrimaryDeviceImpl(bool On);
public:
- virtual ~cXinelibDevice();
+ virtual void MakePrimaryDevice(bool On);
+ void ForcePrimaryDevice(bool On);
+
+
+ // Device capabilities
+
+ public:
virtual bool HasDecoder(void) const { return true; };
virtual bool CanReplay(void) const { return true; };
- virtual void MakePrimaryDevice(bool On);
- void ForcePrimaryDevice(bool On);
- void MainThreadHook(void);
- virtual void Clear(void);
- virtual void Play(void);
- virtual void TrickSpeed(int Speed);
- virtual void Freeze(void);
+ // Playback control
- virtual void StillPicture(const uchar *Data, int Length);
- virtual bool Poll(cPoller &Poller, int TimeoutMs = 0);
- virtual bool Flush(int TimeoutMs = 0);
+ private:
+ ePlayMode m_PlayMode;
+ int m_TrickSpeed;
+ int64_t m_TrickSpeedPts;
+
+ public:
+ virtual bool SetPlayMode(ePlayMode PlayMode);
+ ePlayMode GetPlayMode(void) const { return m_PlayMode; };
+
+ protected:
+ virtual void Clear(void);
+ virtual void Play(void);
+ virtual void TrickSpeed(int Speed);
+ virtual void Freeze(void);
+ virtual bool Flush(int TimeoutMs = 0);
virtual int64_t GetSTC(void);
- // Video format facilities
+
+ // Video format facilities
+
public:
virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat);
virtual void SetVideoFormat(bool VideoFormat16_9);
virtual eVideoSystem GetVideoSystem(void);
- // Track facilities
+
+ // Track facilities
+
protected:
virtual void SetAudioTrackDevice(eTrackType Type);
- // Audio facilities
+ private:
+ // (DVD) SPU tracks, -> cDevice
+ tTrackId m_DvdSpuTrack[64];
+ int m_CurrentDvdSpuTrack;
+
+ public:
+ void ClrAvailableDvdSpuTracks(bool NotifyFrontend = true);
+ bool SetAvailableDvdSpuTrack(int Type, const char *lang = NULL, bool Current = false);
+
+ int NumDvdSpuTracks(void) const;
+ const tTrackId *GetDvdSpuTrack(int Type) const;
+ const char *GetDvdSpuLang(int Type) const;
+
+ int GetCurrentDvdSpuTrack(void) const { return m_CurrentDvdSpuTrack; }
+ bool SetCurrentDvdSpuTrack(int Type);
+
+
+ // Audio facilities
+
private:
eTrackType m_LastTrack;
int m_AudioChannel;
+
protected:
- virtual int GetAudioChannelDevice(void) {return m_AudioChannel;}
+ virtual int GetAudioChannelDevice(void) { return m_AudioChannel; }
virtual void SetAudioChannelDevice(int AudioChannel);
virtual void SetVolumeDevice(int Volume);
virtual void SetDigitalAudioDevice(bool On);
+
+
+ // Image grabbing
+
public:
#if VDRVERSNUM < 10338
@@ -87,21 +151,44 @@ class cXinelibDevice : public cDevice
int Quality = -1, int SizeX = -1, int SizeY = -1);
#endif
+
+ // SPU decoder
+
+ private:
+ cSpuDecoder *m_spuDecoder;
+
+ friend class cXineSpuDecoder;
+
+ public:
virtual cSpuDecoder *GetSpuDecoder(void);
- // Messages from StatusMonitor:
+
+ // Messages from StatusMonitor:
+
+ private:
+ cXinelibStatusMonitor *m_statusMonitor;
+ bool m_liveMode;
+
+ public:
void SetTvMode(cChannel *Channel);
void SetReplayMode(void);
void StopOutput(void);
- // device startup (from cPlugin)
- bool StartDevice(void);
- void StopDevice(void);
- // Osd Commands (from cXinelibOsd)
+ // Osd Commands (from cXinelibOsd)
+
+ public:
void OsdCmd(void *cmd);
- // Configuration
+
+ // Configuration
+
+ private:
+ cList<cXinelibThread> m_clients;
+ cXinelibThread *m_server;
+ cXinelibThread *m_local;
+
+ public:
void ConfigureOSD(bool prescale_osd, bool unscaled_osd);
void ConfigurePostprocessing(const char *deinterlace_method,
int audio_delay,
@@ -121,70 +208,50 @@ class cXinelibDevice : public cDevice
// remote mode:
void Listen(bool activate, int port);
- // File playback
+
+ // File playback
+
+ private:
+ bool m_PlayingFile;
+
+ public:
bool PlayFile(const char *Filename, int Position=0, bool LoopPlay=false);
int PlayFileCtrl(const char *Cmd);
bool EndOfStreamReached(void);
+
+ // Stream data
+
private:
+ bool m_ac3Present;
+ bool m_spuPresent;
+ bool m_RadioStream;
+ int m_AudioCount;
+ bool m_SkipAudio;
+ bool m_StreamStart;
int PlayAny(const uchar *Data, int Length);
protected:
+
+ virtual bool Poll(cPoller &Poller, int TimeoutMs = 0);
+
+ virtual void StillPicture(const uchar *Data, int Length);
+
virtual int PlayVideo(const uchar *Data, int Length);
virtual int PlayAudio(const uchar *Data, int Length, uchar Id);
-#if VDRVERSNUM< 10342
- virtual int PlayAudio(const uchar *Data, int Length)
- { return PlayAudio(Data, Length, 0); }
-#endif
+
virtual int PlaySpu(const uchar *Data, int Length, uchar Id);
-#if 1
// override cDevice to get DVD SPUs
virtual int PlayPesPacket(const uchar *Data, int Length,
bool VideoOnly = false);
- // -> cDevice
- int m_DvdSpuTracks;
- int m_CurrentDvdSpuTrack;
- bool m_DvdSpuTrack[64];
- char m_DvdSpuLang[64][64];
-
- public:
- void ClrAvailableDvdSpuTracks(bool NotifyFrontend = true);
- bool SetAvailableDvdSpuTrack(int Type, const char *lang = NULL, bool Current=false);
- const char *GetDvdSpuLang(int Type);
- int NumDvdSpuTracks(void) const { return m_DvdSpuTracks; }
- int GetCurrentDvdSpuTrack(void) { return m_CurrentDvdSpuTrack; }
- bool SetCurrentDvdSpuTrack(int Type);
- bool HasDvdSpuTrack(int Type) const;
+#if VDRVERSNUM < 10342
+ // API changed in VDR 1.3.42
+ virtual int PlayAudio(const uchar *Data, int Length)
+ { return PlayAudio(Data, Length, 0); }
#endif
-
- virtual bool SetPlayMode(ePlayMode PlayMode);
- ePlayMode GetPlayMode(void) const { return m_PlayMode; };
-
- protected:
- ePlayMode m_PlayMode;
-
- cList<cXinelibThread> m_clients;
- cXinelibThread *m_server;
- cXinelibThread *m_local;
- cXinelibStatusMonitor *m_statusMonitor;
- cSpuDecoder *m_spuDecoder;
-
- bool m_ac3Present;
- bool m_spuPresent;
-
- bool m_liveMode;
- int m_TrickSpeed;
- int64_t m_TrickSpeedPts;
- bool m_SkipAudio;
- bool m_PlayingFile;
- bool m_StreamStart;
- bool m_RadioStream;
- int m_AudioCount;
-
- friend class cXineSpuDecoder;
};
#endif // __XINELIB_DEVICE_H