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); } } }