From 3a81d2944e05d9212a7f5dae6b15351df7f79760 Mon Sep 17 00:00:00 2001 From: Mark Calderbank Date: Sat, 6 Dec 2008 15:08:34 +0000 Subject: [PATCH] DVB Subtitles: Live TV --- demuxer.cc | 8 ++++ demuxerts.cc | 109 +++++++++++++++++++++++++++++++++++------------- demuxerts.h | 9 +++- demuxervdr.cc | 5 ++- dvbsubtitles.cc | 4 +- playerlivetv.cc | 38 ++++++++++++++++- playerlivetv.h | 8 +++- vvideolivetv.cc | 28 ++++++++++++- vvideolivetv.h | 8 +++- 9 files changed, 177 insertions(+), 40 deletions(-) diff --git a/demuxer.cc b/demuxer.cc index 931f33f..21a6eb6 100644 --- a/demuxer.cc +++ b/demuxer.cc @@ -22,6 +22,7 @@ #include "demuxer.h" #include "callback.h" +#include "dvbsubtitles.h" #include "log.h" #define DEMUXER_SEQ_HEAD 0x000001B3 @@ -301,6 +302,12 @@ bool Demuxer::submitPacket(PESPacket& packet) sent = packet.getSize(); } } + else if (packet_type == PESTYPE_PRIVATE_1 && + packet.getSubstream() == 0x20) + { + if (subtitles) subtitles->put(packet); + sent = packet.getSize(); + } else { sent = packet.getSize(); @@ -355,6 +362,7 @@ pre_1_3_19_Recording: //This is for old recordings stuff and live TV { case 0x20://SPU case 0x30://SPU + packet.setSubstream(substream_id); break; case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there? break; diff --git a/demuxerts.cc b/demuxerts.cc index 2b1acd2..03c6a9c 100644 --- a/demuxerts.cc +++ b/demuxerts.cc @@ -1,5 +1,5 @@ /* - Copyright 2006-2007 Mark Calderbank + Copyright 2006-2008 Mark Calderbank This file is part of VOMP. @@ -14,18 +14,20 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "demuxerts.h" #include "log.h" -DemuxerTS::DemuxerTS(int p_vID, int p_aID) +DemuxerTS::DemuxerTS(int p_vID, int p_aID, int p_subID) { - vID = p_vID; - aID = p_aID; + vID = p_vID; vActive = false; + aID = p_aID; aActive = false; + subID = p_subID; subActive = false; atype = 0; + subLength = 0; } void DemuxerTS::flush() @@ -34,27 +36,33 @@ void DemuxerTS::flush() parsed = false; Demuxer::flush(); vPacket.init(PESTYPE_VID0); - switch (atype) { + switch (atype) + { case 1: - aPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_AC30);break; + aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30); + break; default: case 0: - aPacket.init(PESTYPE_AUD0);break; - }; + aPacket.init(PESTYPE_AUD0); + break; + } + subPacket.init(PESTYPE_PRIVATE_1); vActive = false; aActive = false; + subActive = false; + subLength = 0; } int DemuxerTS::scan(UCHAR *buf, int len) { - switch (atype) { + switch (atype) + { case 1: - return PESTYPE_PRIVATE_1; + return PESTYPE_PRIVATE_1; default: case 0: - return PESTYPE_AUD0; - }; - + return PESTYPE_AUD0; + } } void DemuxerTS::setVID(int p_vID) @@ -68,19 +76,29 @@ void DemuxerTS::setAID(int p_aID, int type) { aID = p_aID; atype = type; - switch (atype) { + switch (atype) + { case 1: - aPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_AC30); - setAudioStream(PESTYPE_SUBSTREAM_AC30);break; + aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30); + setAudioStream(PESTYPE_SUBSTREAM_AC30); + break; default: case 0: - aPacket.init(PESTYPE_AUD0); - setAudioStream(PESTYPE_AUD0); - break; - }; + aPacket.init(PESTYPE_AUD0); + setAudioStream(PESTYPE_AUD0); + break; + } aActive = false; } +void DemuxerTS::setSubID(int p_subID) +{ + subID = p_subID; + subPacket.init(PESTYPE_PRIVATE_1); + subActive = false; + subLength = 0; +} + int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest) { UINT LoPattern = 0x100 | PESTYPE_VID0, @@ -219,7 +237,7 @@ int DemuxerTS::processTS(UCHAR* buf) parsePacketDetails(vPacket); parsed = true; } - rc = submitPacket(vPacket); + rc = submitPacket(vPacket); } vActive = true; } @@ -232,10 +250,24 @@ int DemuxerTS::processTS(UCHAR* buf) parsePacketDetails(aPacket); parsed = true; } - rc = submitPacket(aPacket); + rc = submitPacket(aPacket); } aActive = true; } + if (pid == subID) + { + if (subActive) + { + if (!parsed) + { + parsePacketDetails(subPacket); + parsed = true; + } + rc = submitPacket(subPacket); + } + subActive = true; + } + if (rc == 0) return 0; parsed = false; @@ -246,23 +278,34 @@ int DemuxerTS::processTS(UCHAR* buf) } if (pid == aID) { - switch (atype) { + switch (atype) + { case 1: - aPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_AC30);break; + aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30); + break; default: case 0: - aPacket.init(PESTYPE_AUD0);break; - }; + aPacket.init(PESTYPE_AUD0); + break; + } + buf += 6; datalen -= 6; + } + if (pid == subID) + { + subPacket.init(PESTYPE_PRIVATE_1); + subLength = (buf[4] << 8) + buf[5]; buf += 6; datalen -= 6; } } if ( (pid == vID && vActive) || - (pid == aID && aActive) ) + (pid == aID && aActive) || + (pid == subID && subActive) ) { PESPacket* packet = NULL; if (pid == vID) packet = &vPacket; if (pid == aID) packet = &aPacket; + if (pid == subID) packet = &subPacket; if (packet != NULL) { if (packet->write(buf, datalen) == 0) @@ -281,5 +324,13 @@ int DemuxerTS::processTS(UCHAR* buf) } } + if (pid == subID && subActive && subPacket.getLength() == subLength) + { + parsePacketDetails(subPacket); +Log::getInstance()->log("DEMUXERTS", Log::DEBUG, "SUBMITTING A SUBTITLE PACKET %d %x", subLength, subPacket.getSubstream()); + submitPacket(subPacket); + subActive = false; + } + return 1; } diff --git a/demuxerts.h b/demuxerts.h index e58ef7b..0df7cd6 100644 --- a/demuxerts.h +++ b/demuxerts.h @@ -30,14 +30,16 @@ class DemuxerTS : public Demuxer { public: - DemuxerTS(int p_vID = 0, int p_aID = 0); + DemuxerTS(int p_vID = 0, int p_aID = 0, int p_subID = 0); void flush(); int scan(UCHAR* buf, int len); int findPTS(UCHAR* buf, int len, ULLONG* dest); void setVID(int p_vID); void setAID(int p_aID, int type); + void setSubID(int p_subID); int getVID() { return vID; } int getAID() { return aID; } + int getSubID() { return subID; } int put(UCHAR* buf, int len); private: @@ -48,9 +50,12 @@ class DemuxerTS : public Demuxer bool parsed; // Whether PES packet to be submitted has been parsed yet PESPacket vPacket; // Video PES packet under construction PESPacket aPacket; // Audio PES packet under construction - int vID, aID; // TS IDs for video/audio + PESPacket subPacket; // Subtitles PES packet under construction + int vID, aID, subID; // TS IDs for video/audio/subtitles int atype; bool vActive, aActive; // Whether video/audio is actively being captured + bool subActive; // Same for subtitles + UINT subLength; // Expected length of subtitle packet }; #endif diff --git a/demuxervdr.cc b/demuxervdr.cc index 4ff9698..7f3bafc 100644 --- a/demuxervdr.cc +++ b/demuxervdr.cc @@ -323,8 +323,9 @@ void DemuxerVDR::dealWithSubtitlePacket() while (subtitlePacketPosition < subSize) { if (sub_data[subtitlePacketPosition] == 0xFF) - { - subtitles->put(subtitlePacket); + { // Packet is complete. Switch it into the "real" packet to be submitted. + packet = subtitlePacket; + parsePacketDetails(packet); subtitlePacketPosition = 0; // Wait for next non-continuation packet break; } diff --git a/dvbsubtitles.cc b/dvbsubtitles.cc index 43c3932..692d0a3 100644 --- a/dvbsubtitles.cc +++ b/dvbsubtitles.cc @@ -502,8 +502,8 @@ void DVBSubtitles::put(const PESPacket& packet) { if (packet.getPTS() != PESPacket::PTS_INVALID) { - worklist.push_back(packet); - nudge(); + worklist.push_back(packet); + nudge(); } } unlockInput(); diff --git a/playerlivetv.cc b/playerlivetv.cc index 85230eb..5df0680 100644 --- a/playerlivetv.cc +++ b/playerlivetv.cc @@ -29,14 +29,17 @@ #include "remote.h" #include "message.h" #include "channel.h" +#include "dvbsubtitles.h" +#include "osdreceiver.h" // ----------------------------------- Called from outside, one offs or info funcs -PlayerLiveTV::PlayerLiveTV(MessageQueue* tmessageQueue, void* tmessageReceiver, ChannelList* tchanList) +PlayerLiveTV::PlayerLiveTV(MessageQueue* tmessageQueue, void* tmessageReceiver, OSDReceiver* tosdReceiver, ChannelList* tchanList) : vfeed(this), afeed(this) { messageQueue = tmessageQueue; messageReceiver = tmessageReceiver; + osdReceiver = tosdReceiver; chanList = tchanList; audio = Audio::getInstance(); @@ -45,6 +48,7 @@ PlayerLiveTV::PlayerLiveTV(MessageQueue* tmessageQueue, void* tmessageReceiver, vdr = VDR::getInstance(); initted = false; + subtitlesShowing = false; videoStartup = false; stopNow = false; @@ -64,8 +68,10 @@ int PlayerLiveTV::init() demuxer = new DemuxerTS(); if (!demuxer) return 0; + subtitles = new DVBSubtitles(osdReceiver); + if (!subtitles) return 0; - if (!demuxer->init(this, audio, video, 2097152, 524288)) + if (!demuxer->init(this, audio, video, 2097152, 524288, subtitles)) { logger->log("PlayerLiveTV", Log::ERR, "Demuxer failed to init"); shutdown(); @@ -90,6 +96,7 @@ int PlayerLiveTV::shutdown() initted = false; delete demuxer; + delete subtitles; return 1; } @@ -114,6 +121,21 @@ void PlayerLiveTV::setAudioChannel(int newChannel, int type) return demuxer->setAID(newChannel,type); } +bool PlayerLiveTV::toggleSubtitles() +{ + if (!subtitlesShowing) + { + subtitlesShowing = true; + subtitles->show(); + } + else + { + subtitlesShowing = false; + subtitles->hide(); + } + return subtitlesShowing; +} + // ----------------------------------- Externally called events void PlayerLiveTV::go(ULONG index) @@ -299,6 +321,7 @@ void PlayerLiveTV::switchState(UCHAR newState) afeed.start(); vfeed.start(); + subtitles->start(); state = newState; return; @@ -329,6 +352,7 @@ void PlayerLiveTV::switchState(UCHAR newState) clearStreamChunks(); vfeed.stop(); afeed.stop(); + subtitles->stop(); video->blank(); video->reset(); @@ -349,6 +373,7 @@ void PlayerLiveTV::switchState(UCHAR newState) afeed.start(); vfeed.start(); + subtitles->start(); state = newState; return; @@ -359,6 +384,7 @@ void PlayerLiveTV::switchState(UCHAR newState) clearStreamChunks(); vfeed.stop(); afeed.stop(); + subtitles->stop(); video->stop(); video->blank(); audio->stop(); @@ -393,6 +419,7 @@ void PlayerLiveTV::switchState(UCHAR newState) clearStreamChunks(); vfeed.stop(); afeed.stop(); + subtitles->stop(); video->stop(); video->blank(); audio->stop(); @@ -414,6 +441,7 @@ void PlayerLiveTV::switchState(UCHAR newState) afeed.start(); vfeed.start(); + subtitles->start(); state = newState; return; @@ -424,6 +452,7 @@ void PlayerLiveTV::switchState(UCHAR newState) clearStreamChunks(); vfeed.stop(); afeed.stop(); + subtitles->stop(); video->stop(); video->blank(); audio->stop(); @@ -451,6 +480,7 @@ void PlayerLiveTV::switchState(UCHAR newState) clearStreamChunks(); vfeed.stop(); afeed.stop(); + subtitles->stop(); video->stop(); video->blank(); audio->stop(); @@ -465,6 +495,7 @@ void PlayerLiveTV::switchState(UCHAR newState) clearStreamChunks(); vfeed.stop(); afeed.stop(); + subtitles->stop(); video->stop(); video->blank(); audio->stop(); @@ -486,6 +517,7 @@ void PlayerLiveTV::switchState(UCHAR newState) afeed.start(); vfeed.start(); + subtitles->start(); state = newState; return; @@ -580,6 +612,8 @@ void PlayerLiveTV::threadMethod() { logger->log("PlayerLiveTV", Log::WARN, "Demuxer video pid only: %u", chan->vpid); } + if (chan->numSPids > 0) + demuxer->setSubID(chan->spids[0].pid); int streamSuccess = vdr->streamChannel(chan->number, this); if (!checkError() && !streamSuccess) diff --git a/playerlivetv.h b/playerlivetv.h index 9ddf19d..eb589c7 100644 --- a/playerlivetv.h +++ b/playerlivetv.h @@ -49,11 +49,13 @@ class Audio; class Video; class Log; class DemuxerTS; +class OSDReceiver; +class DVBSubtitles; class PlayerLiveTV : public PlayerLive, public Thread_TYPE, public Callback, public StreamReceiver { public: - PlayerLiveTV(MessageQueue* messageQueue, void* messageReceiver, ChannelList* chanList); + PlayerLiveTV(MessageQueue* messageQueue, void* messageReceiver, OSDReceiver* tosdReceiver, ChannelList* chanList); virtual ~PlayerLiveTV(); virtual int init(); @@ -63,6 +65,7 @@ class PlayerLiveTV : public PlayerLive, public Thread_TYPE, public Callback, pub virtual void setChannel(ULONG index); virtual void stop(); virtual void setAudioChannel(int newChannel,int type); + virtual bool toggleSubtitles(); virtual bool* getDemuxerMpegAudioChannels(); virtual bool* getDemuxerAc3AudioChannels(); @@ -88,12 +91,15 @@ class PlayerLiveTV : public PlayerLive, public Thread_TYPE, public Callback, pub void threadPostStopCleanup() {}; private: + bool subtitlesShowing; MessageQueue* messageQueue; void* messageReceiver; + OSDReceiver* osdReceiver; Log* logger; Audio* audio; Video* video; DemuxerTS* demuxer; + DVBSubtitles* subtitles; VDR* vdr; VFeed vfeed; AFeed afeed; diff --git a/vvideolivetv.cc b/vvideolivetv.cc index 5a7773d..63b3ffa 100644 --- a/vvideolivetv.cc +++ b/vvideolivetv.cc @@ -38,6 +38,7 @@ #include "event.h" #include "timers.h" #include "vepg.h" +#include "bitmap.h" VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList) { @@ -78,7 +79,7 @@ VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, V if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO) { streamType = VDR::VIDEO; - player = new PlayerLiveTV(Command::getInstance(), this, chanList); + player = new PlayerLiveTV(Command::getInstance(), this, this, chanList); } else { @@ -402,6 +403,10 @@ int VVideoLiveTV::handleCommand(int command) doEPG(); return 2; } + case Remote::RECORD: + if (streamType = VDR::VIDEO) + (static_cast(player))->toggleSubtitles(); + return 2; } return 1; @@ -1055,3 +1060,24 @@ void VVideoLiveTV::toggleChopSides() } } +void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm) +{ + drawBitmap(posX, posY, bm); + Region r; + r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight(); + boxstack->update(this, &r); +} + +void VVideoLiveTV::clearOSD() +{ + rectangle(area, Colour(0,0,0,0)); + boxstack->update(this, &area); +} + +void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height) +{ + Region r; + r.x = posX; r.y = posY; r.w = width; r.h = height; + rectangle(r, Colour(0,0,0,0)); + boxstack->update(this, &r); +} diff --git a/vvideolivetv.h b/vvideolivetv.h index 78b7339..8057d40 100644 --- a/vvideolivetv.h +++ b/vvideolivetv.h @@ -34,6 +34,7 @@ #include "timerreceiver.h" #include "wsymbol.h" #include "wprogressbar.h" +#include "osdreceiver.h" class VChannelList; class Video; @@ -42,8 +43,9 @@ class BoxStack; class WTextbox; class PlayerLive; class VAudioSelector; +class Bitmap; -class VVideoLiveTV : public Boxx, public TimerReceiver +class VVideoLiveTV : public Boxx, public TimerReceiver, public OSDReceiver { public: VVideoLiveTV(ChannelList* chanList, ULONG initialChannelNumber, VChannelList* vchannelList); @@ -68,6 +70,10 @@ class VVideoLiveTV : public Boxx, public TimerReceiver void timercall(int ref); + void drawOSDBitmap(UINT posX, UINT posY, const Bitmap&); + void clearOSD(); + void clearOSDArea(UINT posX, UINT posY, UINT width, UINT height); + private: BoxStack* boxstack; VDR* vdr; -- 2.39.5