Fixed switching into time shift mode when pausing live video

This commit is contained in:
Klaus Schmidinger 2012-02-19 11:50:20 +01:00
parent 50e09d1232
commit 23ec57d822
11 changed files with 49 additions and 27 deletions

View File

@ -1298,6 +1298,7 @@ Reinhard Nissl <rnissl@gmx.de>
for making subtitle PIDs be decrypted for making subtitle PIDs be decrypted
for making cEITScanner process new transponders before old ones, to make sure for making cEITScanner process new transponders before old ones, to make sure
transponder changes are recognized transponder changes are recognized
for helping to debug switching into time shift mode when pausing live video
Richard Robson <richard_robson@beeb.net> Richard Robson <richard_robson@beeb.net>
for reporting freezing replay if a timer starts while in Transfer Mode from the for reporting freezing replay if a timer starts while in Transfer Mode from the

View File

@ -6847,7 +6847,7 @@ Video Disk Recorder Revision History
- Fixed cRecordings::DelByName() to avoid compilation errors with gcc 4.4 - Fixed cRecordings::DelByName() to avoid compilation errors with gcc 4.4
(backport from version 1.7.9, thanks to Ralf Schueler). (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). - Updated the Italian OSD texts (thanks to Diego Pierotto).
- Fixed a high load in case a transponder can't be received. - Fixed a high load in case a transponder can't be received.
@ -6886,3 +6886,5 @@ Video Disk Recorder Revision History
device numbering. device numbering.
- cReadDir::Next() now skips directory entries "." and "..". - cReadDir::Next() now skips directory entries "." and "..".
- Fixed a possible deadlock in time shift mode. - 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).

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "dvbplayer.h"
@ -216,6 +216,7 @@ private:
cUnbufferedFile *replayFile; cUnbufferedFile *replayFile;
double framesPerSecond; double framesPerSecond;
bool isPesRecording; bool isPesRecording;
bool pauseLive;
bool eof; bool eof;
bool firstPacket; bool firstPacket;
ePlayModes playMode; ePlayModes playMode;
@ -235,7 +236,7 @@ protected:
virtual void Activate(bool On); virtual void Activate(bool On);
virtual void Action(void); virtual void Action(void);
public: public:
cDvbPlayer(const char *FileName); cDvbPlayer(const char *FileName, bool PauseLive);
virtual ~cDvbPlayer(); virtual ~cDvbPlayer();
bool Active(void) { return cThread::Running(); } bool Active(void) { return cThread::Running(); }
void Pause(void); void Pause(void);
@ -256,7 +257,7 @@ public:
#define SPEED_MULT 12 // the speed multiplier #define SPEED_MULT 12 // the speed multiplier
int cDvbPlayer::Speeds[] = { 0, -2, -4, -8, 1, 2, 4, 12, 0 }; 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") :cThread("dvbplayer")
{ {
nonBlockingFileReader = NULL; nonBlockingFileReader = NULL;
@ -265,6 +266,7 @@ cDvbPlayer::cDvbPlayer(const char *FileName)
cRecording Recording(FileName); cRecording Recording(FileName);
framesPerSecond = Recording.FramesPerSecond(); framesPerSecond = Recording.FramesPerSecond();
isPesRecording = Recording.IsPesRecording(); isPesRecording = Recording.IsPesRecording();
pauseLive = PauseLive;
eof = false; eof = false;
firstPacket = true; firstPacket = true;
playMode = pmPlay; playMode = pmPlay;
@ -282,7 +284,7 @@ cDvbPlayer::cDvbPlayer(const char *FileName)
return; return;
ringBuffer = new cRingBufferFrame(PLAYERBUFSIZE); ringBuffer = new cRingBufferFrame(PLAYERBUFSIZE);
// Create the index file: // Create the index file:
index = new cIndexFile(FileName, false, isPesRecording); index = new cIndexFile(FileName, false, isPesRecording, pauseLive);
if (!index) if (!index)
esyslog("ERROR: can't allocate index"); esyslog("ERROR: can't allocate index");
else if (!index->Ok()) { else if (!index->Ok()) {
@ -407,6 +409,8 @@ void cDvbPlayer::Action(void)
int LastReadIFrame = -1; int LastReadIFrame = -1;
int SwitchToPlayFrame = 0; int SwitchToPlayFrame = 0;
if (pauseLive)
Goto(0, true);
while (Running()) { while (Running()) {
if (WaitingForData) if (WaitingForData)
nonBlockingFileReader->WaitForDataMs(10); // this keeps the CPU load low, but reacts immediately on new data 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; cPoller Poller;
DevicePoll(Poller, 10); DevicePoll(Poller, 10);
Sleep = false; Sleep = false;
if (playMode == pmStill || playMode==pmPause) if (playMode == pmStill || playMode == pmPause)
cCondWait::SleepMs(10); cCondWait::SleepMs(10);
} }
{ {
@ -836,8 +840,8 @@ bool cDvbPlayer::GetReplayMode(bool &Play, bool &Forward, int &Speed)
// --- cDvbPlayerControl ----------------------------------------------------- // --- cDvbPlayerControl -----------------------------------------------------
cDvbPlayerControl::cDvbPlayerControl(const char *FileName) cDvbPlayerControl::cDvbPlayerControl(const char *FileName, bool PauseLive)
:cControl(player = new cDvbPlayer(FileName)) :cControl(player = new cDvbPlayer(FileName, PauseLive))
{ {
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __DVBPLAYER_H
@ -19,8 +19,11 @@ class cDvbPlayerControl : public cControl {
private: private:
cDvbPlayer *player; cDvbPlayer *player;
public: public:
cDvbPlayerControl(const char *FileName); cDvbPlayerControl(const char *FileName, bool PauseLive = false);
// Sets up a player for the given file. // 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(); virtual ~cDvbPlayerControl();
bool Active(void); bool Active(void);
void Stop(void); void Stop(void);

11
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "menu.h"
@ -4329,13 +4329,10 @@ bool cRecordControls::PauseLiveVideo(void)
Skins.Message(mtStatus, tr("Pausing live video...")); Skins.Message(mtStatus, tr("Pausing live video..."));
cReplayControl::SetRecording(NULL, NULL); // make sure the new cRecordControl will set cReplayControl::LastReplayed() cReplayControl::SetRecording(NULL, NULL); // make sure the new cRecordControl will set cReplayControl::LastReplayed()
if (Start(NULL, true)) { if (Start(NULL, true)) {
cCondWait::SleepMs(2000); // allow recorded file to fill up enough to start replaying cReplayControl *rc = new cReplayControl(true);
cReplayControl *rc = new cReplayControl;
cControl::Launch(rc); cControl::Launch(rc);
cControl::Attach(); cControl::Attach();
cCondWait::SleepMs(1000); // allow device to replay some frames, so we have a picture
Skins.Message(mtStatus, NULL); Skins.Message(mtStatus, NULL);
rc->ProcessKey(kPause); // pause, allowing replay mode display
return true; return true;
} }
Skins.Message(mtStatus, NULL); Skins.Message(mtStatus, NULL);
@ -4425,8 +4422,8 @@ cReplayControl *cReplayControl::currentReplayControl = NULL;
char *cReplayControl::fileName = NULL; char *cReplayControl::fileName = NULL;
char *cReplayControl::title = NULL; char *cReplayControl::title = NULL;
cReplayControl::cReplayControl(void) cReplayControl::cReplayControl(bool PauseLive)
:cDvbPlayerControl(fileName) :cDvbPlayerControl(fileName, PauseLive)
{ {
currentReplayControl = this; currentReplayControl = this;
displayReplay = NULL; displayReplay = NULL;

4
menu.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __MENU_H
@ -276,7 +276,7 @@ private:
void EditCut(void); void EditCut(void);
void EditTest(void); void EditTest(void);
public: public:
cReplayControl(void); cReplayControl(bool PauseLive = false);
virtual ~cReplayControl(); virtual ~cReplayControl();
void Stop(void); void Stop(void);
virtual cOsdObject *GetInfo(void); virtual cOsdObject *GetInfo(void);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "recording.h"
@ -1555,8 +1555,9 @@ struct tIndexTs {
#define MAXWAITFORINDEXFILE 10 // max. time to wait for the regenerated index file (seconds) #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 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) :resumeFile(FileName, IsPesRecording)
{ {
f = -1; f = -1;
@ -1567,6 +1568,12 @@ cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording)
indexFileGenerator = NULL; indexFileGenerator = NULL;
if (FileName) { if (FileName) {
fileName = IndexFileName(FileName, isPesRecording); 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; int delta = 0;
if (!Record && access(fileName, R_OK) != 0) { if (!Record && access(fileName, R_OK) != 0) {
// Index file doesn't exist, so try to regenerate it: // Index file doesn't exist, so try to regenerate it:

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __RECORDING_H
@ -279,7 +279,7 @@ private:
void ConvertToPes(tIndexTs *IndexTs, int Count); void ConvertToPes(tIndexTs *IndexTs, int Count);
bool CatchUp(int Index = -1); bool CatchUp(int Index = -1);
public: public:
cIndexFile(const char *FileName, bool Record, bool IsPesRecording = false); cIndexFile(const char *FileName, bool Record, bool IsPesRecording = false, bool PauseLive = false);
~cIndexFile(); ~cIndexFile();
bool Ok(void) { return index != NULL; } bool Ok(void) { return index != NULL; }
bool Write(bool Independent, uint16_t FileNumber, off_t FileOffset); bool Write(bool Independent, uint16_t FileNumber, off_t FileOffset);

10
tools.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "tools.h"
@ -563,6 +563,14 @@ time_t LastModifiedTime(const char *FileName)
return 0; 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::cTimeMs(int Ms) cTimeMs::cTimeMs(int Ms)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __TOOLS_H
@ -224,6 +224,7 @@ char *ReadLink(const char *FileName); ///< returns a new string allocated on the
bool SpinUpDisk(const char *FileName); bool SpinUpDisk(const char *FileName);
void TouchFile(const char *FileName); void TouchFile(const char *FileName);
time_t LastModifiedTime(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(int WeekDay);
cString WeekDayName(time_t t); cString WeekDayName(time_t t);
cString WeekDayNameFull(int WeekDay); cString WeekDayNameFull(int WeekDay);

3
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.tvdr.de * 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 <getopt.h> #include <getopt.h>
@ -1160,7 +1160,6 @@ int main(int argc, char *argv[])
} }
switch (state) { switch (state) {
case osPause: DELETE_MENU; case osPause: DELETE_MENU;
cControl::Shutdown(); // just in case
if (!cRecordControls::PauseLiveVideo()) if (!cRecordControls::PauseLiveVideo())
Skins.Message(mtError, tr("No free DVB device to record!")); Skins.Message(mtError, tr("No free DVB device to record!"));
break; break;