Пример #1
0
void cBufferRecorder::FillInitialData(uchar *Data, int Size) {
	if(liveBufferIndex) {
		int64_t search_pts = Data ? TsGetPts(Data, Size) : -1;
		int maxWait = WAIT_WRITING_COUNT;
		uchar buffer[MAXFRAMESIZE];
		int Length;
		bool Independent;
		bool found = false;
		while(Running() && (!Data || (Size >= TS_SIZE))) {
			cUnbufferedFile *file = ((cLiveIndex *)liveBufferIndex)->GetNextBuffer(Length, Independent);
			if(!file) {
				if(((cLiveIndex *)liveBufferIndex)->WritingBufferCanceled()) {
					isyslog("Writing buffer canceled by user");
					if(fileSize) TsSetTeiOnBrokenPackets(Data, Size);
					((cLiveIndex *)liveBufferIndex)->SetBufferStart(0);
					liveBufferIndex = NULL;
					return;
				} // if
				if(!Data || !Size) return;
				if(!maxWait--)
					break;
				usleep(WAIT_WRITING_SLEEP);
				continue;
			} // if
			if (!NextFile())
				break;
			int len = ReadFrame(file, buffer, Length, sizeof(buffer));
			if(len < TS_SIZE) {
				isyslog("Failed to read live buffer data");
				break;
			} // if
			if(Data && Independent && (search_pts == TsGetPts(buffer, len))) {
				found = true;
				break;
			} // if
			if (index)
				index->Write(Independent, fileName->Number(), fileSize);
			if (recordFile->Write(buffer, len) < 0) {
				isyslog("Failed to write live buffer data");
				break;
			} // if
			fileSize += len;
		} // while
		if(Data) {
			isyslog("%lld bytes from live buffer %swritten to recording", fileSize, found ? "seamless ": "");
			if(!found && fileSize) TsSetTeiOnBrokenPackets(Data, Size);
			((cLiveIndex *)liveBufferIndex)->SetBufferStart(0);
			liveBufferIndex = NULL;
		} else if(((cLiveIndex *)liveBufferIndex)->WritingBufferCanceled()) {
			isyslog("%lld bytes from live buffer written to recording (aborted)", fileSize);
			((cLiveIndex *)liveBufferIndex)->SetBufferStart(0);
			liveBufferIndex = NULL;
		} // if
	} else if (Data && fileSize)
		TsSetTeiOnBrokenPackets(Data, Size);
} // cBufferRecorder::FillInitialData
Пример #2
0
void cDvbPlayer::Goto(int Index, bool Still)
{
  if (index) {
     LOCK_THREAD;
     Empty();
     if (++Index <= 0)
        Index = 1; // not '0', to allow GetNextIFrame() below to work!
     uint16_t FileNumber;
     off_t FileOffset;
     int Length;
     Index = index->GetNextIFrame(Index, false, &FileNumber, &FileOffset, &Length);
     if (Index >= 0 && NextFile(FileNumber, FileOffset) && Still) {
        uchar b[MAXFRAMESIZE];
        int r = ReadFrame(replayFile, b, Length, sizeof(b));
        if (r > 0) {
           if (playMode == pmPause)
              DevicePlay();
           DeviceStillPicture(b, r);
           ptsIndex.Put(isPesRecording ? PesGetPts(b) : TsGetPts(b, r), Index);
           }
        playMode = pmStill;
        }
     readIndex = Index;
     }
}
Пример #3
0
void cDvbPlayer::Action(void)
{
  uchar *p = NULL;
  int pc = 0;

  readIndex = Resume();
  if (readIndex >= 0)
     isyslog("resuming replay at index %d (%s)", readIndex, *IndexToHMSF(readIndex, true, framesPerSecond));

  nonBlockingFileReader = new cNonBlockingFileReader;
  int Length = 0;
  bool Sleep = false;
  bool WaitingForData = false;
  time_t StuckAtEof = 0;
  uint32_t LastStc = 0;
  int LastReadIFrame = -1;
  int SwitchToPlayFrame = 0;

  if (pauseLive)
     Goto(0, true);
  while (Running()) {
        if (WaitingForData)
           nonBlockingFileReader->WaitForDataMs(3); // this keeps the CPU load low, but reacts immediately on new data
        else if (Sleep) {
           cPoller Poller;
           DevicePoll(Poller, 10);
           Sleep = false;
           if (playMode == pmStill || playMode == pmPause)
              cCondWait::SleepMs(3);
           }
        {
          LOCK_THREAD;

          // Read the next frame from the file:

          if (playMode != pmStill && playMode != pmPause) {
             if (!readFrame && (replayFile || readIndex >= 0)) {
                if (!nonBlockingFileReader->Reading()) {
                   if (!SwitchToPlayFrame && (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward))) {
                      uint16_t FileNumber;
                      off_t FileOffset;
                      bool TimeShiftMode = index->IsStillRecording();
                      int Index = -1;
                      readIndependent = false;
                      if (DeviceHasIBPTrickSpeed() && playDir == pdForward) {
                         if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length))
                            Index = readIndex + 1;
                         }
                      else {
                         int d = int(round(0.4 * framesPerSecond));
                         if (playDir != pdForward)
                            d = -d;
                         int NewIndex = readIndex + d;
                         if (NewIndex <= 0 && readIndex > 0)
                            NewIndex = 1; // make sure the very first frame is delivered
                         NewIndex = index->GetNextIFrame(NewIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length);
                         if (NewIndex < 0 && TimeShiftMode && playDir == pdForward)
                            SwitchToPlayFrame = readIndex;
                         Index = NewIndex;
                         readIndependent = true;
                         }
                      if (Index >= 0) {
                         readIndex = Index;
                         if (!NextFile(FileNumber, FileOffset))
                            continue;
                         }
                      else if (!(TimeShiftMode && playDir == pdForward))
                         eof = true;
                      }
                   else if (index) {
                      uint16_t FileNumber;
                      off_t FileOffset;
                      if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length) && NextFile(FileNumber, FileOffset))
                         readIndex++;
                      else
                         eof = true;
                      }
                   else // allows replay even if the index file is missing
                      Length = MAXFRAMESIZE;
                   if (Length == -1)
                      Length = MAXFRAMESIZE; // this means we read up to EOF (see cIndex)
                   else if (Length > MAXFRAMESIZE) {
                      esyslog("ERROR: frame larger than buffer (%d > %d)", Length, MAXFRAMESIZE);
                      Length = MAXFRAMESIZE;
                      }
                   if (!eof)
                      nonBlockingFileReader->Request(replayFile, Length);
                   }
                if (!eof) {
                   uchar *b = NULL;
                   int r = nonBlockingFileReader->Result(&b);
                   if (r > 0) {
                      WaitingForData = false;
                      uint32_t Pts = 0;
                      if (readIndependent) {
                         Pts = isPesRecording ? PesGetPts(b) : TsGetPts(b, r);
                         LastReadIFrame = readIndex;
                         }
                      readFrame = new cFrame(b, -r, ftUnknown, readIndex, Pts); // hands over b to the ringBuffer
                      }
                   else if (r < 0) {
                      if (errno == EAGAIN)
                         WaitingForData = true;
                      else if (FATALERRNO) {
                         LOG_ERROR;
                         break;
                         }
                      }
                   else
                      eof = true;
                   }
                }

             // Store the frame in the buffer:

             if (readFrame) {
                if (ringBuffer->Put(readFrame))
                   readFrame = NULL;
                else
                   Sleep = true;
                }
             }
          else
             Sleep = true;

          if (dropFrame) {
             if (!eof || (playDir != pdForward && dropFrame->Index() > 0) || (playDir == pdForward && dropFrame->Index() < readIndex)) {
                ringBuffer->Drop(dropFrame); // the very first and last frame are continously repeated to flush data through the device
                dropFrame = NULL;
                }
             }

          // Get the next frame from the buffer:

          if (!playFrame) {
             playFrame = ringBuffer->Get();
             p = NULL;
             pc = 0;
             }

          // Play the frame:

          if (playFrame) {
             if (!p) {
                p = playFrame->Data();
                pc = playFrame->Count();
                if (p) {
                   if (playFrame->Index() >= 0 && playFrame->Pts() != 0)
                      ptsIndex.Put(playFrame->Pts(), playFrame->Index());
                   if (firstPacket) {
                      if (isPesRecording) {
                         PlayPes(NULL, 0);
                         cRemux::SetBrokenLink(p, pc);
                         }
                      else
                         PlayTs(NULL, 0);
                      firstPacket = false;
                      }
                   }
                }
             if (p) {
                int w;
                if (isPesRecording)
                   w = PlayPes(p, pc, playMode != pmPlay && !(playMode == pmSlow && playDir == pdForward) && DeviceIsPlayingVideo());
                else
                   w = PlayTs(p, pc, playMode != pmPlay && !(playMode == pmSlow && playDir == pdForward) && DeviceIsPlayingVideo());
                if (w > 0) {
                   p += w;
                   pc -= w;
                   }
                else if (w < 0 && FATALERRNO)
                   LOG_ERROR;
                else
                   Sleep = true;
                }
             if (pc <= 0) {
                dropFrame = playFrame;
                playFrame = NULL;
                p = NULL;
                }
             }
          else
             Sleep = true;

          // Handle hitting begin/end of recording:

          if (eof || SwitchToPlayFrame) {
             bool SwitchToPlay = false;
             uint32_t Stc = DeviceGetSTC();
             if (Stc != LastStc)
                StuckAtEof = 0;
             else if (!StuckAtEof)
                StuckAtEof = time(NULL);
             else if (time(NULL) - StuckAtEof > MAXSTUCKATEOF) {
                if (playDir == pdForward)
                   break; // automatically stop at end of recording
                SwitchToPlay = true;
                }
             LastStc = Stc;
             int Index = ptsIndex.FindIndex(Stc);
             if (playDir == pdForward && !SwitchToPlayFrame) {
                if (Index >= LastReadIFrame)
                   break; // automatically stop at end of recording
                }
             else if (Index <= 0 || SwitchToPlayFrame && Index >= SwitchToPlayFrame)
                SwitchToPlay = true;
             if (SwitchToPlay) {
                if (!SwitchToPlayFrame)
                   Empty();
                DevicePlay();
                playMode = pmPlay;
                playDir = pdForward;
                SwitchToPlayFrame = 0;
                }
             }
        }
        }

  cNonBlockingFileReader *nbfr = nonBlockingFileReader;
  nonBlockingFileReader = NULL;
  delete nbfr;
}