audio = Audio::getInstance();
video = Video::getInstance();
logger = Log::getInstance();
+ vdr = VDR::getInstance();
initted = false;
- paused = false;
- playing = false;
- ffwd = false;
- fbwd = false;
lengthBytes = 0;
lengthFrames = 0;
- feedPosition = 0;
- feedMode = MODE_NORMAL;
- lastRescan = 0;
-// startTS = 0;
-// endTS = 0;
+ currentFrameNumber = 0;
+ state = S_STOP;
videoStartup = false;
preBuffering = false;
int Player::shutdown()
{
if (!initted) return 0;
+ switchState(S_STOP);
initted = false;
- // copy of stop
- if (playing)
- {
- playing = false;
- threadStop();
- video->stop();
- video->blank();
- audio->stop();
- vfeed.stop();
-
- afeed.stop();
- video->reset();
- demuxer->reset();
- feedPosition = 0;
- }
-
delete demuxer;
demuxer = NULL;
+
#ifdef WIN32
CloseHandle(mutex);
#endif
void Player::setStartFrame(ULONG startFrame)
{
- startFrameNum = startFrame;
- if (startFrameNum)
- {
- feedPosition = VDR::getInstance()->positionFromFrameNumber(startFrameNum);
- }
- else
- {
- feedPosition = 0;
- }
+ currentFrameNumber = startFrame;
}
void Player::setLengthBytes(ULLONG length)
{
- lastRescan = time(NULL);
lengthBytes = length;
logger->log("Player", Log::DEBUG, "Player has received length bytes of %llu", lengthBytes);
}
// ----------------------------------- Externally called events
-int Player::play()
+void Player::play()
{
+ if (!initted) return;
+ if (state == S_PLAY) return;
lock();
bool doUnlock = false;
- int result = playInt(&doUnlock);
+ if (state == S_PAUSE) doUnlock = true;
+ switchState(S_PLAY);
if (doUnlock) unLock();
- return result;
}
void Player::stop()
{
+ if (!initted) return;
+ if (state == S_STOP) return;
lock();
logger->log("Player", Log::DEBUG, "Stop called lock");
- stopInt();
+ switchState(S_STOP);
unLock();
}
void Player::togglePause()
{
+ if (!initted) return;
lock();
- togglePauseInt();
+ if (state == S_PAUSE) switchState(S_PLAY);
+ else switchState(S_PAUSE);
unLock();
}
void Player::toggleFastForward()
{
+ if (!initted) return;
lock();
- toggleFastForwardInt();
+ if (state == S_FFWD) switchState(S_PLAY);
+ else switchState(S_FFWD);
unLock();
}
void Player::toggleFastBackward()
{
+ if (!initted) return;
lock();
- toggleFastBackwardInt();
+ if (state == S_FBWD) switchState(S_PLAY);
+ else switchState(S_FBWD);
unLock();
}
void Player::jumpToPercent(int percent)
{
lock();
- jumpToPercentInt(percent);
+ logger->log("Player", Log::DEBUG, "JUMP TO %i%%", percent);
+ ULONG newFrame = percent * lengthFrames / 100;
+ switchState(S_JUMP, newFrame);
// unLock(); - let thread unlock this
}
void Player::skipForward(int seconds)
{
lock();
- skipForwardInt(seconds);
+ logger->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
+ ULONG newFrame = getCurrentFrameNum() + (seconds * video->getFPS());
+ if (newFrame > lengthFrames) { switchState(S_PLAY); unLock(); }
+ else switchState(S_JUMP, newFrame);
// unLock(); - let thread unlock this
}
void Player::skipBackward(int seconds)
{
lock();
- skipBackwardInt(seconds);
+ logger->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
+ long newFrameNum = getCurrentFrameNum() - (seconds * video->getFPS());
+ if (newFrameNum < 0) newFrameNum = 0;
+ switchState(S_JUMP, newFrameNum);
// unLock(); - let thread unlock this
}
// ----------------------------------- Implementations called events
-
-int Player::playInt(bool* doUnlock)
-{
- if (!initted) return 0;
-
- // If we are just paused, unpause!
- if (paused)
- {
- togglePauseInt();
- *doUnlock = true;
- return 1;
- }
-
- // If we are fast forwarding, set to normal
- if (ffwd)
- {
- toggleFastForwardInt();
- return 1;
- }
-
- // If we are fast backwarding, set to normal
- if (fbwd)
- {
- toggleFastBackwardInt();
- return 1;
- }
-
- // If we are already playing, ignore. no resyncing to do now!
- if (playing)
- {
- *doUnlock = true;
- return 1;
- }
-
- // Standard play start
- logger->log("Player", Log::DEBUG, "Standard play start");
-
- startup = true;
-
- audio->reset();
- video->reset();
- demuxer->reset();
- if (isRecording)
- {
- if (startFrameNum > lengthFrames) startFrameNum = 0;
- demuxer->setFrameNum(startFrameNum);
- }
- if (!isRadio) demuxer->seek();
-
- videoStartup = true;
- threadStart();
-
- if (isRecording)
- {
- logger->log("Player", Log::DEBUG, "Immediate play");
- afeed.start();
- vfeed.start();
- video->sync();
- audio->sync();
- audio->play();
- video->pause();
- }
- else // do prebuffering
- {
- logger->log("Player", Log::DEBUG, "Prebuffering...");
-// afeed.start();
-// vfeed.start();
- preBuffering = true;
- }
-
- playing = true;
- return 1;
-}
-
-void Player::stopInt()
-{
- if (!initted) return;
- if (!playing) return;
-
- if (ffwd || fbwd)
- {
- ffwd = false;
- fbwd = false;
- afeed.enable();
- video->unFastForward();
- audio->systemMuteOff();
- feedMode = MODE_NORMAL;
- }
-
- playing = false;
- paused = false;
-
- vfeed.stop();
- afeed.stop();
- if (threadIsActive()) threadStop();
- video->stop();
- video->blank();
- audio->stop();
- audio->unPause();
- video->reset();
- demuxer->reset();
-
- feedPosition = 0;
-}
-
-void Player::togglePauseInt()
-{
- if (!initted) return;
- if (!playing) return;
-
- if (ffwd) toggleFastForwardInt();
- if (fbwd) toggleFastBackwardInt();
-
- if (paused)
- {
- video->unPause();
- audio->unPause();
- paused = false;
- }
- else
- {
- video->pause();
- audio->pause();
- paused = true;
- }
-}
-
-void Player::toggleFastForwardInt()
+void Player::switchState(UCHAR toState, ULONG jumpFrame)
{
if (!initted) return;
- if (!playing) return;
- if (paused) togglePauseInt();
- if (fbwd) toggleFastBackwardInt();
+ logger->log("Player", Log::DEBUG, "Switch state from %u to %u", state, toState);
- if (ffwd)
+ switch(state) // current state selector
{
- ffwd = false;
- threadStop();
- vfeed.stop();
- afeed.stop();
- video->stop();
- audio->stop();
- video->reset();
- audio->reset();
- demuxer->flush();
- if (!isRadio) demuxer->seek();
-
- videoStartup = true;
- afeed.enable();
- afeed.start();
- vfeed.start();
- threadStart();
- audio->play();
- video->sync();
- audio->sync();
- audio->systemMuteOff();
- audio->doMuting();
- fbwd = false;
- }
- else
- {
- ffwd = true;
-#ifndef WIN32
- afeed.disable();
-#endif
- audio->systemMuteOn();
- video->fastForward();
- }
-}
-
-void Player::toggleFastBackwardInt()
-{
- if (!initted) return;
- if (!playing) return;
-
- if (paused) togglePauseInt();
- if (ffwd) toggleFastForwardInt();
-
- if (fbwd)
- {
- fbwd = false;
- afeed.enable();
- audio->systemMuteOff();
-
-// threadStop();
- feedMode = MODE_NORMAL;
-// threadStart();
- }
- else
- {
- fbwd = false;
-#ifndef WIN32
- afeed.disable();
-#endif
- audio->systemMuteOn();
-
- threadStop();
- feedMode = MODE_BACKWARDS;
- video->reset();
- video->play();
- demuxer->flush();
- if (!isRadio) demuxer->seek();
-
- threadStart();
+ case S_PLAY: // from S_PLAY -----------------------------------
+ {
+ switch(toState)
+ {
+ case S_PLAY: // to S_PLAY
+ {
+ return;
+ }
+ case S_PAUSE: // to S_PAUSE
+ {
+ video->pause();
+ audio->pause();
+ state = S_PAUSE;
+ return;
+ }
+ case S_FFWD: // to S_FFWD
+ {
+ currentFrameNumber = getCurrentFrameNum();
+ audio->systemMuteOn();
+ threadStop();
+ vfeed.stop();
+ afeed.stop();
+ demuxer->flush();
+ state = S_FFWD;
+ threadStart();
+ return;
+ }
+ case S_FBWD: // to S_FBWD
+ {
+ currentFrameNumber = getCurrentFrameNum();
+ audio->systemMuteOn();
+ threadStop();
+ vfeed.stop();
+ afeed.stop();
+ demuxer->flush();
+ state = S_FBWD;
+ threadStart();
+ return;
+ }
+ case S_STOP: // to S_STOP
+ {
+ vfeed.stop();
+ afeed.stop();
+ threadStop();
+ video->stop();
+ video->blank();
+ audio->stop();
+ audio->unPause();
+ video->reset();
+ demuxer->reset();
+ state = S_STOP;
+ return;
+ }
+ case S_JUMP: // to S_JUMP
+ {
+ restartAtFrame(jumpFrame);
+ return;
+ }
+ }
+ }
+ case S_PAUSE: // from S_PAUSE -----------------------------------
+ {
+ switch(toState)
+ {
+ case S_PLAY: // to S_PLAY
+ {
+ if (threadIsActive())
+ {
+ video->unPause();
+ audio->unPause();
+ state = S_PLAY;
+ }
+ else
+ {
+ state = S_PLAY;
+ restartAtFrame(currentFrameNumber);
+ }
+
+ return;
+ }
+ case S_PAUSE: // to S_PAUSE
+ {
+ return;
+ }
+ case S_FFWD: // to S_FFWD
+ {
+ currentFrameNumber = getCurrentFrameNum();
+ audio->systemMuteOn();
+ vfeed.stop();
+ afeed.stop();
+ if (threadIsActive()) threadStop();
+ video->unPause();
+ audio->unPause();
+ state = S_FFWD;
+ threadStart();
+ return;
+ }
+ case S_FBWD: // to S_FBWD
+ {
+ currentFrameNumber = getCurrentFrameNum();
+ audio->systemMuteOn();
+ vfeed.stop();
+ afeed.stop();
+ if (threadIsActive()) threadStop();
+ video->unPause();
+ audio->unPause();
+ state = S_FBWD;
+ threadStart();
+ return;
+ }
+ case S_STOP: // to S_STOP
+ {
+ vfeed.stop();
+ afeed.stop();
+ if (threadIsActive()) threadStop();
+ video->stop();
+ video->blank();
+ audio->stop();
+ video->reset();
+ audio->unPause();
+ demuxer->reset();
+ audio->systemMuteOff();
+ state = S_FFWD;
+ return;
+ }
+ case S_JUMP: // to S_JUMP
+ {
+ state = S_PLAY;
+ audio->unPause();
+ restartAtFrame(jumpFrame);
+ return;
+ }
+ }
+ }
+ case S_FFWD: // from S_FFWD -----------------------------------
+ {
+ switch(toState)
+ {
+ case S_PLAY: // to S_PLAY
+ {
+ state = S_PLAY;
+ restartAtFrame(currentFrameNumber);
+ return;
+ }
+ case S_PAUSE: // to S_PAUSE
+ {
+ threadStop();
+ state = S_PAUSE;
+ return;
+ }
+ case S_FFWD: // to S_FFWD
+ {
+ return;
+ }
+ case S_FBWD: // to S_FBWD
+ {
+ threadStop();
+ state = S_FBWD;
+ threadStart();
+ return;
+ }
+ case S_STOP: // to S_STOP
+ {
+ threadStop();
+ video->stop();
+ video->blank();
+ audio->stop();
+ video->reset();
+ demuxer->reset();
+ state = S_STOP;
+ return;
+ }
+ case S_JUMP: // to S_JUMP
+ {
+ state = S_PLAY;
+ restartAtFrame(jumpFrame);
+ return;
+ }
+ }
+ }
+ case S_FBWD: // from S_FBWD -----------------------------------
+ {
+ switch(toState)
+ {
+ case S_PLAY: // to S_PLAY
+ {
+ state = S_PLAY;
+ restartAtFrame(currentFrameNumber);
+ return;
+ }
+ case S_PAUSE: // to S_PAUSE
+ {
+ threadStop();
+ state = S_PAUSE;
+ return;
+ }
+ case S_FFWD: // to S_FFWD
+ {
+ threadStop();
+ state = S_FFWD;
+ threadStart();
+ return;
+ }
+ case S_FBWD: // to S_FBWD
+ {
+ return;
+ }
+ case S_STOP: // to S_STOP
+ {
+ threadStop();
+ video->stop();
+ video->blank();
+ audio->stop();
+ video->reset();
+ demuxer->reset();
+ state = S_STOP;
+ return;
+ }
+ case S_JUMP: // to S_JUMP
+ {
+ state = S_PLAY;
+ restartAtFrame(jumpFrame);
+ return;
+ }
+ }
+ }
+ case S_STOP: // from S_STOP -----------------------------------
+ {
+ switch(toState)
+ {
+ case S_PLAY: // to S_PLAY
+ {
+ startup = true;
+
+ audio->reset();
+ audio->systemMuteOff();
+ video->reset();
+ demuxer->reset();
+ if (isRecording)
+ {
+ // FIXME use restartAtFrame here?
+ if (currentFrameNumber > lengthFrames) currentFrameNumber = 0;
+ demuxer->setFrameNum(currentFrameNumber);
+ }
+ if (!isRadio) demuxer->seek();
+
+ videoStartup = true;
+ state = S_PLAY;
+ threadStart();
+
+ if (isRecording)
+ {
+ logger->log("Player", Log::DEBUG, "Immediate play");
+ afeed.start();
+ vfeed.start();
+ video->sync();
+ audio->sync();
+ audio->play();
+ video->pause();
+ }
+ else // do prebuffering
+ {
+ logger->log("Player", Log::DEBUG, "Prebuffering...");
+ preBuffering = true;
+ }
+ return;
+ }
+ case S_PAUSE: // to S_PAUSE
+ {
+ return;
+ }
+ case S_FFWD: // to S_FFWD
+ {
+ return;
+ }
+ case S_FBWD: // to S_FBWD
+ {
+ return;
+ }
+ case S_STOP: // to S_STOP
+ {
+ return;
+ }
+ case S_JUMP: // to S_JUMP
+ {
+ return;
+ }
+ }
+ }
+ // case S_JUMP cannot be selected as a start state because it auto flips to play
}
}
-void Player::skipForwardInt(int seconds)
-{
- logger->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
- restartAtFrame(getCurrentFrameNum() + (seconds * video->getFPS()));
-}
-
-void Player::skipBackwardInt(int seconds)
-{
- logger->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
- long newFrameNum = getCurrentFrameNum() - (seconds * video->getFPS());
- if (newFrameNum < 0) newFrameNum = 0;
- restartAtFrame(newFrameNum);
-}
-
-void Player::jumpToPercentInt(int percent)
-{
- logger->log("Player", Log::DEBUG, "JUMP TO %i%%", percent);
- ULONG newFrame = percent * lengthFrames / 100;
- restartAtFrame(newFrame);
-}
-
-
// ----------------------------------- Internal functions
void Player::lock()
void Player::restartAtFrame(ULONG newFrame)
{
- if (paused) togglePauseInt();
- if (ffwd) toggleFastForwardInt();
-
- ULLONG newPosition = VDR::getInstance()->positionFromFrameNumber(newFrame);
- if (!VDR::getInstance()->isConnected()) { doConnectionLost(); return; }
- logger->log("Player", Log::DEBUG, "wantedframe %i feedpos %llu goto %llu", newFrame, feedPosition, newPosition);
-
vfeed.stop();
afeed.stop();
threadStop();
audio->reset();
demuxer->flush();
if (!isRadio) demuxer->seek();
- feedPosition = newPosition;
+ currentFrameNumber = newFrame;
demuxer->setFrameNum(newFrame);
videoStartup = true;
afeed.start();
audio->sync();
audio->systemMuteOff();
audio->doMuting();
- fbwd = false;
}
void Player::doConnectionLost()
video->sync();
vfeed.release();
unLock();
+ logger->log("Player", Log::DEBUG, "BANG BANG BANG BANG BANG BANG BANG BANG BANG BANG BANG");
}
threadSignalNoLock();
// ----------------------------------- Feed thread
void Player::threadMethod()
+{
+ // this method used to be simple, the only thing it does
+ // is farm out to threadFeed Live/Play/Scan
+ // All the guff is to support scan hitting one end
+
+ if (isRecording)
+ {
+ if ((state == S_FFWD) || (state == S_FBWD))
+ {
+ threadFeedScan();
+ // if this returns then scan hit one end
+ if (state == S_FFWD) // scan hit the end. stop
+ {
+ threadCheckExit();
+ Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex
+ m->message = Message::STOP_PLAYBACK;
+ logger->log("Player", Log::DEBUG, "Posting message to %p...", commandMessageQueue);
+ commandMessageQueue->postMessage(m);
+ logger->log("Player", Log::DEBUG, "Message posted...");
+ return;
+ }
+ // if execution gets to here, threadFeedScan hit the start, go to play mode
+ state = S_PLAY;
+ audio->reset();
+ demuxer->flush();
+ if (!isRadio) demuxer->seek();
+ demuxer->setFrameNum(currentFrameNumber);
+ videoStartup = true;
+ afeed.start();
+ vfeed.start();
+ audio->play();
+ audio->sync();
+ audio->systemMuteOff();
+ audio->doMuting();
+ }
+
+ if (state == S_PLAY) threadFeedPlay();
+ }
+ else
+ {
+ threadFeedLive();
+ }
+}
+
+void Player::threadFeedLive()
{
UINT thisRead;
UINT writeLength;
UINT thisWrite;
UINT preBufferTotal = 0;
- VDR* vdr = VDR::getInstance();
-
UINT askFor;
while(1)
{
threadCheckExit();
- // If we havn't rescanned for a while..
- if (isRecording && ((lastRescan + 60) < time(NULL)))
- {
- lengthBytes = vdr->rescanRecording(&lengthFrames);
- if (!vdr->isConnected()) { doConnectionLost(); return; }
- logger->log("Player", Log::DEBUG, "Rescanned and reset length: %llu", lengthBytes);
- lastRescan = time(NULL);
-// setEndTS();
- }
-
- if (lengthBytes) // is playing a recording
- {
- if (feedPosition >= lengthBytes) break; // finished playback
-
- if (startup)
- {
- if (startupBlockSize > lengthBytes)
- askFor = lengthBytes; // is a very small recording!
- else
- askFor = startupBlockSize; // normal, but a startup sized block to detect all the audio streams
- }
- else
- {
- if ((feedPosition + blockSize) > lengthBytes) // last block of recording
- askFor = lengthBytes - feedPosition;
- else // normal
- askFor = blockSize;
- }
- }
- else // is playing live
- {
- if (startup)
- askFor = startupBlockSize; // find audio streams sized block
- else
- askFor = blockSize; // normal
- }
+ if (startup)
+ askFor = startupBlockSize; // find audio streams sized block
+ else
+ askFor = blockSize; // normal
- threadBuffer = vdr->getBlock(feedPosition, askFor, &thisRead);
+ threadBuffer = vdr->getBlock(0, askFor, &thisRead);
if (!vdr->isConnected())
{
int a_stream = demuxer->scan(threadBuffer, thisRead);
demuxer->setAudioStream(a_stream);
logger->log("Player", Log::DEBUG, "Startup Audio stream chosen %x", a_stream);
-
-// setStartTS(thisRead);
-
-// if (isRecording) setEndTS();
-
startup = false;
}
}
}
- if (feedMode == MODE_NORMAL)
- {
- feedPosition += thisRead;
- }
- else if (feedMode == MODE_BACKWARDS)
+ threadCheckExit();
+
+ while(writeLength < thisRead)
{
- if (feedPosition >= blockSize)
+ thisWrite = demuxer->put(threadBuffer + writeLength, thisRead - writeLength);
+ writeLength += thisWrite;
+
+ if (!thisWrite)
{
- feedPosition -= blockSize;
- if (!isRadio) demuxer->seek();
+ // demuxer is full and can't take anymore
+ threadLock();
+ threadWaitForSignal();
+ threadUnlock();
}
+
+ threadCheckExit();
+ }
+
+ free(threadBuffer);
+ threadBuffer = NULL;
+
+ }
+
+ logger->log("Player", Log::DEBUG, "Live play failed to start or interrupted");
+
+ if (videoStartup) // oh woe. there never was a stream, I was conned!
+ {
+ videoStartup = false;
+ unLock();
+ MILLISLEEP(500); // I think this will solve a race
+ }
+
+ threadCheckExit();
+
+ Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex
+ m->message = Message::STREAM_END;
+ logger->log("Player", Log::DEBUG, "Posting message to %p...", commandMessageQueue);
+ commandMessageQueue->postMessage(m);
+ logger->log("Player", Log::DEBUG, "Message posted...");
+}
+
+void Player::threadFeedPlay()
+{
+ ULLONG feedPosition;
+ UINT thisRead, writeLength, thisWrite, askFor;
+ time_t lastRescan = time(NULL);
+
+ feedPosition = vdr->positionFromFrameNumber(currentFrameNumber);
+ if (!vdr->isConnected()) { doConnectionLost(); return; }
+ logger->log("Player", Log::DEBUG, "startFeedPlay: wantedframe %i goto %llu", currentFrameNumber, feedPosition);
+
+
+ while(1)
+ {
+ thisRead = 0;
+ writeLength = 0;
+ thisWrite = 0;
+
+ threadCheckExit();
+
+ // If we havn't rescanned for a while..
+ if ((lastRescan + 60) < time(NULL))
+ {
+ lengthBytes = vdr->rescanRecording(&lengthFrames);
+ if (!vdr->isConnected()) { doConnectionLost(); return; }
+ logger->log("Player", Log::DEBUG, "Rescanned and reset length: %llu", lengthBytes);
+ lastRescan = time(NULL);
+ }
+
+ if (feedPosition >= lengthBytes) break; // finished playback
+
+ if (startup)
+ {
+ if (startupBlockSize > lengthBytes)
+ askFor = lengthBytes; // is a very small recording!
else
- {
- // got to the start of the recording.. revert to play mode? how?
- feedPosition += thisRead;
- }
+ askFor = startupBlockSize; // normal, but a startup sized block to detect all the audio streams
+ }
+ else
+ {
+ if ((feedPosition + blockSize) > lengthBytes) // last block of recording
+ askFor = lengthBytes - feedPosition;
+ else // normal
+ askFor = blockSize;
+ }
+
+ threadBuffer = vdr->getBlock(feedPosition, askFor, &thisRead);
+ feedPosition += thisRead;
+
+ if (!vdr->isConnected())
+ {
+ doConnectionLost();
+ return;
+ }
+
+ if (!threadBuffer) break;
+
+ if (startup)
+ {
+ int a_stream = demuxer->scan(threadBuffer, thisRead);
+ demuxer->setAudioStream(a_stream);
+ logger->log("Player", Log::DEBUG, "Startup Audio stream chosen %x", a_stream);
+ startup = false;
}
threadCheckExit();
{
thisWrite = demuxer->put(threadBuffer + writeLength, thisRead - writeLength);
writeLength += thisWrite;
-// logger->log("Player", Log::DEBUG, "Put %i to demuxer", thisWrite);
if (!thisWrite)
{
-// logger->log("Player", Log::DEBUG, "DEMUXER FULL!!!");
// demuxer is full and can't take anymore
threadLock();
threadWaitForSignal();
threadUnlock();
-// logger->log("Player", Log::DEBUG, "BACK FROM WAIT");
}
threadCheckExit();
threadCheckExit();
Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex
- if (lengthBytes) m->message = Message::STOP_PLAYBACK; // recording
- else m->message = Message::STREAM_END; // live
+ m->message = Message::STOP_PLAYBACK; // recording
logger->log("Player", Log::DEBUG, "Posting message to %p...", commandMessageQueue);
commandMessageQueue->postMessage(m);
logger->log("Player", Log::DEBUG, "Message posted...");
}
+void Player::threadFeedScan()
+{
+ ULONG direction = 0;
+ ULONG iframeNumber = 0;
+ ULONG iframeLength = 0;
+ ULLONG filePos;
+ UINT amountReceived;
+ UINT videoLength;
+
+ if (state == S_FFWD) direction = 1; // and 0 for backward
+
+ while(1)
+ {
+ if (!vdr->getNextIFrame(currentFrameNumber, direction, &filePos, &iframeNumber, &iframeLength)) break;
+ threadBuffer = vdr->getBlock(filePos, iframeLength, &amountReceived);
+ videoLength = demuxer->stripAudio(threadBuffer, amountReceived);
+ video->displayIFrame(threadBuffer, videoLength);
+ currentFrameNumber = iframeNumber;
+ free(threadBuffer);
+ threadBuffer = NULL;
+ threadCheckExit();
+ MILLISLEEP(100);
+ }
+ // scan has hit one end
+}
+
void Player::threadPostStopCleanup()
{
if (threadBuffer)