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