@@ -1,17 +1,23 @@
// MythTV
#include " iso639.h"
#include " mythdvdbuffer.h"
#include " mythdvdplayer.h"
#include " avformatdecoderdvd.h"
#include " iso639.h"
// FFmpeg
extern " C" {
#include " libavcodec/avcodec.h"
}
#include < unistd.h> // for usleep()
// Std
#include < thread>
#define LOC QString (" AFD_DVD: " )
#define LOC QString (" DVDDec: " )
AvFormatDecoderDVD::AvFormatDecoderDVD(MythPlayer *Parent, const ProgramInfo &PGInfo, PlayerFlags Flags)
: AvFormatDecoder(Parent, PGInfo, Flags)
{
}
AvFormatDecoderDVD::~AvFormatDecoderDVD ()
{
Expand All
@@ -24,7 +30,7 @@ AvFormatDecoderDVD::~AvFormatDecoderDVD()
ReleaseLastVideoPkt ();
}
void AvFormatDecoderDVD::ReleaseLastVideoPkt ()
void AvFormatDecoderDVD::ReleaseLastVideoPkt (void )
{
if (m_lastVideoPkt)
{
Expand All
@@ -35,18 +41,18 @@ void AvFormatDecoderDVD::ReleaseLastVideoPkt()
}
}
void AvFormatDecoderDVD::ReleaseContext (MythDVDContext *&context )
void AvFormatDecoderDVD::ReleaseContext (MythDVDContext *&Context )
{
if (context )
if (Context )
{
context ->DecrRef ();
context = nullptr ;
Context ->DecrRef ();
Context = nullptr ;
}
}
void AvFormatDecoderDVD::Reset (bool reset_video_data , bool seek_reset , bool reset_file )
void AvFormatDecoderDVD::Reset (bool ResetVideoData , bool SeekReset , bool ResetFile )
{
AvFormatDecoder::Reset (reset_video_data, seek_reset, reset_file );
AvFormatDecoder::Reset (ResetVideoData, SeekReset, ResetFile );
SyncPositionMap ();
}
Expand All
@@ -56,9 +62,9 @@ void AvFormatDecoderDVD::UpdateFramesPlayed(void)
if (!m_ringBuffer->IsDVD ())
return ;
auto currentpos = ( long long ) (m_ringBuffer->DVD ()->GetCurrentTime () * m_fps);
auto currentpos = static_cast < long long > (m_ringBuffer->DVD ()->GetCurrentTime () * m_fps);
m_framesPlayed = m_framesRead = currentpos ;
m_parent->SetFramesPlayed (currentpos + 1 );
m_parent->SetFramesPlayed (static_cast < uint64_t >( currentpos + 1 ) );
}
bool AvFormatDecoderDVD::GetFrame (DecodeType /* Type*/ , bool &Retry)
Expand All
@@ -67,7 +73,7 @@ bool AvFormatDecoderDVD::GetFrame(DecodeType /*Type*/, bool &Retry)
return AvFormatDecoder::GetFrame (kDecodeAV , Retry);
}
int AvFormatDecoderDVD::ReadPacket (AVFormatContext *ctx , AVPacket* pkt , bool & storePacket )
int AvFormatDecoderDVD::ReadPacket (AVFormatContext *Ctx , AVPacket* Pkt , bool & StorePacket )
{
int result = 0 ;
Expand All
@@ -77,19 +83,16 @@ int AvFormatDecoderDVD::ReadPacket(AVFormatContext *ctx, AVPacket* pkt, bool& st
if (m_lastVideoPkt)
{
av_packet_ref (pkt, m_lastVideoPkt);
av_packet_ref (Pkt, m_lastVideoPkt);
if (m_lastVideoPkt->pts != AV_NOPTS_VALUE)
m_lastVideoPkt->pts += pkt->duration ;
m_lastVideoPkt->pts += Pkt->duration ;
if (m_lastVideoPkt->dts != AV_NOPTS_VALUE)
m_lastVideoPkt->dts += pkt ->duration ;
m_lastVideoPkt->dts += Pkt ->duration ;
}
else
{
LOG (VB_GENERAL, LOG_ERR, LOC + QString ( " Need to generate frame @ %1 - %2 but no frame available!" )
.arg (pkt->pts )
.arg (m_framesReq));
.arg (Pkt->pts ).arg (m_framesReq));
}
}
else
Expand All
@@ -111,10 +114,8 @@ int AvFormatDecoderDVD::ReadPacket(AVFormatContext *ctx, AVPacket* pkt, bool& st
// Non-seamless jump - clear all buffers
m_framesReq = 0 ;
ReleaseContext (m_curContext);
while (!m_contextList.empty ())
m_contextList.takeFirst ()->DecrRef ();
Reset (true , false , false );
m_audio->Reset ();
m_parent->DiscardVideoFrames (false , false );
Expand All
@@ -133,14 +134,12 @@ int AvFormatDecoderDVD::ReadPacket(AVFormatContext *ctx, AVPacket* pkt, bool& st
// buffer.
// Force AvFormatDecoder to stop buffering frames
storePacket = false ;
StorePacket = false ;
// Return the first buffered packet
AVPacket *storedPkt = m_storedPackets.takeFirst ();
av_packet_ref (pkt , storedPkt);
av_packet_ref (Pkt , storedPkt);
av_packet_unref (storedPkt);
delete storedPkt;
return 0 ;
}
break ;
Expand All
@@ -150,7 +149,6 @@ int AvFormatDecoderDVD::ReadPacket(AVFormatContext *ctx, AVPacket* pkt, bool& st
// and the ringbuffer returned to make sure that any packets still in
// ffmpeg's buffers were flushed.
break ;
default :
LOG (VB_GENERAL, LOG_ERR, LOC + QString (" Unexpected DVD event - %1" )
.arg (lastEvent));
Expand All
@@ -160,19 +158,19 @@ int AvFormatDecoderDVD::ReadPacket(AVFormatContext *ctx, AVPacket* pkt, bool& st
m_ringBuffer->DVD ()->UnblockReading ();
}
result = av_read_frame (ctx, pkt );
result = av_read_frame (Ctx, Pkt );
// Make sure we yield. Otherwise other threads may not
// get chance to take the lock. Shouldn't be necessary
// but calling up the OSD menu in a still frame without
// this still causes a deadlock.
usleep ( 0 );
}while (m_ringBuffer->DVD ()->IsReadingBlocked ());
std::this_thread::yield ( );
} while (m_ringBuffer->DVD ()->IsReadingBlocked ());
if (result >= 0 )
{
pkt ->dts = m_ringBuffer->DVD ()->AdjustTimestamp (pkt ->dts );
pkt ->pts = m_ringBuffer->DVD ()->AdjustTimestamp (pkt ->pts );
Pkt ->dts = m_ringBuffer->DVD ()->AdjustTimestamp (Pkt ->dts );
Pkt ->pts = m_ringBuffer->DVD ()->AdjustTimestamp (Pkt ->pts );
if (m_returnContext)
{
Expand All
@@ -181,7 +179,7 @@ int AvFormatDecoderDVD::ReadPacket(AVFormatContext *ctx, AVPacket* pkt, bool& st
// the packets through that let us find it.
gotPacket = false ;
AVStream *curstream = m_ic->streams [pkt ->stream_index ];
AVStream *curstream = m_ic->streams [Pkt ->stream_index ];
if ((curstream->codecpar ->codec_type == AVMEDIA_TYPE_VIDEO) ||
(curstream->codecpar ->codec_id == AV_CODEC_ID_DVD_NAV))
Expand All
@@ -191,34 +189,28 @@ int AvFormatDecoderDVD::ReadPacket(AVFormatContext *ctx, AVPacket* pkt, bool& st
}
}
}
}while (!gotPacket);
} while (!gotPacket);
}
return result;
}
void AvFormatDecoderDVD::CheckContext (int64_t pts )
void AvFormatDecoderDVD::CheckContext (int64_t Pts )
{
if (pts != AV_NOPTS_VALUE)
if (Pts != AV_NOPTS_VALUE)
{
// Remove any contexts we should have
// already processed.(but have somehow jumped past)
while (!m_contextList.empty () &&
pts >= m_contextList.first ()->GetEndPTS ())
while (!m_contextList.empty () && (Pts >= m_contextList.first ()->GetEndPTS ()))
{
ReleaseContext (m_curContext);
m_curContext = m_contextList.takeFirst ();
LOG (VB_GENERAL, LOG_ERR, LOC +
QString (" DVD context missed! lba: %1, curpts: %2, nav end pts: %3" )
.arg (m_curContext->GetLBA ())
.arg (pts)
.arg (m_curContext->GetEndPTS ()));
LOG (VB_GENERAL, LOG_ERR, LOC + QString (" DVD context missed! lba: %1, curpts: %2, nav end pts: %3" )
.arg (m_curContext->GetLBA ()).arg (Pts).arg (m_curContext->GetEndPTS ()));
}
// See whether we can take the next context from the list
if (!m_contextList.empty () &&
pts >= m_contextList.first ()->GetStartPTS ())
if (!m_contextList.empty () && (Pts >= m_contextList.first ()->GetStartPTS ()))
{
ReleaseContext (m_curContext);
m_curContext = m_contextList.takeFirst ();
Expand Down
Expand Up
@@ -249,16 +241,13 @@ void AvFormatDecoderDVD::CheckContext(int64_t pts)
{
LOG (VB_PLAYBACK, LOG_DEBUG, LOC + QString (" Missing video. Jumping to sector %1" )
.arg (lastVideoSector));
m_ringBuffer->DVD ()->SectorSeek (lastVideoSector);
m_returnContext = m_curContext;
m_curContext = nullptr ;
}
else
{
LOG (VB_GENERAL, LOG_ERR, LOC +
QString (" Missing video frame and no previous frame available! lba: %1" )
LOG (VB_GENERAL, LOG_ERR, LOC + QString (" Missing video frame and no previous frame available! lba: %1" )
.arg (m_curContext->GetLBA ()));
}
}
Expand All
@@ -274,20 +263,20 @@ void AvFormatDecoderDVD::CheckContext(int64_t pts)
}
bool AvFormatDecoderDVD::ProcessVideoPacket (AVStream *stream , AVPacket *pkt , bool &Retry)
bool AvFormatDecoderDVD::ProcessVideoPacket (AVStream *Stream , AVPacket *Pkt , bool &Retry)
{
int64_t pts = pkt ->pts ;
int64_t pts = Pkt ->pts ;
if (pts == AV_NOPTS_VALUE)
pts = pkt ->dts ;
pts = Pkt ->dts ;
CheckContext (pts);
bool ret = AvFormatDecoder::ProcessVideoPacket (stream, pkt , Retry);
bool ret = AvFormatDecoder::ProcessVideoPacket (Stream, Pkt , Retry);
if (Retry)
return ret;
if (ret && m_curContext && (pts != AV_NOPTS_VALUE) && (pts + pkt ->duration == m_curContext->GetSeqEndPTS ()))
if (ret && m_curContext && (pts != AV_NOPTS_VALUE) && (pts + Pkt ->duration == m_curContext->GetSeqEndPTS ()))
{
// If this video frame is the last in the sequence,
// make a copy of it so we can 'generate' more
Expand All
@@ -304,7 +293,7 @@ bool AvFormatDecoderDVD::ProcessVideoPacket(AVStream *stream, AVPacket *pkt, boo
}
av_init_packet (m_lastVideoPkt);
av_packet_ref (m_lastVideoPkt, pkt );
av_packet_ref (m_lastVideoPkt, Pkt );
m_lbaLastVideoPkt = m_curContext->GetLBA ();
if (m_returnContext)
Expand All
@@ -322,42 +311,41 @@ bool AvFormatDecoderDVD::ProcessVideoPacket(AVStream *stream, AVPacket *pkt, boo
else
{
if (m_lastVideoPkt->pts != AV_NOPTS_VALUE)
m_lastVideoPkt->pts += pkt ->duration ;
m_lastVideoPkt->pts += Pkt ->duration ;
if (m_lastVideoPkt->dts != AV_NOPTS_VALUE)
m_lastVideoPkt->dts += pkt ->duration ;
m_lastVideoPkt->dts += Pkt ->duration ;
m_framesReq = m_curContext->GetNumFrames () - m_curContext->GetNumFramesPresent ();
LOG (VB_PLAYBACK, LOG_DEBUG, LOC + QString ( " SeqEnd @ %1 - require %2 frame(s)" )
.arg (pkt->pts )
.arg (m_framesReq));
.arg (Pkt->pts ).arg (m_framesReq));
}
}
return ret;
}
bool AvFormatDecoderDVD::ProcessVideoFrame (AVStream *stream , AVFrame *mpa_pic )
bool AvFormatDecoderDVD::ProcessVideoFrame (AVStream *Stream , AVFrame *Frame )
{
bool ret = true ;
if (m_returnContext == nullptr )
{
// Only process video frames if we're not searching for
// the previous video frame after seeking in a slideshow.
ret = AvFormatDecoder::ProcessVideoFrame (stream, mpa_pic );
ret = AvFormatDecoder::ProcessVideoFrame (Stream, Frame );
}
return ret;
}
bool AvFormatDecoderDVD::ProcessDataPacket (AVStream *curstream , AVPacket *pkt ,
DecodeType decodetype )
bool AvFormatDecoderDVD::ProcessDataPacket (AVStream *Curstream , AVPacket *Pkt ,
DecodeType Decodetype )
{
bool ret = true ;
if (curstream ->codecpar ->codec_id == AV_CODEC_ID_DVD_NAV)
if (Curstream ->codecpar ->codec_id == AV_CODEC_ID_DVD_NAV)
{
MythDVDContext* context = m_ringBuffer->DVD ()->GetDVDContext ();
Expand All
@@ -381,8 +369,7 @@ bool AvFormatDecoderDVD::ProcessDataPacket(AVStream *curstream, AVPacket *pkt,
m_lastVideoPkt->dts = m_lastVideoPkt->pts ;
}
}
else
if (m_lastVideoPkt)
else if (m_lastVideoPkt)
{
// If we've been generating frames, see whether this
// new context should be used already (handles
Expand All
@@ -393,7 +380,7 @@ bool AvFormatDecoderDVD::ProcessDataPacket(AVStream *curstream, AVPacket *pkt,
}
else
{
ret = AvFormatDecoder::ProcessDataPacket (curstream, pkt, decodetype );
ret = AvFormatDecoder::ProcessDataPacket (Curstream, Pkt, Decodetype );
}
return ret;
Expand Down
Expand Up
@@ -492,10 +479,9 @@ void AvFormatDecoderDVD::PostProcessTracks(void)
}
}
}
m_tracks[kTrackTypeSubtitle ] = filteredTracks;
stable_sort ( m_tracks[kTrackTypeSubtitle ]. begin (),
m_tracks[kTrackTypeSubtitle ].end ());
m_tracks[kTrackTypeSubtitle ] = filteredTracks;
stable_sort (m_tracks[ kTrackTypeSubtitle ]. begin (), m_tracks[kTrackTypeSubtitle ].end ());
int trackNo = -1 ;
int selectedStream = m_ringBuffer->DVD ()->GetTrack (kTrackTypeSubtitle );
Expand Down
Expand Up
@@ -527,8 +513,7 @@ void AvFormatDecoderDVD::PostProcessTracks(void)
uint captionmode = m_parent->GetCaptionMode ();
int trackcount = static_cast <int >(m_tracks[kTrackTypeSubtitle ].size ());
if (captionmode == kDisplayAVSubtitle &&
(trackNo < 0 || trackNo >= trackcount))
if (captionmode == kDisplayAVSubtitle && (trackNo < 0 || trackNo >= trackcount))
{
m_parent->EnableSubtitles (false );
}
Expand All
@@ -540,25 +525,25 @@ void AvFormatDecoderDVD::PostProcessTracks(void)
}
}
bool AvFormatDecoderDVD::DoRewindSeek (long long desiredFrame )
bool AvFormatDecoderDVD::DoRewindSeek (long long DesiredFrame )
{
if (!m_ringBuffer->IsDVD ())
return false ;
m_ringBuffer->Seek (DVDFindPosition (desiredFrame ), SEEK_SET);
m_framesPlayed = m_framesRead = m_lastKey = desiredFrame + 1 ;
m_ringBuffer->Seek (DVDFindPosition (DesiredFrame ), SEEK_SET);
m_framesPlayed = m_framesRead = m_lastKey = DesiredFrame + 1 ;
m_frameCounter += 100 ;
return true ;
}
void AvFormatDecoderDVD::DoFastForwardSeek (long long desiredFrame , bool &needflush )
void AvFormatDecoderDVD::DoFastForwardSeek (long long DesiredFrame , bool &NeedFlush )
{
if (!m_ringBuffer->IsDVD ())
return ;
m_ringBuffer->Seek (DVDFindPosition (desiredFrame), SEEK_SET);
needflush = true ;
m_framesPlayed = m_framesRead = m_lastKey = desiredFrame + 1 ;
m_ringBuffer->Seek (DVDFindPosition (DesiredFrame), SEEK_SET);
NeedFlush = true ;
m_framesPlayed = m_framesRead = m_lastKey = DesiredFrame + 1 ;
m_frameCounter += 100 ;
}
Expand Down
Expand Up
@@ -603,19 +588,17 @@ void AvFormatDecoderDVD::StreamChangeCheck(void)
}
}
int AvFormatDecoderDVD::GetAudioLanguage (uint audio_index , uint stream_index )
int AvFormatDecoderDVD::GetAudioLanguage (uint /* AudioIndex */ , uint StreamIndex )
{
(void )audio_index;
if ((m_ic->streams [stream_index]->id >= 0 ) &&
m_ringBuffer && m_ringBuffer->IsDVD ())
if ((m_ic->streams [StreamIndex]->id >= 0 ) && (m_ringBuffer && m_ringBuffer->IsDVD ()))
{
auto track = m_ringBuffer->DVD ()->GetAudioTrackNum (static_cast <uint >(m_ic->streams [stream_index ]->id ));
auto track = m_ringBuffer->DVD ()->GetAudioTrackNum (static_cast <uint >(m_ic->streams [StreamIndex ]->id ));
return static_cast <int >(m_ringBuffer->DVD ()->GetAudioLanguage (track));
}
return iso639_str3_to_key (" und" );
}
long long AvFormatDecoderDVD::DVDFindPosition (long long desiredFrame )
long long AvFormatDecoderDVD::DVDFindPosition (long long DesiredFrame )
{
if (!m_ringBuffer->IsDVD ())
return 0 ;
Expand All
@@ -625,12 +608,12 @@ long long AvFormatDecoderDVD::DVDFindPosition(long long desiredFrame)
if (m_parent)
{
ffrewSkip = m_parent->GetFFRewSkip ();
current_speed = ( int ) m_parent->GetNextPlaySpeed ();
current_speed = static_cast < int >( m_parent->GetNextPlaySpeed () );
}
if (ffrewSkip == 1 || ffrewSkip == 0 )
{
int diffTime = ( int ) ceil ((desiredFrame - m_framesPlayed) / m_fps);
int diffTime = static_cast < int >( ceil ((DesiredFrame - m_framesPlayed) / m_fps) );
long long desiredTimePos = m_ringBuffer->DVD ()->GetCurrentTime () +
diffTime;
if (diffTime <= 0 )
Expand All
@@ -645,14 +628,14 @@ long long AvFormatDecoderDVD::DVDFindPosition(long long desiredFrame)
return current_speed;
}
AudioTrackType AvFormatDecoderDVD::GetAudioTrackType (uint stream_index )
AudioTrackType AvFormatDecoderDVD::GetAudioTrackType (uint Index )
{
int type = 0 ;
if (m_ringBuffer && m_ringBuffer->DVD ())
{
int logical_idx = m_ringBuffer->DVD ()->GetAudioTrackNum (m_ic->streams [stream_index ]->id );
type = m_ringBuffer->DVD ()->GetAudioTrackType (logical_idx);
int logical_idx = m_ringBuffer->DVD ()->GetAudioTrackNum (static_cast < uint >( m_ic->streams [Index ]->id ) );
type = m_ringBuffer->DVD ()->GetAudioTrackType (static_cast < uint >( logical_idx) );
}
// These are the only types defined in unofficial documentation
Expand All
@@ -671,5 +654,5 @@ AudioTrackType AvFormatDecoderDVD::GetAudioTrackType(uint stream_index)
}
// If the DVD metadata doesn't include the info then we might as well fall through, maybe we'll get lucky
return AvFormatDecoder::GetAudioTrackType (stream_index );
return AvFormatDecoder::GetAudioTrackType (Index );
}