STDMETHODIMP CBDDemuxer::GetNextPacket(Packet **ppPacket) { HRESULT hr = m_lavfDemuxer->GetNextPacket(ppPacket); ProcessBDEvents(); Packet * const pPacket = *ppPacket; if (hr == S_OK && pPacket && pPacket->rtStart != Packet::INVALID_TIME) { REFERENCE_TIME rtOffset = m_rtOffset[pPacket->StreamId]; if (rtOffset != m_rtNewOffset && pPacket->bPosition != -1 && pPacket->bPosition >= m_bNewOffsetPos) { DbgLog((LOG_TRACE, 10, L"Actual clip change detected in stream %d; time: %I64d, old offset: %I64d, new offset: %I64d", pPacket->StreamId, pPacket->rtStart, rtOffset, m_rtNewOffset)); rtOffset = m_rtOffset[pPacket->StreamId] = m_rtNewOffset; } //DbgLog((LOG_TRACE, 10, L"Frame: stream: %d, start: %I64d, corrected: %I64d, bytepos: %I64d", pPacket->StreamId, pPacket->rtStart, pPacket->rtStart + rtOffset, pPacket->bPosition)); pPacket->rtStart += rtOffset; pPacket->rtStop += rtOffset; } if (hr == S_OK && m_EndOfStreamPacketFlushProtection && pPacket && pPacket->bPosition != -1) { if (pPacket->bPosition < m_bNewOffsetPos) { DbgLog((LOG_TRACE, 10, L"Dropping packet from a previous segment (pos %I64d, segment started at %I64d) at EOS, from stream %d", pPacket->bPosition, m_bNewOffsetPos, pPacket->StreamId)); SAFE_DELETE(*ppPacket); *ppPacket = nullptr; return S_FALSE; } } return hr; }
STDMETHODIMP CBDDemuxer::ProcessPacket(Packet *pPacket) { ProcessBDEvents(); if (pPacket && pPacket->rtStart != Packet::INVALID_TIME) { REFERENCE_TIME rtOffset = m_rtOffset[pPacket->StreamId]; if (m_StreamClip[pPacket->StreamId] != m_NewClip && pPacket->bPosition != -1 && pPacket->bPosition >= m_bNewOffsetPos) { DbgLog((LOG_TRACE, 10, L"Actual clip change detected in stream %d; time: %I64d, old offset: %I64d, new offset: %I64d", pPacket->StreamId, pPacket->rtStart, rtOffset, m_rtNewOffset)); rtOffset = m_rtOffset[pPacket->StreamId] = m_rtNewOffset; m_StreamClip[pPacket->StreamId] = m_NewClip; // Flush MVC extensions on stream change, it'll re-fill automatically if (m_MVCPlayback && pPacket->StreamId == m_lavfDemuxer->m_nH264MVCBaseStream && m_MVCExtensionClip != m_NewClip) { m_lavfDemuxer->FlushMVCExtensionQueue(); CloseMVCExtensionDemuxer(); OpenMVCExtensionDemuxer(m_NewClip); } } //DbgLog((LOG_TRACE, 10, L"Frame: stream: %d, start: %I64d, corrected: %I64d, bytepos: %I64d", pPacket->StreamId, pPacket->rtStart, pPacket->rtStart + rtOffset, pPacket->bPosition)); pPacket->rtStart += rtOffset; pPacket->rtStop += rtOffset; } if (m_EndOfStreamPacketFlushProtection && pPacket && pPacket->bPosition != -1) { if (pPacket->bPosition < m_bNewOffsetPos) { DbgLog((LOG_TRACE, 10, L"Dropping packet from a previous segment (pos %I64d, segment started at %I64d) at EOS, from stream %d", pPacket->bPosition, m_bNewOffsetPos, pPacket->StreamId)); return S_FALSE; } } return S_OK; }
STDMETHODIMP CBDDemuxer::SetTitle(int idx) { HRESULT hr = S_OK; int ret; // return values if (m_pTitle) { bd_free_title_info(m_pTitle); } // Init Event Queue bd_get_event(m_pBD, nullptr); // Select title m_pTitle = bd_get_title_info(m_pBD, idx, 0); ret = bd_select_title(m_pBD, idx); if (ret == 0) { return E_FAIL; } if (m_pb) { av_free(m_pb->buffer); av_free(m_pb); } uint8_t *buffer = (uint8_t *)av_mallocz(BD_READ_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); m_pb = avio_alloc_context(buffer, BD_READ_BUFFER_SIZE, 0, this, BDByteStreamRead, nullptr, BDByteStreamSeek); SafeRelease(&m_lavfDemuxer); SAFE_CO_FREE(m_rtOffset); m_lavfDemuxer = new CLAVFDemuxer(m_pLock, m_pSettings); m_lavfDemuxer->AddRef(); m_lavfDemuxer->SetBluRay(this); if (FAILED(hr = m_lavfDemuxer->OpenInputStream(m_pb, nullptr, "mpegts", TRUE))) { SafeRelease(&m_lavfDemuxer); return hr; } m_lavfDemuxer->SeekByte(0, 0); // Process any events that occured during opening ProcessBDEvents(); // Reset EOS protection m_EndOfStreamPacketFlushProtection = FALSE; // space for storing stream offsets m_rtOffset = (REFERENCE_TIME *)CoTaskMemAlloc(sizeof(REFERENCE_TIME) * m_lavfDemuxer->GetNumStreams()); if (!m_rtOffset) return E_OUTOFMEMORY; memset(m_rtOffset, 0, sizeof(REFERENCE_TIME) * m_lavfDemuxer->GetNumStreams()); DbgLog((LOG_TRACE, 20, L"Opened BD title with %d clips and %d chapters", m_pTitle->clip_count, m_pTitle->chapter_count)); return S_OK; }
STDMETHODIMP CBDDemuxer::GetNextPacket(Packet **ppPacket) { HRESULT hr = m_lavfDemuxer->GetNextPacket(ppPacket); ProcessBDEvents(); Packet * const pPacket = *ppPacket; if (hr == S_OK && pPacket && pPacket->rtStart != Packet::INVALID_TIME) { REFERENCE_TIME rtOffset = m_rtOffset[pPacket->StreamId]; if (rtOffset != m_rtNewOffset && pPacket->bPosition != -1 && pPacket->bPosition >= m_bNewOffsetPos) { DbgLog((LOG_TRACE, 10, L"Actual clip change detected in stream %d; time: %I64d, old offset: %I64d, new offset: %I64d", pPacket->StreamId, pPacket->rtStart, rtOffset, m_rtNewOffset)); rtOffset = m_rtOffset[pPacket->StreamId] = m_rtNewOffset; } //DbgLog((LOG_TRACE, 10, L"Frame: stream: %d, start: %I64d, corrected: %I64d, bytepos: %I64d", pPacket->StreamId, pPacket->rtStart, pPacket->rtStart + rtOffset, pPacket->bPosition)); pPacket->rtStart += rtOffset; pPacket->rtStop += rtOffset; } return hr; }
STDMETHODIMP CBDDemuxer::SetTitle(int idx) { HRESULT hr = S_OK; int ret; // return values if (m_pTitle) { bd_free_title_info(m_pTitle); } // Init Event Queue bd_get_event(m_pBD, nullptr); // Select title m_pTitle = bd_get_title_info(m_pBD, idx, 0); ret = bd_select_title(m_pBD, idx); if (ret == 0) { return E_FAIL; } MPLS_PL * mpls = bd_get_title_mpls(m_pBD); if (mpls) { for (int i = 0; i < mpls->ext_sub_count; i++) { if (mpls->ext_sub_path[i].type == 8 && mpls->ext_sub_path[i].sub_playitem_count == mpls->list_count) { DbgLog((LOG_TRACE, 20, L"CBDDemuxer::SetTitle(): Enabling BD3D MVC demuxing")); DbgLog((LOG_TRACE, 20, L" -> MVC_Base_view_R_flag: %d", m_pTitle->mvc_base_view_r_flag)); m_MVCPlayback = TRUE; m_MVCExtensionSubPathIndex = i; break; } } } CloseMVCExtensionDemuxer(); if (m_pb) { av_free(m_pb->buffer); av_free(m_pb); } uint8_t *buffer = (uint8_t *)av_mallocz(BD_READ_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); m_pb = avio_alloc_context(buffer, BD_READ_BUFFER_SIZE, 0, this, BDByteStreamRead, nullptr, BDByteStreamSeek); SafeRelease(&m_lavfDemuxer); SAFE_CO_FREE(m_StreamClip); SAFE_CO_FREE(m_rtOffset); m_lavfDemuxer = new CLAVFDemuxer(m_pLock, m_pSettings); m_lavfDemuxer->AddRef(); m_lavfDemuxer->SetBluRay(this); if (FAILED(hr = m_lavfDemuxer->OpenInputStream(m_pb, nullptr, "mpegts", TRUE))) { SafeRelease(&m_lavfDemuxer); return hr; } if (m_MVCPlayback && !m_lavfDemuxer->m_bH264MVCCombine) { DbgLog((LOG_TRACE, 10, L"CBDDemuxer::SetTitle(): MVC demuxing was requested, but main demuxer did not activate MVC mode, disabling.")); CloseMVCExtensionDemuxer(); m_MVCPlayback = FALSE; } m_lavfDemuxer->SeekByte(0, 0); // Process any events that occured during opening ProcessBDEvents(); // Reset EOS protection m_EndOfStreamPacketFlushProtection = FALSE; // space for storing stream offsets m_StreamClip = (uint16_t *)CoTaskMemAlloc(sizeof(*m_StreamClip) * m_lavfDemuxer->GetNumStreams()); if (!m_StreamClip) return E_OUTOFMEMORY; memset(m_StreamClip, -1, sizeof(*m_StreamClip) * m_lavfDemuxer->GetNumStreams()); m_rtOffset = (REFERENCE_TIME *)CoTaskMemAlloc(sizeof(*m_rtOffset) * m_lavfDemuxer->GetNumStreams()); if (!m_rtOffset) return E_OUTOFMEMORY; memset(m_rtOffset, 0, sizeof(*m_rtOffset) * m_lavfDemuxer->GetNumStreams()); DbgLog((LOG_TRACE, 20, L"Opened BD title with %d clips and %d chapters", m_pTitle->clip_count, m_pTitle->chapter_count)); return S_OK; }