Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Simplify DVD startup to improve playback reliability

The startup code for DVD playback jumps around somewhat trying to find
a playable title, which is then used to create audio/video decoders
before playback is restarted at firstplay.

This doesn't always work as it can leave the DVDs VM in an
inconsistent state and, depending on the DVD, looks ugly as playback
starts and then restarts or appears to jump somewhere else after a
couple of seconds. Because the VM can be left in an inconsistent
state, menu navigation/selection issues can arise, which can make it
difficult to start playback.

The attached patch attempts to clean up the startup code. The
DVDRingBuffer no longer tries to find a playable title in OpenFile?,
but rather just lets the VM get on with playback. AVFormatDecoder no
longer processes the initial frames more than is required to create
decoders. Once this has been achieved, any cached data is flushed
before jumping back to 'firstplay' (and cleanly resetting the VM). By
not displaying the initial frames used to determine the decoders and
flushing the cached data, the ugly jump at the start of some DVDs is
no longer visible.

Fixes #11288

Signed-off-by: Stuart Morgan <smorgan@mythtv.org>
  • Loading branch information...
commit 414de880b9d65263849e2339df9e083df0301033 1 parent c5a4229
Richard authored stuartm committed
6 mythtv/libs/libmythtv/DVD/avformatdecoderdvd.cpp
View
@@ -26,6 +26,12 @@ void AvFormatDecoderDVD::UpdateFramesPlayed(void)
m_parent->SetFramesPlayed(currentpos + 1);
}
+bool AvFormatDecoderDVD::GetFrame(DecodeType decodetype)
+{
+ // Always try to decode audio and video for DVDs
+ return AvFormatDecoder::GetFrame( kDecodeAV );
+}
+
void AvFormatDecoderDVD::PostProcessTracks(void)
{
if (!ringBuffer)
1  mythtv/libs/libmythtv/DVD/avformatdecoderdvd.h
View
@@ -10,6 +10,7 @@ class AvFormatDecoderDVD : public AvFormatDecoder
PlayerFlags flags);
virtual void Reset(bool reset_video_data, bool seek_reset, bool reset_file);
virtual void UpdateFramesPlayed(void);
+ virtual bool GetFrame(DecodeType decodetype); // DecoderBase
private:
virtual bool DoRewindSeek(long long desiredFrame);
50 mythtv/libs/libmythtv/DVD/dvdringbuffer.cpp
View
@@ -342,55 +342,6 @@ bool DVDRingBuffer::OpenFile(const QString &lfilename, uint retry_ms)
dvdnav_set_readahead_flag(m_dvdnav, 0);
dvdnav_set_PGC_positioning_flag(m_dvdnav, 1);
- int32_t num_titles = 0;
- res = dvdnav_get_number_of_titles(m_dvdnav, &num_titles);
- if (num_titles == 0 || res == DVDNAV_STATUS_ERR)
- {
- char buf[DVD_BLOCK_SIZE * 5];
- LOG(VB_GENERAL, LOG_INFO,
- LOC + QString("Reading %1 bytes from the drive")
- .arg(DVD_BLOCK_SIZE * 5));
- safe_read(buf, DVD_BLOCK_SIZE * 5);
- res = dvdnav_get_number_of_titles(m_dvdnav, &num_titles);
- }
-
- if (res == DVDNAV_STATUS_ERR)
- {
- LOG(VB_GENERAL, LOG_ERR,
- LOC + QString("Failed to get the number of titles on the DVD" ));
- }
- else
- {
- LOG(VB_GENERAL, LOG_INFO,
- LOC + QString("There are %1 titles on the disk")
- .arg(num_titles));
- }
-
- int startTitle = 1;
- dvdnav_status_t result = DVDNAV_STATUS_ERR;
- while (startTitle <= num_titles)
- {
- result = dvdnav_title_play(m_dvdnav, startTitle);
- if (result == DVDNAV_STATUS_OK)
- break;
- else if (startTitle < num_titles)
- LOG(VB_GENERAL, LOG_WARNING, QString("Unable to play DVD title %1, "
- "trying next title")
- .arg(startTitle));
- startTitle++;
- }
-
- if (result == DVDNAV_STATUS_ERR)
- {
- LOG(VB_GENERAL, LOG_ERR, QString("Unable to play any title on this "
- "DVD. Disc may be damaged or "
- "corrupted as a means of copy "
- "protection."));
-
- rwlock.unlock();
- return false;
- }
-
// Check we aren't starting in a still frame (which will probably fail as
// ffmpeg will be unable to create a decoder)
if (dvdnav_get_next_still_flag(m_dvdnav))
@@ -446,6 +397,7 @@ bool DVDRingBuffer::StartFromBeginning(void)
if (m_dvdnav)
{
QMutexLocker lock(&m_seekLock);
+ dvdnav_reset(m_dvdnav);
dvdnav_first_play(m_dvdnav);
m_audioStreamsChanged = true;
}
39 mythtv/libs/libmythtv/avformatdecoder.cpp
View
@@ -334,7 +334,8 @@ AvFormatDecoder::AvFormatDecoder(MythPlayer *parent,
// Audio
disable_passthru(false),
m_fps(0.0f),
- codec_is_mpeg(false)
+ codec_is_mpeg(false),
+ m_processFrames(true)
{
memset(&readcontext, 0, sizeof(readcontext));
memset(ccX08_in_pmt, 0, sizeof(ccX08_in_pmt));
@@ -684,9 +685,6 @@ void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames,
if (!ringBuffer)
return; // nothing to reset...
- if (ringBuffer->IsInDiscMenuOrStillFrame() || newKey == 0)
- return;
-
LOG(VB_PLAYBACK, LOG_INFO, LOC +
QString("SeekReset(%1, %2, %3 flush, %4 discard)")
.arg(newKey).arg(skipFrames)
@@ -935,6 +933,11 @@ int AvFormatDecoder::OpenFile(RingBuffer *rbuffer, bool novideo,
ringBuffer = rbuffer;
+ // Process frames immediately unless we're decoding
+ // a DVD, in which case don't so that we don't show
+ // anything whilst probing the data streams.
+ m_processFrames = !ringBuffer->IsDVD();
+
if (avfRingBuffer)
delete avfRingBuffer;
avfRingBuffer = new AVFRingBuffer(rbuffer);
@@ -982,12 +985,6 @@ int AvFormatDecoder::OpenFile(RingBuffer *rbuffer, bool novideo,
}
int ret = FindStreamInfo();
-
- // Reset DVD/bluray ringbuffers
- if (!ringBuffer->StartFromBeginning())
- return -1;
- ringBuffer->IgnoreWaitStates(false);
-
if (ret < 0)
{
LOG(VB_GENERAL, LOG_ERR, LOC + "Could not find codec parameters. " +
@@ -1143,6 +1140,23 @@ int AvFormatDecoder::OpenFile(RingBuffer *rbuffer, bool novideo,
if (getenv("FORCE_DTS_TIMESTAMPS"))
force_dts_timestamps = true;
+ if (ringBuffer->IsDVD())
+ {
+ // Reset DVD playback and clear any of
+ // our buffers so that none of the data
+ // parsed so far to determine decoders
+ // gets shown.
+ if (!ringBuffer->StartFromBeginning())
+ return -1;
+ ringBuffer->IgnoreWaitStates(false);
+
+ Reset(true, true, true);
+
+ // Now we're ready to process and show frames
+ m_processFrames = true;
+ }
+
+
// Return true if recording has position map
return recordingHasPositionMap;
}
@@ -4484,6 +4498,11 @@ bool AvFormatDecoder::GetFrame(DecodeType decodetype)
skipaudio = (lastvpts == 0);
+ if( !m_processFrames )
+ {
+ return false;
+ }
+
hasVideo = HasVideo(ic);
needDummyVideoFrames = false;
1  mythtv/libs/libmythtv/avformatdecoder.h
View
@@ -360,6 +360,7 @@ class AvFormatDecoder : public DecoderBase
float m_fps;
bool codec_is_mpeg;
+ bool m_processFrames;
};
#endif
Please sign in to comment.
Something went wrong with that request. Please try again.