Ticket #868: 868-v1.patch

File 868-v1.patch, 29.9 KB (added by danielk, 15 years ago)

fixes mpeg4 NUV problem, and removes seek hack

  • 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

     
    3737#endif
    3838      ffmpeg_extradatasize(0), ffmpeg_extradata(0), usingextradata(false),
    3939      disablevideo(false), totalLength(0), totalFrames(0), effdsp(0),
    40       directbuf(0), mpa_codec(0), mpa_ctx(0), directrendering(false),
     40      directframe(NULL), mpa_codec(0), mpa_ctx(0), directrendering(false),
    4141      lastct('1'), strm(0), buf(0), buf2(0),
    4242      videosizetotal(0), videoframesread(0), setreadahead(false)
    4343{
     
    566566    int width = c->width;
    567567    int height = c->height;
    568568
    569     pic->data[0] = nd->directbuf;
     569    pic->data[0] = nd->directframe->buf;
    570570    pic->data[1] = pic->data[0] + width * height;
    571571    pic->data[2] = pic->data[1] + width * height / 4;
    572572
     
    574574    pic->linesize[1] = width / 2;
    575575    pic->linesize[2] = width / 2;
    576576
    577     pic->opaque = nd;
     577    pic->opaque = nd->directframe;
    578578    pic->type = FF_BUFFER_TYPE_USER;
    579579
    580580    pic->age = 256 * 256 * 256 * 64;
     
    587587    (void)c;
    588588    assert(pic->type == FF_BUFFER_TYPE_USER);
    589589
     590    NuppelDecoder *nd = (NuppelDecoder *)(c->opaque);
     591    if (nd && nd->GetNVP() && nd->GetNVP()->getVideoOutput())
     592        nd->GetNVP()->getVideoOutput()->DeLimboFrame((VideoFrame*)pic->opaque);
     593
    590594    int i;
    591595    for (i = 0; i < 4; i++)
    592596        pic->data[i] = NULL;
     
    683687    int compoff = 0;
    684688
    685689    unsigned char *outbuf = frame->buf;
     690    directframe = frame;
    686691
    687692    if (!buf2)
    688693    {
     
    759764        int gotpicture = 0;
    760765        pthread_mutex_lock(&avcodeclock);
    761766        // if directrendering, writes into buf
    762         directbuf = outbuf;
    763767        int ret = avcodec_decode_video(mpa_ctx, &mpa_pic, &gotpicture,
    764768                                       lstrm, frameheader->packetlength);
     769        directframe = NULL;
    765770        pthread_mutex_unlock(&avcodeclock);
    766771        if (ret < 0)
    767772        {
     
    10461051
    10471052            buf->frameNumber = framesPlayed;
    10481053            GetNVP()->ReleaseNextVideoFrame(buf, frameheader.timecode);
     1054            if (directframe)
     1055                GetNVP()->getVideoOutput()->DeLimboFrame(buf);
    10491056            gotvideo = 1;
    10501057            if (getrawframes && getrawvideo)
    10511058                StoreRawData(strm);
     
    11461153    if (mpa_codec && needFlush)
    11471154        avcodec_flush_buffers(mpa_ctx);
    11481155
     1156    if (discardFrames)
     1157        GetNVP()->DiscardVideoFrames(needFlush);
     1158
    11491159    while (skipFrames > 0)
    11501160    {
    11511161        GetFrame(0);
  • libs/libmythtv/NuppelVideoPlayer.cpp

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

     
    6565    height = (height + 15) & (~0xf);
    6666}
    6767
     68typedef MythDeque<AVFrame*> avframe_q;
     69
    6870class AvFormatDecoderPrivate
    6971{
    7072  public:
     
    8385  private:
    8486    mpeg2dec_t *mpeg2dec;
    8587    bool        allow_mpeg2dec;
     88    avframe_q   partialFrames;
    8689};
    8790
    8891bool AvFormatDecoderPrivate::InitMPEG2()
     
    103106void AvFormatDecoderPrivate::DestroyMPEG2()
    104107{
    105108    if (mpeg2dec)
     109    {
    106110        mpeg2_close(mpeg2dec);
    107     mpeg2dec = NULL;
     111        mpeg2dec = NULL;
     112
     113        avframe_q::iterator it = partialFrames.begin();
     114        for (; it != partialFrames.end(); ++it)
     115            delete (*it);
     116        partialFrames.clear();
     117    }
    108118}
    109119
    110120void AvFormatDecoderPrivate::ResetMPEG2()
    111121{
    112122    if (mpeg2dec)
     123    {
    113124        mpeg2_reset(mpeg2dec, 0);
     125
     126        avframe_q::iterator it = partialFrames.begin();
     127        for (; it != partialFrames.end(); ++it)
     128            delete (*it);
     129        partialFrames.clear();
     130    }
    114131}
    115132
    116133int AvFormatDecoderPrivate::DecodeMPEG2Video(AVCodecContext *avctx,
     
    145162                mpeg2_set_buf(mpeg2dec, picture->data, picture->opaque);
    146163                break;
    147164            case STATE_BUFFER:
    148                 // We're supposed to wait for STATE_SLICE, but
    149                 // STATE_BUFFER is returned first. Since we handed
    150                 // libmpeg2 a full frame, we know it should be
    151                 // done once it's finished with the data.
    152                 if (info->display_fbuf)
     165                // We're finished with the buffer...
     166                if (partialFrames.size())
    153167                {
    154                     picture->data[0] = info->display_fbuf->buf[0];
    155                     picture->data[1] = info->display_fbuf->buf[1];
    156                     picture->data[2] = info->display_fbuf->buf[2];
    157                     picture->opaque  = info->display_fbuf->id;
     168                    AVFrame *frm = partialFrames.dequeue();
    158169                    *got_picture_ptr = 1;
    159                     picture->top_field_first = !!(info->display_picture->flags &
    160                                                   PIC_FLAG_TOP_FIELD_FIRST);
    161                     picture->interlaced_frame = !(info->display_picture->flags &
    162                                                   PIC_FLAG_PROGRESSIVE_FRAME);
     170                    *picture = *frm;
     171                    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
    163181                }
    164182                return buf_size;
    165183            case STATE_INVALID:
    166184                // This is the error state. The decoder must be
    167185                // reset on an error.
    168                 mpeg2_reset(mpeg2dec, 0);
     186                ResetMPEG2();
    169187                return -1;
     188
     189            case STATE_SLICE:
     190            case STATE_END:
     191            case STATE_INVALID_END:
     192                if (info->display_fbuf)
     193                {
     194                    bool exists = false;
     195                    avframe_q::iterator it = partialFrames.begin();
     196                    for (; it != partialFrames.end(); ++it)
     197                        if ((*it)->opaque == info->display_fbuf->id)
     198                            exists = true;
     199
     200                    if (!exists)
     201                    {
     202                        AVFrame *frm = new AVFrame();
     203                        frm->data[0] = info->display_fbuf->buf[0];
     204                        frm->data[1] = info->display_fbuf->buf[1];
     205                        frm->data[2] = info->display_fbuf->buf[2];
     206                        frm->data[3] = NULL;
     207                        frm->opaque  = info->display_fbuf->id;
     208                        frm->type    = FF_BUFFER_TYPE_USER;
     209                        frm->top_field_first =
     210                            !!(info->display_picture->flags &
     211                               PIC_FLAG_TOP_FIELD_FIRST);
     212                        frm->interlaced_frame =
     213                            !(info->display_picture->flags &
     214                              PIC_FLAG_PROGRESSIVE_FRAME);
     215                        partialFrames.enqueue(frm);
     216                       
     217                    }
     218                }
     219                if (info->discard_fbuf)
     220                {
     221                    bool exists = false;
     222                    avframe_q::iterator it = partialFrames.begin();
     223                    for (; it != partialFrames.end(); ++it)
     224                    {
     225                        if ((*it)->opaque == info->discard_fbuf->id)
     226                        {
     227                            exists = true;
     228                            (*it)->data[3] = (unsigned char*) 1;
     229                        }
     230                    }
     231
     232                    if (!exists)
     233                    {
     234                        AVFrame frame;
     235                        frame.opaque = info->discard_fbuf->id;
     236                        frame.type   = FF_BUFFER_TYPE_USER;
     237                        avctx->release_buffer(avctx, &frame);
     238                    }
     239                }
     240                break;
    170241            default:
    171242                break;
    172243        }
     
    266337    return DoFastForward(desiredFrame, doflush);
    267338}
    268339
    269 bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool doflush)
     340bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool discardFrames)
    270341{
    271     VERBOSE(VB_PLAYBACK, LOC + "DoFastForward("
    272             <<desiredFrame<<", "<<( doflush ? "do" : "don't" )<<" flush)");
     342    VERBOSE(VB_PLAYBACK, LOC +
     343            QString("DoFastForward(%1 (%2), %3 discard frames)")
     344            .arg(desiredFrame).arg(framesPlayed)
     345            .arg((discardFrames) ? "do" : "don't"));
    273346
    274347    if (recordingHasPositionMap || livetv)
    275         return DecoderBase::DoFastForward(desiredFrame, doflush);
     348        return DecoderBase::DoFastForward(desiredFrame, discardFrames);
    276349
    277350    bool oldrawstate = getrawframes;
    278351    getrawframes = false;
     
    333406
    334407    int normalframes = desiredFrame - framesPlayed;
    335408
    336     SeekReset(lastKey, normalframes, doflush, doflush);
     409    SeekReset(lastKey, normalframes, discardFrames, discardFrames);
    337410
    338     if (doflush)
     411    if (discardFrames)
    339412    {
    340413        GetNVP()->SetFramesPlayed(framesPlayed + 1);
    341414        GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed + 1);
     
    355428
    356429    DecoderBase::SeekReset(newKey, skipFrames, doflush, discardFrames);
    357430
    358     lastapts = 0;
    359     lastvpts = 0;
    360     lastccptsu = 0;
    361     save_cctc[0] = save_cctc[1] = 0;
     431    if (doflush)
     432    {
     433        lastapts = 0;
     434        lastvpts = 0;
     435        lastccptsu = 0;
     436        save_cctc[0] = save_cctc[1] = 0;
     437        av_read_frame_flush(ic);
    362438
    363     av_read_frame_flush(ic);
    364    
    365     d->ResetMPEG2();
     439        // Only reset the internal state if we're using our seeking,
     440        // not when using libavformat's seeking
     441        if (recordingHasPositionMap || livetv)
     442        {
     443            ic->pb.pos = ringBuffer->GetReadPosition();
     444            ic->pb.buf_ptr = ic->pb.buffer;
     445            ic->pb.buf_end = ic->pb.buffer;
     446            ic->pb.eof_reached = 0;
     447        }
    366448
    367     // Only reset the internal state if we're using our seeking,
    368     // not when using libavformat's seeking
    369     if (recordingHasPositionMap || livetv)
    370     {
    371         ic->pb.pos = ringBuffer->GetReadPosition();
    372         ic->pb.buf_ptr = ic->pb.buffer;
    373         ic->pb.buf_end = ic->pb.buffer;
    374         ic->pb.eof_reached = 0;
    375     }
    376 
    377     // Flush the avcodec buffers
    378     if (doflush)
    379     {
     449        // Flush the avcodec buffers
    380450        VERBOSE(VB_PLAYBACK, LOC + "SeekReset() flushing");
    381451        for (int i = 0; i < ic->nb_streams; i++)
    382452        {
     
    384454            if (enc->codec)
    385455                avcodec_flush_buffers(enc);
    386456        }
     457        d->ResetMPEG2();
    387458    }
    388459
    389460    // Discard all the queued up decoded frames
    390461    if (discardFrames)
    391         GetNVP()->DiscardVideoFrames();
     462        GetNVP()->DiscardVideoFrames(doflush);
    392463
    393     // Free up the stored up packets
    394     while (doflush && storedPackets.count() > 0)
     464    if (doflush)
    395465    {
    396         AVPacket *pkt = storedPackets.first();
    397         storedPackets.removeFirst();
    398         av_free_packet(pkt);
    399         delete pkt;
     466        // Free up the stored up packets
     467        while (storedPackets.count() > 0)
     468        {
     469            AVPacket *pkt = storedPackets.first();
     470            storedPackets.removeFirst();
     471            av_free_packet(pkt);
     472            delete pkt;
     473        }
     474
     475        prevgoppos = 0;
     476        gopset = false;
    400477    }
    401478
    402     prevgoppos = 0;
    403     gopset = false;
    404 
    405      // Skip all the desired number of skipFrames
     479    // Skip all the desired number of skipFrames
    406480    for (;skipFrames > 0 && !ateof; skipFrames--)
    407481    {
    408482        GetFrame(0);
     
    416490    VERBOSE(VB_PLAYBACK, LOC + QString("Reset(%1, %2)")
    417491            .arg(reset_video_data).arg(seek_reset));
    418492    if (seek_reset)
    419         SeekReset(0, 0, true, true);
     493        SeekReset(0, 0, true, false);
    420494
    421495    if (reset_video_data)
    422496    {
     
    24982572
    24992573                    picframe->frameNumber = framesPlayed;
    25002574                    GetNVP()->ReleaseNextVideoFrame(picframe, temppts);
     2575                    if (d->HasMPEG2Dec() && mpa_pic.data[3])
     2576                        context->release_buffer(context, &mpa_pic);
    25012577                    if (!directrendering)
    25022578                        GetNVP()->DiscardVideoFrame(picframe);
    25032579
  • 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/nuppeldecoder.h

     
    9999
    100100    int effdsp;
    101101
    102     unsigned char *directbuf;
     102    VideoFrame *directframe;
    103103
    104104    AVCodec *mpa_codec;
    105105    AVCodecContext *mpa_ctx;
  • 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
     
    29482948            frame_queue_t children = vbuffers.Children(pframe);
    29492949            if (!children.empty())
    29502950            {
     2951#if 0
    29512952                VERBOSE(VB_PLAYBACK, LOC + QString(
    29522953                            "Frame %1 w/children: %2 is being held for later "
    29532954                            "discarding.")
    29542955                        .arg(DebugString(pframe, true))
    29552956                        .arg(DebugString(children)));
    2956 
     2957#endif
    29572958                frame_queue_t::iterator cit;
    29582959                for (cit = children.begin(); cit != children.end(); ++cit)
    29592960                {
  • libs/libmythtv/decoderbase.cpp

     
    407407    }
    408408}
    409409
    410 bool DecoderBase::DoRewind(long long desiredFrame, bool doflush)
     410bool DecoderBase::DoRewind(long long desiredFrame, bool discardFrames)
    411411{
    412     VERBOSE(VB_PLAYBACK, LOC + "DoRewind("
    413             <<desiredFrame<<", "<<( doflush ? "do" : "don't" )<<" flush)");
     412    VERBOSE(VB_PLAYBACK, LOC +
     413            QString("DoRewind(%1 (%2), %3 discard frames)")
     414            .arg(desiredFrame).arg(framesPlayed)
     415            .arg((discardFrames) ? "do" : "don't"));
    414416
    415417    if (m_positionMap.empty())
    416418        return false;
    417419
    418     {
    419         bool ok = true;
    420         if (ringBuffer->isDVD())
    421             ok = DoRewindDVD(desiredFrame);
    422         else
    423             ok = DoRewindNormal(desiredFrame);
     420    if (!DoRewindSeek(desiredFrame))
     421        return false;
    424422
    425         if (!ok)
    426             return false;
    427     }
    428 
    429423    framesPlayed = lastKey;
    430424    framesRead = lastKey;
    431425
    432426    // Do any Extra frame-by-frame seeking for exactseeks mode
    433427    // And flush pre-seek frame if we are allowed to and need to..
    434428    int normalframes = (exactseeks) ? desiredFrame - framesPlayed : 0;
    435     SeekReset(lastKey, normalframes, true, doflush);
     429    SeekReset(lastKey, normalframes, true, discardFrames);
    436430
    437     // ???
    438     if (doflush)
     431    if (discardFrames)
    439432    {
     433        // We need to tell the NVP and VideoOutput what frame we're on.
    440434        GetNVP()->SetFramesPlayed(framesPlayed+1);
    441435        GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed+1);
    442436    }
     
    444438    return true;
    445439}
    446440
    447 bool DecoderBase::DoRewindDVD(long long desiredFrame)
     441bool DecoderBase::DoRewindSeek(long long desiredFrame)
    448442{
    449     long long pos = DVDFindPosition(desiredFrame);
    450     ringBuffer->Seek(pos, SEEK_SET);
    451     lastKey = desiredFrame + 1;
    452     return true;
    453 }
     443    if (ringBuffer->isDVD())
     444    {
     445        long long pos = DVDFindPosition(desiredFrame);
     446        ringBuffer->Seek(pos, SEEK_SET);
     447        lastKey = desiredFrame + 1;
     448        return true;
     449    }
    454450
    455 bool DecoderBase::DoRewindNormal(long long desiredFrame)
    456 {
    457451    // Find keyframe <= desiredFrame, store in lastKey (frames)
    458452    int pre_idx, post_idx;
    459453    FindPosition(desiredFrame, hasKeyFrameAdjustTable, pre_idx, post_idx);
     
    528522            .arg(desiredFrame).arg(framesPlayed)
    529523            .arg((discardFrames) ? "do" : "don't"));
    530524
    531     // Rewind if we have already played the desiredFrame.
    532     if (desiredFrame < framesPlayed)
     525    // Rewind if we have already played the desiredFrame. The +1 is for
     526    // MPEG4 NUV files, which need to decode an extra frame sometimes.
     527    // This shouldn't effect how this works in general because this is
     528    // only triggered on the first keyframe/frame skip when paused. At
     529    // that point the decoding is more than one frame ahead of display.
     530    if (desiredFrame+1 < framesPlayed)
    533531        return DoRewind(desiredFrame, discardFrames);
     532    desiredFrame = max(desiredFrame, framesPlayed);
    534533
    535534    // Save rawframe state, for later restoration...
    536535    bool oldrawstate = getrawframes;
     
    627626    lastKey = (hasKeyFrameAdjustTable) ? e.adjFrame : e.index * keyframedist;
    628627
    629628    // if commented out as a temporary fix for #868.
    630     //if (framesPlayed < lastKey)
     629    if (framesPlayed < lastKey)
    631630    {
    632631        ringBuffer->Seek(e.pos, SEEK_SET);
    633632        needflush    = true;
  • 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);
     
    137137    frame_queue_t         *queue(BufferType type);
    138138    const frame_queue_t   *queue(BufferType type) const;
    139139
    140     frame_queue_t          available, used, limbo, pause, displayed;
     140    frame_queue_t          available, used, limbo, pause, displayed, decode;
    141141    vbuffer_map_t          vbufferMap; // videobuffers to buffer's index
    142142    frame_vector_t         buffers;
    143143    uchar_vector_t         allocated_structs; // for DeleteBuffers
  • libs/libmythtv/videobuffers.cpp

     
    221221        success = false;
    222222        global_lock.lock();
    223223        frame = available.dequeue();
     224
     225        // Try to get a frame not being used by the decoder
     226        for (uint i = 0; i <= available.size() && decode.contains(frame); i++)
     227        {
     228            if (!available.contains(frame))
     229                available.enqueue(frame);
     230            frame = available.dequeue();
     231        }
     232
    224233        while (frame && used.contains(frame))
    225234        {
    226235            VERBOSE(VB_IMPORTANT,
     
    243252        }
    244253        if (frame)
    245254        {
    246             frame_queue_t *q = queue(enqueue_to);
    247             if (q)
    248                 q->enqueue(frame);
     255            safeEnqueue(enqueue_to, frame);
     256
    249257            success = true;
    250258            if (with_lock)
    251259                success = TryLockFrame(frame, "GetNextFreeFrame");
    252260            if (!success)
    253             {
    254                 available.enqueue(frame);
    255                 q->remove(frame);
    256             }
     261                safeEnqueue(kVideoBuffer_avail, frame);
    257262        }
    258263
    259264        global_lock.unlock();
     
    283288                        QString("GetNextFreeFrame() unable to "
    284289                        "lock frame %1 times. Discarding Frames.")
    285290                        .arg(TRY_LOCK_SPINS));
    286                 DiscardFrames();
     291                DiscardFrames(true);
    287292            }
    288293        }
    289294    }
     
    302307    global_lock.lock();
    303308    vpos = vbufferMap[frame];
    304309    limbo.remove(frame);
     310    decode.enqueue(frame);
    305311    used.enqueue(frame);
    306312    global_lock.unlock();
    307313}
     
    319325        limbo.remove(frame);
    320326        available.enqueue(frame);
    321327    }
     328    decode.remove(frame);
    322329    global_lock.unlock();
    323330}
    324331
     
    592599}
    593600
    594601/**
    595  * \fn VideoBuffers::DiscardFrames(void)
     602 * \fn VideoBuffers::DiscardFrames(bool)
    596603 *  Mark all used frames as ready to be reused, this is for seek.
    597604 */
    598 void VideoBuffers::DiscardFrames(void)
     605void VideoBuffers::DiscardFrames(bool next_frame_keyframe)
    599606{
    600     global_lock.lock();
    601     VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(): %1")
    602             .arg(GetStatus()));
     607    QMutexLocker locker(&global_lock);
     608    VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(%1): %2")
     609            .arg(next_frame_keyframe).arg(GetStatus()));
    603610
     611    if (!next_frame_keyframe)
     612    {
     613        for (bool change = true; change;)
     614        {
     615            change = false;
     616            frame_queue_t ula(used);
     617            frame_queue_t::iterator it = ula.begin();
     618            for (; it != ula.end(); ++it)
     619            {
     620                if (!HasChildren(*it))
     621                {
     622                    RemoveInheritence(*it);
     623                    DiscardFrame(*it);
     624                    change = true;
     625                }
     626            }
     627        }
     628        VERBOSE(VB_PLAYBACK,
     629                QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
     630                .arg(next_frame_keyframe).arg(GetStatus()));
     631        return;
     632    }
     633
    604634    // Remove inheritence of all frames not in displayed or pause
    605635    frame_queue_t ula(used);
    606636    ula.insert(ula.end(), limbo.begin(), limbo.end());
     
    634664        }
    635665    }
    636666
    637     VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(): %1 -- done()")
    638             .arg(GetStatus()));
     667    // Make sure frames used by decoder are last...
     668    // This is for libmpeg2 which still uses the frames after a reset.
     669    for (it = decode.begin(); it != decode.end(); ++it)
     670        remove(kVideoBuffer_all, *it);
     671    for (it = decode.begin(); it != decode.end(); ++it)
     672        available.enqueue(*it);
     673    decode.clear();
    639674
    640     global_lock.unlock();
     675    VERBOSE(VB_PLAYBACK,
     676            QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
     677            .arg(next_frame_keyframe).arg(GetStatus()));
    641678}
    642679
    643680void VideoBuffers::ClearAfterSeek(void)
     
    11851222        unsigned long long d = to_bitmap(displayed);
    11861223        unsigned long long l = to_bitmap(limbo);
    11871224        unsigned long long p = to_bitmap(pause);
     1225        unsigned long long x = to_bitmap(decode);
    11881226        for (uint i=0; i<(uint)n; i++)
    11891227        {
    11901228            unsigned long long mask = 1<<i;
    11911229            if (a & mask)
    1192                 str += "A";
     1230                str += (x & mask) ? "a" : "A";
    11931231            else if (u & mask)
    1194                 str += "U";
     1232                str += (x & mask) ? "u" : "U";
    11951233            else if (d & mask)
    1196                 str += "d";
     1234                str += (x & mask) ? "d" : "D";
    11971235            else if (l & mask)
    1198                 str += "L";
     1236                str += (x & mask) ? "l" : "L";
    11991237            else if (p & mask)
    1200                 str += "p";
     1238                str += (x & mask) ? "p" : "P";
    12011239            else
    12021240                str += " ";
    12031241        }