Mailing List archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[vdr] Re: High CPU Load @ replay
Am Freitag, 14. Februar 2003 16:01 schrieb Klaus Schmidinger:
> Are Årseth wrote:
> > > when replaying recordings with vdr-1.1.23 & 24 my VDR consumes a whole
> > > lot of CPU power (~40% of a PIII Tualatin 1,13). The thread seems to be
> > > the one called "dvbplayer". Could this behaviour have anything to to
> > > with the newly introduced "non blocking file reader"?
I confirm this. I just took the dvbplayer.c from 1.1.20, recompiled and the
CPU load is normal again. (with 1.1.24 ~40% on Tualatin 1,2, driver from 23.12.2002,
_not_ the ci driver from 2003).
I compared the two versions with gcov.
Below is the gcov output of the Action() function of dvbplayer.c 1.1.24 after quite
exactly 55 seconds of replay. There are 5.5 million loops and it seems
that PlayVideo is called 5.5 million times although there are only 1490 frames
put in the ringbuffer (?)
void cDvbPlayer::Action(void)
1 {
1 dsyslog("dvbplayer thread started (pid=%d)", getpid());
1 uchar *b = NULL;
1 const uchar *p = NULL;
1 int pc = 0;
1 readIndex = Resume();
1 if (readIndex >= 0)
1 isyslog("resuming replay at index %d (%s)", readIndex, IndexToHMSF(readIndex, true));
1 nonBlockingFileReader = new cNonBlockingFileReader;
1 int Length = 0;
1 int AudioTrack = 0; // -1 = any, 0 = none, >0 = audioTrack
1 running = true;
5593014 while (running && (NextFile() || readIndex >= 0 || ringBuffer->Available())) {
5593013 cPoller Poller;
5593013 if (!readFrame)
5589102 Poller.Add(replayFile, false);
5593013 if (DevicePoll(Poller, 100)) {
5593007 LOCK_THREAD;
// Read the next frame from the file:
5593007 if (!readFrame && (replayFile >= 0 || readIndex >= 0)) {
5589103 if (playMode != pmStill) {
5589103 if (!nonBlockingFileReader->Reading()) {
1491 if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) {
###### uchar FileNumber;
###### int FileOffset;
###### int Index = index->GetNextIFrame(readIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length, true);
###### if (Index >= 0) {
###### if (!NextFile(FileNumber, FileOffset))
###### continue;
}
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;
###### AudioTrack = 0;
// must clear all audio packets because the buffer is not emptied
// when falling back from "fast forward" to "play" (see above)
}
1491 else if (index) {
1491 uchar FileNumber;
1491 int FileOffset;
1491 readIndex++;
1491 if (!(index->Get(readIndex, &FileNumber, &FileOffset, NULL, &Length) && NextFile(FileNumber, FileOffset))) {
###### readIndex = -1;
###### eof = true;
###### continue;
}
1491 AudioTrack = audioTrack;
}
else { // allows replay even if the index file is missing
###### Length = MAXFRAMESIZE;
###### AudioTrack = -1;
}
1491 if (Length == -1)
###### Length = MAXFRAMESIZE; // this means we read up to EOF (see cIndex)
1491 else if (Length > MAXFRAMESIZE) {
###### esyslog("ERROR: frame larger than buffer (%d > %d)", Length, MAXFRAMESIZE);
###### Length = MAXFRAMESIZE;
}
1491 b = MALLOC(uchar, Length);
}
5589103 int r = nonBlockingFileReader->Read(replayFile, b, Length);
5589103 if (r > 0) {
1491 if (AudioTrack >= 0)
1491 StripAudioPackets(b, r, AudioTrack);
1491 readFrame = new cFrame(b, -r, ftUnknown, readIndex); // hands over b to the ringBuffer
1491 b = NULL;
}
5587612 else if (r == 0)
###### eof = true;
5587612 else if (r < 0 && FATALERRNO) {
###### LOG_ERROR;
###### break;
}
}
else//XXX
###### usleep(1); // this keeps the CPU load low
}
// Store the frame in the buffer:
5593007 if (readFrame) {
5395 if (ringBuffer->Put(readFrame))
1490 readFrame = NULL;
}
// Get the next frame from the buffer:
5593007 if (!playFrame) {
30175 playFrame = ringBuffer->Get();
30175 p = NULL;
30175 pc = 0;
}
// Play the frame:
5593007 if (playFrame) {
5564212 if (!p) {
1380 p = playFrame->Data();
1380 pc = playFrame->Count();
}
5564212 if (p) {
5564212 int w = PlayVideo(p, pc);
5564212 if (w > 0) {
6289 p += w;
6289 pc -= w;
}
5557923 else if (w < 0 && FATALERRNO) {
###### LOG_ERROR;
###### break;
}
}
5564212 if (pc == 0) {
1379 writeIndex = playFrame->Index();
1379 backTrace->Add(playFrame->Index(), playFrame->Count());
1379 ringBuffer->Drop(playFrame);
1379 playFrame = NULL;
1379 p = 0;
}
}
}
}
1 active = running = false;
1 cNonBlockingFileReader *nbfr = nonBlockingFileReader;
1 nonBlockingFileReader = NULL;
1 delete nbfr;
1 dsyslog("dvbplayer thread ended (pid=%d)", getpid());
}
Now the gcov output of the 1.1.20 file after 31 seconds of replay.
It is pretty obvious that there is a factor of 500 between the versions.
1 {
1 dsyslog("dvbplayer thread started (pid=%d)", getpid());
1 uchar b[MAXFRAMESIZE];
1 const uchar *p = NULL;
1 int pc = 0;
1 readIndex = Resume();
1 if (readIndex >= 0)
1 isyslog("resuming replay at index %d (%s)", readIndex, IndexToHMSF(readIndex, true));
1 running = true;
4612 while (running && (NextFile() || readIndex >= 0 || ringBuffer->Available())) {
4611 cPoller Poller;
4611 if (!readFrame)
849 Poller.Add(replayFile, false);
4611 if (DevicePoll(Poller, 100)) {
4604 LOCK_THREAD;
// Read the next frame from the file:
4604 if (!readFrame && (replayFile >= 0 || readIndex >= 0)) {
849 if (playMode != pmStill) {
849 int r = 0;
849 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))
###### continue;
}
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);
}
849 else if (index) {
849 uchar FileNumber;
849 int FileOffset, Length;
849 readIndex++;
849 if (!(index->Get(readIndex, &FileNumber, &FileOffset, NULL, &Length) && NextFile(FileNumber, FileOffset))) {
###### readIndex = -1;
###### eof = true;
###### continue;
}
849 r = ReadFrame(replayFile, b, Length, sizeof(b));
849 StripAudioPackets(b, r, audioTrack);
}
else // allows replay even if the index file is missing
###### r = read(replayFile, b, sizeof(b));
849 if (r > 0)
849 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
}
// Store the frame in the buffer:
4604 if (readFrame) {
4604 if (ringBuffer->Put(readFrame))
848 readFrame = NULL;
}
// Get the next frame from the buffer:
4604 if (!playFrame) {
786 playFrame = ringBuffer->Get();
786 p = NULL;
786 pc = 0;
}
// Play the frame:
4604 if (playFrame) {
4604 if (!p) {
786 p = playFrame->Data();
786 pc = playFrame->Count();
}
4604 if (p) {
4604 int w = PlayVideo(p, pc);
4604 if (w > 0) {
3781 p += w;
3781 pc -= w;
}
823 else if (w < 0 && FATALERRNO) {
###### LOG_ERROR;
###### break;
}
}
4604 if (pc == 0) {
785 writeIndex = playFrame->Index();
785 backTrace->Add(playFrame->Index(), playFrame->Count());
785 ringBuffer->Drop(playFrame);
785 playFrame = NULL;
785 p = 0;
}
}
}
}
1 active = running = false;
1 dsyslog("dvbplayer thread ended (pid=%d)", getpid());
}
Marcel
--
Info:
To unsubscribe send a mail to listar@linuxtv.org with "unsubscribe vdr" as subject.
Home |
Main Index |
Thread Index