Ticket #11579: 0002-Add-DVD-context-class-to-encapsulate-the-state-of-th.patch

File 0002-Add-DVD-context-class-to-encapsulate-the-state-of-th.patch, 16.0 KB (added by peper03@…, 8 years ago)
  • mythtv/libs/libmythtv/DVD/avformatdecoderdvd.cpp

    From 5cf7ffe9220b67c4c15f427ce3348d28b48e267c Mon Sep 17 00:00:00 2001
    From: Richard <peper03@yahoo.com>
    Date: Mon, 8 Apr 2013 20:53:21 +0200
    Subject: [PATCH 2/4] Add DVD context class to encapsulate the state of the
     DVD VM so that this can be decoupled from the
     ringbuffer. As the decoder and player lag the
     ringbuffer by up to a second or more, this will allow
     them to base their operation on the DVD state at the
     time any given frame was read and not on the 'current'
     state, which may well not be the same.
    
    This change adds no real functionality but implements the base functionality to be built on in further commits.
    ---
     mythtv/libs/libmythtv/DVD/avformatdecoderdvd.cpp |  107 ++++++++++++++++++----
     mythtv/libs/libmythtv/DVD/avformatdecoderdvd.h   |   13 ++-
     mythtv/libs/libmythtv/DVD/dvdringbuffer.cpp      |   95 ++++++++++++++++++-
     mythtv/libs/libmythtv/DVD/dvdringbuffer.h        |   28 +++++-
     mythtv/libs/libmythtv/avformatdecoder.h          |    8 +-
     5 files changed, 221 insertions(+), 30 deletions(-)
    
    diff --git a/mythtv/libs/libmythtv/DVD/avformatdecoderdvd.cpp b/mythtv/libs/libmythtv/DVD/avformatdecoderdvd.cpp
    index 9f12774..b802e31 100644
    a b  
    22#include "mythdvdplayer.h"
    33#include "avformatdecoderdvd.h"
    44
     5extern "C" {
     6#include "libavcodec/avcodec.h"
     7}
     8
    59#define LOC QString("AFD_DVD: ")
    610
    711AvFormatDecoderDVD::AvFormatDecoderDVD(
    812    MythPlayer *parent, const ProgramInfo &pginfo, PlayerFlags flags)
    913  : AvFormatDecoder(parent, pginfo, flags)
     14  , m_curContext(NULL)
    1015{
    1116}
    1217
     18AvFormatDecoderDVD::~AvFormatDecoderDVD()
     19{
     20    if (m_curContext)
     21        m_curContext->DecrRef();
     22
     23    while (m_contextList.size() > 0)
     24        m_contextList.takeFirst()->DecrRef();
     25}
     26
    1327void AvFormatDecoderDVD::Reset(bool reset_video_data, bool seek_reset, bool reset_file)
    1428{
    1529    AvFormatDecoder::Reset(reset_video_data, seek_reset, reset_file);
    bool AvFormatDecoderDVD::GetFrame(DecodeType decodetype) 
    3246    return AvFormatDecoder::GetFrame( kDecodeAV );
    3347}
    3448
    35 int64_t AvFormatDecoderDVD::AdjustTimestamp(int64_t timestamp)
    36 {
    37     int64_t newTimestamp = timestamp;
    38 
    39     if (newTimestamp != AV_NOPTS_VALUE)
    40     {
    41         int64_t timediff = ringBuffer->DVD()->GetTimeDiff();
    42         if (newTimestamp >= timediff)
    43         {
    44             newTimestamp -= timediff;
    45         }
    46     }
    47 
    48     return newTimestamp;
    49 }
    50 
    5149int AvFormatDecoderDVD::ReadPacket(AVFormatContext *ctx, AVPacket* pkt)
    5250{
    5351    int result = av_read_frame(ctx, pkt);
    int AvFormatDecoderDVD::ReadPacket(AVFormatContext *ctx, AVPacket* pkt) 
    6765
    6866    if (result >= 0)
    6967    {
    70         pkt->dts = AdjustTimestamp(pkt->dts);
    71         pkt->pts = AdjustTimestamp(pkt->pts);
     68        pkt->dts = ringBuffer->DVD()->AdjustTimestamp(pkt->dts);
     69        pkt->pts = ringBuffer->DVD()->AdjustTimestamp(pkt->pts);
    7270    }
    7371
    7472    return result;
    7573}
    7674
     75void AvFormatDecoderDVD::CheckContext(int64_t pts)
     76{
     77    if (pts != AV_NOPTS_VALUE)
     78    {
     79        while (m_contextList.size() > 0 &&
     80               pts >= m_contextList.first()->GetEndPTS())
     81        {
     82            if (m_curContext)
     83                m_curContext->DecrRef();
     84
     85            m_curContext = m_contextList.takeFirst();
     86
     87            LOG(VB_GENERAL, LOG_ERR, LOC +
     88                QString("DVD context missed! lba: %1, curpts: %2, nav end pts: %3")
     89                .arg(m_curContext->GetLBA())
     90                .arg(pts)
     91                .arg(m_curContext->GetEndPTS()));
     92        }
     93
     94        if (m_contextList.size() > 0 &&
     95            pts >= m_contextList.first()->GetStartPTS())
     96        {
     97            if (m_curContext)
     98                m_curContext->DecrRef();
     99
     100            m_curContext = m_contextList.takeFirst();
     101        }
     102    }
     103}
     104
     105
     106bool AvFormatDecoderDVD::ProcessVideoPacket(AVStream *stream, AVPacket *pkt)
     107{
     108    int64_t pts = pkt->pts;
     109
     110    if (pts == AV_NOPTS_VALUE)
     111        pts = pkt->dts;
     112
     113    CheckContext(pts);
     114
     115    return AvFormatDecoder::ProcessVideoPacket(stream, pkt);
     116}
     117
     118bool AvFormatDecoderDVD::ProcessDataPacket(AVStream *curstream, AVPacket *pkt,
     119                                           DecodeType decodetype)
     120{
     121    bool ret = true;
     122
     123    if (curstream->codec->codec_id == AV_CODEC_ID_DVD_NAV)
     124    {
     125        MythDVDContext* context = ringBuffer->DVD()->GetDVDContext();
     126
     127        if (context)
     128            m_contextList.append(context);
     129    }
     130    else
     131    {
     132        ret = AvFormatDecoder::ProcessDataPacket(curstream, pkt, decodetype);
     133    }
     134
     135    return ret;
     136}
     137
    77138void AvFormatDecoderDVD::PostProcessTracks(void)
    78139{
    79140    if (!ringBuffer)
    void AvFormatDecoderDVD::StreamChangeCheck(void) 
    238299
    239300    // Always use the first video stream
    240301    // (must come after ScanStreams above)
    241     selectedTrack[kTrackTypeVideo].av_stream_index = 0;
     302    for (uint i = 0; i < ic->nb_streams; i++)
     303    {
     304        AVStream *st = ic->streams[i];
     305        if (st && st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
     306        {
     307            selectedTrack[kTrackTypeVideo].av_stream_index = i;
     308            break;
     309        }
     310    }
    242311}
    243312
    244313int AvFormatDecoderDVD::GetAudioLanguage(uint audio_index, uint stream_index)
  • mythtv/libs/libmythtv/DVD/avformatdecoderdvd.h

    diff --git a/mythtv/libs/libmythtv/DVD/avformatdecoderdvd.h b/mythtv/libs/libmythtv/DVD/avformatdecoderdvd.h
    index bdb64e4..7a167f0 100644
    a b  
    11#ifndef AVFORMATDECODERDVD_H
    22#define AVFORMATDECODERDVD_H
    33
     4#include <QList>
    45#include "avformatdecoder.h"
    56
     7class MythDVDContext;
     8
    69class AvFormatDecoderDVD : public AvFormatDecoder
    710{
    811  public:
    912    AvFormatDecoderDVD(MythPlayer *parent, const ProgramInfo &pginfo,
    1013                       PlayerFlags flags);
     14    virtual ~AvFormatDecoderDVD();
    1115    virtual void Reset(bool reset_video_data, bool seek_reset, bool reset_file);
    1216    virtual void UpdateFramesPlayed(void);
    1317    virtual bool GetFrame(DecodeType decodetype); // DecoderBase
    1418
    1519  protected:
    16     int64_t AdjustTimestamp(int64_t timestamp);
    1720    virtual int  ReadPacket(AVFormatContext *ctx, AVPacket *pkt);
     21    virtual bool ProcessVideoPacket(AVStream *stream, AVPacket *pkt);
     22    virtual bool ProcessDataPacket(AVStream *curstream, AVPacket *pkt,
     23                                   DecodeType decodetype);
    1824
    1925  private:
    2026    virtual bool DoRewindSeek(long long desiredFrame);
    class AvFormatDecoderDVD : public AvFormatDecoder 
    2430    virtual int GetAudioLanguage(uint audio_index, uint stream_index);
    2531    virtual AudioTrackType GetAudioTrackType(uint stream_index);
    2632
     33    void CheckContext(int64_t pts);
     34
    2735    long long DVDFindPosition(long long desiredFrame);
     36
     37    MythDVDContext*        m_curContext;
     38    QList<MythDVDContext*> m_contextList;
    2839};
    2940
    3041#endif // AVFORMATDECODERDVD_H
  • mythtv/libs/libmythtv/DVD/dvdringbuffer.cpp

    diff --git a/mythtv/libs/libmythtv/DVD/dvdringbuffer.cpp b/mythtv/libs/libmythtv/DVD/dvdringbuffer.cpp
    index 8e2b227..c023d73 100644
    a b bool DVDInfo::GetNameAndSerialNum(QString &name, QString &serial) 
    7878    return true;
    7979}
    8080
     81MythDVDContext::MythDVDContext() :
     82    ReferenceCounter("MythDVDContext")
     83{
     84}
     85
     86MythDVDContext::~MythDVDContext()
     87{
     88}
     89
    8190DVDRingBuffer::DVDRingBuffer(const QString &lfilename) :
    8291    RingBuffer(kRingBuffer_DVD),
    8392    m_dvdnav(NULL),     m_dvdBlockReadBuf(NULL),
    DVDRingBuffer::DVDRingBuffer(const QString &lfilename) : 
    113122    m_currentTime(0),
    114123    m_parent(NULL),
    115124    m_forcedAspect(-1.0f),
     125    m_contextLock(QMutex::Recursive), m_context(NULL),
    116126    m_processState(PROCESS_NORMAL),
    117127    m_dvdStat(DVDNAV_STATUS_OK),
    118128    m_dvdEvent(0),
    DVDRingBuffer::~DVDRingBuffer() 
    149159
    150160void DVDRingBuffer::CloseDVD(void)
    151161{
     162    QMutexLocker contextLocker(&m_contextLock);
    152163    rwlock.lockForWrite();
    153164    if (m_dvdnav)
    154165    {
    void DVDRingBuffer::CloseDVD(void) 
    156167        dvdnav_close(m_dvdnav);
    157168        m_dvdnav = NULL;
    158169    }
     170
     171    if (m_context)
     172    {
     173        m_context->DecrRef();
     174        m_context = NULL;
     175    }
     176
    159177    m_gotStop = false;
    160178    m_audioStreamsChanged = true;
    161179    rwlock.unlock();
    void DVDRingBuffer::GetDescForPos(QString &desc) 
    321339
    322340bool DVDRingBuffer::OpenFile(const QString &lfilename, uint retry_ms)
    323341{
     342    QMutexLocker contextLocker(&m_contextLock);
    324343    rwlock.lockForWrite();
    325344
    326345    if (m_dvdnav)
    bool DVDRingBuffer::OpenFile(const QString &lfilename, uint retry_ms) 
    347366    LOG(VB_GENERAL, LOG_INFO, LOC + QString("Opened DVD device at %1")
    348367            .arg(fname.constData()));
    349368
     369    if (m_context)
     370        m_context->DecrRef();
     371
     372    m_context = new MythDVDContext();
     373
    350374    dvdnav_set_readahead_flag(m_dvdnav, 0);
    351375    dvdnav_set_PGC_positioning_flag(m_dvdnav, 1);
    352376
    bool DVDRingBuffer::StartFromBeginning(void) 
    408432    m_endPts = 0;
    409433    m_timeDiff = 0;
    410434
     435    QMutexLocker contextLocker(&m_contextLock);
     436    if (m_context)
     437        m_context->DecrRef();
     438
     439    m_context = new MythDVDContext();
     440
    411441    return m_dvdnav;
    412442}
    413443
    long long DVDRingBuffer::GetReadPosition(void) const 
    472502    return pos * DVD_BLOCK_SIZE;
    473503}
    474504
     505uint32_t DVDRingBuffer::AdjustTimestamp(uint32_t timestamp)
     506{
     507    uint32_t newTimestamp = timestamp;
     508
     509    if (newTimestamp >= m_timeDiff)
     510    {
     511        newTimestamp -= m_timeDiff;
     512    }
     513
     514    return newTimestamp;
     515}
     516
     517int64_t DVDRingBuffer::AdjustTimestamp(int64_t timestamp)
     518{
     519    int64_t newTimestamp = timestamp;
     520
     521    if (newTimestamp != AV_NOPTS_VALUE && newTimestamp >= m_timeDiff)
     522    {
     523        newTimestamp -= m_timeDiff;
     524    }
     525
     526    return newTimestamp;
     527}
     528
     529MythDVDContext *DVDRingBuffer::GetDVDContext(void)
     530{
     531    QMutexLocker contextLocker(&m_contextLock);
     532
     533    if (m_context)
     534        m_context->IncrRef();
     535
     536    return m_context;
     537}
     538
    475539void DVDRingBuffer::WaitForPlayer(void)
    476540{
    477541    if (!m_skipstillorwait)
    int DVDRingBuffer::safe_read(void *data, uint sz) 
    759823
    760824                m_endPts = pci->pci_gi.vobu_e_ptm;
    761825
     826                QMutexLocker contextLocker(&m_contextLock);
     827                if (m_context)
     828                    m_context->DecrRef();
     829
     830                m_context = new MythDVDContext();
     831
     832                m_context->m_pci = *pci;
     833
     834                m_context->m_pci.pci_gi.vobu_s_ptm = AdjustTimestamp(m_context->m_pci.pci_gi.vobu_s_ptm);
     835                m_context->m_pci.pci_gi.vobu_e_ptm = AdjustTimestamp(m_context->m_pci.pci_gi.vobu_e_ptm);
     836
     837                if (pci->pci_gi.vobu_se_e_ptm != 0)
     838                    m_context->m_pci.pci_gi.vobu_se_e_ptm = AdjustTimestamp(m_context->m_pci.pci_gi.vobu_se_e_ptm);
     839
    762840                // get the latest nav
    763841                m_lastNav = (dvdnav_t *)blockBuf;
    764842
    765                 // retrive the latest Data Search Information
     843                // retrieve the latest Data Search Information
    766844                dsi_t *dsi = dvdnav_get_current_nav_dsi(m_dvdnav);
    767845
     846                m_context->m_dsi = *dsi;
     847
    768848                // if we are in a looping menu, we don't want to reset the
    769849                // selected button when we restart
    770850                m_vobid  = dsi->dsi_gi.vobu_vob_idn;
    int DVDRingBuffer::safe_read(void *data, uint sz) 
    781861
    782862                if (m_seeking)
    783863                {
    784 
    785864                    int relativetime =
    786865                        (int)((m_seektime - m_currentTime)/ 90000);
    787866                    if (abs(relativetime) <= 1)
    int DVDRingBuffer::safe_read(void *data, uint sz) 
    814893                }
    815894
    816895                // debug
    817                 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("DVDNAV_NAV_PACKET - time:%1, pos:%2, vob:%3, cell:%4, seeking:%5, seektime:%6")
    818                     .arg(m_currentTime)
    819                     .arg(m_currentpos)
     896                LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("DVDNAV_NAV_PACKET - time:%1, lba:%2, vob:%3, cell:%4, seeking:%5, seektime:%6")
     897                    .arg(m_context->GetStartPTS())
     898                    .arg(m_context->GetLBA())
    820899                    .arg(m_vobid)
    821900                    .arg(m_cellid)
    822901                    .arg(m_seeking)
    823902                    .arg(m_seektime));
    824903
     904                if (!m_seeking)
     905                {
     906                    memcpy(dest + offset, blockBuf, DVD_BLOCK_SIZE);
     907                    tot += DVD_BLOCK_SIZE;
     908                }
     909
    825910                // release buffer
    826911                if (blockBuf != m_dvdBlockWriteBuf)
    827912                    dvdnav_free_cache_block(m_dvdnav, blockBuf);
  • mythtv/libs/libmythtv/DVD/dvdringbuffer.h

    diff --git a/mythtv/libs/libmythtv/DVD/dvdringbuffer.h b/mythtv/libs/libmythtv/DVD/dvdringbuffer.h
    index 546843b..a331d4a 100644
    a b  
    1212
    1313#include "ringbuffer.h"
    1414#include "mythdate.h"
     15#include "referencecounter.h"
    1516
    1617extern "C" {
    1718#include "libavcodec/avcodec.h"
    extern "C" { 
    1920
    2021#include "dvdnav/dvdnav.h"
    2122
     23class MTV_PUBLIC MythDVDContext : public ReferenceCounter
     24{
     25    friend class DVDRingBuffer;
     26
     27  public:
     28    virtual ~MythDVDContext();
     29
     30    int64_t  GetStartPTS()         const { return (int64_t)m_pci.pci_gi.vobu_s_ptm;    }
     31    int64_t  GetEndPTS()           const { return (int64_t)m_pci.pci_gi.vobu_e_ptm;    }
     32    int64_t  GetSeqEndPTS()        const { return (int64_t)m_pci.pci_gi.vobu_se_e_ptm; }
     33    uint32_t GetLBA()              const { return m_pci.pci_gi.nv_pck_lbn;             }
     34
     35  protected:
     36    MythDVDContext();
     37
     38  protected:
     39    dsi_t          m_dsi;
     40    pci_t          m_pci;
     41};
     42
    2243/** \class DVDRingBufferPriv
    2344 *  \brief RingBuffer class for DVD's
    2445 *
    class MTV_PUBLIC DVDRingBuffer : public RingBuffer 
    7899    bool IsWaiting(void) const           { return m_dvdWaiting;          }
    79100    int  NumPartsInTitle(void)     const { return m_titleParts;          }
    80101    void GetMenuSPUPkt(uint8_t *buf, int len, int stream_id, uint32_t startTime);
    81     int64_t GetTimeDiff(void)      const { return m_timeDiff; }
     102
     103    uint32_t AdjustTimestamp(uint32_t timestamp);
     104    int64_t AdjustTimestamp(int64_t timestamp);
     105    MythDVDContext* GetDVDContext(void);
    82106
    83107    // Public menu/button stuff
    84108    AVSubtitle *GetMenuSubtitle(uint &version);
    class MTV_PUBLIC DVDRingBuffer : public RingBuffer 
    206230    MythDVDPlayer *m_parent;
    207231    float          m_forcedAspect;
    208232
     233    QMutex          m_contextLock;
     234    MythDVDContext *m_context;
    209235    processState_t  m_processState;
    210236    dvdnav_status_t m_dvdStat;
    211237    int32_t        m_dvdEvent;
  • mythtv/libs/libmythtv/avformatdecoder.h

    diff --git a/mythtv/libs/libmythtv/avformatdecoder.h b/mythtv/libs/libmythtv/avformatdecoder.h
    index ea08fc9..52cc8e9 100644
    a b class AvFormatDecoder : public DecoderBase 
    9696    static void GetDecoders(render_opts &opts);
    9797    AvFormatDecoder(MythPlayer *parent, const ProgramInfo &pginfo,
    9898                    PlayerFlags flags);
    99    ~AvFormatDecoder();
     99    virtual ~AvFormatDecoder();
    100100
    101101    virtual void SetEof(bool eof);
    102102
    class AvFormatDecoder : public DecoderBase 
    222222    void MpegPreProcessPkt(AVStream *stream, AVPacket *pkt);
    223223    int  H264PreProcessPkt(AVStream *stream, AVPacket *pkt);
    224224    bool PreProcessVideoPacket(AVStream *stream, AVPacket *pkt);
    225     bool ProcessVideoPacket(AVStream *stream, AVPacket *pkt);
     225    virtual bool ProcessVideoPacket(AVStream *stream, AVPacket *pkt);
    226226    bool ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic);
    227227    bool ProcessAudioPacket(AVStream *stream, AVPacket *pkt,
    228228                            DecodeType decodetype);
    229229    bool ProcessSubtitlePacket(AVStream *stream, AVPacket *pkt);
    230230    bool ProcessRawTextPacket(AVPacket *pkt);
    231     bool ProcessDataPacket(AVStream *curstream, AVPacket *pkt,
    232                            DecodeType decodetype);
     231    virtual bool ProcessDataPacket(AVStream *curstream, AVPacket *pkt,
     232                                   DecodeType decodetype);
    233233
    234234    void ProcessVBIDataPacket(const AVStream *stream, const AVPacket *pkt);
    235235    void ProcessDVBDataPacket(const AVStream *stream, const AVPacket *pkt);