OBJ_COMMON = command.o tcp.o dsock.o thread.o timers.o i18n.o vdp6.o \
message.o messagequeue.o wol.o audio.o video.o log.o \
vdr.o recman.o recording.o recinfo.o channel.o rectimer.o event.o \
- directory.o mark.o option.o player.o playerradio.o vfeed.o afeed.o \
+ directory.o mark.o option.o playervideorec.o playerradio.o vfeed.o afeed.o \
demuxer.o demuxervdr.o demuxerts.o stream.o osd.o surface.o \
region.o colour.o boxstack.o boxx.o tbboxx.o vrecording.o \
vinfo.o vquestion.o vrecordinglist.o vrecordinglistclassic.o \
OBJ_RASPBERRY = main.o threadp.o osdopenvg.o \
ledraspberry.o videoomx.o audioomx.o imageomx.o \
- wjpegsimple.o inputlinux.o inputcec.o signal.o
+ wjpegsimple.o inputlinux.o inputcec.o
OBJ_WINDOWS = winmain.o threadwin.o inputwin.o ledwin.o videowin.o \
audiowin.o windowsosd.o dsallocator.o dssourcefilter.o dssourcepin.o \
{
if (instance) return;
instance = this;
- initted = 0;
fdOsd = 0;
screen = NULL;
protected:
static Osd* instance;
- int initted;
+ bool initted{};
Surface* screen;
int fdOsd;
};
osd_layer->GetConfiguration(osd_layer,&layer_config);
- initted = 1; // must set this here or create surface won't work
+ initted = true; // must set this here or create surface won't work
/* TODO clean up sizes */
Video* video = Video::getInstance();
int OsdDirectFB::shutdown()
{
if (!initted) return 0;
- initted = 0;
+ initted = false;
delete screen;
if (osd_layer) osd_layer->Release(osd_layer);
if (dfb) dfb->Release(dfb);
screen->create(video->getScreenWidth(), video->getScreenHeight());
screen->display();
- initted = 1; // must set this here or create surface won't work
+ initted = true; // must set this here or create surface won't work
//glGenBuffers(1, &vB);
//glGenBuffers(1, &iB);
{
if (!initted) return 0;
glmutex.lock();
- initted = 0;
+ initted = false;
threadStop();
delete screen;
screen=NULL;
Log::getInstance()->log("OSD", Log::DEBUG, "Making egl current out 1%d",syscall(SYS_gettid));
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
//Now we will create the Screen
- initted = 1; // must set this here or create surface won't work
+ initted = true; // must set this here or create surface won't work
/*if (((VideoOMX*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init stuff
if (!initted) return 0;
- initted = 0;
+ initted = false;
Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark1");
threadStop();
Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark1a");
screen = new SurfaceWin(Surface::SCREEN);
screen->create(video->getScreenWidth(), video->getScreenHeight());
screen->display();
- initted = 1; // must set this here or create surface won't work
+ initted = true; // must set this here or create surface won't work
startRenderLoop();
int OsdWinPixel::shutdown()
{
if (!initted) return 0;
- initted = 0;
+ initted = false;
stopRenderLoop();
shutdownDirect3D9Objects();
int init();
int shutdown();
- int isInitialized() { return initted; }
+ bool isInitialized() { return initted; }
int getFD();
loadFont(false);
- initted = 1; // must set this here or create surface won't work
+ initted = true; // must set this here or create surface won't work
startRenderLoop();
int init();
int shutdown();
- int isInitialized() { return initted; }
+ bool isInitialized() { return initted; }
void getScreenSize(int &width, int &height);
void getRealScreenSize(int &width, int &height);
+++ /dev/null
-/*
- Copyright 2004-2008 Chris Tallon
-
- This file is part of VOMP.
-
- VOMP is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- VOMP is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with VOMP. If not, see <https://www.gnu.org/licenses/>.
-*/
-
-#include "player.h"
-
-#include "log.h"
-#include "audio.h"
-#include "video.h"
-#include "demuxervdr.h"
-#include "demuxerts.h"
-#include "vdr.h"
-#include "messagequeue.h"
-#include "input.h"
-#include "message.h"
-#include "dvbsubtitles.h"
-#include "osdreceiver.h"
-
-#define USER_RESPONSE_TIME 500 // Milliseconds
-
-// ----------------------------------- Called from outside, one offs or info funcs
-
-Player::Player(MessageQueue* tmessageQueue, void* tmessageReceiver, OSDReceiver* tosdReceiver)
-: vfeed(this), afeed(this), tfeed(this)
-{
- messageQueue = tmessageQueue;
- messageReceiver = tmessageReceiver;
- osdReceiver = tosdReceiver;
- audio = Audio::getInstance();
- video = Video::getInstance();
- logger = Log::getInstance();
- vdr = VDR::getInstance();
-
- video->turnVideoOn();
-}
-
-Player::~Player()
-{
- if (initted) shutdown();
-}
-
-int Player::init(bool p_isPesRecording, double framespersecond)
-{
- if (initted) return 0;
-#ifndef WIN32
- pthread_mutex_init(&mutex, NULL);
-#else
- mutex=CreateMutex(NULL,FALSE,NULL);
-#endif
- is_pesrecording = p_isPesRecording;
- fps = framespersecond;
- if (is_pesrecording)
- demuxer = new DemuxerVDR();
- else
- demuxer = new DemuxerTS();
- if (!demuxer) return 0;
- subtitles = new DVBSubtitles(osdReceiver);
- if (!subtitles) return 0;
-
- teletext = new TeletextDecoderVBIEBU();
- if (!teletext) return 0;
- teletext->setRecordigMode(true);
- unsigned int demux_video_size = 2097152;
- unsigned int demux_audio_size = 524288;
- if (video->supportsh264())
- {
- demux_video_size *= 5 * 2;
- }
- if (audio->maysupportAc3())
- {
- //demux_audio_size*=2;
- }
-
- if (!demuxer->init(this, audio, video,teletext, demux_video_size,demux_audio_size,65536, framespersecond, subtitles))
- {
- logger->log("Player", Log::ERR, "Demuxer failed to init");
- shutdown();
- return 0;
- }
-
- vfeed.init();
- afeed.init();
- tfeed.init();
-
- video->stop();
- video->blank();
- audio->stop();
-
- if (Command::getInstance()->getSubDefault())
- turnSubtitlesOn(true);
- else
- turnSubtitlesOn(false);
-
- initted = true;
- return 1;
-}
-
-int Player::shutdown()
-{
- if (!initted) return 0;
- switchState(S_STOP);
- initted = false;
-
- delete demuxer;
- demuxer = NULL;
- delete subtitles;
- subtitles = NULL;
- delete teletext;
- teletext = NULL;
-
-#ifdef WIN32
- CloseHandle(mutex);
-#endif
-
- return 1;
-}
-
-void Player::setStartFrame(ULONG startFrame)
-{
- ULONG nextiframeNumber;
- ULONG iframeLength;
- ULONG iframeNumber;
- ULLONG filePos;
-
- // newFrame could be anywhere, go forwards to next I-Frame
- if (!vdr->getNextIFrame(startFrame, 1, &filePos, &nextiframeNumber, &iframeLength)) return;
-
- // Now step back a GOP. This ensures we go to the greatest I-Frame equal to or less than the requested frame
- vdr->getNextIFrame(nextiframeNumber, 0, &filePos, &iframeNumber, &iframeLength);
-
- logger->log("Player", Log::DEBUG, "setStartFrame %lu %lu %lu", startFrame, nextiframeNumber,iframeNumber);
- currentFrameNumber = iframeNumber;
-}
-
-void Player::setLengthBytes(ULLONG length)
-{
- lengthBytes = length;
- logger->log("Player", Log::DEBUG, "Player has received length bytes of %llu", lengthBytes);
-}
-
-void Player::setLengthFrames(ULONG length)
-{
- lengthFrames = length;
- logger->log("Player", Log::DEBUG, "Player has received length frames of %lu", lengthFrames);
-}
-
-ULONG Player::getLengthFrames()
-{
- return lengthFrames;
-}
-
-ULONG Player::getCurrentFrameNum()
-{
- if (startup) return 0;
- switch(state)
- {
- case S_PLAY:
- case S_PAUSE_P:
- return demuxer->getFrameNumFromPTS(video->getCurrentTimestamp());
- case S_PAUSE_I:
- case S_FFWD:
- case S_FBWD:
- return currentFrameNumber;
- default:
- return 0; // shouldn't happen
- }
-}
-
-bool* Player::getDemuxerMpegAudioChannels()
-{
- return demuxer->getmpAudioChannels();
-}
-
-bool* Player::getDemuxerAc3AudioChannels()
-{
- return demuxer->getac3AudioChannels();
-}
-
-bool* Player::getDemuxerSubtitleChannels()
-{
- return demuxer->getSubtitleChannels();
-}
-
-int Player::getCurrentAudioChannel()
-{
- if (is_pesrecording)
- return demuxer->getselAudioChannel();
- else
- return dynamic_cast<DemuxerTS*>(demuxer)->getAID();
-}
-
-int Player::getCurrentSubtitleChannel()
-{
- if (is_pesrecording)
- return demuxer->getselSubtitleChannel();
- else
- return dynamic_cast<DemuxerTS*>(demuxer)->getSubID();
-}
-
-void Player::setSubtitleChannel(int newChannel)
-{
- if (is_pesrecording)
- demuxer->setDVBSubtitleStream(newChannel);
- else
- dynamic_cast<DemuxerTS*>(demuxer)->setSubID(newChannel);
-}
-
-int *Player::getTeletxtSubtitlePages()
-{
- return teletext->getSubtitlePages();
-}
-
-void Player::setAudioChannel(int newChannel, int type, int streamtype)
-{
- if (is_pesrecording)
- {
- demuxer->setAudioStream(newChannel);
- return;
- }
- else
- {
- dynamic_cast<DemuxerTS*>(demuxer)->setAID(newChannel,type,streamtype,false);
- return;
- }
-}
-
-bool Player::toggleSubtitles()
-{
- if (!subtitlesShowing)
- {
- subtitlesShowing = true;
- subtitles->show();
- }
- else
- {
- subtitlesShowing = false;
- subtitles->hide();
- }
- return subtitlesShowing;
-}
-
-void Player::turnSubtitlesOn(bool ison)
-{
- if (ison)
- {
- subtitlesShowing = true;
- subtitles->show();
- }
- else
- {
- subtitlesShowing = false;
- subtitles->hide();
- }
-}
-
-void Player::tellSubtitlesOSDVisible(bool visible)
-{
- subtitles->setOSDMenuVisibility(visible);
-}
-
-Channel * Player::getDemuxerChannel()
-{
- if (!is_pesrecording)
- {
- return dynamic_cast<DemuxerTS*>(demuxer)->getChannelInfo();
- }
- return NULL; //Should not happen!
-}
-
-
-// ----------------------------------- Externally called events
-
-void Player::play()
-{
- if (!initted) return;
- if (state == S_PLAY) return;
- lock();
-
- bool doUnlock = false;
- if (state == S_PAUSE_P) doUnlock = true;
- switchState(S_PLAY);
- if (doUnlock) unLock();
-}
-
-void Player::playpause()
-{
- if (!initted) return;
- lock();
-
- bool doUnlock = false;
- if (state==S_PLAY)
- {
- doUnlock=true;
- switchState(S_PAUSE_P);
- }
- else
- {
- if (state == S_PAUSE_P) doUnlock = true;
- switchState(S_PLAY);
- }
- if (doUnlock) unLock();
-}
-
-void Player::stop()
-{
- if (!initted) return;
- if (state == S_STOP) return;
- lock();
- logger->log("Player", Log::DEBUG, "Stop called lock");
- switchState(S_STOP);
- unLock();
-}
-
-void Player::pause()
-{
- if (!initted) return;
- lock();
-
- if ((state == S_FFWD) || (state == S_FBWD))
- {
- switchState(S_PAUSE_I);
- }
- else if ((state == S_PAUSE_I) || (state == S_PAUSE_P))
- {
- switchState(S_PLAY);
- }
- else
- {
- switchState(S_PAUSE_P);
- }
-
- unLock();
-}
-
-void Player::fastForward()
-{
- if (!initted) return;
- lock();
-
- if (state == S_FFWD)
- {
- // change the rate
- switch(ifactor)
- {
- case 4: ifactor = 8; break;
- case 8: ifactor = 16; break;
- case 16: ifactor = 32; break;
- case 32: ifactor = 4; break;
- }
- }
- else
- {
- ifactor = 4;
- switchState(S_FFWD);
- }
- unLock();
-}
-
-void Player::fastBackward()
-{
- if (!initted) return;
- lock();
-
- if (state == S_FBWD)
- {
- // change the rate
- switch(ifactor)
- {
- case 4: ifactor = 8; break;
- case 8: ifactor = 16; break;
- case 16: ifactor = 32; break;
- case 32: ifactor = 4; break;
- }
- }
- else
- {
- ifactor = 4;
- switchState(S_FBWD);
- }
- unLock();
-}
-
-void Player::jumpToPercent(double percent)
-{
- lock();
- logger->log("Player", Log::DEBUG, "JUMP TO %f%%", percent);
- ULONG newFrame = static_cast<ULONG>(percent * lengthFrames / 100);
- switchState(S_JUMP, newFrame);
-// unLock(); - let thread unlock this
-}
-
-void Player::jumpToMark(int mark)
-{
- lock();
- logger->log("Player", Log::DEBUG, "JUMP TO MARK %i%%", mark);
- switchState(S_JUMP, mark);
-// unLock(); - let thread unlock this
-}
-
-void Player::jumpToFrameP(int newFrame)
-{
- lock();
- logger->log("Player", Log::DEBUG, "JUMP TO FRAME AND PAUSE %i", newFrame);
- switchState(S_JUMP_PI, newFrame);
- unLock();
-}
-
-void Player::skipForward(int seconds)
-{
- lock();
- logger->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
- ULONG newFrame = getCurrentFrameNum();
- if (newFrame == 0) { unLock(); return; } // Current pos from demuxer is not valid
- newFrame += static_cast<ULONG>(static_cast<double>(seconds) * fps);
- if (newFrame > lengthFrames) { switchState(S_PLAY); unLock(); }
- else switchState(S_JUMP, newFrame);
-// unLock(); - let thread unlock this
-}
-
-void Player::skipBackward(int seconds)
-{
- lock();
- logger->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
- long newFrame = getCurrentFrameNum();
- if (newFrame == 0) { unLock(); return; } // Current pos from demuxer is not valid
- newFrame -= static_cast<ULONG>(static_cast<double>(seconds) * fps);
- if (newFrame < 0) newFrame = 0;
- switchState(S_JUMP, newFrame);
-// unLock(); - let thread unlock this
-}
-
-// ----------------------------------- Implementations called events
-
-void Player::switchState(UCHAR toState, ULONG jumpFrame)
-{
- if (!initted) return;
-
- logger->log("Player", Log::DEBUG, "Switch state from %u to %u", state, toState);
-
- switch(state) // current state selector
- {
- case S_PLAY: // from S_PLAY -----------------------------------
- {
- switch(toState)
- {
- case S_PLAY: // to S_PLAY
- {
- return;
- }
- case S_PAUSE_P: // to S_PAUSE_P
- {
- #ifdef VOMP_PLATFORM_RASPBERRY
- vfeed.stop(); // can't vfeed during pause
- #endif
-
- video->pause();
- audio->pause();
- state = S_PAUSE_P;
- return;
- }
- case S_PAUSE_I: // to S_PAUSE_I
- {
- // can't occur
- return;
- }
- case S_FFWD: // to S_FFWD
- {
- currentFrameNumber = getCurrentFrameNum();
- audio->systemMuteOn();
- threadStop();
- vfeed.stop();
- afeed.stop();
- tfeed.stop();
- subtitles->stop();
- demuxer->flush();
- state = S_FFWD;
- threadStart();
- return;
- }
- case S_FBWD: // to S_FBWD
- {
- currentFrameNumber = getCurrentFrameNum();
- audio->systemMuteOn();
- threadStop();
- vfeed.stop();
- afeed.stop();
- tfeed.stop();
- subtitles->stop();
- demuxer->flush();
- state = S_FBWD;
- threadStart();
- return;
- }
- case S_STOP: // to S_STOP
- {
- vfeed.stop();
- afeed.stop();
- tfeed.stop();
- subtitles->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_JUMP_PI: // to S_JUMP_PI
- {
- audio->systemMuteOn();
- threadStop();
- vfeed.stop();
- afeed.stop();
- tfeed.stop();
- subtitles->stop();
- demuxer->flush();
- state = S_PAUSE_I;
- video->reset();
- video->play();
- restartAtFramePI(jumpFrame);
- return;
- }
- }
- }
- FALLTHROUGH // keep compiler happy (all posibilities return)
- case S_PAUSE_P: // from S_PAUSE_P -----------------------------------
- {
- switch(toState)
- {
- case S_PLAY: // to S_PLAY
- {
- video->unPause();
- audio->unPause();
-
- #ifdef VOMP_PLATFORM_RASPBERRY
- vfeed.start(false);
- #endif
-
- state = S_PLAY;
- return;
- }
- case S_PAUSE_P: // to S_PAUSE_P
- {
- return;
- }
- case S_PAUSE_I: // to S_PAUSE_I
- {
- return;
- }
- case S_FFWD: // to S_FFWD
- {
- currentFrameNumber = getCurrentFrameNum();
- audio->systemMuteOn();
- vfeed.stop();
- afeed.stop();
- tfeed.stop();
- subtitles->stop();
- threadStop();
- video->unPause();
- audio->unPause();
- state = S_FFWD;
- threadStart();
- return;
- }
- case S_FBWD: // to S_FBWD
- {
- currentFrameNumber = getCurrentFrameNum();
- audio->systemMuteOn();
- vfeed.stop();
- afeed.stop();
- tfeed.stop();
- subtitles->stop();
- threadStop();
- video->unPause();
- audio->unPause();
- state = S_FBWD;
- threadStart();
- return;
- }
- case S_STOP: // to S_STOP
- {
- vfeed.stop();
- afeed.stop();
- tfeed.stop();
- subtitles->stop();
- threadStop();
- video->stop();
- video->blank();
- audio->stop();
- video->reset();
- audio->unPause();
- demuxer->reset();
- audio->systemMuteOff();
- state = S_STOP;
- return;
- }
- case S_JUMP: // to S_JUMP
- {
- state = S_PLAY;
- audio->systemMuteOn();
- audio->unPause();
- restartAtFrame(jumpFrame);
- return;
- }
- case S_JUMP_PI: // to S_JUMP_PI
- {
- audio->systemMuteOn();
- audio->unPause();
- threadStop();
- vfeed.stop();
- afeed.stop();
- tfeed.stop();
- subtitles->stop();
- demuxer->flush();
- state = S_PAUSE_I;
- video->reset();
- video->play();
- restartAtFramePI(jumpFrame);
- return;
- }
- }
- }
- FALLTHROUGH // keep compiler happy (all posibilities return)
- case S_PAUSE_I: // from S_PAUSE_I -----------------------------------
- {
- switch(toState)
- {
- case S_PLAY: // to S_PLAY
- {
- state = S_PLAY;
- restartAtFrame(currentFrameNumber);
- return;
- }
- case S_PAUSE_P: // to S_PAUSE_P
- {
- return;
- }
- case S_PAUSE_I: // to S_PAUSE_I
- {
- return;
- }
- case S_FFWD: // to S_FFWD
- {
- state = S_FFWD;
- threadStart();
- return;
- }
- case S_FBWD: // to S_FBWD
- {
- state = S_FBWD;
- threadStart();
- return;
- }
- case S_STOP: // to S_STOP
- {
- video->stop();
- video->blank();
- audio->stop();
- video->reset();
- demuxer->reset();
- audio->systemMuteOff();
- state = S_STOP;
- return;
- }
- case S_JUMP: // to S_JUMP
- {
- state = S_PLAY;
- restartAtFrame(jumpFrame);
- return;
- }
- case S_JUMP_PI: // to S_JUMP_PI
- {
- restartAtFramePI(jumpFrame);
- return;
- }
- }
- }
- FALLTHROUGH // keep compiler happy (all posibilities return)
- case S_FFWD: // from S_FFWD -----------------------------------
- {
- switch(toState)
- {
- case S_PLAY: // to S_PLAY
- {
- state = S_PLAY;
- ULONG stepback = static_cast<ULONG>(USER_RESPONSE_TIME * ifactor * fps / 1000);
- if (stepback < currentFrameNumber)
- currentFrameNumber -= stepback;
- else
- currentFrameNumber = 0;
- restartAtFrame(currentFrameNumber);
- return;
- }
- case S_PAUSE_P: // to S_PAUSE_P
- {
- // can't occur
- return;
- }
- case S_PAUSE_I: // to S_PAUSE_I
- {
- threadStop();
- state = S_PAUSE_I;
- 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_JUMP_PI: // to S_JUMP_PI
- {
- threadStop();
- state = S_PAUSE_I;
- restartAtFramePI(jumpFrame);
- return;
- }
- }
- }
- FALLTHROUGH // keep compiler happy (all posibilities return)
- case S_FBWD: // from S_FBWD -----------------------------------
- {
- switch(toState)
- {
- case S_PLAY: // to S_PLAY
- {
- state = S_PLAY;
- restartAtFrame(currentFrameNumber);
- return;
- }
- case S_PAUSE_P: // to S_PAUSE_P
- {
- // can't occur
- return;
- }
- case S_PAUSE_I: // to S_PAUSE_I
- {
- threadStop();
- state = S_PAUSE_I;
- 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_JUMP_PI: // to S_JUMP_PI
- {
- threadStop();
- state = S_PAUSE_I;
- restartAtFramePI(jumpFrame);
- return;
- }
- }
- }
- FALLTHROUGH // keep compiler happy (all posibilities return)
- case S_STOP: // from S_STOP -----------------------------------
- {
- switch(toState)
- {
- case S_PLAY: // to S_PLAY
- {
- startup = true;
-
- audio->reset();
- audio->setStreamType(Audio::MPEG2_PES);
- audio->systemMuteOff();
- video->reset();
- demuxer->reset();
- // FIXME use restartAtFrame here?
- if (currentFrameNumber > lengthFrames) currentFrameNumber = 0;
- demuxer->setFrameNum(currentFrameNumber);
- demuxer->seek();
- videoStartup = true;
- state = S_PLAY;
- threadStart();
- logger->log("Player", Log::DEBUG, "Immediate play");
- afeed.start();
- vfeed.start();
- tfeed.start();
- subtitles->start();
- video->sync();
- audio->sync();
- audio->play();
- video->pause();
- return;
- }
- case S_PAUSE_P: // to S_PAUSE_P
- {
- return;
- }
- case S_PAUSE_I: // to S_PAUSE_I
- {
- 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_PI: // to S_JUMP_PI
- {
- return;
- }
- }
- }
- // case S_JUMP cannot be a start state because it auto flips to play
- // case S_JUMP_PI cannot be a start state because it auto flips to S_PAUSE_I
- }
-}
-
-// ----------------------------------- Internal functions
-
-void Player::lock()
-{
-#ifndef WIN32
- pthread_mutex_lock(&mutex);
- logger->log("Player", Log::DEBUG, "LOCKED");
-
-#else
- WaitForSingleObject(mutex, INFINITE);
-#endif
-}
-
-void Player::unLock()
-{
-#ifndef WIN32
- logger->log("Player", Log::DEBUG, "UNLOCKING");
- pthread_mutex_unlock(&mutex);
-#else
- ReleaseMutex(mutex);
-#endif
-}
-
-void Player::restartAtFrame(ULONG newFrame)
-{
- vfeed.stop();
- afeed.stop();
- tfeed.stop();
- subtitles->stop();
- threadStop();
- video->stop();
- video->reset();
- audio->reset();
- audio->setStreamType(Audio::MPEG2_PES);
- demuxer->flush();
- demuxer->seek();
- currentFrameNumber = newFrame;
- demuxer->setFrameNum(newFrame);
- videoStartup = true;
- afeed.start();
- tfeed.start();
- vfeed.start();
- subtitles->start();
- threadStart();
- audio->play();
- video->sync();
- audio->sync();
- audio->systemMuteOff();
- audio->doMuting();
-}
-
-
-void Player::restartAtFramePI(ULONG newFrame)
-{
- ULLONG filePos;
- ULONG nextiframeNumber;
- ULONG iframeLength;
- ULONG iframeNumber;
-
- UCHAR* buffer;
- UINT amountReceived;
- UINT videoLength;
-
- // newFrame could be anywhere, go forwards to next I-Frame
- if (!vdr->getNextIFrame(newFrame, 1, &filePos, &nextiframeNumber, &iframeLength)) return;
-
- // Now step back a GOP. This ensures we go to the greatest I-Frame equal to or less than the requested frame
- vdr->getNextIFrame(nextiframeNumber, 0, &filePos, &iframeNumber, &iframeLength);
-
- buffer = vdr->getBlock(filePos, iframeLength, &amountReceived);
- 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()
-{
- logger->log("Player", Log::DEBUG, "Connection lost, sending message");
- Message* m = new Message();
- m->to = messageReceiver;
- m->from = this;
- m->message = Message::PLAYER_EVENT;
- m->parameter = Player::CONNECTION_LOST;
- messageQueue->postMessage(m);
-}
-
-// ----------------------------------- Callback
-
-void Player::call(void* caller)
-{
- if (caller == demuxer)
- {
- logger->log("Player", Log::DEBUG, "Callback from demuxer");
-
- if (video->getTVsize() == Video::ASPECT4X3)
- {
- logger->log("Player", Log::DEBUG, "TV is 4:3, ignoring aspect switching");
- return;
- }
-
- int parx,pary;
- int dxCurrentAspect = demuxer->getAspectRatio(&parx,&pary);
- if (dxCurrentAspect == Demuxer::ASPECT_4_3)
- {
- logger->log("Player", Log::DEBUG, "Demuxer said video is 4:3 aspect, switching TV");
- video->setAspectRatio(Video::ASPECT4X3,parx,pary);
-
- Message* m = new Message();
- m->from = this;
- m->to = messageReceiver;
- m->message = Message::PLAYER_EVENT;
- m->parameter = Player::ASPECT43;
- messageQueue->postMessage(m);
- }
- else if (dxCurrentAspect == Demuxer::ASPECT_16_9)
- {
- logger->log("Player", Log::DEBUG, "Demuxer said video is 16:9 aspect, switching TV");
- video->setAspectRatio(Video::ASPECT16X9,parx,pary);
-
- Message* m = new Message();
- m->from = this;
- m->to = messageReceiver;
- m->message = Message::PLAYER_EVENT;
- m->parameter = Player::ASPECT169;
- messageQueue->postMessage(m);
- }
- else
- {
- logger->log("Player", Log::DEBUG, "Demuxer said video is something else... setting it anyway");
- video->setAspectRatio(static_cast<UCHAR>(dxCurrentAspect), parx, pary);
- }
-
- }
- else
- {
- if (videoStartup)
- {
- videoStartup = false;
- video->reset();
- video->play();
- video->sync();
- vfeed.release();
- unLock();
- }
-
- 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 ((state == S_FFWD) || (state == S_FBWD))
- {
- if (video->PTSIFramePlayback()) threadPTSFeedScan();
- else 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->to = messageReceiver;
- m->from = this;
- m->message = Message::PLAYER_EVENT;
- m->parameter = STOP_PLAYBACK;
- logger->log("Player", Log::DEBUG, "Posting message to %p...", messageQueue);
- messageQueue->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();
- audio->setStreamType(Audio::MPEG2_PES);
- demuxer->flush();
- demuxer->seek();
- demuxer->setFrameNum(currentFrameNumber);
- videoStartup = true;
- afeed.start();
- tfeed.start();
- vfeed.start();
- subtitles->start();
- audio->play();
- audio->sync();
- audio->systemMuteOff();
- audio->doMuting();
- }
-
- if (state == S_PLAY) threadFeedPlay();
-}
-
-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 = static_cast<UINT>(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 = static_cast<UINT>(lengthBytes - feedPosition);
- else // normal
- askFor = blockSize;
- }
- //logger->log("Player", Log::DEBUG, "Get Block in");
-
- threadBuffer = vdr->getBlock(feedPosition, askFor, &thisRead);
- //logger->log("Player", Log::DEBUG, "Get Block out");
-
- 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();
-
- while(writeLength < thisRead)
- {
- //logger->log("Player", Log::DEBUG, "Put in");
- thisWrite = demuxer->put(threadBuffer + writeLength, thisRead - writeLength);
- //logger->log("Player", Log::DEBUG, "Put out");
- writeLength += thisWrite;
-
- if (!thisWrite)
- {
- // demuxer is full and can't take anymore
- threadLock();
- if (!threadActive) { threadUnlock(); threadCheckExit(); }
- threadWaitForSignal();
- threadUnlock();
- }
-
- threadCheckExit();
- }
-
- free(threadBuffer);
- threadBuffer = NULL;
-
- }
-
- // end of recording
- logger->log("Player", Log::DEBUG, "Recording playback ends");
-
- 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->to = messageReceiver;
- m->from = this;
- m->message = Message::PLAYER_EVENT;
- m->parameter = Player::STOP_PLAYBACK;
- logger->log("Player", Log::DEBUG, "Posting message to %p...", messageQueue);
- messageQueue->postMessage(m);
-}
-
-
-void Player::threadPTSFeedScan()
-{
- // This method manipulates the PTS instead of waiting, this is for the android devices, maybe later for windows?
-
- ULONG direction = 0;
- int dir_fac=-1;
- ULONG baseFrameNumber = 0;
- ULONG iframeNumber = 0;
- ULONG iframeLength = 0;
- ULONG currentfeedFrameNumber=currentFrameNumber;
- ULONG firstFrameNumber=currentFrameNumber;
- ULLONG filePos;
- UINT amountReceived;
- UINT videoLength;
-
- UINT playtime=0;
-
- int frameTimeOffset = 0; // Time in msec between frames
-
- if (state == S_FFWD)
- {
- direction = 1; // and 0 for backward
- dir_fac = 1;
- }
- video->EnterIframePlayback();
-
- while(1)
- {
- baseFrameNumber = currentfeedFrameNumber;
-
- threadCheckExit();
- if (!vdr->getNextIFrame(baseFrameNumber, direction, &filePos, &iframeNumber, &iframeLength))
- return;
-
- if (iframeNumber >= lengthFrames) return;
- // scan has got to the end of what we knew to be there before we started scanning
-
- baseFrameNumber = iframeNumber;
-
- frameTimeOffset =(int) ((double)(abs((int)iframeNumber - (int)currentfeedFrameNumber) * 1000) / (fps * (double)ifactor));
-
- logger->log("Player", Log::DEBUG, "XXX Got frame");
-
- threadBuffer = vdr->getBlock(filePos, iframeLength, &amountReceived);
-
- if (!vdr->isConnected())
- {
- if (threadBuffer) free(threadBuffer);
- doConnectionLost();
- break;
- }
-
-
- threadCheckExit();
-
-
- videoLength = demuxer->stripAudio(threadBuffer, amountReceived);
- demuxer->changeTimes(threadBuffer,videoLength,playtime);
- int count=0;
- while (!video->displayIFrame(threadBuffer, videoLength)) // the device might block
- {
- MILLISLEEP(20);
- threadCheckExit();
- count++;
- if (count%300==0) {
- ULLONG cur_time=video->getCurrentTimestamp();
- // logger->log("Player", Log::ERR, "FFN: %d CFN: %d dirfac %d time %lld ifac %d fps %g",
- // firstFrameNumber, currentFrameNumber,dir_fac,cur_time,ifactor,fps);
- if (cur_time!=0) {
- currentFrameNumber=firstFrameNumber+(int)(((double)(dir_fac*((long long)cur_time)*((int)ifactor))*fps/90000.));
- }
- }
-
- }
- playtime +=frameTimeOffset;
- currentfeedFrameNumber = iframeNumber;
- {
- ULLONG cur_time=video->getCurrentTimestamp();
- // logger->log("Player", Log::ERR, "FFN: %d CFN: %d dirfac %d time %lld ifac %d fps %g",
- // firstFrameNumber, currentFrameNumber,dir_fac,cur_time,ifactor,fps);
- if (cur_time!=0) {
- currentFrameNumber=firstFrameNumber+(int)(((double)(dir_fac*((long long)cur_time)*((int)ifactor))*fps/90000.));
- }
- }
-
- free(threadBuffer);
- threadBuffer = NULL;
- }
-}
-
-
-
-void Player::threadFeedScan()
-{
- // This method is actually really simple - get frame from vdr,
- // spit it at the video chip, wait for a time. Most of the code here
- // is to get the wait right so that the scan occurs at the correct rate.
-
- ULONG direction = 0;
- ULONG baseFrameNumber = 0;
- ULONG iframeNumber = 0;
- ULONG iframeLength = 0;
- ULLONG filePos;
- UINT amountReceived;
- UINT videoLength;
-
-#ifndef WIN32
- struct timeval clock0 = {0,0}; // Time stamp after fetching I-frame info
- struct timeval clock1 = {0,0}; // Time stamp after fetching I-frame data
- struct timeval clock2 = {0,0} ; // Time stamp after displaying I-frame
-#else
- DWORD clock0 = 0, clock1 = 0, clock2 = 0;
-#endif
-
- int frameTimeOffset = 0; // Time in msec between frames
- int disp_msec = 0; // Time taken to display data
- int total_msec = 0; // Time taken to fetch data and display it
- int sleepTime = 0;
-
- if (state == S_FFWD) direction = 1; // and 0 for backward
-
- while(1)
- {
- // Fetch I-frames until we get one that can be displayed in good time
- // Repeat while clock0 + total_msec > clock2 + frameTimeOffset
-
- baseFrameNumber = currentFrameNumber;
- do
- {
- threadCheckExit();
- if (!vdr->getNextIFrame(baseFrameNumber, direction, &filePos, &iframeNumber, &iframeLength))
- return;
-
- if (iframeNumber >= lengthFrames) return;
- // scan has got to the end of what we knew to be there before we started scanning
-
- baseFrameNumber = iframeNumber;
- frameTimeOffset =(int) ((double)(abs((int)iframeNumber - (int)currentFrameNumber) * 1000) / (fps * (double)ifactor));
-#ifndef WIN32
- gettimeofday(&clock0, NULL);
-#else
- clock0 = timeGetTime();
-#endif
- }
-#ifndef WIN32
- while (clock2.tv_sec != 0 &&
- (clock0.tv_sec - clock2.tv_sec) * 1000 +
- (clock0.tv_usec - clock2.tv_usec) / 1000 > frameTimeOffset - total_msec);
-#else
- while (clock2 != 0 && clock0 + total_msec > clock2 + frameTimeOffset);
-#endif
- logger->log("Player", Log::DEBUG, "XXX Got frame");
-
- threadBuffer = vdr->getBlock(filePos, iframeLength, &amountReceived);
-
- if (!vdr->isConnected() || !amountReceived)
- {
- if (threadBuffer) free(threadBuffer);
- doConnectionLost();
- break;
- }
-
-#ifndef WIN32
- gettimeofday(&clock1, NULL);
- if (clock2.tv_sec != 0)
- sleepTime = (clock2.tv_sec - clock1.tv_sec) * 1000
- + (clock2.tv_usec - clock1.tv_usec) / 1000
- + frameTimeOffset - disp_msec;
-#else
- clock1 = timeGetTime();
- if (clock2 != 0)
- sleepTime = clock2 + frameTimeOffset - disp_msec - clock1;
-#endif
- if (sleepTime < 0) sleepTime = 0;
- threadCheckExit();
- MILLISLEEP(sleepTime);
- logger->log("Player", Log::DEBUG, "XXX Slept for %d", sleepTime);
-
- videoLength = demuxer->stripAudio(threadBuffer, amountReceived);
- video->displayIFrame(threadBuffer, videoLength);
- currentFrameNumber = iframeNumber;
- free(threadBuffer);
- threadBuffer = NULL;
-
-#ifndef WIN32
- gettimeofday(&clock2, NULL);
- total_msec = (clock2.tv_sec - clock0.tv_sec) * 1000
- + (clock2.tv_usec - clock0.tv_usec) / 1000
- - sleepTime;
- disp_msec = (clock2.tv_sec - clock1.tv_sec) * 1000
- + (clock2.tv_usec - clock1.tv_usec) / 1000
- - sleepTime;
-#else
- clock2 = timeGetTime();
- total_msec = clock2 - clock0 - sleepTime;
- disp_msec = clock2 - clock1 - sleepTime;
-#endif
- logger->log("Player", Log::DEBUG, "XXX disp_msec = %4d total_msec = %4d", disp_msec, total_msec);
- }
-}
-
-void Player::threadPostStopCleanup()
-{
- if (threadBuffer)
- {
- free(threadBuffer);
- threadBuffer = NULL;
- }
-}
-
-// ----------------------------------- Dev
-
-#ifdef DEV
-void Player::test1()
-{
- logger->log("Player", Log::DEBUG, "PLAYER TEST 1");
-}
-
-void Player::test2()
-{
- logger->log("Player", Log::DEBUG, "PLAYER TEST 2");
-}
-#endif
+++ /dev/null
-/*
- Copyright 2004-2008 Chris Tallon
-
- This file is part of VOMP.
-
- VOMP is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- VOMP is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- 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.
-*/
-
-#ifndef PLAYER_H
-#define PLAYER_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef WIN32
-#include <sys/time.h>
-#endif
-#include <time.h>
-
-#include "threadsystem.h"
-
-#include "callback.h"
-#include "defines.h"
-#include "vfeed.h"
-#include "afeed.h"
-#include "tfeed.h"
-
-#include "teletextdecodervbiebu.h"
-
-class MessageQueue;
-class Audio;
-class Video;
-class VDR;
-class Log;
-class Demuxer;
-class OSDReceiver;
-class DVBSubtitles;
-class Channel;
-
-class Player : public Thread_TYPE, public Callback
-{
- public:
- Player(MessageQueue* messageQueue, void* messageReceiver, OSDReceiver* osdReceiver);
- virtual ~Player();
-
- int init(bool p_isPesRecording,double framespersec);
- int shutdown();
- void setStartFrame(ULONG frameNum);
- void setLengthBytes(ULLONG length);
- void setLengthFrames(ULONG length);
- void setAudioChannel(int newChannel, int type, int streamtype);
- void setSubtitleChannel(int newChannel);
- bool toggleSubtitles();
- void turnSubtitlesOn(bool ison);
- bool isSubtitlesOn() { return subtitlesShowing; }
- void tellSubtitlesOSDVisible(bool visible);
-
- void play();
- void stop();
- void pause();
- void playpause();
- void fastForward();
- void fastBackward();
- void jumpToPercent(double percent);
- void skipForward(int seconds);
- void skipBackward(int seconds);
- void jumpToMark(int mark);
- void jumpToFrameP(int newFrame);
-
- UCHAR getState() { return state; }
- ULONG getCurrentFrameNum();
- ULONG getLengthFrames();
- UCHAR getIScanRate() { return ifactor; }
- bool* getDemuxerMpegAudioChannels();
- bool* getDemuxerAc3AudioChannels();
- bool* getDemuxerSubtitleChannels();
- int *getTeletxtSubtitlePages();
- int getCurrentAudioChannel();
- int getCurrentSubtitleChannel();
- bool isPesRecording() { return is_pesrecording; }
- Channel *getDemuxerChannel();
-
- TeletextDecoderVBIEBU * getTeletextDecoder() { return teletext; }
-
- void call(void*); // for callback interface
-
- const static UCHAR S_PLAY = 1;
- const static UCHAR S_PAUSE_P = 2;
- const static UCHAR S_PAUSE_I = 3;
- const static UCHAR S_FFWD = 4;
- const static UCHAR S_FBWD = 5;
- const static UCHAR S_STOP = 6;
- const static UCHAR S_JUMP = 7;
- const static UCHAR S_JUMP_PI = 8; // Jump to Pause_I mode
-
- // Player events
-
- // FIXME so far this just duplicates the old system + the wss
-
- const static UCHAR CONNECTION_LOST = 1;
- const static UCHAR STOP_PLAYBACK = 2;
- const static UCHAR STREAM_END = 3;
- const static UCHAR ASPECT43 = 4;
- const static UCHAR ASPECT169 = 5;
-
-#ifdef DEV
- void test1();
- void test2();
-#endif
-
- protected:
- void threadMethod();
- void threadPostStopCleanup();
-
- private:
- void switchState(UCHAR newState, ULONG jumpFrame=0);
-
- void threadFeedPlay();
- void threadFeedScan();
- void threadPTSFeedScan();
-
- void doConnectionLost();
- void restartAtFrame(ULONG newFrame);
- void restartAtFramePI(ULONG newFrame);
-
- bool subtitlesShowing{};
- MessageQueue* messageQueue;
- void* messageReceiver;
- OSDReceiver* osdReceiver;
- Log* logger;
- Audio* audio;
- Video* video;
- Demuxer* demuxer;
- DVBSubtitles* subtitles;
- VDR* vdr;
- VFeed vfeed;
- AFeed afeed;
- TFeed tfeed;
- TeletextDecoderVBIEBU *teletext;
-
-
-
- bool initted{};
- bool startup;
- bool videoStartup{};
-
- bool is_pesrecording{true};
- double fps;
-
-#ifndef WIN32
- pthread_mutex_t mutex;
-#else
- HANDLE mutex;
-#endif
- void lock();
- void unLock();
-
- ULLONG lengthBytes{};
- ULONG lengthFrames{};
- ULONG currentFrameNumber{};
- UINT blockSize{100000};
- UINT startupBlockSize{250000};
- UCHAR* threadBuffer{};
- UCHAR state{S_STOP};
- UCHAR ifactor{4}; // 4, 8, 16, 32
-};
-
-#endif
-
-
-/*
-
-Possible states:
-
-Play, Pause, FFwd, FBwd, (Stop), [Jump]
-
- Possible Working
-
-Play -> PauseP * *
- -> PauseI
- -> FFwd * *
- -> FBwd * *
- -> Stop * *
- -> Jump * *
- -> Jump_PI * *
-
-PauseP -> Play * *
- -> PauseI
- -> FFwd * *
- -> FBwd * *
- -> Stop * *
- -> Jump * *
- -> Jump_PI * *
-
-PauseI -> Play * *
- -> PauseP
- -> FFwd * *
- -> FBwd * *
- -> Stop * *
- -> Jump * *
- -> Jump_PI * *
-
-FFwd -> Play * *
- -> PauseP
- -> PauseI * *
- -> FBwd * *
- -> Stop * *
- -> Jump * *
- -> Jump_PI * *
-
-FBwd -> Play * *
- -> PauseP
- -> PauseI * *
- -> FFwd * *
- -> Stop * *
- -> Jump * *
- -> Jump_PI * *
-
-Stop -> Play * *
- -> PauseP
- -> PauseI
- -> FFwd
- -> FBwd
- -> Jump
- -> Jump_PI
-
-*/
const static UCHAR S_PLAY = 1;
const static UCHAR S_PAUSE_P = 2;
+ const static UCHAR S_PAUSE_I = 3;
const static UCHAR S_STOP = 6;
const static UCHAR S_JUMP = 7;
--- /dev/null
+/*
+ Copyright 2004-2008 Chris Tallon
+
+ This file is part of VOMP.
+
+ VOMP is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ VOMP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with VOMP. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "log.h"
+#include "audio.h"
+#include "video.h"
+#include "demuxervdr.h"
+#include "demuxerts.h"
+#include "vdr.h"
+#include "messagequeue.h"
+#include "input.h"
+#include "message.h"
+#include "dvbsubtitles.h"
+#include "osdreceiver.h"
+
+#include "playervideorec.h"
+
+#define USER_RESPONSE_TIME 500 // Milliseconds
+
+// ----------------------------------- Called from outside, one offs or info funcs
+
+PlayerVideoRec::PlayerVideoRec(MessageQueue* tmessageQueue, void* tmessageReceiver, OSDReceiver* tosdReceiver)
+: vfeed(this), afeed(this), tfeed(this), messageQueue(tmessageQueue),
+ messageReceiver(tmessageReceiver), osdReceiver(tosdReceiver)
+{
+ audio = Audio::getInstance();
+ video = Video::getInstance();
+ logger = Log::getInstance();
+ vdr = VDR::getInstance();
+
+ video->turnVideoOn();
+}
+
+PlayerVideoRec::~PlayerVideoRec()
+{
+ if (initted) shutdown();
+}
+
+int PlayerVideoRec::init(bool p_isPesRecording, double framespersecond)
+{
+ if (initted) return 0;
+ is_pesrecording = p_isPesRecording;
+ fps = framespersecond;
+ if (is_pesrecording)
+ demuxer = new DemuxerVDR();
+ else
+ demuxer = new DemuxerTS();
+ if (!demuxer) return 0;
+ subtitles = new DVBSubtitles(osdReceiver);
+ if (!subtitles) return 0;
+
+ teletext = new TeletextDecoderVBIEBU();
+ if (!teletext) return 0;
+ teletext->setRecordigMode(true);
+ unsigned int demux_video_size = 2097152;
+ unsigned int demux_audio_size = 524288;
+ if (video->supportsh264())
+ {
+ demux_video_size *= 5 * 2;
+ }
+ if (audio->maysupportAc3())
+ {
+ //demux_audio_size*=2;
+ }
+
+ if (!demuxer->init(this, audio, video,teletext, demux_video_size,demux_audio_size,65536, framespersecond, subtitles))
+ {
+ logger->log("Player", Log::ERR, "Demuxer failed to init");
+ shutdown();
+ return 0;
+ }
+
+ vfeed.init();
+ afeed.init();
+ tfeed.init();
+
+ video->stop();
+ video->blank();
+ audio->stop();
+
+ if (Command::getInstance()->getSubDefault())
+ turnSubtitlesOn(true);
+ else
+ turnSubtitlesOn(false);
+
+ initted = true;
+ return 1;
+}
+
+int PlayerVideoRec::shutdown()
+{
+ if (!initted) return 0;
+ switchState(S_STOP);
+ initted = false;
+
+ delete demuxer;
+ demuxer = NULL;
+ delete subtitles;
+ subtitles = NULL;
+ delete teletext;
+ teletext = NULL;
+
+ return 1;
+}
+
+void PlayerVideoRec::setStartFrame(ULONG startFrame)
+{
+ ULONG nextiframeNumber;
+ ULONG iframeLength;
+ ULONG iframeNumber;
+ ULLONG filePos;
+
+ // newFrame could be anywhere, go forwards to next I-Frame
+ if (!vdr->getNextIFrame(startFrame, 1, &filePos, &nextiframeNumber, &iframeLength)) return;
+
+ // Now step back a GOP. This ensures we go to the greatest I-Frame equal to or less than the requested frame
+ vdr->getNextIFrame(nextiframeNumber, 0, &filePos, &iframeNumber, &iframeLength);
+
+ logger->log("Player", Log::DEBUG, "setStartFrame %lu %lu %lu", startFrame, nextiframeNumber,iframeNumber);
+ currentFrameNumber = iframeNumber;
+}
+
+void PlayerVideoRec::setLengthBytes(ULLONG length)
+{
+ lengthBytes = length;
+ logger->log("Player", Log::DEBUG, "Player has received length bytes of %llu", lengthBytes);
+}
+
+void PlayerVideoRec::setLengthFrames(ULONG length)
+{
+ lengthFrames = length;
+ logger->log("Player", Log::DEBUG, "Player has received length frames of %lu", lengthFrames);
+}
+
+ULONG PlayerVideoRec::getLengthFrames()
+{
+ return lengthFrames;
+}
+
+ULONG PlayerVideoRec::getCurrentFrameNum()
+{
+ if (startup) return 0;
+ switch(state)
+ {
+ case S_PLAY:
+ case S_PAUSE_P:
+ return demuxer->getFrameNumFromPTS(video->getCurrentTimestamp());
+ case S_PAUSE_I:
+ case S_FFWD:
+ case S_FBWD:
+ return currentFrameNumber;
+ default:
+ return 0; // shouldn't happen
+ }
+}
+
+bool* PlayerVideoRec::getDemuxerMpegAudioChannels()
+{
+ return demuxer->getmpAudioChannels();
+}
+
+bool* PlayerVideoRec::getDemuxerAc3AudioChannels()
+{
+ return demuxer->getac3AudioChannels();
+}
+
+bool* PlayerVideoRec::getDemuxerSubtitleChannels()
+{
+ return demuxer->getSubtitleChannels();
+}
+
+int PlayerVideoRec::getCurrentAudioChannel()
+{
+ if (is_pesrecording)
+ return demuxer->getselAudioChannel();
+ else
+ return dynamic_cast<DemuxerTS*>(demuxer)->getAID();
+}
+
+int PlayerVideoRec::getCurrentSubtitleChannel()
+{
+ if (is_pesrecording)
+ return demuxer->getselSubtitleChannel();
+ else
+ return dynamic_cast<DemuxerTS*>(demuxer)->getSubID();
+}
+
+void PlayerVideoRec::setSubtitleChannel(int newChannel)
+{
+ if (is_pesrecording)
+ demuxer->setDVBSubtitleStream(newChannel);
+ else
+ dynamic_cast<DemuxerTS*>(demuxer)->setSubID(newChannel);
+}
+
+int *PlayerVideoRec::getTeletxtSubtitlePages()
+{
+ return teletext->getSubtitlePages();
+}
+
+void PlayerVideoRec::setAudioChannel(int newChannel, int type, int streamtype)
+{
+ if (is_pesrecording)
+ {
+ demuxer->setAudioStream(newChannel);
+ return;
+ }
+ else
+ {
+ dynamic_cast<DemuxerTS*>(demuxer)->setAID(newChannel,type,streamtype,false);
+ return;
+ }
+}
+
+bool PlayerVideoRec::toggleSubtitles()
+{
+ if (!subtitlesShowing)
+ {
+ subtitlesShowing = true;
+ subtitles->show();
+ }
+ else
+ {
+ subtitlesShowing = false;
+ subtitles->hide();
+ }
+ return subtitlesShowing;
+}
+
+void PlayerVideoRec::turnSubtitlesOn(bool ison)
+{
+ if (ison)
+ {
+ subtitlesShowing = true;
+ subtitles->show();
+ }
+ else
+ {
+ subtitlesShowing = false;
+ subtitles->hide();
+ }
+}
+
+void PlayerVideoRec::tellSubtitlesOSDVisible(bool visible)
+{
+ subtitles->setOSDMenuVisibility(visible);
+}
+
+Channel * PlayerVideoRec::getDemuxerChannel()
+{
+ if (!is_pesrecording)
+ {
+ return dynamic_cast<DemuxerTS*>(demuxer)->getChannelInfo();
+ }
+ return NULL; //Should not happen!
+}
+
+
+// ----------------------------------- Externally called events
+
+void PlayerVideoRec::play()
+{
+ if (!initted) return;
+ if (state == S_PLAY) return;
+ stateMutex.lock();
+
+ bool doUnlock = false;
+ if (state == S_PAUSE_P) doUnlock = true;
+ switchState(S_PLAY);
+ if (doUnlock) stateMutex.unlock();
+}
+
+void PlayerVideoRec::playpause()
+{
+ if (!initted) return;
+ stateMutex.lock();
+
+ bool doUnlock = false;
+ if (state==S_PLAY)
+ {
+ doUnlock=true;
+ switchState(S_PAUSE_P);
+ }
+ else
+ {
+ if (state == S_PAUSE_P) doUnlock = true;
+ switchState(S_PLAY);
+ }
+ if (doUnlock) stateMutex.unlock();
+}
+
+void PlayerVideoRec::stop()
+{
+ if (!initted) return;
+ if (state == S_STOP) return;
+ stateMutex.lock();
+ logger->log("Player", Log::DEBUG, "Stop called lock");
+ switchState(S_STOP);
+ stateMutex.unlock();
+}
+
+void PlayerVideoRec::pause()
+{
+ if (!initted) return;
+ stateMutex.lock();
+
+ if ((state == S_FFWD) || (state == S_FBWD))
+ {
+ switchState(S_PAUSE_I);
+ }
+ else if ((state == S_PAUSE_I) || (state == S_PAUSE_P))
+ {
+ switchState(S_PLAY);
+ }
+ else
+ {
+ switchState(S_PAUSE_P);
+ }
+
+ stateMutex.unlock();
+}
+
+void PlayerVideoRec::fastForward()
+{
+ if (!initted) return;
+ stateMutex.lock();
+
+ if (state == S_FFWD)
+ {
+ // change the rate
+ switch(ifactor)
+ {
+ case 4: ifactor = 8; break;
+ case 8: ifactor = 16; break;
+ case 16: ifactor = 32; break;
+ case 32: ifactor = 4; break;
+ }
+ }
+ else
+ {
+ ifactor = 4;
+ switchState(S_FFWD);
+ }
+ stateMutex.unlock();
+}
+
+void PlayerVideoRec::fastBackward()
+{
+ if (!initted) return;
+ stateMutex.lock();
+
+ if (state == S_FBWD)
+ {
+ // change the rate
+ switch(ifactor)
+ {
+ case 4: ifactor = 8; break;
+ case 8: ifactor = 16; break;
+ case 16: ifactor = 32; break;
+ case 32: ifactor = 4; break;
+ }
+ }
+ else
+ {
+ ifactor = 4;
+ switchState(S_FBWD);
+ }
+ stateMutex.unlock();
+}
+
+void PlayerVideoRec::jumpToPercent(double percent)
+{
+ stateMutex.lock();
+ logger->log("Player", Log::DEBUG, "JUMP TO %f%%", percent);
+ ULONG newFrame = static_cast<ULONG>(percent * lengthFrames / 100);
+ switchState(S_JUMP, newFrame);
+// stateMutex.unlock(); - let thread unlock this
+}
+
+void PlayerVideoRec::jumpToMark(int mark)
+{
+ stateMutex.lock();
+ logger->log("Player", Log::DEBUG, "JUMP TO MARK %i%%", mark);
+ switchState(S_JUMP, mark);
+// stateMutex.unlock(); - let thread unlock this
+}
+
+void PlayerVideoRec::jumpToFrameP(int newFrame)
+{
+ stateMutex.lock();
+ logger->log("Player", Log::DEBUG, "JUMP TO FRAME AND PAUSE %i", newFrame);
+ switchState(S_JUMP_PI, newFrame);
+ stateMutex.unlock();
+}
+
+void PlayerVideoRec::skipForward(int seconds)
+{
+ stateMutex.lock();
+ logger->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
+ ULONG newFrame = getCurrentFrameNum();
+ if (newFrame == 0) { stateMutex.unlock(); return; } // Current pos from demuxer is not valid
+ newFrame += static_cast<ULONG>(static_cast<double>(seconds) * fps);
+ if (newFrame > lengthFrames) { switchState(S_PLAY); stateMutex.unlock(); }
+ else switchState(S_JUMP, newFrame);
+// stateMutex.unlock(); - let thread unlock this
+}
+
+void PlayerVideoRec::skipBackward(int seconds)
+{
+ stateMutex.lock();
+ logger->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
+ long newFrame = getCurrentFrameNum();
+ if (newFrame == 0) { stateMutex.unlock(); return; } // Current pos from demuxer is not valid
+ newFrame -= static_cast<ULONG>(static_cast<double>(seconds) * fps);
+ if (newFrame < 0) newFrame = 0;
+ switchState(S_JUMP, newFrame);
+// stateMutex.unlock(); - let thread unlock this
+}
+
+// ----------------------------------- Implementations called events
+
+void PlayerVideoRec::switchState(UCHAR toState, ULONG jumpFrame)
+{
+ if (!initted) return;
+
+ logger->log("Player", Log::DEBUG, "Switch state from %u to %u", state, toState);
+
+ switch(state) // current state selector
+ {
+ case S_PLAY: // from S_PLAY -----------------------------------
+ {
+ switch(toState)
+ {
+ case S_PLAY: // to S_PLAY
+ {
+ return;
+ }
+ case S_PAUSE_P: // to S_PAUSE_P
+ {
+ #ifdef VOMP_PLATFORM_RASPBERRY
+ vfeed.stop(); // can't vfeed during pause
+ #endif
+
+ video->pause();
+ audio->pause();
+ state = S_PAUSE_P;
+ return;
+ }
+ case S_PAUSE_I: // to S_PAUSE_I
+ {
+ // can't occur
+ return;
+ }
+ case S_FFWD: // to S_FFWD
+ {
+ currentFrameNumber = getCurrentFrameNum();
+ audio->systemMuteOn();
+ threadStop();
+ vfeed.stop();
+ afeed.stop();
+ tfeed.stop();
+ subtitles->stop();
+ demuxer->flush();
+ state = S_FFWD;
+ threadStart();
+ return;
+ }
+ case S_FBWD: // to S_FBWD
+ {
+ currentFrameNumber = getCurrentFrameNum();
+ audio->systemMuteOn();
+ threadStop();
+ vfeed.stop();
+ afeed.stop();
+ tfeed.stop();
+ subtitles->stop();
+ demuxer->flush();
+ state = S_FBWD;
+ threadStart();
+ return;
+ }
+ case S_STOP: // to S_STOP
+ {
+ vfeed.stop();
+ afeed.stop();
+ tfeed.stop();
+ subtitles->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_JUMP_PI: // to S_JUMP_PI
+ {
+ audio->systemMuteOn();
+ threadStop();
+ vfeed.stop();
+ afeed.stop();
+ tfeed.stop();
+ subtitles->stop();
+ demuxer->flush();
+ state = S_PAUSE_I;
+ video->reset();
+ video->play();
+ restartAtFramePI(jumpFrame);
+ return;
+ }
+ }
+ }
+ FALLTHROUGH // keep compiler happy (all posibilities return)
+ case S_PAUSE_P: // from S_PAUSE_P -----------------------------------
+ {
+ switch(toState)
+ {
+ case S_PLAY: // to S_PLAY
+ {
+ video->unPause();
+ audio->unPause();
+
+ #ifdef VOMP_PLATFORM_RASPBERRY
+ vfeed.start(false);
+ #endif
+
+ state = S_PLAY;
+ return;
+ }
+ case S_PAUSE_P: // to S_PAUSE_P
+ {
+ return;
+ }
+ case S_PAUSE_I: // to S_PAUSE_I
+ {
+ return;
+ }
+ case S_FFWD: // to S_FFWD
+ {
+ currentFrameNumber = getCurrentFrameNum();
+ audio->systemMuteOn();
+ vfeed.stop();
+ afeed.stop();
+ tfeed.stop();
+ subtitles->stop();
+ threadStop();
+ video->unPause();
+ audio->unPause();
+ state = S_FFWD;
+ threadStart();
+ return;
+ }
+ case S_FBWD: // to S_FBWD
+ {
+ currentFrameNumber = getCurrentFrameNum();
+ audio->systemMuteOn();
+ vfeed.stop();
+ afeed.stop();
+ tfeed.stop();
+ subtitles->stop();
+ threadStop();
+ video->unPause();
+ audio->unPause();
+ state = S_FBWD;
+ threadStart();
+ return;
+ }
+ case S_STOP: // to S_STOP
+ {
+ vfeed.stop();
+ afeed.stop();
+ tfeed.stop();
+ subtitles->stop();
+ threadStop();
+ video->stop();
+ video->blank();
+ audio->stop();
+ video->reset();
+ audio->unPause();
+ demuxer->reset();
+ audio->systemMuteOff();
+ state = S_STOP;
+ return;
+ }
+ case S_JUMP: // to S_JUMP
+ {
+ state = S_PLAY;
+ audio->systemMuteOn();
+ audio->unPause();
+ restartAtFrame(jumpFrame);
+ return;
+ }
+ case S_JUMP_PI: // to S_JUMP_PI
+ {
+ audio->systemMuteOn();
+ audio->unPause();
+ threadStop();
+ vfeed.stop();
+ afeed.stop();
+ tfeed.stop();
+ subtitles->stop();
+ demuxer->flush();
+ state = S_PAUSE_I;
+ video->reset();
+ video->play();
+ restartAtFramePI(jumpFrame);
+ return;
+ }
+ }
+ }
+ FALLTHROUGH // keep compiler happy (all posibilities return)
+ case S_PAUSE_I: // from S_PAUSE_I -----------------------------------
+ {
+ switch(toState)
+ {
+ case S_PLAY: // to S_PLAY
+ {
+ state = S_PLAY;
+ restartAtFrame(currentFrameNumber);
+ return;
+ }
+ case S_PAUSE_P: // to S_PAUSE_P
+ {
+ return;
+ }
+ case S_PAUSE_I: // to S_PAUSE_I
+ {
+ return;
+ }
+ case S_FFWD: // to S_FFWD
+ {
+ state = S_FFWD;
+ threadStart();
+ return;
+ }
+ case S_FBWD: // to S_FBWD
+ {
+ state = S_FBWD;
+ threadStart();
+ return;
+ }
+ case S_STOP: // to S_STOP
+ {
+ video->stop();
+ video->blank();
+ audio->stop();
+ video->reset();
+ demuxer->reset();
+ audio->systemMuteOff();
+ state = S_STOP;
+ return;
+ }
+ case S_JUMP: // to S_JUMP
+ {
+ state = S_PLAY;
+ restartAtFrame(jumpFrame);
+ return;
+ }
+ case S_JUMP_PI: // to S_JUMP_PI
+ {
+ restartAtFramePI(jumpFrame);
+ return;
+ }
+ }
+ }
+ FALLTHROUGH // keep compiler happy (all posibilities return)
+ case S_FFWD: // from S_FFWD -----------------------------------
+ {
+ switch(toState)
+ {
+ case S_PLAY: // to S_PLAY
+ {
+ state = S_PLAY;
+ ULONG stepback = static_cast<ULONG>(USER_RESPONSE_TIME * ifactor * fps / 1000);
+ if (stepback < currentFrameNumber)
+ currentFrameNumber -= stepback;
+ else
+ currentFrameNumber = 0;
+ restartAtFrame(currentFrameNumber);
+ return;
+ }
+ case S_PAUSE_P: // to S_PAUSE_P
+ {
+ // can't occur
+ return;
+ }
+ case S_PAUSE_I: // to S_PAUSE_I
+ {
+ threadStop();
+ state = S_PAUSE_I;
+ 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_JUMP_PI: // to S_JUMP_PI
+ {
+ threadStop();
+ state = S_PAUSE_I;
+ restartAtFramePI(jumpFrame);
+ return;
+ }
+ }
+ }
+ FALLTHROUGH // keep compiler happy (all posibilities return)
+ case S_FBWD: // from S_FBWD -----------------------------------
+ {
+ switch(toState)
+ {
+ case S_PLAY: // to S_PLAY
+ {
+ state = S_PLAY;
+ restartAtFrame(currentFrameNumber);
+ return;
+ }
+ case S_PAUSE_P: // to S_PAUSE_P
+ {
+ // can't occur
+ return;
+ }
+ case S_PAUSE_I: // to S_PAUSE_I
+ {
+ threadStop();
+ state = S_PAUSE_I;
+ 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_JUMP_PI: // to S_JUMP_PI
+ {
+ threadStop();
+ state = S_PAUSE_I;
+ restartAtFramePI(jumpFrame);
+ return;
+ }
+ }
+ }
+ FALLTHROUGH // keep compiler happy (all posibilities return)
+ case S_STOP: // from S_STOP -----------------------------------
+ {
+ switch(toState)
+ {
+ case S_PLAY: // to S_PLAY
+ {
+ startup = true;
+
+ audio->reset();
+ audio->setStreamType(Audio::MPEG2_PES);
+ audio->systemMuteOff();
+ video->reset();
+ demuxer->reset();
+ // FIXME use restartAtFrame here?
+ if (currentFrameNumber > lengthFrames) currentFrameNumber = 0;
+ demuxer->setFrameNum(currentFrameNumber);
+ demuxer->seek();
+ videoStartup = true;
+ state = S_PLAY;
+ threadStart();
+ logger->log("Player", Log::DEBUG, "Immediate play");
+ afeed.start();
+ vfeed.start();
+ tfeed.start();
+ subtitles->start();
+ video->sync();
+ audio->sync();
+ audio->play();
+ video->pause();
+ return;
+ }
+ case S_PAUSE_P: // to S_PAUSE_P
+ {
+ return;
+ }
+ case S_PAUSE_I: // to S_PAUSE_I
+ {
+ 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_PI: // to S_JUMP_PI
+ {
+ return;
+ }
+ }
+ }
+ // case S_JUMP cannot be a start state because it auto flips to play
+ // case S_JUMP_PI cannot be a start state because it auto flips to S_PAUSE_I
+ }
+}
+
+// ----------------------------------- Internal functions
+
+void PlayerVideoRec::restartAtFrame(ULONG newFrame)
+{
+ vfeed.stop();
+ afeed.stop();
+ tfeed.stop();
+ subtitles->stop();
+ threadStop();
+ video->stop();
+ video->reset();
+ audio->reset();
+ audio->setStreamType(Audio::MPEG2_PES);
+ demuxer->flush();
+ demuxer->seek();
+ currentFrameNumber = newFrame;
+ demuxer->setFrameNum(newFrame);
+ videoStartup = true;
+ afeed.start();
+ tfeed.start();
+ vfeed.start();
+ subtitles->start();
+ threadStart();
+ audio->play();
+ video->sync();
+ audio->sync();
+ audio->systemMuteOff();
+ audio->doMuting();
+}
+
+
+void PlayerVideoRec::restartAtFramePI(ULONG newFrame)
+{
+ ULLONG filePos;
+ ULONG nextiframeNumber;
+ ULONG iframeLength;
+ ULONG iframeNumber;
+
+ UCHAR* buffer;
+ UINT amountReceived;
+ UINT videoLength;
+
+ // newFrame could be anywhere, go forwards to next I-Frame
+ if (!vdr->getNextIFrame(newFrame, 1, &filePos, &nextiframeNumber, &iframeLength)) return;
+
+ // Now step back a GOP. This ensures we go to the greatest I-Frame equal to or less than the requested frame
+ vdr->getNextIFrame(nextiframeNumber, 0, &filePos, &iframeNumber, &iframeLength);
+
+ buffer = vdr->getBlock(filePos, iframeLength, &amountReceived);
+ 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 PlayerVideoRec::doConnectionLost()
+{
+ logger->log("Player", Log::DEBUG, "Connection lost, sending message");
+ Message* m = new Message();
+ m->to = messageReceiver;
+ m->from = this;
+ m->message = Message::PLAYER_EVENT;
+ m->parameter = PlayerVideoRec::CONNECTION_LOST;
+ messageQueue->postMessage(m);
+}
+
+// ----------------------------------- Callback
+
+void PlayerVideoRec::call(void* caller)
+{
+ if (caller == demuxer)
+ {
+ logger->log("Player", Log::DEBUG, "Callback from demuxer");
+
+ if (video->getTVsize() == Video::ASPECT4X3)
+ {
+ logger->log("Player", Log::DEBUG, "TV is 4:3, ignoring aspect switching");
+ return;
+ }
+
+ int parx,pary;
+ int dxCurrentAspect = demuxer->getAspectRatio(&parx,&pary);
+ if (dxCurrentAspect == Demuxer::ASPECT_4_3)
+ {
+ logger->log("Player", Log::DEBUG, "Demuxer said video is 4:3 aspect, switching TV");
+ video->setAspectRatio(Video::ASPECT4X3,parx,pary);
+
+ Message* m = new Message();
+ m->from = this;
+ m->to = messageReceiver;
+ m->message = Message::PLAYER_EVENT;
+ m->parameter = PlayerVideoRec::ASPECT43;
+ messageQueue->postMessage(m);
+ }
+ else if (dxCurrentAspect == Demuxer::ASPECT_16_9)
+ {
+ logger->log("Player", Log::DEBUG, "Demuxer said video is 16:9 aspect, switching TV");
+ video->setAspectRatio(Video::ASPECT16X9,parx,pary);
+
+ Message* m = new Message();
+ m->from = this;
+ m->to = messageReceiver;
+ m->message = Message::PLAYER_EVENT;
+ m->parameter = PlayerVideoRec::ASPECT169;
+ messageQueue->postMessage(m);
+ }
+ else
+ {
+ logger->log("Player", Log::DEBUG, "Demuxer said video is something else... setting it anyway");
+ video->setAspectRatio(static_cast<UCHAR>(dxCurrentAspect), parx, pary);
+ }
+
+ }
+ else
+ {
+ if (videoStartup)
+ {
+ videoStartup = false;
+ video->reset();
+ video->play();
+ video->sync();
+ vfeed.release();
+ stateMutex.unlock();
+ }
+
+ threadSignalNoLock();
+ }
+}
+
+// ----------------------------------- Feed thread
+
+void PlayerVideoRec::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 ((state == S_FFWD) || (state == S_FBWD))
+ {
+ if (video->PTSIFramePlayback()) threadPTSFeedScan();
+ else 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->to = messageReceiver;
+ m->from = this;
+ m->message = Message::PLAYER_EVENT;
+ m->parameter = STOP_PLAYBACK;
+ logger->log("Player", Log::DEBUG, "Posting message to %p...", messageQueue);
+ messageQueue->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();
+ audio->setStreamType(Audio::MPEG2_PES);
+ demuxer->flush();
+ demuxer->seek();
+ demuxer->setFrameNum(currentFrameNumber);
+ videoStartup = true;
+ afeed.start();
+ tfeed.start();
+ vfeed.start();
+ subtitles->start();
+ audio->play();
+ audio->sync();
+ audio->systemMuteOff();
+ audio->doMuting();
+ }
+
+ if (state == S_PLAY) threadFeedPlay();
+}
+
+void PlayerVideoRec::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 = static_cast<UINT>(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 = static_cast<UINT>(lengthBytes - feedPosition);
+ else // normal
+ askFor = blockSize;
+ }
+ //logger->log("Player", Log::DEBUG, "Get Block in");
+
+ threadBuffer = vdr->getBlock(feedPosition, askFor, &thisRead);
+ //logger->log("Player", Log::DEBUG, "Get Block out");
+
+ 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();
+
+ while(writeLength < thisRead)
+ {
+ //logger->log("Player", Log::DEBUG, "Put in");
+ thisWrite = demuxer->put(threadBuffer + writeLength, thisRead - writeLength);
+ //logger->log("Player", Log::DEBUG, "Put out");
+ writeLength += thisWrite;
+
+ if (!thisWrite)
+ {
+ // demuxer is full and can't take anymore
+ threadLock();
+ if (!threadActive) { threadUnlock(); threadCheckExit(); }
+ threadWaitForSignal();
+ threadUnlock();
+ }
+
+ threadCheckExit();
+ }
+
+ free(threadBuffer);
+ threadBuffer = NULL;
+
+ }
+
+ // end of recording
+ logger->log("Player", Log::DEBUG, "Recording playback ends");
+
+ if (videoStartup) // oh woe. there never was a stream, I was conned!
+ {
+ videoStartup = false;
+ stateMutex.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->to = messageReceiver;
+ m->from = this;
+ m->message = Message::PLAYER_EVENT;
+ m->parameter = PlayerVideoRec::STOP_PLAYBACK;
+ logger->log("Player", Log::DEBUG, "Posting message to %p...", messageQueue);
+ messageQueue->postMessage(m);
+}
+
+
+void PlayerVideoRec::threadPTSFeedScan()
+{
+ // This method manipulates the PTS instead of waiting, this is for the android devices, maybe later for windows?
+
+ ULONG direction = 0;
+ int dir_fac=-1;
+ ULONG baseFrameNumber = 0;
+ ULONG iframeNumber = 0;
+ ULONG iframeLength = 0;
+ ULONG currentfeedFrameNumber=currentFrameNumber;
+ ULONG firstFrameNumber=currentFrameNumber;
+ ULLONG filePos;
+ UINT amountReceived;
+ UINT videoLength;
+
+ UINT playtime=0;
+
+ int frameTimeOffset = 0; // Time in msec between frames
+
+ if (state == S_FFWD)
+ {
+ direction = 1; // and 0 for backward
+ dir_fac = 1;
+ }
+ video->EnterIframePlayback();
+
+ while(1)
+ {
+ baseFrameNumber = currentfeedFrameNumber;
+
+ threadCheckExit();
+ if (!vdr->getNextIFrame(baseFrameNumber, direction, &filePos, &iframeNumber, &iframeLength))
+ return;
+
+ if (iframeNumber >= lengthFrames) return;
+ // scan has got to the end of what we knew to be there before we started scanning
+
+ baseFrameNumber = iframeNumber;
+
+ frameTimeOffset =(int) ((double)(abs((int)iframeNumber - (int)currentfeedFrameNumber) * 1000) / (fps * (double)ifactor));
+
+ logger->log("Player", Log::DEBUG, "XXX Got frame");
+
+ threadBuffer = vdr->getBlock(filePos, iframeLength, &amountReceived);
+
+ if (!vdr->isConnected())
+ {
+ if (threadBuffer) free(threadBuffer);
+ doConnectionLost();
+ break;
+ }
+
+
+ threadCheckExit();
+
+
+ videoLength = demuxer->stripAudio(threadBuffer, amountReceived);
+ demuxer->changeTimes(threadBuffer,videoLength,playtime);
+ int count=0;
+ while (!video->displayIFrame(threadBuffer, videoLength)) // the device might block
+ {
+ MILLISLEEP(20);
+ threadCheckExit();
+ count++;
+ if (count%300==0) {
+ ULLONG cur_time=video->getCurrentTimestamp();
+ // logger->log("Player", Log::ERR, "FFN: %d CFN: %d dirfac %d time %lld ifac %d fps %g",
+ // firstFrameNumber, currentFrameNumber,dir_fac,cur_time,ifactor,fps);
+ if (cur_time!=0) {
+ currentFrameNumber=firstFrameNumber+(int)(((double)(dir_fac*((long long)cur_time)*((int)ifactor))*fps/90000.));
+ }
+ }
+
+ }
+ playtime +=frameTimeOffset;
+ currentfeedFrameNumber = iframeNumber;
+ {
+ ULLONG cur_time=video->getCurrentTimestamp();
+ // logger->log("Player", Log::ERR, "FFN: %d CFN: %d dirfac %d time %lld ifac %d fps %g",
+ // firstFrameNumber, currentFrameNumber,dir_fac,cur_time,ifactor,fps);
+ if (cur_time!=0) {
+ currentFrameNumber=firstFrameNumber+(int)(((double)(dir_fac*((long long)cur_time)*((int)ifactor))*fps/90000.));
+ }
+ }
+
+ free(threadBuffer);
+ threadBuffer = NULL;
+ }
+}
+
+
+
+void PlayerVideoRec::threadFeedScan()
+{
+ // This method is actually really simple - get frame from vdr,
+ // spit it at the video chip, wait for a time. Most of the code here
+ // is to get the wait right so that the scan occurs at the correct rate.
+
+ ULONG direction = 0;
+ ULONG baseFrameNumber = 0;
+ ULONG iframeNumber = 0;
+ ULONG iframeLength = 0;
+ ULLONG filePos;
+ UINT amountReceived;
+ UINT videoLength;
+
+#ifndef WIN32
+ struct timeval clock0 = {0,0}; // Time stamp after fetching I-frame info
+ struct timeval clock1 = {0,0}; // Time stamp after fetching I-frame data
+ struct timeval clock2 = {0,0} ; // Time stamp after displaying I-frame
+#else
+ DWORD clock0 = 0, clock1 = 0, clock2 = 0;
+#endif
+
+ int frameTimeOffset = 0; // Time in msec between frames
+ int disp_msec = 0; // Time taken to display data
+ int total_msec = 0; // Time taken to fetch data and display it
+ int sleepTime = 0;
+
+ if (state == S_FFWD) direction = 1; // and 0 for backward
+
+ while(1)
+ {
+ // Fetch I-frames until we get one that can be displayed in good time
+ // Repeat while clock0 + total_msec > clock2 + frameTimeOffset
+
+ baseFrameNumber = currentFrameNumber;
+ do
+ {
+ threadCheckExit();
+ if (!vdr->getNextIFrame(baseFrameNumber, direction, &filePos, &iframeNumber, &iframeLength))
+ return;
+
+ if (iframeNumber >= lengthFrames) return;
+ // scan has got to the end of what we knew to be there before we started scanning
+
+ baseFrameNumber = iframeNumber;
+ frameTimeOffset =(int) ((double)(abs((int)iframeNumber - (int)currentFrameNumber) * 1000) / (fps * (double)ifactor));
+#ifndef WIN32
+ gettimeofday(&clock0, NULL);
+#else
+ clock0 = timeGetTime();
+#endif
+ }
+#ifndef WIN32
+ while (clock2.tv_sec != 0 &&
+ (clock0.tv_sec - clock2.tv_sec) * 1000 +
+ (clock0.tv_usec - clock2.tv_usec) / 1000 > frameTimeOffset - total_msec);
+#else
+ while (clock2 != 0 && clock0 + total_msec > clock2 + frameTimeOffset);
+#endif
+ logger->log("Player", Log::DEBUG, "XXX Got frame");
+
+ threadBuffer = vdr->getBlock(filePos, iframeLength, &amountReceived);
+
+ if (!vdr->isConnected() || !amountReceived)
+ {
+ if (threadBuffer) free(threadBuffer);
+ doConnectionLost();
+ break;
+ }
+
+#ifndef WIN32
+ gettimeofday(&clock1, NULL);
+ if (clock2.tv_sec != 0)
+ sleepTime = (clock2.tv_sec - clock1.tv_sec) * 1000
+ + (clock2.tv_usec - clock1.tv_usec) / 1000
+ + frameTimeOffset - disp_msec;
+#else
+ clock1 = timeGetTime();
+ if (clock2 != 0)
+ sleepTime = clock2 + frameTimeOffset - disp_msec - clock1;
+#endif
+ if (sleepTime < 0) sleepTime = 0;
+ threadCheckExit();
+ MILLISLEEP(sleepTime);
+ logger->log("Player", Log::DEBUG, "XXX Slept for %d", sleepTime);
+
+ videoLength = demuxer->stripAudio(threadBuffer, amountReceived);
+ video->displayIFrame(threadBuffer, videoLength);
+ currentFrameNumber = iframeNumber;
+ free(threadBuffer);
+ threadBuffer = NULL;
+
+#ifndef WIN32
+ gettimeofday(&clock2, NULL);
+ total_msec = (clock2.tv_sec - clock0.tv_sec) * 1000
+ + (clock2.tv_usec - clock0.tv_usec) / 1000
+ - sleepTime;
+ disp_msec = (clock2.tv_sec - clock1.tv_sec) * 1000
+ + (clock2.tv_usec - clock1.tv_usec) / 1000
+ - sleepTime;
+#else
+ clock2 = timeGetTime();
+ total_msec = clock2 - clock0 - sleepTime;
+ disp_msec = clock2 - clock1 - sleepTime;
+#endif
+ logger->log("Player", Log::DEBUG, "XXX disp_msec = %4d total_msec = %4d", disp_msec, total_msec);
+ }
+}
+
+void PlayerVideoRec::threadPostStopCleanup()
+{
+ if (threadBuffer)
+ {
+ free(threadBuffer);
+ threadBuffer = NULL;
+ }
+}
+
+// ----------------------------------- Dev
+
+#ifdef DEV
+void PlayerVideoRec::test1()
+{
+ logger->log("Player", Log::DEBUG, "PLAYER TEST 1");
+}
+
+void PlayerVideoRec::test2()
+{
+ logger->log("Player", Log::DEBUG, "PLAYER TEST 2");
+}
+#endif
--- /dev/null
+/*
+ Copyright 2004-2008 Chris Tallon
+
+ This file is part of VOMP.
+
+ VOMP is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ VOMP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+*/
+
+#ifndef PLAYERVIDEOREC_H
+#define PLAYERVIDEOREC_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+#include <time.h>
+#include <mutex>
+
+#include "threadsystem.h"
+
+#include "callback.h"
+#include "defines.h"
+#include "vfeed.h"
+#include "afeed.h"
+#include "tfeed.h"
+
+#include "teletextdecodervbiebu.h"
+
+class MessageQueue;
+class Audio;
+class Video;
+class VDR;
+class Log;
+class Demuxer;
+class OSDReceiver;
+class DVBSubtitles;
+class Channel;
+
+class PlayerVideoRec : public Thread_TYPE, public Callback
+{
+ public:
+ PlayerVideoRec(MessageQueue* messageQueue, void* messageReceiver, OSDReceiver* osdReceiver);
+ virtual ~PlayerVideoRec();
+
+ int init(bool p_isPesRecording,double framespersec);
+ int shutdown();
+ void setStartFrame(ULONG frameNum);
+ void setLengthBytes(ULLONG length);
+ void setLengthFrames(ULONG length);
+ void setAudioChannel(int newChannel, int type, int streamtype);
+ void setSubtitleChannel(int newChannel);
+ bool toggleSubtitles();
+ void turnSubtitlesOn(bool ison);
+ bool isSubtitlesOn() { return subtitlesShowing; }
+ void tellSubtitlesOSDVisible(bool visible);
+
+ void play();
+ void stop();
+ void pause();
+ void playpause();
+ void fastForward();
+ void fastBackward();
+ void jumpToPercent(double percent);
+ void skipForward(int seconds);
+ void skipBackward(int seconds);
+ void jumpToMark(int mark);
+ void jumpToFrameP(int newFrame);
+
+ UCHAR getState() { return state; }
+ ULONG getCurrentFrameNum();
+ ULONG getLengthFrames();
+ UCHAR getIScanRate() { return ifactor; }
+ bool* getDemuxerMpegAudioChannels();
+ bool* getDemuxerAc3AudioChannels();
+ bool* getDemuxerSubtitleChannels();
+ int *getTeletxtSubtitlePages();
+ int getCurrentAudioChannel();
+ int getCurrentSubtitleChannel();
+ bool isPesRecording() { return is_pesrecording; }
+ Channel *getDemuxerChannel();
+
+ TeletextDecoderVBIEBU * getTeletextDecoder() { return teletext; }
+
+ void call(void*); // for callback interface
+
+ const static UCHAR S_PLAY = 1;
+ const static UCHAR S_PAUSE_P = 2;
+ const static UCHAR S_PAUSE_I = 3;
+ const static UCHAR S_FFWD = 4;
+ const static UCHAR S_FBWD = 5;
+ const static UCHAR S_STOP = 6;
+ const static UCHAR S_JUMP = 7;
+ const static UCHAR S_JUMP_PI = 8; // Jump to Pause_I mode
+
+ // Player events
+
+ // FIXME so far this just duplicates the old system + the wss
+
+ const static UCHAR CONNECTION_LOST = 1;
+ const static UCHAR STOP_PLAYBACK = 2;
+ const static UCHAR STREAM_END = 3;
+ const static UCHAR ASPECT43 = 4;
+ const static UCHAR ASPECT169 = 5;
+
+#ifdef DEV
+ void test1();
+ void test2();
+#endif
+
+ protected:
+ void threadMethod();
+ void threadPostStopCleanup();
+
+ private:
+ void switchState(UCHAR newState, ULONG jumpFrame=0);
+
+ void threadFeedPlay();
+ void threadFeedScan();
+ void threadPTSFeedScan();
+
+ void doConnectionLost();
+ void restartAtFrame(ULONG newFrame);
+ void restartAtFramePI(ULONG newFrame);
+
+ bool subtitlesShowing{};
+ MessageQueue* messageQueue;
+ void* messageReceiver;
+ OSDReceiver* osdReceiver;
+ Log* logger;
+ Audio* audio;
+ Video* video;
+ Demuxer* demuxer;
+ DVBSubtitles* subtitles;
+ VDR* vdr;
+ VFeed vfeed;
+ AFeed afeed;
+ TFeed tfeed;
+ TeletextDecoderVBIEBU *teletext;
+
+ bool initted{};
+ bool startup;
+ bool videoStartup{};
+
+ bool is_pesrecording{true};
+ double fps;
+
+ std::mutex stateMutex;
+
+ ULLONG lengthBytes{};
+ ULONG lengthFrames{};
+ ULONG currentFrameNumber{};
+ UINT blockSize{100000};
+ UINT startupBlockSize{250000};
+ UCHAR* threadBuffer{};
+ UCHAR state{S_STOP};
+ UCHAR ifactor{4}; // 4, 8, 16, 32
+};
+
+#endif
+
+
+/*
+
+Possible states:
+
+Play, Pause, FFwd, FBwd, (Stop), [Jump]
+
+ Possible Working
+
+Play -> PauseP * *
+ -> PauseI
+ -> FFwd * *
+ -> FBwd * *
+ -> Stop * *
+ -> Jump * *
+ -> Jump_PI * *
+
+PauseP -> Play * *
+ -> PauseI
+ -> FFwd * *
+ -> FBwd * *
+ -> Stop * *
+ -> Jump * *
+ -> Jump_PI * *
+
+PauseI -> Play * *
+ -> PauseP
+ -> FFwd * *
+ -> FBwd * *
+ -> Stop * *
+ -> Jump * *
+ -> Jump_PI * *
+
+FFwd -> Play * *
+ -> PauseP
+ -> PauseI * *
+ -> FBwd * *
+ -> Stop * *
+ -> Jump * *
+ -> Jump_PI * *
+
+FBwd -> Play * *
+ -> PauseP
+ -> PauseI * *
+ -> FFwd * *
+ -> Stop * *
+ -> Jump * *
+ -> Jump_PI * *
+
+Stop -> Play * *
+ -> PauseP
+ -> PauseI
+ -> FFwd
+ -> FBwd
+ -> Jump
+ -> Jump_PI
+
+*/
vresp = new VDR_ResponsePacket();
vresp->setResponse(requestID, reinterpret_cast<UCHAR*>(userData), userDataLength);
- logger->log("VDR", Log::DEBUG, "Rxd a response packet, requestID=%lu, len=%lu", requestID, userDataLength);
+// logger->log("VDR", Log::DEBUG, "Rxd a response packet, requestID=%lu, len=%lu", requestID, userDataLength);
if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() )
{
#include "command.h"
#include "osd.h"
-#include "player.h"
#include "wsymbol.h"
#include "recording.h"
#include "recinfo.h"
switch(m->parameter)
{
- case Player::CONNECTION_LOST: // connection lost detected
+ case PlayerRadio::CONNECTION_LOST: // connection lost detected
{
// I can't handle this, send it to command
Message* m2 = new Message();
MessageQueue::getInstance()->postMessage(m2);
break;
}
- case Player::STOP_PLAYBACK:
+ case PlayerRadio::STOP_PLAYBACK:
{
// FIXME Obselete ish - improve this
Message* m2 = new Message(); // Must be done after this thread finishes, and must break into master mutex
else
{
playerState = player->getState();
- if (playerState == Player::S_PAUSE_P) w.nextSymbol = WSymbol::PAUSE;
- else if (playerState == Player::S_PAUSE_I) w.nextSymbol = WSymbol::PAUSE;
- else w.nextSymbol = WSymbol::PLAY;
+ if (playerState == PlayerRadio::S_PAUSE_P) w.nextSymbol = WSymbol::PAUSE;
+ else if (playerState == PlayerRadio::S_PAUSE_I) w.nextSymbol = WSymbol::PAUSE;
+ else w.nextSymbol = WSymbol::PLAY;
}
w.draw();
#include "audio.h"
#include "vdr.h"
#include "video.h"
-#include "player.h"
+#include "playervideorec.h"
#include "recording.h"
#include "vaudioselector.h"
#include "message.h"
video->seth264mode(ish264);
- player = new Player(Command::getInstance(), this, this);
+ player = new PlayerVideoRec(Command::getInstance(), this, this);
player->init(myRec->IsPesRecording,myRec->recInfo->fps);
char* cstartMargin = vdr->configLoad("Timers", "Start margin");
if (m->message != Message::PLAYER_EVENT) return;
switch(m->parameter)
{
- case Player::CONNECTION_LOST: // connection lost detected
+ case PlayerVideoRec::CONNECTION_LOST: // connection lost detected
{
// I can't handle this, send it to command
Message* m2 = new Message();
MessageQueue::getInstance()->postMessage(m2);
break;
}
- case Player::STOP_PLAYBACK:
+ case PlayerVideoRec::STOP_PLAYBACK:
{
// FIXME Obselete ish - improve this
Message* m2 = new Message(); // Must be done after this thread finishes, and must break into master mutex
MessageQueue::getInstance()->postMessage(m2);
break;
}
- case Player::ASPECT43:
+ case PlayerVideoRec::ASPECT43:
{
break;
}
- case Player::ASPECT169:
+ case PlayerVideoRec::ASPECT169:
{
break;
}
case 0x10: { //dvbsubtitle
player->setSubtitleChannel((m->parameter & 0xFFFF));
player->turnSubtitlesOn(true);
- VTeletextView *vtxt=((Player*)player)->getTeletextDecoder()->getTeletxtView();
+ VTeletextView *vtxt = player->getTeletextDecoder()->getTeletxtView();
if (vtxt && vtxt->isInSubtitleMode()) {
BoxStack::getInstance()->remove(vtxt);
}
case 0xFF: { //nosubtitles
player->turnSubtitlesOn(false);
- VTeletextView *vtxt=((Player*)player)->getTeletextDecoder()->getTeletxtView();
+ VTeletextView *vtxt = player->getTeletextDecoder()->getTeletxtView();
if (vtxt && vtxt->isInSubtitleMode()) {
BoxStack::getInstance()->remove(vtxt);
}
case 0x11: { //videotext
player->turnSubtitlesOn(false);
doTeletext();
- ((Player*)player)->getTeletextDecoder()->setPage((m->parameter & 0xFFFF));
+ player->getTeletextDecoder()->setPage((m->parameter & 0xFFFF));
} break;
};
if (vas) {
else
{
playerState = player->getState();
- if (playerState == Player::S_PAUSE_P) w.nextSymbol = WSymbol::PAUSE;
- else if (playerState == Player::S_PAUSE_I) w.nextSymbol = WSymbol::PAUSE;
- else if (playerState == Player::S_FFWD) w.nextSymbol = WSymbol::FFWD;
- else if (playerState == Player::S_FBWD) w.nextSymbol = WSymbol::FBWD;
+ if (playerState == PlayerVideoRec::S_PAUSE_P) w.nextSymbol = WSymbol::PAUSE;
+ else if (playerState == PlayerVideoRec::S_PAUSE_I) w.nextSymbol = WSymbol::PAUSE;
+ else if (playerState == PlayerVideoRec::S_FFWD) w.nextSymbol = WSymbol::FFWD;
+ else if (playerState == PlayerVideoRec::S_FBWD) w.nextSymbol = WSymbol::FBWD;
else w.nextSymbol = WSymbol::PLAY;
}
w.draw();
- if ((playerState == Player::S_FFWD) || (playerState == Player::S_FBWD))
+ if ((playerState == PlayerVideoRec::S_FFWD) || (playerState == PlayerVideoRec::S_FBWD))
{
// draw blips to show how fast the scan is
UCHAR scanrate = player->getIScanRate();
timers->cancelTimer(this, 1);
- if ((playerState == Player::S_FFWD) || (playerState == Player::S_FBWD)) barScanHold = true;
+ if ((playerState == PlayerVideoRec::S_FFWD) || (playerState == PlayerVideoRec::S_FBWD)) barScanHold = true;
else barScanHold = false;
if (!barGenHold && !barScanHold && !barVasHold) timers->setTimerD(this, 1, 4);
// will repaint all the bar (it will call this function again, but
// this section won't run because stickyBarF will then == false)
- if ((playerState != Player::S_FFWD) && (playerState != Player::S_FBWD))
+ if ((playerState != PlayerVideoRec::S_FFWD) && (playerState != PlayerVideoRec::S_FBWD))
{
barScanHold = false;
doBar(0);
#include "video.h"
class VDR;
-class Player;
+class PlayerVideoRec;
class Recording;
class VAudioSelector;
class Message;
VDR* vdr;
Video* video;
Timers* timers;
- Player* player;
+ PlayerVideoRec* player;
Recording* myRec;
VAudioSelector* vas;