bool BDRingBuffer::UpdateTitleInfo(void) { QMutexLocker locker(&m_infoLock); if (!m_currentTitleInfo) return false; m_titleChanged = true; m_currentTitleLength = m_currentTitleInfo->duration; m_currentTitleAngleCount = m_currentTitleInfo->angle_count; m_currentAngle = 0; m_titlesize = bd_get_title_size(bdnav); uint32_t chapter_count = GetNumChapters(); uint64_t total_secs = m_currentTitleLength / 90000; int hours = (int)total_secs / 60 / 60; int minutes = ((int)total_secs / 60) - (hours * 60); double secs = (double)total_secs - (double)(hours * 60 * 60 + minutes * 60); QString duration = QString("%1:%2:%3") .arg(QString().sprintf("%02d", hours)) .arg(QString().sprintf("%02d", minutes)) .arg(QString().sprintf("%02.1f", secs)); LOG(VB_GENERAL, LOG_INFO, LOC + QString("New title info: Index %1 Playlist: %2 Duration: %3 " "Chapters: %5") .arg(m_currentTitleInfo->idx).arg(m_currentTitleInfo->playlist) .arg(duration).arg(chapter_count)); LOG(VB_GENERAL, LOG_INFO, LOC + QString("New title info: Clips: %1 Angles: %2 Title Size: %3 " "Frame Rate %4") .arg(m_currentTitleInfo->clip_count) .arg(m_currentTitleAngleCount).arg(m_titlesize) .arg(GetFrameRate())); if (chapter_count) { for (uint i = 0; i < chapter_count; i++) { uint64_t total_secs = GetChapterStartTime(i); uint64_t framenum = GetChapterStartFrame(i); int hours = (int)total_secs / 60 / 60; int minutes = ((int)total_secs / 60) - (hours * 60); double secs = (double)total_secs - (double)(hours * 60 * 60 + minutes * 60); LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Chapter %1 found @ [%2:%3:%4]->%5") .arg(QString().sprintf("%02d", i + 1)) .arg(QString().sprintf("%02d", hours)) .arg(QString().sprintf("%02d", minutes)) .arg(QString().sprintf("%06.3f", secs)) .arg(framenum)); } } int still = BLURAY_STILL_NONE; int time = 0; if (m_currentTitleInfo->clip_count) { for (uint i = 0; i < m_currentTitleInfo->clip_count; i++) { LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Clip %1 stillmode %2 stilltime %3 videostreams %4 " "audiostreams %5 igstreams %6") .arg(i).arg(m_currentTitleInfo->clips[i].still_mode) .arg(m_currentTitleInfo->clips[i].still_time) .arg(m_currentTitleInfo->clips[i].video_stream_count) .arg(m_currentTitleInfo->clips[i].audio_stream_count) .arg(m_currentTitleInfo->clips[i].ig_stream_count)); still |= m_currentTitleInfo->clips[i].still_mode; time = m_currentTitleInfo->clips[i].still_time; } } if (m_currentTitleInfo->clip_count > 1 && still != BLURAY_STILL_NONE) LOG(VB_GENERAL, LOG_WARNING, LOC + "Warning: more than 1 clip, following still " "frame analysis may be wrong"); if (still == BLURAY_STILL_TIME) { LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Entering still frame (%1 seconds) UNSUPPORTED").arg(time)); bd_read_skip_still(bdnav); } else if (still == BLURAY_STILL_INFINITE) { LOG(VB_PLAYBACK, LOG_INFO, LOC + "Entering infinite still frame."); } m_stillMode = still; m_stillTime = time; return true; }
/*********************************************************************** * 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; }
/*********************************************************************** * 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; }