From f9c1974f2de4b749ffc698f72331530c3adc65ea Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 25 Jan 2009 11:39:43 +0100 Subject: [PATCH] Improved fast-forward/-rewind for audio recordings --- HISTORY | 14 +++++++++++++- PLUGINS.html | 15 ++++++++++++--- device.c | 9 +++++++-- device.h | 6 +++++- dvbplayer.c | 20 +++++++++++++------- player.h | 3 ++- 6 files changed, 52 insertions(+), 15 deletions(-) diff --git a/HISTORY b/HISTORY index 8e768db0..88600b75 100644 --- a/HISTORY +++ b/HISTORY @@ -5912,7 +5912,7 @@ Video Disk Recorder Revision History can handle DVB-S2. The #define is still there to allow people with older drivers who don't need DVB-S2 to use this version without pathcing. -2009-01-24: Version 1.7.4 +2009-01-25: Version 1.7.4 - Removed the '#define FE_CAN_2ND_GEN_MODULATION', since it was wrong and the flag is now in the driver, anyway. @@ -5966,3 +5966,15 @@ Video Disk Recorder Revision History - The PAT/PMT is now only processed if its version changes (reported by Reinhard Nissl). - Fixed handling the maximum video file size (reported by Udo Richter). +- Improved fast-forward/-rewind for audio recordings. The actual data is now sent + to the output device, so that it can be replayed and thus cause the proper delay. + For pure audio recordings the audio is no longer muted in fast-forward/-rewind + mode, so that some orientation regarding the position within the recording is + possible. There may still be some offset in the replay position displayed by the + progress indicator when switching from fast-forward/-rewind to play mode, as well + as in the current position during normal play mode. This is due to the various + buffers between the player and the output device and will be addressed later. + Note the new function cDevice::IsPlayingVideo(), which is used to inform the + player whether there is video data in the currently replayed stream. If a derived + cDevice class reimplements PlayTs() or PlayPes(), it also needs to make sure this + new function works as expected. diff --git a/PLUGINS.html b/PLUGINS.html index 9dc48e7f..dfee7395 100644 --- a/PLUGINS.html +++ b/PLUGINS.html @@ -16,7 +16,10 @@ html, body { text-align: center; } .code { - background-color: #f0f0f0; + background-color: #F0F0F0; +} +.modified { + background-color: #FFDDDD; } @@ -25,12 +28,15 @@ html, body {

The VDR Plugin System

-Version 1.6 +Version 1.7

-Copyright © 2008 Klaus Schmidinger
+Copyright © 2009 Klaus Schmidinger
kls@cadsoft.de
www.cadsoft.de/vdr

+
+Important modifications introduced since version 1.6 are marked like this. +

VDR provides an easy to use plugin interface that allows additional functionality to be added to the program by implementing a dynamically loadable library file. @@ -1844,6 +1850,9 @@ virtual bool HasDecoder(void) const; virtual bool CanReplay(void) const; virtual bool SetPlayMode(ePlayMode PlayMode); virtual int64_t GetSTC(void); +

+virtual bool IsPlayingVideo(void) const; +
virtual bool HasIBPTrickSpeed(void); virtual void TrickSpeed(int Speed); virtual void Clear(void); diff --git a/device.c b/device.c index 23c0870a..1f806e02 100644 --- a/device.c +++ b/device.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.c 2.10 2009/01/24 13:40:54 kls Exp $ + * $Id: device.c 2.11 2009/01/25 11:10:56 kls Exp $ */ #include "device.h" @@ -81,6 +81,7 @@ cDevice::cDevice(void) startScrambleDetection = 0; player = NULL; + isPlayingVideo = false; ClrAvailableTracks(); currentAudioTrack = ttNone; currentAudioTrackMissingCount = 0; @@ -1099,6 +1100,7 @@ void cDevice::Detach(cPlayer *Player) SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat)); PlayTs(NULL, 0); Audios.ClearAudio(); + isPlayingVideo = false; } } @@ -1151,6 +1153,7 @@ int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly) switch (c) { case 0xBE: // padding stream, needed for MPEG1 case 0xE0 ... 0xEF: // video + isPlayingVideo = true; w = PlayVideo(Start, d); break; case 0xC0 ... 0xDF: // audio @@ -1322,8 +1325,10 @@ int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly) patPmtParser.ParsePat(Data, Length); else if (Pid == patPmtParser.PmtPid()) patPmtParser.ParsePmt(Data, Length); - else if (Pid == patPmtParser.Vpid()) + else if (Pid == patPmtParser.Vpid()) { + isPlayingVideo = true; return PlayTsVideo(Data, Length); + } else if (Pid == availableTracks[currentAudioTrack].id) { if (!VideoOnly || HasIBPTrickSpeed()) { int w = PlayTsAudio(Data, Length); diff --git a/device.h b/device.h index 13a77e39..67c9be44 100644 --- a/device.h +++ b/device.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.h 2.5 2009/01/10 10:04:30 kls Exp $ + * $Id: device.h 2.6 2009/01/25 11:04:39 kls Exp $ */ #ifndef __DEVICE_H @@ -477,6 +477,7 @@ private: cTsToPes tsToPesVideo; cTsToPes tsToPesAudio; cTsToPes tsToPesSubtitle; + bool isPlayingVideo; protected: virtual bool CanReplay(void) const; ///< Returns true if this device can currently start a replay session. @@ -542,6 +543,9 @@ public: ///< Gets the current System Time Counter, which can be used to ///< synchronize audio and video. If this device is unable to ///< provide the STC, -1 will be returned. + virtual bool IsPlayingVideo(void) const { return isPlayingVideo; } + ///< \return Returns true if the currently attached player has delivered + ///< any video packets. virtual bool HasIBPTrickSpeed(void) { return false; } ///< Returns true if this device can handle all frames in 'fast forward' ///< trick speeds. diff --git a/dvbplayer.c b/dvbplayer.c index 9e3cd2fd..6e004403 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.2 2009/01/24 11:42:07 kls Exp $ + * $Id: dvbplayer.c 2.3 2009/01/25 11:11:39 kls Exp $ */ #include "dvbplayer.h" @@ -412,8 +412,12 @@ void cDvbPlayer::Action(void) if (index->Get(readIndex + 1, &FileNumber, &FileOffset, NULL, &Length)) Index = readIndex + 1; } - else - Index = index->GetNextIFrame(readIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length, TimeShiftMode); + else { + int d = int(round(0.4 * framesPerSecond)); + if (playDir != pdForward) + d = -d; + Index = index->GetNextIFrame(readIndex + d, playDir == pdForward, &FileNumber, &FileOffset, &Length, TimeShiftMode); + } if (Index >= 0) { if (!NextFile(FileNumber, FileOffset)) { readIndex = Index; @@ -516,9 +520,9 @@ void cDvbPlayer::Action(void) if (p) { int w; if (isPesRecording) - w = PlayPes(p, pc, playMode != pmPlay); + w = PlayPes(p, pc, playMode != pmPlay && DeviceIsPlayingVideo()); else - w = PlayTs(p, TS_SIZE, playMode != pmPlay); + w = PlayTs(p, TS_SIZE, playMode != pmPlay && DeviceIsPlayingVideo()); if (w > 0) { p += w; pc -= w; @@ -593,7 +597,8 @@ void cDvbPlayer::Forward(void) LOCK_THREAD; if (!(DeviceHasIBPTrickSpeed() && playDir == pdForward)) Empty(); - DeviceMute(); + if (DeviceIsPlayingVideo()) + DeviceMute(); playMode = pmFast; playDir = pdForward; trickSpeed = NORMAL_SPEED; @@ -639,7 +644,8 @@ void cDvbPlayer::Backward(void) case pmPlay: { LOCK_THREAD; Empty(); - DeviceMute(); + if (DeviceIsPlayingVideo()) + DeviceMute(); playMode = pmFast; playDir = pdBackward; trickSpeed = NORMAL_SPEED; diff --git a/player.h b/player.h index 9bd5a368..d252c574 100644 --- a/player.h +++ b/player.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: player.h 2.2 2009/01/05 13:04:10 kls Exp $ + * $Id: player.h 2.3 2009/01/25 11:03:44 kls Exp $ */ #ifndef __PLAYER_H @@ -26,6 +26,7 @@ protected: bool DevicePoll(cPoller &Poller, int TimeoutMs = 0) { return device ? device->Poll(Poller, TimeoutMs) : false; } bool DeviceFlush(int TimeoutMs = 0) { return device ? device->Flush(TimeoutMs) : true; } bool DeviceHasIBPTrickSpeed(void) { return device ? device->HasIBPTrickSpeed() : false; } + bool DeviceIsPlayingVideo(void) { return device ? device->IsPlayingVideo() : false; } void DeviceTrickSpeed(int Speed) { if (device) device->TrickSpeed(Speed); } void DeviceClear(void) { if (device) device->Clear(); } void DevicePlay(void) { if (device) device->Play(); }