Ticket #868: 868-v3.patch

File 868-v3.patch, 19.8 KB (added by danielk, 15 years ago)

updated to apply to latest svn [8427].

  • libs/libmythtv/NuppelVideoPlayer.h

     
    210210        { videoOutput->ReleaseFrame(GetNextVideoFrame(false)); }
    211211    void ReleaseCurrentFrame(VideoFrame *frame);
    212212    void DiscardVideoFrame(VideoFrame *buffer);
    213     void DiscardVideoFrames(void);
     213    void DiscardVideoFrames(bool next_frame_keyframe);
    214214    void DrawSlice(VideoFrame *frame, int x, int y, int w, int h);
    215215
    216216    // Reinit
  • libs/libmythtv/nuppeldecoder.cpp

     
    11701170        avcodec_flush_buffers(mpa_ctx);
    11711171
    11721172    if (discardFrames)
    1173         GetNVP()->DiscardVideoFrames();
     1173        GetNVP()->DiscardVideoFrames(doFlush);
    11741174
    11751175    for (;(skipFrames > 0) && !ateof; skipFrames--)
    11761176    {
  • libs/libmythtv/NuppelVideoPlayer.cpp

     
    804804       MAXTBUFFER - 1. */
    805805}
    806806
     807/** \fn NuppelVideoPlayer::GetNextVideoFrame(bool)
     808 *  \brief Removes a frame from the available queue for decoding onto.
     809 *
     810 *   This places the frame in the limbo queue, from which frames are
     811 *   removed if they are added to another queue. Normally a frame is
     812 *   freed from limbo either by a ReleaseNextVideoFrame() or
     813 *   DiscardVideoFrame() call; but limboed frames are also freed
     814 *   during a seek reset.
     815 *
     816 *  \param allow_unsafe if true then a frame will be taken from the queue
     817 *         of frames ready for display if we can't find a frame in the
     818 *         available queue.
     819 */
    807820VideoFrame *NuppelVideoPlayer::GetNextVideoFrame(bool allow_unsafe)
    808821{
    809822    return videoOutput->GetNextFreeFrame(false, allow_unsafe);
    810823}
    811824
     825/** \fn NuppelVideoPlayer::ReleaseNextVideoFrame(VideoFrame*,long long)
     826 *  \brief Places frame on the queue of frames ready for display.
     827 */
    812828void NuppelVideoPlayer::ReleaseNextVideoFrame(VideoFrame *buffer,
    813829                                              long long timecode)
    814830{
     
    818834    videoOutput->ReleaseFrame(buffer);
    819835}
    820836
     837/** \fn NuppelVideoPlayer::DiscardVideoFrame(VideoFrame*)
     838 *  \brief Places frame in the available frames queue.
     839 */
    821840void NuppelVideoPlayer::DiscardVideoFrame(VideoFrame *buffer)
    822841{
    823842    if (videoOutput)
    824843        videoOutput->DiscardFrame(buffer);
    825844}
    826845
    827 void NuppelVideoPlayer::DiscardVideoFrames()
     846/** \fn DiscardVideoFrames(bool)
     847 *  \brief Places frames in the available frames queue.
     848 *
     849 *   If called with 'next_frame_keyframe' set to false then all frames
     850 *   not in use by the decoder are made available for decoding. Otherwise,
     851 *   all frames are made available for decoding; this is only safe if
     852 *   the next frame is a keyframe.
     853 *
     854 *  \param next_frame_keyframe if this is true all frames are placed
     855 *         in the available queue.
     856 */
     857void NuppelVideoPlayer::DiscardVideoFrames(bool next_frame_keyframe)
    828858{
    829859    if (videoOutput)
    830         videoOutput->DiscardFrames();
     860        videoOutput->DiscardFrames(next_frame_keyframe);
    831861}
    832862
    833863void NuppelVideoPlayer::DrawSlice(VideoFrame *frame, int x, int y, int w, int h)
     
    16591689                VERBOSE(VB_IMPORTANT, LOC + "Prebuffer wait timed out, and"
    16601690                        "\n\t\t\tthere are not enough free frames. "
    16611691                        "Discarding buffered frames.");
    1662                 DiscardVideoFrames();
     1692                // This call will result in some ugly frames, but allows us
     1693                // to recover from serious problems if frames get leaked.
     1694                DiscardVideoFrames(true);
    16631695            }
    16641696            prebuffer_tries = 0;
    16651697        }
     
    30133045/** \fn NuppelVideoPlayer::ClearAfterSeek(void)
    30143046 *  \brief This is to support seeking...
    30153047 *
    3016  *   It can be very dangerous as it removes all frames from
    3017  *   the videoOutput, so you can't restart playback immediately.
     3048 *   This resets the output classes and discards all
     3049 *   frames no longer being used by the decoder class.
    30183050 *
    30193051 *   Note: caller should not hold any locks
    30203052 */
  • libs/libmythtv/avformatdecoder.cpp

     
    169169                    *got_picture_ptr = 1;
    170170                    *picture = *frm;
    171171                    delete frm;
     172#if 0
     173                    QString msg("");
     174                    AvFormatDecoder *nd = (AvFormatDecoder *)(avctx->opaque);
     175                    if (nd && nd->GetNVP() && nd->GetNVP()->getVideoOutput())
     176                        msg = nd->GetNVP()->getVideoOutput()->GetFrameStatus();
     177
     178                    VERBOSE(VB_IMPORTANT, "ret frame: "<<picture->opaque
     179                            <<"           "<<msg);
     180#endif
    172181                }
    173182                return buf_size;
    174183            case STATE_INVALID:
     
    316325    return  ((lsb - base_ts)&mask);
    317326}
    318327
    319 bool AvFormatDecoder::DoRewind(long long desiredFrame, bool doflush)
     328bool AvFormatDecoder::DoRewind(long long desiredFrame, bool discardFrames)
    320329{
    321330    VERBOSE(VB_PLAYBACK, LOC + "DoRewind("
    322             <<desiredFrame<<", "<<( doflush ? "do" : "don't" )<<" flush)");
     331            <<desiredFrame<<", "
     332            <<( discardFrames ? "do" : "don't" )<<" discard frames)");
    323333
    324334    if (recordingHasPositionMap || livetv)
    325         return DecoderBase::DoRewind(desiredFrame, doflush);
     335        return DecoderBase::DoRewind(desiredFrame, discardFrames);
    326336
    327337    // avformat-based seeking
    328     return DoFastForward(desiredFrame, doflush);
     338    return DoFastForward(desiredFrame, discardFrames);
    329339}
    330340
    331 bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool doflush)
     341bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool discardFrames)
    332342{
    333     VERBOSE(VB_PLAYBACK, LOC + "DoFastForward("
    334             <<desiredFrame<<", "<<( doflush ? "do" : "don't" )<<" flush)");
     343    VERBOSE(VB_PLAYBACK, LOC +
     344            QString("DoFastForward(%1 (%2), %3 discard frames)")
     345            .arg(desiredFrame).arg(framesPlayed)
     346            .arg((discardFrames) ? "do" : "don't"));
    335347
    336348    if (recordingHasPositionMap || livetv)
    337         return DecoderBase::DoFastForward(desiredFrame, doflush);
     349        return DecoderBase::DoFastForward(desiredFrame, discardFrames);
    338350
    339351    bool oldrawstate = getrawframes;
    340352    getrawframes = false;
     
    395407
    396408    int normalframes = desiredFrame - framesPlayed;
    397409
    398     SeekReset(lastKey, normalframes, doflush, doflush);
     410    SeekReset(lastKey, normalframes, discardFrames, discardFrames);
    399411
    400     if (doflush)
     412    if (discardFrames)
    401413    {
    402414        GetNVP()->SetFramesPlayed(framesPlayed + 1);
    403415        GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed + 1);
     
    450462
    451463    // Discard all the queued up decoded frames
    452464    if (discardFrames)
    453         GetNVP()->DiscardVideoFrames();
     465        GetNVP()->DiscardVideoFrames(doflush);
    454466
    455467    if (doflush)
    456468    {
  • libs/libmythtv/decoderbase.h

     
    9494  protected:
    9595    void FileChanged(void);
    9696
    97     bool DoRewindDVD(long long desiredFrame);
    98     bool DoRewindNormal(long long desiredFrame);
     97    bool DoRewindSeek(long long desiredFrame);
    9998    void DoFastForwardSeek(long long desiredFrame, bool &needflush);
    10099
    101100    long long GetLastFrameInPosMap(long long desiredFrame);
  • libs/libmythtv/videooutbase.cpp

     
    422422    XJ_height = height;
    423423    SetVideoAspectRatio(aspect);
    424424   
    425     DiscardFrames();
     425    DiscardFrames(true);
    426426}
    427427
    428428/**
  • libs/libmythtv/videoout_xv.h

     
    103103
    104104    VideoFrame *GetNextFreeFrame(bool allow_unsafe);
    105105    void DiscardFrame(VideoFrame*);
    106     void DiscardFrames(void);
     106    void DiscardFrames(bool kf);
    107107    void DoneDisplayingFrame(void);
    108108
    109109    void ProcessFrameXvMC(VideoFrame *frame, OSD *osd);
  • libs/libmythtv/videoout_xv.cpp

     
    16421642void VideoOutputXv::DeleteBuffers(VOSType subtype, bool delete_pause_frame)
    16431643{
    16441644    (void) subtype;
    1645     DiscardFrames();
     1645    DiscardFrames(true);
    16461646
    16471647#ifdef USING_XVMC
    16481648    // XvMC buffers
     
    16511651        xvmc_vo_surf_t *surf = (xvmc_vo_surf_t*) xvmc_surfs[i];
    16521652        X11S(XvMCHideSurface(XJ_disp, &(surf->surface)));
    16531653    }
    1654     DiscardFrames();
     1654    DiscardFrames(true);
    16551655    for (uint i=0; i<xvmc_surfs.size(); i++)
    16561656    {
    16571657        xvmc_vo_surf_t *surf = (xvmc_vo_surf_t*) xvmc_surfs[i];
     
    18241824void VideoOutputXv::ClearAfterSeek(void)
    18251825{
    18261826    VERBOSE(VB_PLAYBACK, LOC + "ClearAfterSeek()");
    1827     DiscardFrames();
     1827    DiscardFrames(false);
    18281828#ifdef USING_XVMC
    18291829    if (VideoOutputSubType() > XVideo)
    18301830    {
     
    18331833            xvmc_vo_surf_t *surf = (xvmc_vo_surf_t*) xvmc_surfs[i];
    18341834            X11S(XvMCHideSurface(XJ_disp, &(surf->surface)));
    18351835        }
    1836         DiscardFrames();
     1836        DiscardFrames(true);
    18371837    }
    18381838#endif
    18391839}
     
    18441844        vbuffers.end_lock(); \
    18451845    } while (0)
    18461846
    1847 void VideoOutputXv::DiscardFrames(void)
     1847void VideoOutputXv::DiscardFrames(bool next_frame_keyframe)
    18481848{
    18491849    if (VideoOutputSubType() <= XVideo)
    18501850    {
    1851         vbuffers.DiscardFrames();
     1851        vbuffers.DiscardFrames(next_frame_keyframe);
    18521852        return;
    18531853    }
    18541854
     
    20102010void VideoOutputXv::PrepareFrameXv(VideoFrame *frame)
    20112011{
    20122012    if (!frame)
     2013    {
    20132014        frame = vbuffers.GetScratchFrame();
     2015        vbuffers.GetScratchFrame()->frameNumber = framesPlayed - 1LL;
     2016    }
    20142017
    20152018    XvImage *image = NULL;
    20162019    {
     
    20492052void VideoOutputXv::PrepareFrameMem(VideoFrame *buffer, FrameScanType /*scan*/)
    20502053{
    20512054    if (!buffer)
     2055    {
    20522056        buffer = vbuffers.GetScratchFrame();
     2057        vbuffers.GetScratchFrame()->frameNumber = framesPlayed - 1LL;
     2058    }
    20532059
    20542060    vbuffers.LockFrame(buffer, "PrepareFrameMem");
    20552061
     
    25322538            vbuffers.TryLockFrame(vbuffers.GetScratchFrame(),
    25332539                                  "UpdatePauseFrame -- scratch"))
    25342540        {
     2541            vbuffers.GetScratchFrame()->frameNumber = framesPlayed - 1;
    25352542            CopyFrame(&av_pause_frame, vbuffers.GetScratchFrame());
    25362543            vbuffers.UnlockFrame(vbuffers.GetScratchFrame(),
    25372544                                 "UpdatePauseFrame -- scratch");
     
    27892796    if (!frame)
    27902797    {
    27912798        frame = vbuffers.GetScratchFrame();
     2799        frame->frameNumber = framesPlayed - 1LL;
    27922800        vector<const VideoFrame*> locks;
    27932801        locks.push_back(frame);
    27942802        locks.push_back(&av_pause_frame);
     
    29482956            frame_queue_t children = vbuffers.Children(pframe);
    29492957            if (!children.empty())
    29502958            {
     2959#if 0
    29512960                VERBOSE(VB_PLAYBACK, LOC + QString(
    29522961                            "Frame %1 w/children: %2 is being held for later "
    29532962                            "discarding.")
    29542963                        .arg(DebugString(pframe, true))
    29552964                        .arg(DebugString(children)));
    2956 
     2965#endif
    29572966                frame_queue_t::iterator cit;
    29582967                for (cit = children.begin(); cit != children.end(); ++cit)
    29592968                {
  • libs/libmythtv/decoderbase.cpp

     
    408408    }
    409409}
    410410
    411 bool DecoderBase::DoRewind(long long desiredFrame, bool doflush)
     411bool DecoderBase::DoRewind(long long desiredFrame, bool discardFrames)
    412412{
    413     VERBOSE(VB_PLAYBACK, LOC + "DoRewind("
    414             <<desiredFrame<<", "<<( doflush ? "do" : "don't" )<<" flush)");
     413    VERBOSE(VB_PLAYBACK, LOC +
     414            QString("DoRewind(%1 (%2), %3 discard frames)")
     415            .arg(desiredFrame).arg(framesPlayed)
     416            .arg((discardFrames) ? "do" : "don't"));
    415417
    416418    if (m_positionMap.empty())
    417419        return false;
    418420
    419     {
    420         bool ok = true;
    421         if (ringBuffer->isDVD())
    422             ok = DoRewindDVD(desiredFrame);
    423         else
    424             ok = DoRewindNormal(desiredFrame);
     421    if (!DoRewindSeek(desiredFrame))
     422        return false;
    425423
    426         if (!ok)
    427             return false;
    428     }
    429 
    430424    framesPlayed = lastKey;
    431425    framesRead = lastKey;
    432426
    433427    // Do any Extra frame-by-frame seeking for exactseeks mode
    434428    // And flush pre-seek frame if we are allowed to and need to..
    435429    int normalframes = (exactseeks) ? desiredFrame - framesPlayed : 0;
     430    normalframes = max(normalframes, 0);
     431    SeekReset(lastKey, normalframes, true, discardFrames);
    436432
    437     // This shouldn't happen, but it's nasty if it does so prevent it
    438     if (normalframes < 0)
    439         normalframes = 0;
    440 
    441     SeekReset(lastKey, normalframes, true, doflush);
    442 
    443     // ???
    444     if (doflush)
     433    if (discardFrames)
    445434    {
     435        // We need to tell the NVP and VideoOutput what frame we're on.
    446436        GetNVP()->SetFramesPlayed(framesPlayed+1);
    447437        GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed+1);
    448438    }
     
    456446    return (hasKeyFrameAdjustTable) ? e.adjFrame :(e.index - indexOffset) * kf;
    457447}
    458448
    459 bool DecoderBase::DoRewindDVD(long long desiredFrame)
     449bool DecoderBase::DoRewindSeek(long long desiredFrame)
    460450{
    461     long long pos = DVDFindPosition(desiredFrame);
    462     ringBuffer->Seek(pos, SEEK_SET);
    463     lastKey = desiredFrame + 1;
    464     return true;
    465 }
     451    if (ringBuffer->isDVD())
     452    {
     453        long long pos = DVDFindPosition(desiredFrame);
     454        ringBuffer->Seek(pos, SEEK_SET);
     455        lastKey = desiredFrame + 1;
     456        return true;
     457    }
    466458
    467 bool DecoderBase::DoRewindNormal(long long desiredFrame)
    468 {
    469459    // Find keyframe <= desiredFrame, store in lastKey (frames)
    470460    int pre_idx, post_idx;
    471461    FindPosition(desiredFrame, hasKeyFrameAdjustTable, pre_idx, post_idx);
     
    538528            .arg(desiredFrame).arg(framesPlayed)
    539529            .arg((discardFrames) ? "do" : "don't"));
    540530
    541     // Rewind if we have already played the desiredFrame.
    542     if (desiredFrame < framesPlayed)
     531    // Rewind if we have already played the desiredFrame. The +1 is for
     532    // MPEG4 NUV files, which need to decode an extra frame sometimes.
     533    // This shouldn't effect how this works in general because this is
     534    // only triggered on the first keyframe/frame skip when paused. At
     535    // that point the decoding is more than one frame ahead of display.
     536    if (desiredFrame+1 < framesPlayed)
    543537        return DoRewind(desiredFrame, discardFrames);
     538    desiredFrame = max(desiredFrame, framesPlayed);
    544539
    545540    // Save rawframe state, for later restoration...
    546541    bool oldrawstate = getrawframes;
  • libs/libmythtv/ivtvdecoder.cpp

     
    2020#include "videoout_ivtv.h"
    2121#include "videodev_myth.h"
    2222
     23#define LOC QString("IVD: ")
     24#define LOC_ERR QString("IVD Error: ")
     25
    2326bool IvtvDecoder::ntsc = true;
    2427
    2528IvtvDecoder::IvtvDecoder(NuppelVideoPlayer *parent, ProgramInfo *pginfo)
     
    5356void IvtvDecoder::SeekReset(long long newkey, uint skipframes,
    5457                            bool needFlush, bool discardFrames)
    5558{
     59    VERBOSE(VB_PLAYBACK, LOC + QString("SeekReset(%1, %2 flush, %3 discard)")
     60            .arg(skipframes).arg((needFlush) ? "do" : "don't")
     61            .arg((discardFrames) ? "do" : "don't"));
     62
    5663    DecoderBase::SeekReset(newkey, skipframes, needFlush, discardFrames);
    5764
    5865    if (!exactseeks)
     
    7784        vidframes = 0;
    7885        queuedlist.clear();
    7986
    80         videoout->Stop(false);
     87        videoout->Stop(false /* hide */);
    8188        videoout->Flush();
    8289
    8390        videoout->Start(0, skipframes+5);
  • libs/libmythtv/videooutbase.h

     
    253253    virtual void DiscardFrame(VideoFrame *frame) { vbuffers.DiscardFrame(frame); }
    254254    /// \brief Releases all frames not being actively displayed from any queue
    255255    ///        onto the queue of frames ready for decoding onto.
    256     virtual void DiscardFrames(void) { vbuffers.DiscardFrames(); }
     256    virtual void DiscardFrames(bool kf) { vbuffers.DiscardFrames(kf); }
    257257
    258258    /// \bug not implemented correctly. vpos is not updated.
    259259    VideoFrame *GetLastDecodedFrame(void) { return vbuffers.GetLastDecodedFrame(); }
  • libs/libmythtv/videobuffers.h

     
    5959    void DeleteBuffers(void);
    6060
    6161    void Reset(void);
    62     void DiscardFrames(void);
     62    void DiscardFrames(bool next_frame_keyframe);
    6363    void ClearAfterSeek(void);
    6464
    6565    void SetPrebuffering(bool normal);
  • libs/libmythtv/videobuffers.cpp

     
    288288                        QString("GetNextFreeFrame() unable to "
    289289                        "lock frame %1 times. Discarding Frames.")
    290290                        .arg(TRY_LOCK_SPINS));
    291                 DiscardFrames();
     291                DiscardFrames(true);
    292292            }
    293293        }
    294294    }
     
    597597}
    598598
    599599/**
    600  * \fn VideoBuffers::DiscardFrames(void)
     600 * \fn VideoBuffers::DiscardFrames(bool)
    601601 *  Mark all used frames as ready to be reused, this is for seek.
    602602 */
    603 void VideoBuffers::DiscardFrames(void)
     603void VideoBuffers::DiscardFrames(bool next_frame_keyframe)
    604604{
    605     global_lock.lock();
    606     VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(): %1")
    607             .arg(GetStatus()));
     605    QMutexLocker locker(&global_lock);
     606    VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(%1): %2")
     607            .arg(next_frame_keyframe).arg(GetStatus()));
    608608
     609    if (!next_frame_keyframe)
     610    {
     611        for (bool change = true; change;)
     612        {
     613            change = false;
     614            frame_queue_t ula(used);
     615            frame_queue_t::iterator it = ula.begin();
     616            for (; it != ula.end(); ++it)
     617            {
     618                if (!HasChildren(*it))
     619                {
     620                    RemoveInheritence(*it);
     621                    DiscardFrame(*it);
     622                    change = true;
     623                }
     624            }
     625        }
     626        VERBOSE(VB_PLAYBACK,
     627                QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
     628                .arg(next_frame_keyframe).arg(GetStatus()));
     629        return;
     630    }
     631
    609632    // Remove inheritence of all frames not in displayed or pause
    610633    frame_queue_t ula(used);
    611634    ula.insert(ula.end(), limbo.begin(), limbo.end());
     
    650673    VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(): %1 -- done()")
    651674            .arg(GetStatus()));
    652675
    653     global_lock.unlock();
     676    VERBOSE(VB_PLAYBACK,
     677            QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
     678            .arg(next_frame_keyframe).arg(GetStatus()));
    654679}
    655680
    656681void VideoBuffers::ClearAfterSeek(void)