コード例 #1
0
ファイル: TsDuration.cpp プロジェクト: BMOTech/MediaPortal-1
//*********************************************************
// Determines the total duration of the file (or timeshifting files)
// 
// 
void CTsDuration::UpdateDuration(bool logging)
{
  if (!m_pFileReadBuffer)
  {
    m_startPcr.Reset();
    m_endPcr.Reset();
    LogDebug("CTsDuration::UpdateDuration() - ERROR no buffer !!");
    return;
  }

  int Loop=5 ;
  int searchLoopCnt;

  do
  {
    m_bSearchStart=true;
    m_bSearchEnd=false;
    m_startPcr.Reset();
    m_endPcr.Reset();
    m_maxPcr.Reset();
    searchLoopCnt = 2;
    __int64 offset=0;

    Reset() ; // Reset internal "PacketSync" buffer

    if (logging)
    {
      LogDebug("UpdateDuration - find pcr");
    }
    //find the first pcr in the file
    while (!m_startPcr.IsValid)
    {     
      if (m_bStopping) 
      {
        m_startPcr.Reset();
        m_endPcr.Reset();
        return;
      }
      DWORD dwBytesRead = 0;
      m_reader->SetFilePointer(offset,FILE_BEGIN);
      if (!SUCCEEDED(m_reader->Read(m_pFileReadBuffer,DUR_READ_SIZE,&dwBytesRead)))
      {
        return;
      }
      if (dwBytesRead<=0) 
      {
        return;
      }
      OnRawData2(m_pFileReadBuffer,dwBytesRead);
      
      offset += (DUR_READ_SIZE*(searchLoopCnt/2)); //Move file pointer
      
      if (searchLoopCnt<65)
      {
        searchLoopCnt++;
      }
      else if (m_videoPid<0)
      {
        //failed to find a first PCR
        return;
      }     
      else
      {
        //Search for any PCR from the beginning again
        m_videoPid = -1;
        searchLoopCnt = 2;
        offset = 0;
        Reset() ; // Reset internal "PacketSync" buffer
      }     
      
			Sleep(1) ;
    }

    if (logging)
    {
      LogDebug("UpdateDuration - found startPcr, iterations:%d offset:%d", searchLoopCnt-2, offset);
    }
    //find the last pcr in the file
    m_bSearchEnd=true;
    m_bSearchStart=false;
    searchLoopCnt = 2;
    offset=DUR_READ_SIZE;
  
    while (!m_endPcr.IsValid)
    {
      if (m_bStopping) 
      {
        m_startPcr.Reset();
        m_endPcr.Reset();
        return;
      }
      DWORD dwBytesRead = 0;
      m_reader->SetFilePointer(-offset,FILE_END);
      if (!SUCCEEDED(m_reader->Read(m_pFileReadBuffer,DUR_READ_SIZE,&dwBytesRead)))
      {
        m_startPcr.Reset();
        m_endPcr.Reset();
        return;
      }
      if (dwBytesRead<=0) 
      {
        m_startPcr.Reset();
        m_endPcr.Reset();
        return;
      }
      Reset() ; // Reset internal "PacketSync" buffer
      OnRawData2(m_pFileReadBuffer,dwBytesRead);
      if (searchLoopCnt<65)
      {
        searchLoopCnt++;
      }
      else
      {
        //failed to find an end PCR
        m_startPcr.Reset();
        m_endPcr.Reset();
        return;
      }
      offset += ( (DUR_READ_SIZE*(searchLoopCnt/2)) - (188*16)); //step back a few packets less than a buffer so that buffers overlap
			Sleep(1) ;
    }
    if (logging)
    {
      LogDebug("UpdateDuration - found endPcr, iterations:%d offset:%d", searchLoopCnt-2, offset);
    }

    Loop-- ;
    if(m_endPcr.PcrReferenceBase < m_startPcr.PcrReferenceBase)
		{
			if (Loop < 4)		// Show log on 2nd wrong detection.
				LogDebug("Abnormal start PCR, endPcr %I64d, startPcr %I64d",m_endPcr.PcrReferenceBase, m_startPcr.PcrReferenceBase);
			Sleep(20) ;
		}
  }
  while ((m_endPcr.PcrReferenceBase < m_startPcr.PcrReferenceBase) && Loop) ;
    // When startPcr > endPcr, it could be a result of wrong file used to find "startPcr".
    // If this file is just reused by TsWriter, and list buffer not updated yet, the search will operate
    // in the latest ts packets received causing the start higher the end ( readed in the previous buffer )
    // The only thing to do to discriminate an error and a real rollover is to re-search startPcr. 
    // Entering the following code with erroneous startPcr > endPcr makes an endless loop !!
    // The startPcr read can also failed when it occurs between deleting and reusing the ts buffer.
    // This abort the method. Duration will be updated on next call.
  if (Loop==0)
    LogDebug("PCR rollover normally found ! endPcr %I64d, startPcr %I64d",m_endPcr.PcrReferenceBase, m_startPcr.PcrReferenceBase);
  else
  {
    if(Loop<3)  // 1 failed + 1 succeded is quasi-normal, more is a bit suspicious ( disk drive too slow or problem ? )
      LogDebug("Recovered wrong start PCR, seek to 'begin' on reused file ! ( Retried %d times )",4-Loop) ;
  }

  //When the last pcr < first pcr then a pcr roll over occured
  //find where in the file this rollover happened
  //and fill maxPcr
  if (m_endPcr.PcrReferenceBase < m_startPcr.PcrReferenceBase)
  {
    m_maxPcr.PcrReferenceBase = 0x1ffffffffULL;
    m_maxPcr.PcrReferenceExtension = 0x1ffULL;
    m_maxPcr.IsValid = true;
  }
  
}
コード例 #2
0
ファイル: TsFileSeek.cpp プロジェクト: Benoire/MediaPortal-1
//*********************************************************
// Seeks in the file to the specific timestamp
// refTime : timestamp. Should be 0 < timestamp < duration
//
// The method will make a guess where the timestamp is located in the file
// and do a PCR seek from there until it finds the correct timestamp
//
bool CTsFileSeek::Seek(CRefTime refTime)
{
  double fileDuration=(double)m_duration.Duration().Millisecs();
  double seekTimeStamp=(double)refTime.Millisecs();
  
  //sanity checks...
  if (seekTimeStamp < 0) seekTimeStamp=0;
  //if (seekTimeStamp > fileDuration) seekTimeStamp=fileDuration;

  //make a guess where should start looking in the file
  double percent=seekTimeStamp/fileDuration;
  __int64 filePos=(__int64)(m_reader->GetFileSize()*percent);

  filePos/=188;
  filePos*=188;

  seekTimeStamp /= 1000.0f; // convert to seconds.

  m_seekPid=m_duration.GetPid();
  LogDebug("FileSeek: seek to %f filepos:%x pid:%x", seekTimeStamp,(DWORD)filePos, m_seekPid);
  
  byte buffer[188*10];
  __int64 binaryMax=m_reader->GetFileSize();
  __int64 binaryMin=0;
  __int64 lastFilePos=0;
  int seekingIteration=0;
  __int64 firstFilePos=filePos;
  int noPCRIteration=0;
  bool noPCRloop = false;

  Reset() ;   // Reset "PacketSync"
  while (true)
  {
    //sanity checks
    if (filePos<=0)
    {
      //no need to seek for timestamp 0,
      //simply set the pointer at the beginning of the file
      m_reader->SetFilePointer(0,FILE_BEGIN);
      return false;
    }
    if (filePos+sizeof(buffer) > m_reader->GetFileSize())
    {
      //no need to seek when we want to seek to end of file
      //simply set the pointer at the end of the file
      m_reader->SetFilePointer(0,FILE_END);
      return false;
    }

    //set filepointer to filePos
    m_reader->SetFilePointer(filePos,FILE_BEGIN);

    //read buffer from file at position filePos
    DWORD dwBytesRead;
    if (!SUCCEEDED(m_reader->Read(buffer, sizeof(buffer),&dwBytesRead)))
    {
      LogDebug("FileSeek: read failed at filePos: %x - target time: %f, iterations: %d", (DWORD)filePos, seekTimeStamp, seekingIteration);
      return true;
    }
    if (dwBytesRead <= 0) //end-of-file
    {
      LogDebug("FileSeek: end-of-file at filePos: %x - target time: %f, iterations: %d", (DWORD)filePos, seekTimeStamp, seekingIteration);
      return true;
    }
    //process data
    m_pcrFound.Reset();
    OnRawData2(buffer,dwBytesRead);

    //did we find a pcr?
    if (m_pcrFound.IsValid)
    {
      //yes. pcr found
      double clockFound=m_pcrFound.ToClock();
      double diff = clockFound - seekTimeStamp;
      //LogDebug(" got %f at filepos %x diff %f ( %I64x, %I64x )", clockFound, (DWORD)filePos, diff, binaryMin, binaryMax);

      // Make sure that seeking position is at least the target one
      if (0 <= diff && diff <= SEEKING_ACCURACY)
      {
        LogDebug("FileSeek: stop seek: %f at %x - target: %f, diff: %f, iterations: %d",
          clockFound, (DWORD)filePos, seekTimeStamp, diff, seekingIteration);
        m_reader->SetFilePointer(filePos,FILE_BEGIN);
        return false;
      }

      noPCRIteration = 0;
      seekingIteration++;
      if( seekingIteration > MAX_SEEKING_ITERATIONS )
      {
        LogDebug("FileSeek: stop seek max iterations reached (%d): %f at %x - target: %f, diff: %f",
          MAX_SEEKING_ITERATIONS, clockFound, (DWORD)filePos, seekTimeStamp, diff);
          
        if (fabs(diff) < 2.0)
        {
          m_reader->SetFilePointer(filePos,FILE_BEGIN);
        }
        else
        {
          //Set the file pointer to the initial estimate - the best we can do...
          m_reader->SetFilePointer(firstFilePos,FILE_BEGIN);
        }
        return false;
      }

      // lower bound becomes valid
      if( clockFound > seekTimeStamp )
      {
        if (filePos < binaryMax) binaryMax = filePos-1;
      }
      else
      {
        if (filePos > binaryMin) binaryMin = filePos+1;
      }

      lastFilePos=filePos;
      filePos = binaryMin + ( binaryMax - binaryMin ) / 2;
      filePos/=188;
      filePos*=188;

      if (lastFilePos==filePos)
      {
        LogDebug("FileSeek: stop seek closer target found : %f at %x - target: %f, diff: %f",
          clockFound, (DWORD)filePos, seekTimeStamp, diff);
        m_reader->SetFilePointer(filePos,FILE_BEGIN);
        return false;
      }

      Reset() ;   // Random jump, Reset "PacketSync"
    }
    else // no first PCR
    {
      //move filepointer forward and continue searching for a PCR
      filePos += sizeof(buffer);
      noPCRIteration++;
      if (noPCRIteration > MAX_BUFFER_ITERATIONS)
      {
        if (noPCRloop) //second time this has happened
        {
          LogDebug("FileSeek: stop seek, no PCR found, max iterations reached (%d)", MAX_BUFFER_ITERATIONS);
          //Set the file pointer to the initial estimate - the best we can do...
          m_reader->SetFilePointer(firstFilePos,FILE_BEGIN);
          return false;
        }
        //Let's try looking for any PCR pid 
        //starting again from the initial position
        LogDebug("FileSeek: No PCR found (pid = %d), trying for any PCR pid", m_seekPid);
        m_seekPid = -1;
        filePos = firstFilePos;
        noPCRIteration = 0;
        noPCRloop = true;
      }
    }
  }
  return false;
}