#include "player.h"
+// ----------------------------------- Called from outside, one offs or info funcs
+
Player::Player(MessageQueue* messageQueue, bool tIsRecording, bool tIsRadio)
: vfeed(this), afeed(this)
{
audio = Audio::getInstance();
video = Video::getInstance();
logger = Log::getInstance();
- initted = 0;
+ initted = false;
paused = false;
playing = false;
ffwd = false;
Player::~Player()
{
if (initted) shutdown();
- if (demuxer != NULL) delete demuxer;
}
int Player::init()
{
if (initted) return 0;
- demuxer = new DemuxerVDR;
+ pthread_mutex_init(&mutex, NULL);
- if (demuxer == NULL) return 0;
+ demuxer = new DemuxerVDR();
+ if (!demuxer) return 0;
if (!demuxer->init(this))
{
video->blank();
audio->stop();
- initted = 1;
+ initted = true;
return 1;
}
int Player::shutdown()
{
if (!initted) return 0;
- initted = 0;
+ initted = false;
// copy of stop
if (playing)
video->blank();
audio->stop();
vfeed.stop();
+
afeed.stop();
video->reset();
demuxer->reset();
feedPosition = 0;
}
+ delete demuxer;
+ demuxer = NULL;
+
return 1;
}
+void Player::setPosition(ULLONG position)
+{
+ feedPosition = position;
+}
+
+void Player::setLength(ULLONG length)
+{
+ lastRescan = time(NULL);
+ streamLength = length;
+ logger->log("Player", Log::DEBUG, "Player has received length of %llu", streamLength);
+}
+
+ULLONG Player::getEndTS() // used internally (jump to percent)
+{
+ long long rendTS = endTS - startTS;
+ if (rendTS < 0) rendTS += 8589934592ULL;
+ return (ULLONG)rendTS;
+}
+
+ULLONG Player::getPositionTS() // used internall (skip fw/bw)
+{
+ if (startup) return 0ULL;
+ long long currentTS = video->getCurrentTimestamp() - startTS;
+ if (currentTS < 0) currentTS += 8589934592ULL;
+ return (ULLONG)currentTS;
+}
+
+// ----------------------------------- Externally called events
+
int Player::play()
+{
+ lock();
+ return playInt();
+// unLock(); - let thread unlock this
+}
+
+void Player::stop()
+{
+ lock();
+ stopInt();
+ unLock();
+}
+
+void Player::togglePause()
+{
+ lock();
+ togglePauseInt();
+ unLock();
+}
+
+void Player::toggleFastForward()
+{
+ lock();
+ toggleFastForwardInt();
+ unLock();
+}
+
+void Player::toggleFastBackward()
+{
+ lock();
+ toggleFastBackwardInt();
+ unLock();
+}
+
+void Player::jumpToPercent(int percent)
+{
+ threadLock();
+ jumpToPercentInt(percent);
+// unLock(); - let thread unlock this
+}
+
+void Player::skipForward(int seconds)
+{
+ lock();
+ skipForwardInt(seconds);
+// unLock(); - let thread unlock this
+}
+
+void Player::skipBackward(int seconds)
+{
+ lock();
+ skipBackwardInt(seconds);
+// unLock(); - let thread unlock this
+}
+
+// ----------------------------------- Implementations called events
+
+
+int Player::playInt()
{
if (!initted) return 0;
// If we are just paused, unpause!
if (paused)
{
- togglePause();
+ togglePauseInt();
return 1;
}
- // If we are still seeking in from the last jump, ignore
- if (videoStartup) return 1;
-
// If we are fast forwarding, set to normal
if (ffwd)
{
- toggleFastForward();
+ toggleFastForwardInt();
return 1;
}
// If we are fast backwarding, set to normal
if (fbwd)
{
- toggleFastBackward();
+ toggleFastBackwardInt();
return 1;
}
preBuffering = true;
}
-// ------------------------------------------------------------------------------------------------
-
playing = true;
return 1;
}
-void Player::stop()
+void Player::stopInt()
{
if (!initted) return;
if (!playing) return;
- // If we are still seeking in from the last jump, ignore
- if (videoStartup) return;
-
if (ffwd || fbwd)
{
ffwd = false;
feedPosition = 0;
}
-void Player::togglePause()
+void Player::togglePauseInt()
{
if (!initted) return;
if (!playing) return;
- if (ffwd) toggleFastForward();
- if (fbwd) toggleFastBackward();
+ if (ffwd) toggleFastForwardInt();
+ if (fbwd) toggleFastBackwardInt();
if (paused)
{
}
}
-void Player::setPosition(ULLONG position)
-{
- feedPosition = position;
-}
-
-void Player::setLength(ULLONG length)
-{
- lastRescan = time(NULL);
- streamLength = length;
- logger->log("Player", Log::DEBUG, "Player has received length of %llu", streamLength);
-}
-
-void Player::restartAt(ULLONG timecode)
-{
- // If we are still seeking in from the last jump, ignore
- if (videoStartup) return;
-
- if (paused) togglePause();
- if (ffwd) toggleFastForward();
-
- ULONG wantedFrameNumber = video->timecodeToFrameNumber(timecode);
- ULLONG newPosition = VDR::getInstance()->positionFromFrameNumber(wantedFrameNumber);
- if (!VDR::getInstance()->isConnected()) { doConnectionLost(); return; }
- logger->log("Player", Log::DEBUG, "wantedframe %i feedpos %llu goto %llu", wantedFrameNumber, feedPosition, newPosition);
-
- vfeed.stop();
- afeed.stop();
- threadStop();
- video->stop();
- video->reset();
- audio->reset();
- demuxer->flush();
- if (!isRadio) demuxer->seek();
- feedPosition = newPosition;
- videoStartup = true;
- afeed.start();
- vfeed.start();
- threadStart();
- audio->play();
- video->sync();
- audio->sync();
- audio->systemMuteOff();
- audio->doMuting();
- fbwd = false;
-}
-
-void Player::skipForward(int seconds)
-{
- logger->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
- restartAt(getPositionTS() + (seconds * 90000));
-}
-
-void Player::skipBackward(int seconds)
-{
- logger->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
- long long newTimeCode = getPositionTS() - (seconds * 90000);
- if (newTimeCode < 0) newTimeCode = 0;
- restartAt(newTimeCode);
-}
-
-void Player::jumpToPercent(int percent)
-{
- logger->log("Player", Log::DEBUG, "JUMP TO %i%%", percent);
- ULLONG newTimeCode = (ULLONG)(getEndTS() * ((float)percent / 100));
- restartAt(newTimeCode);
-}
-
-void Player::toggleFastForward()
+void Player::toggleFastForwardInt()
{
if (!initted) return;
if (!playing) return;
- // If we are still seeking in from the last jump, ignore
- if (videoStartup) return;
-
- if (paused) togglePause();
- if (fbwd) toggleFastBackward();
+ if (paused) togglePauseInt();
+ if (fbwd) toggleFastBackwardInt();
if (ffwd)
{
}
}
-void Player::toggleFastBackward()
+void Player::toggleFastBackwardInt()
{
if (!initted) return;
if (!playing) return;
- // If we are still seeking in from the last jump, ignore
- if (videoStartup) return;
-
- if (paused) togglePause();
- if (ffwd) toggleFastForward();
+ if (paused) togglePauseInt();
+ if (ffwd) toggleFastForwardInt();
if (fbwd)
{
}
}
-ULLONG Player::getPositionTS()
+void Player::skipForwardInt(int seconds)
{
- if (startup) return 0ULL;
- long long currentTS = video->getCurrentTimestamp() - startTS;
- if (currentTS < 0) currentTS += 8589934592ULL;
- return (ULLONG)currentTS;
+ logger->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
+ restartAt(getPositionTS() + (seconds * 90000));
}
-ULLONG Player::getEndTS()
+void Player::skipBackwardInt(int seconds)
{
- long long rendTS = endTS - startTS;
- if (rendTS < 0) rendTS += 8589934592ULL;
- return (ULLONG)rendTS;
+ logger->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
+ long long newTimeCode = getPositionTS() - (seconds * 90000);
+ if (newTimeCode < 0) newTimeCode = 0;
+ restartAt(newTimeCode);
}
+void Player::jumpToPercentInt(int percent)
+{
+ logger->log("Player", Log::DEBUG, "JUMP TO %i%%", percent);
+ ULLONG newTimeCode = (ULLONG)(getEndTS() * ((float)percent / 100));
+ restartAt(newTimeCode);
+}
+
+
+// ----------------------------------- Internal functions
+
+void Player::lock()
+{
+#ifndef WIN32
+ pthread_mutex_lock(&mutex);
+#else
+ // FIXME Marten
+#endif
+}
+
+void Player::unLock()
+{
+#ifndef WIN32
+ pthread_mutex_unlock(&mutex);
+#else
+ // FIXME Marten
+#endif
+}
+
+void Player::restartAt(ULLONG timecode)
+{
+ if (paused) togglePauseInt();
+ if (ffwd) toggleFastForwardInt();
+
+ ULONG wantedFrameNumber = video->timecodeToFrameNumber(timecode);
+ ULLONG newPosition = VDR::getInstance()->positionFromFrameNumber(wantedFrameNumber);
+ if (!VDR::getInstance()->isConnected()) { doConnectionLost(); return; }
+ logger->log("Player", Log::DEBUG, "wantedframe %i feedpos %llu goto %llu", wantedFrameNumber, feedPosition, newPosition);
+
+ vfeed.stop();
+ afeed.stop();
+ threadStop();
+ video->stop();
+ video->reset();
+ audio->reset();
+ demuxer->flush();
+ if (!isRadio) demuxer->seek();
+ feedPosition = newPosition;
+ videoStartup = true;
+ afeed.start();
+ vfeed.start();
+ threadStart();
+ audio->play();
+ video->sync();
+ audio->sync();
+ audio->systemMuteOff();
+ audio->doMuting();
+ fbwd = false;
+}
+
+void Player::setStartTS(UINT dataInBuffer)
+{
+ if (isRecording && feedPosition) // (feedPosition != 0)
+ {
+ // FIXME find out how much data need to get to find a TS
+ // Need to get the actual start of the recording
+
+ UINT thisRead;
+ UCHAR* tempBuffer = VDR::getInstance()->getBlock(0, 100000, &thisRead);
+ if (!tempBuffer && !VDR::getInstance()->isConnected()) { doConnectionLost(); return; }
+ if (!tempBuffer) return;
+ if (thisRead) demuxer->findVideoPTS(tempBuffer, thisRead, &startTS);
+ free(tempBuffer);
+ }
+ else
+ {
+ demuxer->findVideoPTS(threadBuffer, dataInBuffer, &startTS);
+ }
+}
+
+void Player::setEndTS()
+{
+ logger->log("Player", Log::DEBUG, "Setting end TS");
+
+ UINT thisRead;
+ UCHAR* tempBuffer = VDR::getInstance()->getBlock((streamLength - 100000), 100000, &thisRead);
+ if (!tempBuffer && !VDR::getInstance()->isConnected()) { doConnectionLost(); return; }
+ if (!tempBuffer) return;
+ if (thisRead) demuxer->findVideoPTS(tempBuffer, thisRead, &endTS);
+ free(tempBuffer);
+ logger->log("Player", Log::DEBUG, "Set end TS");
+}
+
+void Player::doConnectionLost()
+{
+ Message* m = new Message();
+ m->message = Message::CONNECTION_LOST;
+ m->to = this;
+ commandMessageQueue->postMessage(m);
+}
+
+// ----------------------------------- Callback
+
void Player::call(void* caller)
{
if (caller == demuxer)
video->play();
video->sync();
vfeed.release();
+ unLock();
}
threadSignalNoLock();
}
}
-void Player::doConnectionLost()
-{
- Message* m = new Message();
- m->message = Message::CONNECTION_LOST;
- m->to = this;
- commandMessageQueue->postMessage(m);
-}
-// Feed thread
+// ----------------------------------- Feed thread
void Player::threadMethod()
{
video->pause();
afeed.start();
vfeed.start();
+// unLock(); // thread will be locked by play until here
// FIXME - see if this can segfault because it is starting threads out of the master mutex
}
}
if (!thisWrite)
{
// logger->log("Player", Log::DEBUG, "DEMUXER FULL!!!");
- // demuxer is full and can't take any more
+ // demuxer is full and can't take anymore
threadLock();
threadWaitForSignal();
threadUnlock();
}
}
-void Player::setStartTS(UINT dataInBuffer)
-{
- if (isRecording && feedPosition) // (feedPosition != 0)
- {
- // FIXME find out how much data need to get to find a TS
- // Need to get the actual start of the recording
-
- UINT thisRead;
- UCHAR* tempBuffer = VDR::getInstance()->getBlock(0, 100000, &thisRead);
- if (!tempBuffer && !VDR::getInstance()->isConnected()) { doConnectionLost(); return; }
- if (!tempBuffer) return;
- if (thisRead) demuxer->findVideoPTS(tempBuffer, thisRead, &startTS);
- free(tempBuffer);
- }
- else
- {
- demuxer->findVideoPTS(threadBuffer, dataInBuffer, &startTS);
- }
-}
-
-void Player::setEndTS()
-{
- logger->log("Player", Log::DEBUG, "Setting end TS");
-
- UINT thisRead;
- UCHAR* tempBuffer = VDR::getInstance()->getBlock((streamLength - 100000), 100000, &thisRead);
- if (!tempBuffer && !VDR::getInstance()->isConnected()) { doConnectionLost(); return; }
- if (!tempBuffer) return;
- if (thisRead) demuxer->findVideoPTS(tempBuffer, thisRead, &endTS);
- free(tempBuffer);
- logger->log("Player", Log::DEBUG, "Set end TS");
-}
+// ----------------------------------- Dev
#ifdef DEV
void Player::test1()