mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Using cPoller instead of NeedsData
This commit is contained in:
parent
038766dccd
commit
470415ad23
4
HISTORY
4
HISTORY
@ -1405,8 +1405,8 @@ Video Disk Recorder Revision History
|
||||
- Temporarily made cDevice::ProvidesCa() virtual (Andreas Schultz needs this
|
||||
in his DXR3 plugin).
|
||||
- cDevice no longer exposes a file handle to cPlayer. A derived cPlayer class
|
||||
can now call DeviceNeedsData() to see whether the replay device is ready for
|
||||
further data. A derived cDevice class must implement NeedsData() and shall
|
||||
can now call DevicePoll() to see whether the replay device is ready for
|
||||
further data. A derived cDevice class must implement Poll() and shall
|
||||
check if any of its file handles is ready for data.
|
||||
- Implemented several replay modes to allow players that play only audio (thanks
|
||||
to Stefan Huelswitt).
|
||||
|
@ -962,7 +962,7 @@ DVB device doesn't run out of data.
|
||||
To avoid busy loops the player should call its member function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
bool DeviceNeedsData(int Wait = 0);
|
||||
bool DevicePoll(cPoller &Poller, int TimeoutMs = 0);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
to determine whether the device is ready for further data.
|
||||
@ -1238,7 +1238,7 @@ virtual void Play(void);
|
||||
virtual void Freeze(void);
|
||||
virtual void Mute(void);
|
||||
virtual void StillPicture(const uchar *Data, int Length);
|
||||
virtual bool NeedsData(int Wait = 0);
|
||||
virtual bool Poll(cPoller &Poller, int TimeoutMs = 0);
|
||||
virtual int PlayVideo(const uchar *Data, int Length);
|
||||
</pre></td></tr></table><p>
|
||||
<!--X1.1.7--></td></tr></table>
|
||||
|
4
device.c
4
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 1.10 2002/08/15 10:30:08 kls Exp $
|
||||
* $Id: device.c 1.11 2002/08/16 08:52:56 kls Exp $
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
@ -397,7 +397,7 @@ void cDevice::StopReplay(void)
|
||||
}
|
||||
}
|
||||
|
||||
bool cDevice::NeedsData(int Wait)
|
||||
bool cDevice::Poll(cPoller &Poller, int TimeoutMs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
9
device.h
9
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 1.8 2002/08/15 11:09:21 kls Exp $
|
||||
* $Id: device.h 1.9 2002/08/16 08:52:27 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DEVICE_H
|
||||
@ -226,9 +226,10 @@ public:
|
||||
// Turns off audio while replaying.
|
||||
virtual void StillPicture(const uchar *Data, int Length);
|
||||
// Displays the given I-frame as a still picture.
|
||||
virtual bool NeedsData(int Wait = 0);
|
||||
// Returns true if the device needs further data for replaying.
|
||||
// If Wait is not zero, the device will wait up to the given number
|
||||
virtual bool Poll(cPoller &Poller, int TimeoutMs = 0);
|
||||
// Returns true if the device itself or any of the file handles in
|
||||
// Poller is ready for further action.
|
||||
// If TimeoutMs is not zero, the device will wait up to the given number
|
||||
// of milleseconds before returning in case there is no immediate
|
||||
// need for data.
|
||||
virtual int PlayVideo(const uchar *Data, int Length);
|
||||
|
17
dvbdevice.c
17
dvbdevice.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.c 1.5 2002/08/15 11:13:46 kls Exp $
|
||||
* $Id: dvbdevice.c 1.6 2002/08/16 09:22:29 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbdevice.h"
|
||||
@ -27,7 +27,6 @@ extern "C" {
|
||||
#include <ost/sec.h>
|
||||
#include <ost/video.h>
|
||||
#endif
|
||||
#include <poll.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include "dvbosd.h"
|
||||
@ -694,9 +693,10 @@ void cDvbDevice::StillPicture(const uchar *Data, int Length)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool cDvbDevice::NeedsData(int Wait)
|
||||
bool cDvbDevice::Poll(cPoller &Poller, int TimeoutMs)
|
||||
{
|
||||
return cFile::FileReadyForWriting(fd_video, Wait);
|
||||
Poller.Add(playMode == pmAudioOnly ? fd_audio : fd_video, true);
|
||||
return Poller.Poll(TimeoutMs);
|
||||
}
|
||||
|
||||
int cDvbDevice::PlayVideo(const uchar *Data, int Length)
|
||||
@ -731,13 +731,8 @@ void cDvbDevice::CloseDvr(void)
|
||||
int cDvbDevice::GetTSPacket(uchar *Data)
|
||||
{
|
||||
if (fd_dvr >= 0) {
|
||||
pollfd pfd;
|
||||
pfd.fd = fd_dvr;
|
||||
pfd.events = POLLIN;
|
||||
|
||||
poll(&pfd, 1, 100);
|
||||
|
||||
if (pfd.revents & POLLIN != 0) {
|
||||
cPoller Poller(fd_dvr, false);
|
||||
if (Poller.Poll(100)) {
|
||||
int r = read(fd_dvr, Data, TS_SIZE);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.h 1.4 2002/08/15 10:59:25 kls Exp $
|
||||
* $Id: dvbdevice.h 1.5 2002/08/16 08:53:30 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBDEVICE_H
|
||||
@ -92,7 +92,7 @@ public:
|
||||
virtual void Freeze(void);
|
||||
virtual void Mute(void);
|
||||
virtual void StillPicture(const uchar *Data, int Length);
|
||||
virtual bool NeedsData(int Wait = 0);
|
||||
virtual bool Poll(cPoller &Poller, int TimeoutMs = 0);
|
||||
virtual int PlayVideo(const uchar *Data, int Length);
|
||||
virtual int PlayAudio(const uchar *Data, int Length);
|
||||
|
||||
|
189
dvbplayer.c
189
dvbplayer.c
@ -4,11 +4,10 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbplayer.c 1.10 2002/08/15 10:00:28 kls Exp $
|
||||
* $Id: dvbplayer.c 1.11 2002/08/16 09:16:38 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbplayer.h"
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
#include "recording.h"
|
||||
#include "ringbuffer.h"
|
||||
@ -65,7 +64,7 @@ int cBackTrace::Get(bool Forward)
|
||||
p = BACKTRACE_ENTRIES - 1;
|
||||
i = index[p] - 1;
|
||||
l -= length[p];
|
||||
n--;
|
||||
n--;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@ -302,7 +301,6 @@ void cDvbPlayer::Action(void)
|
||||
uchar b[MAXFRAMESIZE];
|
||||
const uchar *p = NULL;
|
||||
int pc = 0;
|
||||
bool CanWrite = true;
|
||||
|
||||
readIndex = Resume();
|
||||
if (readIndex >= 0)
|
||||
@ -310,103 +308,106 @@ void cDvbPlayer::Action(void)
|
||||
|
||||
running = true;
|
||||
while (running && NextFile()) {
|
||||
{
|
||||
LOCK_THREAD;
|
||||
cPoller Poller;
|
||||
if (!readFrame)
|
||||
Poller.Add(replayFile, false);
|
||||
if (DevicePoll(Poller, 100)) {
|
||||
|
||||
// Read the next frame from the file:
|
||||
LOCK_THREAD;
|
||||
|
||||
if (!readFrame) {
|
||||
if (playMode != pmStill) {
|
||||
int r = 0;
|
||||
if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) {
|
||||
uchar FileNumber;
|
||||
int FileOffset, Length;
|
||||
int Index = index->GetNextIFrame(readIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length, true);
|
||||
if (Index >= 0) {
|
||||
if (!NextFile(FileNumber, FileOffset))
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// can't call Play() here, because those functions may only be
|
||||
// called from the foreground thread - and we also don't need
|
||||
// to empty the buffer here
|
||||
DevicePlay();
|
||||
playMode = pmPlay;
|
||||
playDir = pdForward;
|
||||
continue;
|
||||
}
|
||||
readIndex = Index;
|
||||
r = ReadFrame(replayFile, b, Length, sizeof(b));
|
||||
// must call StripAudioPackets() here because the buffer is not emptied
|
||||
// when falling back from "fast forward" to "play" (see above)
|
||||
StripAudioPackets(b, r);
|
||||
}
|
||||
else if (index) {
|
||||
uchar FileNumber;
|
||||
int FileOffset, Length;
|
||||
readIndex++;
|
||||
if (!(index->Get(readIndex, &FileNumber, &FileOffset, NULL, &Length) && NextFile(FileNumber, FileOffset)))
|
||||
break;
|
||||
r = ReadFrame(replayFile, b, Length, sizeof(b));
|
||||
}
|
||||
else // allows replay even if the index file is missing
|
||||
r = read(replayFile, b, sizeof(b));
|
||||
if (r > 0)
|
||||
readFrame = new cFrame(b, r, ftUnknown, readIndex);
|
||||
else if (r == 0)
|
||||
eof = true;
|
||||
else if (r < 0 && FATALERRNO) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else//XXX
|
||||
usleep(1); // this keeps the CPU load low
|
||||
}
|
||||
// Read the next frame from the file:
|
||||
|
||||
// Store the frame in the buffer:
|
||||
if (!readFrame) {
|
||||
if (playMode != pmStill) {
|
||||
int r = 0;
|
||||
if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) {
|
||||
uchar FileNumber;
|
||||
int FileOffset, Length;
|
||||
int Index = index->GetNextIFrame(readIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length, true);
|
||||
if (Index >= 0) {
|
||||
if (!NextFile(FileNumber, FileOffset))
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// can't call Play() here, because those functions may only be
|
||||
// called from the foreground thread - and we also don't need
|
||||
// to empty the buffer here
|
||||
DevicePlay();
|
||||
playMode = pmPlay;
|
||||
playDir = pdForward;
|
||||
continue;
|
||||
}
|
||||
readIndex = Index;
|
||||
r = ReadFrame(replayFile, b, Length, sizeof(b));
|
||||
// must call StripAudioPackets() here because the buffer is not emptied
|
||||
// when falling back from "fast forward" to "play" (see above)
|
||||
StripAudioPackets(b, r);
|
||||
}
|
||||
else if (index) {
|
||||
uchar FileNumber;
|
||||
int FileOffset, Length;
|
||||
readIndex++;
|
||||
if (!(index->Get(readIndex, &FileNumber, &FileOffset, NULL, &Length) && NextFile(FileNumber, FileOffset)))
|
||||
break;
|
||||
r = ReadFrame(replayFile, b, Length, sizeof(b));
|
||||
}
|
||||
else // allows replay even if the index file is missing
|
||||
r = read(replayFile, b, sizeof(b));
|
||||
if (r > 0)
|
||||
readFrame = new cFrame(b, r, ftUnknown, readIndex);
|
||||
else if (r == 0)
|
||||
eof = true;
|
||||
else if (r < 0 && FATALERRNO) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else//XXX
|
||||
usleep(1); // this keeps the CPU load low
|
||||
}
|
||||
|
||||
if (readFrame) {
|
||||
if (ringBuffer->Put(readFrame))
|
||||
readFrame = NULL;
|
||||
}
|
||||
// Store the frame in the buffer:
|
||||
|
||||
// Get the next frame from the buffer:
|
||||
|
||||
if (!playFrame) {
|
||||
playFrame = ringBuffer->Get();
|
||||
p = NULL;
|
||||
pc = 0;
|
||||
}
|
||||
if (readFrame) {
|
||||
if (ringBuffer->Put(readFrame))
|
||||
readFrame = NULL;
|
||||
}
|
||||
|
||||
// Play the frame:
|
||||
// Get the next frame from the buffer:
|
||||
|
||||
if (playFrame && CanWrite) {
|
||||
if (!p) {
|
||||
p = playFrame->Data();
|
||||
pc = playFrame->Count();
|
||||
}
|
||||
if (p) {
|
||||
int w = PlayVideo(p, pc);
|
||||
if (w > 0) {
|
||||
p += w;
|
||||
pc -= w;
|
||||
}
|
||||
else if (w < 0 && FATALERRNO) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pc == 0) {
|
||||
writeIndex = playFrame->Index();
|
||||
backTrace->Add(playFrame->Index(), playFrame->Count());
|
||||
ringBuffer->Drop(playFrame);
|
||||
playFrame = NULL;
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
CanWrite = DeviceNeedsData(readFrame ? 10 : 0);
|
||||
if (!playFrame) {
|
||||
playFrame = ringBuffer->Get();
|
||||
p = NULL;
|
||||
pc = 0;
|
||||
}
|
||||
|
||||
// Play the frame:
|
||||
|
||||
if (playFrame) {
|
||||
if (!p) {
|
||||
p = playFrame->Data();
|
||||
pc = playFrame->Count();
|
||||
}
|
||||
if (p) {
|
||||
int w = PlayVideo(p, pc);
|
||||
if (w > 0) {
|
||||
p += w;
|
||||
pc -= w;
|
||||
}
|
||||
else if (w < 0 && FATALERRNO) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pc == 0) {
|
||||
writeIndex = playFrame->Index();
|
||||
backTrace->Add(playFrame->Index(), playFrame->Count());
|
||||
ringBuffer->Drop(playFrame);
|
||||
playFrame = NULL;
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
active = running = false;
|
||||
|
||||
|
4
player.h
4
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 1.7 2002/08/15 11:10:09 kls Exp $
|
||||
* $Id: player.h 1.8 2002/08/16 09:14:12 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __PLAYER_H
|
||||
@ -19,7 +19,7 @@ private:
|
||||
cDevice *device;
|
||||
ePlayMode playMode;
|
||||
protected:
|
||||
bool DeviceNeedsData(int Wait = 0) { return device ? device->NeedsData(Wait) : false; }
|
||||
bool DevicePoll(cPoller &Poller, int TimeoutMs = 0) { return device ? device->Poll(Poller, TimeoutMs) : false; }
|
||||
void DeviceTrickSpeed(int Speed) { if (device) device->TrickSpeed(Speed); }
|
||||
void DeviceClear(void) { if (device) device->Clear(); }
|
||||
void DevicePlay(void) { if (device) device->Play(); }
|
||||
|
38
tools.c
38
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 1.69 2002/08/11 11:49:08 kls Exp $
|
||||
* $Id: tools.c 1.70 2002/08/16 08:52:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include "tools.h"
|
||||
@ -482,6 +482,42 @@ const char *DayDateTime(time_t t)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// --- cPoller ---------------------------------------------------------------
|
||||
|
||||
cPoller::cPoller(int FileHandle, bool Out)
|
||||
{
|
||||
numFileHandles = 0;
|
||||
Add(FileHandle, Out);
|
||||
}
|
||||
|
||||
bool cPoller::Add(int FileHandle, bool Out)
|
||||
{
|
||||
if (FileHandle >= 0) {
|
||||
for (int i = 0; i < numFileHandles; i++) {
|
||||
if (pfd[i].fd == FileHandle)
|
||||
return true;
|
||||
}
|
||||
if (numFileHandles < MaxPollFiles) {
|
||||
pfd[numFileHandles].fd = FileHandle;
|
||||
pfd[numFileHandles].events = Out ? POLLOUT : POLLIN;
|
||||
numFileHandles++;
|
||||
return true;
|
||||
}
|
||||
esyslog("ERROR: too many file handles in cPoller");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cPoller::Poll(int TimeoutMs)
|
||||
{
|
||||
if (numFileHandles) {
|
||||
if (poll(pfd, numFileHandles, TimeoutMs) != 0)
|
||||
return true; // returns true even in case of an error, to let the caller
|
||||
// access the file and thus see the error code
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// --- cFile -----------------------------------------------------------------
|
||||
|
||||
bool cFile::files[FD_SETSIZE] = { false };
|
||||
|
14
tools.h
14
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 1.48 2002/08/11 11:34:26 kls Exp $
|
||||
* $Id: tools.h 1.49 2002/08/16 08:52:01 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TOOLS_H
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
@ -76,6 +77,17 @@ bool SpinUpDisk(const char *FileName);
|
||||
const char *WeekDayName(int WeekDay); // returns a statically allocated string!
|
||||
const char *DayDateTime(time_t t = 0); // returns a statically allocated string!
|
||||
|
||||
class cPoller {
|
||||
private:
|
||||
enum { MaxPollFiles = 16 };
|
||||
pollfd pfd[MaxPollFiles];
|
||||
int numFileHandles;
|
||||
public:
|
||||
cPoller(int FileHandle = -1, bool Out = false);
|
||||
bool Add(int FileHandle, bool Out);
|
||||
bool Poll(int TimeoutMs = 0);
|
||||
};
|
||||
|
||||
class cFile {
|
||||
private:
|
||||
static bool files[];
|
||||
|
Loading…
Reference in New Issue
Block a user