/* * streamdevice.c: streaming network device * * See the README file for copyright information and how to reach the author. * */ #include "vdr/player.h" #include "streamdevice.h" #include "osdworker.h" #include "tsworker.h" #include "netosd.h" #include "clientcontrol.h" cStreamDevice::cStreamDevice(void) { dsyslog("[ffnetdev] Device: Constructor cStreamDevice \n"); //m_Remux = new cPES2TSRemux(TS_VPID, TS_APID); m_Remux = new cPES2PESRemux(); m_Playing = false; m_PlayState = psPlay; m_PlayMode = pmNone; } cStreamDevice::~cStreamDevice(void) { dsyslog("[ffnetdev] Device: Destructor cStreamDevice \n"); m_PlayState = psPlay; cOSDWorker::Exit(); cTSWorker::Exit(); cClientControl::Exit(); DELETENULL(m_Remux); } void cStreamDevice::MakePrimaryDevice(bool On) { dsyslog("[ffnetdev] Device: ffnetdev becomes primary device. Registering our OSD provider...\n"); new cNetOSDProvider(); } int cStreamDevice::ProvidesCa(const cChannel *Channel) const { return 0; } bool cStreamDevice::HasDecoder(void) const { return true; // We can decode MPEG2 } bool cStreamDevice::CanReplay(void) const { return true; // We can replay } bool cStreamDevice::SetPlayMode(ePlayMode PlayMode) { dsyslog("[ffnetdev] Device: Setting playmode. Mode: %d\n",PlayMode); cOSDWorker::SendPlayMode(PlayMode); m_PlayMode = PlayMode; if (PlayMode == pmNone) { m_PlayState = psBufferReset; m_Remux->ClearInput(); m_Remux->ClearOutput(); } else { while (((m_PlayState == psBufferReset) || (m_PlayState == psBufferReseted)) && (!cClientControl::PlayStateReq()) && (cTSWorker::HaveStreamClient())) cCondWait::SleepMs(10); dsyslog("[ffnetdev] PlayStateReq\n"); m_PlayState = psPlay; } cControl *pControl = cControl::Control(); if (pControl) { pControl->GetReplayMode(m_Playing, m_Forward, m_Speed); if (m_Speed == -1) m_Speed = 0; if (!cClientControl::SendPlayState(PlayMode, m_Playing, m_Forward, m_Speed)) m_PlayState = psPlay; } else { m_Playing = false; m_Forward = true; m_Speed = 0; if (!cClientControl::SendPlayState(PlayMode, m_Playing, m_Forward, m_Speed)) m_PlayState = psPlay; } return true; } void cStreamDevice::TrickSpeed(int Speed) { dsyslog("[ffnetdev] Device: Trickspeed. Speed: %d\n", Speed); cControl *pControl = cControl::Control(); if (pControl) pControl->GetReplayMode(m_Playing, m_Forward, m_Speed); m_Speed = Speed; if (!cClientControl::SendPlayState(m_PlayMode, m_Playing, m_Forward, m_Speed)) m_PlayState = psPlay; } void cStreamDevice::Clear(void) { dsyslog("[ffnetdev] Device: Clear\n"); // workaround for clearing in vdrviewer (speed-change resets the buffer) if (!cClientControl::SendPlayState(m_PlayMode, m_Playing, m_Forward, 1)) m_PlayState = psPlay; if (!cClientControl::SendPlayState(m_PlayMode, m_Playing, m_Forward, m_Speed)) m_PlayState = psPlay; // cDevice::Clear(); } void cStreamDevice::Play(void) { dsyslog("[ffnetdev] Device: Play.\n"); m_PlayMode = pmAudioVideo; m_Playing = true; m_Forward = true; m_Speed = 0; if (!cClientControl::SendPlayState(m_PlayMode, m_Playing, m_Forward, m_Speed)) m_PlayState = psPlay; // cDevice::Play(); } void cStreamDevice::Freeze(void) { dsyslog("[ffnetdev] Device: Freeze.\n"); m_Playing = false; cClientControl::SendSFreeze(); // cDevice::Freeze(); } void cStreamDevice::Mute(void) { dsyslog("[ffnetdev] Device: Mute.\n"); m_PlayMode = pmVideoOnly; if (!cClientControl::SendPlayState(m_PlayMode, m_Playing, m_Forward, m_Speed)) m_PlayState = psPlay; // cDevice::Mute(); } void cStreamDevice::SetVolumeDevice(int Volume) { dsyslog("[ffnetdev] Device: Setting volume to %d (not implemented).\n", Volume); } void cStreamDevice::StillPicture(const uchar *Data, int Length) { dsyslog("[ffnetdev] Device: StillPicture %d Bytes.\n", Length); cClientControl::SendStillPicture(Data, Length); } bool cStreamDevice::Poll(cPoller &Poller, int TimeoutMs) { //dsyslog("[ffnetdev] Device: Poll TimeoutMs: %d ....\n",TimeoutMs); return true; } /* ---------------------------------------------------------------------------- */ #if VDRVERSNUM < 10342 int cStreamDevice::PlayAudio(const uchar *Data, int Length) #else int cStreamDevice::PlayAudio(const uchar *Data, int Length, uchar Id) #endif { if (cTSWorker::HaveStreamClient()) { while ((((!m_Playing) && (m_Remux->InputFree() < Length)) || ((m_Playing) && ((m_Remux->InputFree() < Length) || (m_Remux->Fill() > TCP_SEND_SIZE * 10)))) && (cTSWorker::HaveStreamClient())) cCondWait::SleepMs(1); int result=m_Remux->Put(Data, Length); if (result!=Length) { dsyslog("[ffnetdev] Device: Did not put all in input buffer(audio). result:%d Length: %d Skipping Audio PES packet...\n", result, Length ); // Delete part of data already written to buffer m_Remux->DelInput(result); return (0); } else { return ( Length ); } } else { m_Remux->ClearInput(); // usleep(10000); return ( Length ); } } /* ---------------------------------------------------------------------------- */ int cStreamDevice::PlayVideo(const uchar *Data, int Length) { if (cTSWorker::HaveStreamClient()) { while ((((!m_Playing) && (m_Remux->InputFree() < Length)) || ((m_Playing) && ((m_Remux->InputFree() < Length) || (m_Remux->Fill() > TCP_SEND_SIZE * 10)))) && (cTSWorker::HaveStreamClient())) cCondWait::SleepMs(1); int result=m_Remux->Put(Data, Length); if (result!=Length) { dsyslog("[ffnetdev] Device: Did not put all in input buffer(video). result:%d Length: %d Skipping Video PES packet...\n", result, Length ); // Delete part of data already written to buffer m_Remux->DelInput(result); return (0); } else { return ( Length ); } } else { m_Remux->ClearInput(); // usleep(10000); return ( Length ); } }