From a1d0698e7ee75994f9d75c277f743f43212506f2 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Sun, 11 May 2008 15:38:24 +0000 Subject: [PATCH] Live radio prebuffering display - code upgrades for connection lost handling --- channel.cc | 8 +++- command.cc | 3 ++ player.cc | 27 ++++++++++--- playerliveradio.cc | 95 +++++++++++++++++++++++++++++++++++++--------- playerliveradio.h | 4 +- playerlivetv.cc | 69 ++++++++++++++++++++++----------- playerlivetv.h | 1 + playerradio.cc | 2 + recording.cc | 7 +++- vtimerlist.cc | 1 + vvideolivetv.cc | 6 +-- 11 files changed, 169 insertions(+), 54 deletions(-) diff --git a/channel.cc b/channel.cc index d4367b5..052d042 100644 --- a/channel.cc +++ b/channel.cc @@ -22,6 +22,7 @@ #include "vdr.h" #include "log.h" +#include "command.h" Channel::Channel() { @@ -67,7 +68,12 @@ void Channel::loadPids() } VDR::getInstance()->getChannelPids(this); // FIXME sort out this system - + if (!VDR::getInstance()->isConnected()) + { + Command::getInstance()->connectionLost(); + return; + } + Log::getInstance()->log("Channel", Log::DEBUG, "C.%lu loaded, VPid=%lu, numApids=%lu, numDpids=%lu, numSpids=%lu TPid=%lu", number, vpid, numAPids, numDPids, numSPids, tpid); for (ULONG i = 0; i < numAPids; i++) diff --git a/command.cc b/command.cc index e00328b..16fa00a 100644 --- a/command.cc +++ b/command.cc @@ -400,6 +400,7 @@ void Command::processMessage(Message* m) boxstack->removeAll(); boxstack->update(wallpaper); I18n::initialize(); + if (!VDR::getInstance()->isConnected()) { connectionLost(); break; } VWelcome* vw = new VWelcome(); vw->draw(); boxstack->add(vw); @@ -593,6 +594,8 @@ void Command::buildCrashedBox() void Command::doJustConnected(VConnect* vconnect) { I18n::initialize(); + if (!VDR::getInstance()->isConnected()) { connectionLost(); return; } + Video* video = Video::getInstance(); Audio* audio = Audio::getInstance(); boxstack->remove(vconnect); diff --git a/player.cc b/player.cc index 3937d20..74ed286 100644 --- a/player.cc +++ b/player.cc @@ -822,12 +822,19 @@ void Player::restartAtFramePI(ULONG newFrame) vdr->getNextIFrame(nextiframeNumber, 0, &filePos, &iframeNumber, &iframeLength); buffer = vdr->getBlock(filePos, iframeLength, &amountReceived); - videoLength = demuxer->stripAudio(buffer, amountReceived); - video->displayIFrame(buffer, videoLength); - video->displayIFrame(buffer, videoLength); // If you do it twice, it works :) - free(buffer); - - currentFrameNumber = iframeNumber; + if (!vdr->isConnected()) + { + if (buffer) free(buffer); + doConnectionLost(); + } + else + { + videoLength = demuxer->stripAudio(buffer, amountReceived); + video->displayIFrame(buffer, videoLength); + video->displayIFrame(buffer, videoLength); // If you do it twice, it works :) + free(buffer); + currentFrameNumber = iframeNumber; + } } void Player::doConnectionLost() @@ -1242,6 +1249,14 @@ void Player::threadFeedScan() // logger->log("Player", Log::DEBUG, "XXX Got frame"); threadBuffer = vdr->getBlock(filePos, iframeLength, &amountReceived); + + if (!vdr->isConnected()) + { + if (threadBuffer) free(threadBuffer); + doConnectionLost(); + break; + } + #ifndef WIN32 gettimeofday(&clock1, NULL); if (clock2.tv_sec != 0) diff --git a/playerliveradio.cc b/playerliveradio.cc index 7a27112..5e798ae 100644 --- a/playerliveradio.cc +++ b/playerliveradio.cc @@ -150,6 +150,22 @@ void PlayerLiveRadio::call(void* caller) void PlayerLiveRadio::streamReceive(ULONG flag, void* data, ULONG len) { + // Flag: + // 0 = normal stream packet + // 1 = stream end + + if (flag == 1) + { + if (data) abort(); + + Message* m = new Message(); + m->from = this; + m->to = messageReceiver; + m->message = Message::PLAYER_EVENT; + m->parameter = PlayerLiveRadio::STREAM_END; + messageQueue->postMessageFromOuterSpace(m); + } + if (streamChunks.size() < 11) { StreamChunk s; @@ -181,9 +197,9 @@ void PlayerLiveRadio::chunkToDemuxer() { StreamChunk s = streamChunks.front(); streamChunks.pop(); - logger->log("PlayerLiveRadio", Log::DEBUG, "About to call demuxer with %p %lu", s.data, s.len); - int a = demuxer->put((UCHAR*)s.data, s.len); - logger->log("PlayerLiveRadio", Log::DEBUG, "put %i to demuxer", a); + //logger->log("PlayerLiveRadio", Log::DEBUG, "About to call demuxer with %p %lu", s.data, s.len); + /*int a =*/ demuxer->put((UCHAR*)s.data, s.len); + //logger->log("PlayerLiveRadio", Log::DEBUG, "put %i to demuxer", a); free(s.data); } @@ -309,6 +325,24 @@ void PlayerLiveRadio::switchState(UCHAR newState) } } +bool PlayerLiveRadio::checkError() +{ + if (!vdr->isConnected()) + { + switchState(S_STOP); + + Message* m = new Message(); + m->from = this; + m->to = messageReceiver; + m->message = Message::PLAYER_EVENT; + m->parameter = PlayerLiveRadio::CONNECTION_LOST; + messageQueue->postMessageFromOuterSpace(m); + + return true; + } + return false; +} + void PlayerLiveRadio::optimizeInstructionQueue() { // Walk the list @@ -321,7 +355,6 @@ void PlayerLiveRadio::optimizeInstructionQueue() i = instructions.front(); if (i.instruction == I_SETCHANNEL) { - logger->log("PlayerLiveRadio", Log::DEBUG, "Optimised out setch to %i", i.channelIndex); instructions.pop(); // if this is the first of more than 1 command, currently it cannot possibly be relevant } else if (i.instruction == I_STOP) @@ -352,25 +385,38 @@ void PlayerLiveRadio::threadMethod() switchState(S_PREBUFFERING); - Channel* chan = (*chanList)[i.channelIndex]; - chan->loadPids(); - - if (chan->numAPids > 0) + if (!checkError()) { - demuxer->setAID(chan->apids[0].pid,0); - logger->log("PlayerLiveRadio", Log::DEBUG, "Demuxer pids: %u %u", chan->vpid, chan->apids[0].pid); + Channel* chan = (*chanList)[i.channelIndex]; + chan->loadPids(); + + if (chan->numAPids > 0) + { + demuxer->setAID(chan->apids[0].pid,0); + logger->log("PlayerLiveRadio", Log::DEBUG, "Demuxer pids: %u %u", chan->vpid, chan->apids[0].pid); + } + else + { + logger->log("PlayerLiveRadio", Log::WARN, "Demuxer no pids!"); + } + + int streamSuccess = vdr->streamChannel(chan->number, this); + if (!checkError() && !streamSuccess) + { + Message* m = new Message(); + m->from = this; + m->to = messageReceiver; + m->message = Message::PLAYER_EVENT; + m->parameter = PlayerLiveRadio::STREAM_END; + messageQueue->postMessageFromOuterSpace(m); + } } - else - { - logger->log("PlayerLiveRadio", Log::WARN, "Demuxer no pids!"); - } - - vdr->streamChannel(chan->number, this); } else if (i.instruction == I_STOP) { logger->log("PlayerLiveRadio", Log::DEBUG, "Stopping"); switchState(S_STOP); + checkError(); stopNow = true; break; @@ -384,10 +430,23 @@ void PlayerLiveRadio::threadMethod() chunkToDemuxer(); if (state == S_PREBUFFERING) - { - if (++preBufferCount == preBufferAmount) + { + ++preBufferCount; + ULONG percentDone = (ULONG)(preBufferCount / (float)preBufferAmount * 100); + logger->log("PlayerLiveRadio", Log::DEBUG, "Prebuffering %lu%%", percentDone); + + Message* m = new Message(); + m->from = this; + m->to = messageReceiver; + m->message = Message::PLAYER_EVENT; + m->parameter = PlayerLiveRadio::PREBUFFERING; + m->tag = percentDone; + messageQueue->postMessageFromOuterSpace(m); + + if (preBufferCount == preBufferAmount) { switchState(S_PLAY); + checkError(); } } } diff --git a/playerliveradio.h b/playerliveradio.h index abf9145..9f6aee3 100644 --- a/playerliveradio.h +++ b/playerliveradio.h @@ -79,7 +79,8 @@ class PlayerLiveRadio : public PlayerLive, public Thread_TYPE, public Callback, const static UCHAR STREAM_END = 3; const static UCHAR ASPECT43 = 4; const static UCHAR ASPECT169 = 5; - + const static UCHAR PREBUFFERING = 6; + protected: void threadMethod(); void threadPostStopCleanup() {}; @@ -107,6 +108,7 @@ class PlayerLiveRadio : public PlayerLive, public Thread_TYPE, public Callback, const static UCHAR S_PREBUFFERING = 2; const static UCHAR S_PLAY = 3; void switchState(UCHAR newState); + bool checkError(); bool stopNow; int preBufferCount; diff --git a/playerlivetv.cc b/playerlivetv.cc index 9057949..d0591ea 100644 --- a/playerlivetv.cc +++ b/playerlivetv.cc @@ -500,6 +500,24 @@ void PlayerLiveTV::switchState(UCHAR newState) } } +bool PlayerLiveTV::checkError() +{ + if (!vdr->isConnected()) + { + switchState(S_STOP); + + Message* m = new Message(); + m->from = this; + m->to = messageReceiver; + m->message = Message::PLAYER_EVENT; + m->parameter = PlayerLiveTV::CONNECTION_LOST; + messageQueue->postMessageFromOuterSpace(m); + + return true; + } + return false; +} + void PlayerLiveTV::optimizeInstructionQueue() { // Walk the list @@ -530,6 +548,8 @@ void PlayerLiveTV::threadMethod() switchState(S_PREBUFFERING); videoStartup = false; preBufferCount = 0; + + checkError(); } while(!instructions.empty()) @@ -544,35 +564,39 @@ void PlayerLiveTV::threadMethod() logger->log("PlayerLiveTV", Log::DEBUG, "start new stream"); switchState(S_VIDEOSTARTUP); - - Channel* chan = (*chanList)[i.channelIndex]; - chan->loadPids(); - demuxer->setVID(chan->vpid); - if (chan->numAPids > 0) - { - demuxer->setAID(chan->apids[0].pid,0); - logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer pids: %u %u", chan->vpid, chan->apids[0].pid); - } - else + + if (!checkError()) { - logger->log("PlayerLiveTV", Log::WARN, "Demuxer video pid only: %u", chan->vpid); - } - - int streamSuccess = vdr->streamChannel(chan->number, this); - if (!streamSuccess) - { - Message* m = new Message(); - m->from = this; - m->to = messageReceiver; - m->message = Message::PLAYER_EVENT; - m->parameter = PlayerLiveTV::STREAM_END; - messageQueue->postMessageFromOuterSpace(m); + Channel* chan = (*chanList)[i.channelIndex]; + chan->loadPids(); + demuxer->setVID(chan->vpid); + if (chan->numAPids > 0) + { + demuxer->setAID(chan->apids[0].pid,0); + logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer pids: %u %u", chan->vpid, chan->apids[0].pid); + } + else + { + logger->log("PlayerLiveTV", Log::WARN, "Demuxer video pid only: %u", chan->vpid); + } + + int streamSuccess = vdr->streamChannel(chan->number, this); + if (!checkError() && !streamSuccess) + { + Message* m = new Message(); + m->from = this; + m->to = messageReceiver; + m->message = Message::PLAYER_EVENT; + m->parameter = PlayerLiveTV::STREAM_END; + messageQueue->postMessageFromOuterSpace(m); + } } } else if (i.instruction == I_STOP) { logger->log("PlayerLiveTV", Log::DEBUG, "Stopping"); switchState(S_STOP); + checkError(); stopNow = true; break; @@ -602,6 +626,7 @@ void PlayerLiveTV::threadMethod() if (preBufferCount == preBufferAmount) { switchState(S_PLAY); + checkError(); } } } diff --git a/playerlivetv.h b/playerlivetv.h index c82e37d..9ddf19d 100644 --- a/playerlivetv.h +++ b/playerlivetv.h @@ -113,6 +113,7 @@ class PlayerLiveTV : public PlayerLive, public Thread_TYPE, public Callback, pub const static UCHAR S_PREBUFFERING = 3; const static UCHAR S_PLAY = 4; void switchState(UCHAR newState); + bool checkError(); bool videoStartup; bool stopNow; diff --git a/playerradio.cc b/playerradio.cc index 783276b..0dd2161 100644 --- a/playerradio.cc +++ b/playerradio.cc @@ -105,6 +105,7 @@ int PlayerRadio::init(ULLONG tlengthBytes, ULONG tlengthPackets) { logger->log("PlayerRadio", Log::ERR, "Failed to get start block"); shutdown(); + if (!vdr->isConnected()) doConnectionLost(); return 0; } @@ -140,6 +141,7 @@ bool PlayerRadio::setLengthSeconds() if (!buffer) { logger->log("PlayerRadio", Log::ERR, "Failed to get end block"); + if (!vdr->isConnected()) doConnectionLost(); return false; } diff --git a/recording.cc b/recording.cc index 220430e..9e8bdd3 100644 --- a/recording.cc +++ b/recording.cc @@ -24,6 +24,7 @@ #include "mark.h" #include "log.h" #include "demuxer.h" +#include "command.h" Recording* Recording::recInfoFor = NULL; RecInfo* Recording::recInfo = NULL; @@ -103,6 +104,8 @@ void Recording::loadRecInfo() recInfoFor = this; recInfo = vdr->getRecInfo(fileName); Log::getInstance()->log("Recording", Log::DEBUG, "Recording has loaded recInfo %p", recInfo); + + if (!VDR::getInstance()->isConnected()) Command::getInstance()->connectionLost(); } void Recording::dropRecInfo() @@ -115,6 +118,7 @@ void Recording::dropRecInfo() void Recording::loadMarks() { markList = vdr->getMarks(fileName); + if (!VDR::getInstance()->isConnected()) Command::getInstance()->connectionLost(); } bool Recording::isRadio() @@ -137,8 +141,9 @@ bool Recording::isRadio() free(buffer); - // FIXME vdr->stopStreaming(); + if (!VDR::getInstance()->isConnected()) Command::getInstance()->connectionLost(); + Log::getInstance()->log("Recording", Log::DEBUG, "Recording has messed about and worked out radio = %u", !hasVideo); diff --git a/vtimerlist.cc b/vtimerlist.cc index e6c154e..b2bfd60 100644 --- a/vtimerlist.cc +++ b/vtimerlist.cc @@ -342,6 +342,7 @@ void VTimerList::processMessage(Message* m) ULONG retval = VDR::getInstance()->deleteTimer(recTimer); + if (!VDR::getInstance()->isConnected()) { Command::getInstance()->connectionLost(); return; } Log::getInstance()->log("VTimerList", Log::DEBUG, "Got return fron delete timer: %lu", retval); if (retval != 10) diff --git a/vvideolivetv.cc b/vvideolivetv.cc index 7197cd7..925f6f4 100644 --- a/vvideolivetv.cc +++ b/vvideolivetv.cc @@ -898,11 +898,7 @@ void VVideoLiveTV::processMessage(Message* m) case PlayerLiveTV::CONNECTION_LOST: // connection lost detected { Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player"); - // I can't handle this, send it to command - Message* m2 = new Message(); - m2->to = Command::getInstance(); - m2->message = Message::CONNECTION_LOST; - Command::getInstance()->postMessageNoLock(m2); + Command::getInstance()->connectionLost(); break; } -- 2.39.2