diff --git a/CONTRIBUTORS b/CONTRIBUTORS index a7f9c5cd..72f4a44a 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1298,6 +1298,7 @@ Reinhard Nissl for making subtitle PIDs be decrypted for making cEITScanner process new transponders before old ones, to make sure transponder changes are recognized + for helping to debug switching into time shift mode when pausing live video Richard Robson for reporting freezing replay if a timer starts while in Transfer Mode from the diff --git a/HISTORY b/HISTORY index 82c02128..3ecb8c65 100644 --- a/HISTORY +++ b/HISTORY @@ -6847,7 +6847,7 @@ Video Disk Recorder Revision History - Fixed cRecordings::DelByName() to avoid compilation errors with gcc 4.4 (backport from version 1.7.9, thanks to Ralf Schueler). -2012-02-18: Version 1.7.24 +2012-02-19: Version 1.7.24 - Updated the Italian OSD texts (thanks to Diego Pierotto). - Fixed a high load in case a transponder can't be received. @@ -6886,3 +6886,5 @@ Video Disk Recorder Revision History device numbering. - cReadDir::Next() now skips directory entries "." and "..". - Fixed a possible deadlock in time shift mode. +- Fixed switching into time shift mode when pausing live video (thanks to Reinhard + Nissl for helping to debug this one). diff --git a/dvbplayer.c b/dvbplayer.c index d644e203..b0adac40 100644 --- a/dvbplayer.c +++ b/dvbplayer.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbplayer.c 2.22 2012/02/17 15:36:41 kls Exp $ + * $Id: dvbplayer.c 2.23 2012/02/19 10:48:02 kls Exp $ */ #include "dvbplayer.h" @@ -216,6 +216,7 @@ private: cUnbufferedFile *replayFile; double framesPerSecond; bool isPesRecording; + bool pauseLive; bool eof; bool firstPacket; ePlayModes playMode; @@ -235,7 +236,7 @@ protected: virtual void Activate(bool On); virtual void Action(void); public: - cDvbPlayer(const char *FileName); + cDvbPlayer(const char *FileName, bool PauseLive); virtual ~cDvbPlayer(); bool Active(void) { return cThread::Running(); } void Pause(void); @@ -256,7 +257,7 @@ public: #define SPEED_MULT 12 // the speed multiplier int cDvbPlayer::Speeds[] = { 0, -2, -4, -8, 1, 2, 4, 12, 0 }; -cDvbPlayer::cDvbPlayer(const char *FileName) +cDvbPlayer::cDvbPlayer(const char *FileName, bool PauseLive) :cThread("dvbplayer") { nonBlockingFileReader = NULL; @@ -265,6 +266,7 @@ cDvbPlayer::cDvbPlayer(const char *FileName) cRecording Recording(FileName); framesPerSecond = Recording.FramesPerSecond(); isPesRecording = Recording.IsPesRecording(); + pauseLive = PauseLive; eof = false; firstPacket = true; playMode = pmPlay; @@ -282,7 +284,7 @@ cDvbPlayer::cDvbPlayer(const char *FileName) return; ringBuffer = new cRingBufferFrame(PLAYERBUFSIZE); // Create the index file: - index = new cIndexFile(FileName, false, isPesRecording); + index = new cIndexFile(FileName, false, isPesRecording, pauseLive); if (!index) esyslog("ERROR: can't allocate index"); else if (!index->Ok()) { @@ -407,6 +409,8 @@ void cDvbPlayer::Action(void) int LastReadIFrame = -1; int SwitchToPlayFrame = 0; + if (pauseLive) + Goto(0, true); while (Running()) { if (WaitingForData) nonBlockingFileReader->WaitForDataMs(10); // this keeps the CPU load low, but reacts immediately on new data @@ -414,7 +418,7 @@ void cDvbPlayer::Action(void) cPoller Poller; DevicePoll(Poller, 10); Sleep = false; - if (playMode == pmStill || playMode==pmPause) + if (playMode == pmStill || playMode == pmPause) cCondWait::SleepMs(10); } { @@ -836,8 +840,8 @@ bool cDvbPlayer::GetReplayMode(bool &Play, bool &Forward, int &Speed) // --- cDvbPlayerControl ----------------------------------------------------- -cDvbPlayerControl::cDvbPlayerControl(const char *FileName) -:cControl(player = new cDvbPlayer(FileName)) +cDvbPlayerControl::cDvbPlayerControl(const char *FileName, bool PauseLive) +:cControl(player = new cDvbPlayer(FileName, PauseLive)) { } diff --git a/dvbplayer.h b/dvbplayer.h index 41590257..e2f2082d 100644 --- a/dvbplayer.h +++ b/dvbplayer.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbplayer.h 1.2 2002/06/23 10:13:51 kls Exp $ + * $Id: dvbplayer.h 2.1 2012/02/19 11:40:36 kls Exp $ */ #ifndef __DVBPLAYER_H @@ -19,8 +19,11 @@ class cDvbPlayerControl : public cControl { private: cDvbPlayer *player; public: - cDvbPlayerControl(const char *FileName); + cDvbPlayerControl(const char *FileName, bool PauseLive = false); // Sets up a player for the given file. + // If PauseLive is true, special care is taken to make sure the index + // file of the recording is long enough to allow the player to display + // the first frame in still picture mode. virtual ~cDvbPlayerControl(); bool Active(void); void Stop(void); diff --git a/menu.c b/menu.c index 7acffe7a..61dcdfcb 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 2.36 2012/02/16 11:57:51 kls Exp $ + * $Id: menu.c 2.37 2012/02/19 11:37:55 kls Exp $ */ #include "menu.h" @@ -4329,13 +4329,10 @@ bool cRecordControls::PauseLiveVideo(void) Skins.Message(mtStatus, tr("Pausing live video...")); cReplayControl::SetRecording(NULL, NULL); // make sure the new cRecordControl will set cReplayControl::LastReplayed() if (Start(NULL, true)) { - cCondWait::SleepMs(2000); // allow recorded file to fill up enough to start replaying - cReplayControl *rc = new cReplayControl; + cReplayControl *rc = new cReplayControl(true); cControl::Launch(rc); cControl::Attach(); - cCondWait::SleepMs(1000); // allow device to replay some frames, so we have a picture Skins.Message(mtStatus, NULL); - rc->ProcessKey(kPause); // pause, allowing replay mode display return true; } Skins.Message(mtStatus, NULL); @@ -4425,8 +4422,8 @@ cReplayControl *cReplayControl::currentReplayControl = NULL; char *cReplayControl::fileName = NULL; char *cReplayControl::title = NULL; -cReplayControl::cReplayControl(void) -:cDvbPlayerControl(fileName) +cReplayControl::cReplayControl(bool PauseLive) +:cDvbPlayerControl(fileName, PauseLive) { currentReplayControl = this; displayReplay = NULL; diff --git a/menu.h b/menu.h index ec1c175b..c74d8c25 100644 --- a/menu.h +++ b/menu.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.h 2.3 2010/03/06 16:15:59 kls Exp $ + * $Id: menu.h 2.4 2012/02/19 10:51:56 kls Exp $ */ #ifndef __MENU_H @@ -276,7 +276,7 @@ private: void EditCut(void); void EditTest(void); public: - cReplayControl(void); + cReplayControl(bool PauseLive = false); virtual ~cReplayControl(); void Stop(void); virtual cOsdObject *GetInfo(void); diff --git a/recording.c b/recording.c index ac1ff2c7..7617d734 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 2.49 2012/02/17 13:57:05 kls Exp $ + * $Id: recording.c 2.50 2012/02/19 10:44:45 kls Exp $ */ #include "recording.h" @@ -1555,8 +1555,9 @@ struct tIndexTs { #define MAXWAITFORINDEXFILE 10 // max. time to wait for the regenerated index file (seconds) #define INDEXFILECHECKINTERVAL 500 // ms between checks for existence of the regenerated index file +#define INDEXFILETESTINTERVAL 10 // ms between tests for the size of the index file in case of pausing live video -cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording) +cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording, bool PauseLive) :resumeFile(FileName, IsPesRecording) { f = -1; @@ -1567,6 +1568,12 @@ cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording) indexFileGenerator = NULL; if (FileName) { fileName = IndexFileName(FileName, isPesRecording); + if (!Record && PauseLive) { + // Wait until the index file contains at least two frames: + time_t tmax = time(NULL) + MAXWAITFORINDEXFILE; + while (time(NULL) < tmax && FileSize(fileName) < 2 * sizeof(tIndexTs)) + cCondWait::SleepMs(INDEXFILETESTINTERVAL); + } int delta = 0; if (!Record && access(fileName, R_OK) != 0) { // Index file doesn't exist, so try to regenerate it: diff --git a/recording.h b/recording.h index d3dbd1da..61ec2a64 100644 --- a/recording.h +++ b/recording.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.h 2.26 2011/12/04 13:38:17 kls Exp $ + * $Id: recording.h 2.27 2012/02/19 10:44:53 kls Exp $ */ #ifndef __RECORDING_H @@ -279,7 +279,7 @@ private: void ConvertToPes(tIndexTs *IndexTs, int Count); bool CatchUp(int Index = -1); public: - cIndexFile(const char *FileName, bool Record, bool IsPesRecording = false); + cIndexFile(const char *FileName, bool Record, bool IsPesRecording = false, bool PauseLive = false); ~cIndexFile(); bool Ok(void) { return index != NULL; } bool Write(bool Independent, uint16_t FileNumber, off_t FileOffset); diff --git a/tools.c b/tools.c index 145af7af..3296b540 100644 --- a/tools.c +++ b/tools.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 2.21 2012/02/17 13:58:49 kls Exp $ + * $Id: tools.c 2.22 2012/02/18 15:30:35 kls Exp $ */ #include "tools.h" @@ -563,6 +563,14 @@ time_t LastModifiedTime(const char *FileName) return 0; } +off_t FileSize(const char *FileName) +{ + struct stat fs; + if (stat(FileName, &fs) == 0) + return fs.st_size; + return -1; +} + // --- cTimeMs --------------------------------------------------------------- cTimeMs::cTimeMs(int Ms) diff --git a/tools.h b/tools.h index 86e8fb06..52bf8a7f 100644 --- a/tools.h +++ b/tools.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.h 2.14 2011/12/04 14:48:03 kls Exp $ + * $Id: tools.h 2.15 2012/02/18 15:29:50 kls Exp $ */ #ifndef __TOOLS_H @@ -224,6 +224,7 @@ char *ReadLink(const char *FileName); ///< returns a new string allocated on the bool SpinUpDisk(const char *FileName); void TouchFile(const char *FileName); time_t LastModifiedTime(const char *FileName); +off_t FileSize(const char *FileName); ///< returns the size of the given file, or -1 in case of an error (e.g. if the file doesn't exist) cString WeekDayName(int WeekDay); cString WeekDayName(time_t t); cString WeekDayNameFull(int WeekDay); diff --git a/vdr.c b/vdr.c index 0913614f..417ee19d 100644 --- a/vdr.c +++ b/vdr.c @@ -22,7 +22,7 @@ * * The project's page is at http://www.tvdr.de * - * $Id: vdr.c 2.28 2012/02/11 12:34:01 kls Exp $ + * $Id: vdr.c 2.29 2012/02/19 11:37:35 kls Exp $ */ #include @@ -1160,7 +1160,6 @@ int main(int argc, char *argv[]) } switch (state) { case osPause: DELETE_MENU; - cControl::Shutdown(); // just in case if (!cRecordControls::PauseLiveVideo()) Skins.Message(mtError, tr("No free DVB device to record!")); break;