Exemple #1
0
STDMETHODIMP CBDReaderFilter::GetDuration(REFERENCE_TIME* pDuration)
{
  if (!pDuration)
    return E_INVALIDARG;

  ULONGLONG pos = 0, dur = 0;

  if (lib.CurrentPosition(pos, dur))
    *pDuration = CONVERT_90KHz_DS(dur);
  else
    pDuration = 0;

  return NOERROR;
}
void COverlayRenderer::OverlayProc(const BD_OVERLAY* ov)
{
  if (!ov)
    return;
  
  if (ov->cmd == BD_OVERLAY_CLOSE || ov->cmd == BD_OVERLAY_INIT)
  {
    ProcessOverlay(ov);
    return;
  }

  BD_OVERLAY_EX *copy = (BD_OVERLAY_EX*)malloc(sizeof(BD_OVERLAY_EX));
  if (!copy)
    return;

  memcpy(copy, ov, sizeof(*ov));
  copy->scheduled = false;

  if (ov->palette) 
  {
    copy->palette = (BD_PG_PALETTE_ENTRY*)malloc(PALETTE_SIZE * sizeof(BD_PG_PALETTE_ENTRY));
    memcpy((void*)copy->palette, ov->palette, PALETTE_SIZE * sizeof(BD_PG_PALETTE_ENTRY));
  }

  if (copy->img)
    m_pLib->IncreaseRefCount(copy->img);

  {
#ifdef LOG_DRAWING
    LogDebug("new arriva PTS: %6.3f wait: %6.3f", (CONVERT_90KHz_DS(copy->pts)) / 10000000.0);
#endif

    CAutoLock queueLock(&m_csOverlayQueue);

    m_overlayQueue[copy->plane].push_back(copy);
    SetEvent(m_hNewOverlayAvailable);
  }
}
 bool COverlayRenderer::NextScheduleTime(REFERENCE_TIME& rtPts, UINT8 plane)
{
  if (!m_overlayQueue[plane].empty())
  {
    BD_OVERLAY_EX* overlay = *m_overlayQueue[plane].begin();
    if (overlay->scheduled)
      return false;

    if (overlay->pts <= 0)
    {
      rtPts = 0;
#ifdef LOG_DRAWING
      LogDebug("INSTANT HANDLING");
#endif
    }
    else
    {
      REFERENCE_TIME pts = CONVERT_90KHz_DS(overlay->pts);
      rtPts = pts - m_rtPlaybackPosition + m_rtOffset;

      //ASSERT(rtPts > 0);
      if (rtPts < 0)
      {
        rtPts = 0;
        LogDebug("SCHEDULING --- was negative -> 0");
      }

#ifdef LOG_DRAWING
      LogDebug("SCHEDULING PTS: %6.3f wait: %6.3f", pts / 10000000.0, rtPts / 10000000.0);
#endif
    }

    return true;
  }

  rtPts = -1;
  return false;
}
void COverlayRenderer::SetScr(INT64 pts, INT64 offset)
{
  m_rtPlaybackPosition = CONVERT_90KHz_DS(pts);
  m_rtOffset = CONVERT_90KHz_DS(offset);
}
DWORD COverlayRenderer::ScheduleThread()
{
  const DWORD eventArraySize = 4;

  HANDLE handles[eventArraySize];
  handles[0] = m_hStopThreadEvent;
  handles[1] = m_hOverlayTimerIG;
  handles[2] = m_hOverlayTimerPG;
  handles[3] = m_hNewOverlayAvailable;

  DWORD stopThread = WAIT_OBJECT_0;
  DWORD processOverlayIG = WAIT_OBJECT_0 + 1;
  DWORD processOverlayPG = WAIT_OBJECT_0 + 2;
  DWORD newOverlayAvailable = WAIT_OBJECT_0 + 3;

  while (true)
  {
    ScheduleOverlays();

    DWORD result = WaitForMultipleObjects(eventArraySize, handles, false, INFINITE);

    if (result == WAIT_FAILED)
      return 0;
    else if (result == stopThread)
      return 0;
    else if(result == newOverlayAvailable)
    {
      CAutoLock queueLock(&m_csOverlayQueue);
      ResetEvent(m_hNewOverlayAvailable);
#ifdef LOG_DRAWING
      LogDebug("newOverlayAvailable");
#endif
    }
    else if (result == processOverlayIG || result == processOverlayPG)
    {
      UINT8 plane = result == processOverlayIG ? BD_OVERLAY_IG : BD_OVERLAY_PG;

      CAutoLock queueLock(&m_csOverlayQueue);

      if (!m_overlayQueue[plane].empty())
      {
        ivecOverlayQueue it = m_overlayQueue[plane].begin();

        if ((*it))
        {
  #ifdef LOG_DRAWING
          LogDebug("RENDERING PTS: %6.3f", (CONVERT_90KHz_DS((*it)->pts) + m_rtOffset) / 10000000.0);
  #endif

          // close frees all overlays
          bool freeOverlay = (*it)->cmd != BD_OVERLAY_CLOSE;

          ProcessOverlay((*it));

          if (freeOverlay)
            FreeOverlay(it);
        }
        else
          FreeOverlay(it);
      }
    }
  }
  
  return 0;
}
void CDeMultiplexer::FillAudio(CTsHeader& header, byte* tsPacket)
{
  //LogDebug("FillAudio - audio PID %d", m_audioPid );

  if (m_iAudioStream < 0 || m_iAudioStream >= m_audioStreams.size()) return;

  m_audioPid = m_audioStreams[m_iAudioStream].pid;
  if (m_audioPid == 0 || m_audioPid != header.Pid) return;
  if (header.AdaptionFieldOnly()) return;

  bool packetProcessed = false;

  CAutoLock lock (&m_sectionAudio);
  if (header.PayloadUnitStart)
  {
    byte* p = tsPacket + header.PayLoadStart;
    if ((p[0] == 0) && (p[1] == 0) && (p[2] == 1))
    {
      CPcr pts;
      CPcr dts;

      if (m_pCurrentAudioBuffer)
      {
        delete m_pCurrentAudioBuffer;
        m_pCurrentAudioBuffer = NULL;
      }

      m_pCurrentAudioBuffer = new Packet();

      if (CPcr::DecodeFromPesHeader(p, 0, pts, dts))
      {
#ifdef LOG_DEMUXER_AUDIO_SAMPLES
        LogDebug("demux: aud pts: %6.3f clip: %d playlist: %d", pts.ToClock(), m_nClip, m_nPlaylist);
#endif
        m_bAC3Substream = false;

        m_pCurrentAudioBuffer->rtStart = pts.IsValid ? CONVERT_90KHz_DS(pts.PcrReferenceBase) : Packet::INVALID_TIME;
        
        WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_audioParser->pmt.pbFormat;
        if (wfe)
        {
          REFERENCE_TIME duration = (wfe->nBlockAlign * 10000000) / wfe->nAvgBytesPerSec;
          m_pCurrentAudioBuffer->rtStop = m_pCurrentAudioBuffer->rtStart + duration;
        }
        else
          m_pCurrentAudioBuffer->rtStop = m_pCurrentAudioBuffer->rtStart + 1;  

        m_pCurrentAudioBuffer->nClipNumber = m_nClip;
        m_pCurrentAudioBuffer->nPlaylist = m_nPlaylist;
        m_pCurrentAudioBuffer->rtTitleDuration = m_rtTitleDuration;

        UINT32 pesHeaderLen = p[8] + 9;
        m_nAudioPesLenght = (p[4] << 8) + p[5] - (pesHeaderLen - 6);

        unsigned int flags = p[7];
        const BYTE* pos = p + 9;

        if ((flags & 0xc0) == 0x80) 
          pos += 5; // PTS
        else if ((flags & 0xc0) == 0xc0) 
          pos += 10; // PTS & DTS

        if (flags & 0x01) // PES extension
        {
          unsigned int pes_ext = *pos++;
          // Skip PES private data, program packet sequence counter and P-STD buffer
          unsigned int skip = (pes_ext >> 4) & 0xb;
          skip += skip & 0x9;
          pos += skip;
          
          if ((pes_ext & 0x41) == 0x01 && (pos + 2) <= (p + pesHeaderLen)) 
          {  
            // PES extension 2
            if ((pos[0] & 0x7f) > 0 && (pos[1] & 0x80) == 0)
            {
              if (pos[1] == 0x76)
                m_bAC3Substream = true; // this stream will get discarded
            }
          }
        }
void CDeMultiplexer::HandleBDEvent(BD_EVENT& pEv)
{
  switch (pEv.event)
  {
    case BD_EVENT_ERROR:
    case BD_EVENT_READ_ERROR:
      m_bEndOfFile = true;
      m_filter.NotifyEvent(EC_ERRORABORT, 0, 0);
      break;

    case BD_EVENT_ENCRYPTED:
      m_bEndOfFile = true;
      m_filter.NotifyEvent(EC_ERRORABORT, STG_E_STATUS_COPY_PROTECTION_FAILURE, 0);
      break;

    case BD_EVENT_PLAYLIST_STOP:
      Flush(true);
      m_bLibRequestedFlush = true;
      break;

    case BD_EVENT_SEEK:
      Flush(true);
      break;

    case BD_EVENT_STILL_TIME:
      m_bStreamPaused = true;
      break;

    case BD_EVENT_STILL:
      if (pEv.param == 1)
        m_bStreamPaused = true;
      break;

    case BD_EVENT_TITLE:
      m_bTitleChanged = true;
      m_nTitle = pEv.param;
      m_filter.GetTime(&m_rtTitleChangeStarted);
      break;

    case BD_EVENT_PLAYLIST:
      m_nPlaylist = pEv.param;
      break;

    case BD_EVENT_AUDIO_STREAM:
      if (!m_filter.lib.ForceTitleBasedPlayback() && pEv.param < 0xff)
      {
        m_iAudioIdx = pEv.param - 1;
        ParseAudioStreams(m_filter.lib.CurrentClipInfo());
        m_bAudioFormatParsed = false;
      }
      break;

    case BD_EVENT_PG_TEXTST_STREAM:
      break;

    case BD_EVENT_PLAYITEM:
      LogDebug("demux: New playitem %d", pEv.param);
      
      m_bFlushBuffersOnPause = true;
      
      UINT64 clipStart = 0, clipIn = 0, bytePos = 0, duration = 0;
      int ret = m_filter.lib.GetClipInfo(pEv.param, &clipStart, &clipIn, &bytePos, &duration);
      if (ret) 
      {
        REFERENCE_TIME rtOldOffset = m_rtOffset;

        m_rtOffset = clipStart - clipIn;
        m_nClip = pEv.param;

        BLURAY_CLIP_INFO* clip = m_filter.lib.CurrentClipInfo();
        if (!clip)
        {
          LogDebug("demux: HandleBDEvent - failed to get clip info!");
          return;
        }

        UINT64 position = 0;
        m_filter.lib.CurrentPosition(position, (UINT64&)m_rtTitleDuration);
        m_rtTitleDuration = CONVERT_90KHz_DS(m_rtTitleDuration);

        //if (!m_bStarting)
        {
          REFERENCE_TIME clipOffset = m_rtOffset * -1;

          FlushPESBuffers(false, false);

          m_playlistManager->CreateNewPlaylistClip(m_nPlaylist, m_nClip, AudioStreamsAvailable(clip),
            CONVERT_90KHz_DS(clipIn), CONVERT_90KHz_DS(clipOffset), CONVERT_90KHz_DS(duration), CONVERT_90KHz_DS(position), m_bLibRequestedFlush);

          if (m_bLibRequestedFlush)
          {
            m_playlistManager->ClearClips();
            CVideoPin* pVideoPin = m_filter.GetVideoPin();
            if (pVideoPin)
              pVideoPin->SyncClipBoundary();
          }

          m_bLibRequestedFlush = false;
        }

        m_bVideoFormatParsed = false;
        m_bAudioFormatParsed = false;

        ParseVideoStream(clip);
        ParseAudioStreams(clip);
        ParseSubtitleStreams(clip);
      }
  } 
}