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; }
bool BDRingBuffer::HandleBDEvents(void) { BD_EVENT ev; while (bd_get_event(bdnav, &ev)) { HandleBDEvent(ev); if (ev.event == BD_EVENT_NONE || ev.event == BD_EVENT_ERROR) { return false; } } return true; }
void CBDDemuxer::ProcessBDEvents() { // Check for clip change BD_EVENT event; while(bd_get_event(m_pBD, &event)) { if (event.event == BD_EVENT_PLAYITEM) { uint64_t clip_start, clip_in, bytepos; int ret = bd_get_clip_infos(m_pBD, event.param, &clip_start, &clip_in, &bytepos, NULL); if (ret) { m_rtNewOffset = Convert90KhzToDSTime(clip_start - clip_in) + m_lavfDemuxer->GetStartTime(); m_bNewOffsetPos = bytepos; DbgLog((LOG_TRACE, 10, L"New clip! offset: %I64d bytepos: %I64u", m_rtNewOffset, bytepos)); } } } }
/*********************************************************************** * hb_bd_start *********************************************************************** * Title and chapter start at 1 **********************************************************************/ int hb_bd_start( hb_bd_t * d, hb_title_t *title ) { BD_EVENT event; d->pkt_count = title->block_count; // Calling bd_get_event initializes libbluray event queue. bd_select_title( d->bd, d->title_info[title->index - 1]->idx ); bd_get_event( d->bd, &event ); d->chapter = 1; d->stream = hb_bd_stream_open( title ); if ( d->stream == NULL ) { return 0; } return 1; }
void CBDDemuxer::ProcessBDEvents() { // Check for clip change BD_EVENT event; while(bd_get_event(m_pBD, &event)) { if (event.event == BD_EVENT_PLAYITEM) { uint64_t clip_start, clip_in, bytepos; int ret = bd_get_clip_infos(m_pBD, event.param, &clip_start, &clip_in, &bytepos, nullptr); if (ret) { m_rtNewOffset = Convert90KhzToDSTime(clip_start - clip_in) + m_lavfDemuxer->GetStartTime(); m_bNewOffsetPos = bytepos-4; DbgLog((LOG_TRACE, 10, L"New clip! offset: %I64d bytepos: %I64u", m_rtNewOffset, bytepos)); } m_EndOfStreamPacketFlushProtection = FALSE; } else if (event.event == BD_EVENT_END_OF_TITLE) { m_EndOfStreamPacketFlushProtection = TRUE; } else if (event.event == BD_EVENT_SEEK) { m_EndOfStreamPacketFlushProtection = FALSE; } } }
/*********************************************************************** * hb_bd_read *********************************************************************** * **********************************************************************/ hb_buffer_t * hb_bd_read( hb_bd_t * d ) { int result; int error_count = 0; uint8_t buf[192]; BD_EVENT event; uint64_t pos; hb_buffer_t * out = NULL; uint8_t discontinuity; while ( 1 ) { discontinuity = 0; result = next_packet( d->bd, buf ); if ( result < 0 ) { hb_error("bd: Read Error"); pos = bd_tell( d->bd ); bd_seek( d->bd, pos + 192 ); error_count++; if (error_count > 10) { hb_error("bd: Error, too many consecutive read errors"); hb_set_work_error(d->h, HB_ERROR_READ); return NULL; } continue; } else if ( result == 0 ) { return NULL; } error_count = 0; while ( bd_get_event( d->bd, &event ) ) { switch ( event.event ) { case BD_EVENT_CHAPTER: // The muxers expect to only get chapter 2 and above // They write chapter 1 when chapter 2 is detected. if (event.param > d->chapter) { d->next_chap = event.param; } break; case BD_EVENT_PLAYITEM: discontinuity = 1; hb_deep_log(2, "bd: Playitem %u", event.param); break; case BD_EVENT_STILL: bd_read_skip_still( d->bd ); break; default: break; } } // buf+4 to skip the BD timestamp at start of packet if (d->chapter != d->next_chap) { d->chapter = d->next_chap; out = hb_ts_decode_pkt(d->stream, buf+4, d->chapter, discontinuity); } else { out = hb_ts_decode_pkt(d->stream, buf+4, 0, discontinuity); } if (out != NULL) { return out; } } return NULL; }
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; }
/*********************************************************************** * hb_bd_read *********************************************************************** * **********************************************************************/ hb_buffer_t * hb_bd_read( hb_bd_t * d ) { int result; int error_count = 0; uint8_t buf[192]; BD_EVENT event; uint64_t pos; hb_buffer_t * b; uint8_t discontinuity; int new_chap = 0; discontinuity = 0; while ( 1 ) { if ( d->next_chap != d->chapter ) { new_chap = d->chapter = d->next_chap; } result = next_packet( d->bd, buf ); if ( result < 0 ) { hb_error("bd: Read Error"); pos = bd_tell( d->bd ); bd_seek( d->bd, pos + 192 ); error_count++; if (error_count > 10) { hb_error("bd: Error, too many consecutive read errors"); return 0; } continue; } else if ( result == 0 ) { return 0; } error_count = 0; while ( bd_get_event( d->bd, &event ) ) { switch ( event.event ) { case BD_EVENT_CHAPTER: // The muxers expect to only get chapter 2 and above // They write chapter 1 when chapter 2 is detected. d->next_chap = event.param; break; case BD_EVENT_PLAYITEM: discontinuity = 1; hb_deep_log(2, "bd: Playitem %u", event.param); break; case BD_EVENT_STILL: bd_read_skip_still( d->bd ); break; default: break; } } // buf+4 to skip the BD timestamp at start of packet b = hb_ts_decode_pkt( d->stream, buf+4 ); if ( b ) { b->s.discontinuity = discontinuity; b->s.new_chap = new_chap; return b; } } return NULL; }