Ticket #868: 868-v2.patch

File 868-v2.patch, 41.3 KB (added by danielk, 15 years ago)

updated patch

  • 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

     
    2525#include "bswap.h"
    2626#endif
    2727
     28#define LOC QString("NVD: ")
     29#define LOC_ERR QString("NVD Error: ")
    2830
    2931pthread_mutex_t avcodeclock = PTHREAD_MUTEX_INITIALIZER;
    3032
     
    3739#endif
    3840      ffmpeg_extradatasize(0), ffmpeg_extradata(0), usingextradata(false),
    3941      disablevideo(false), totalLength(0), totalFrames(0), effdsp(0),
    40       directbuf(0), mpa_codec(0), mpa_ctx(0), directrendering(false),
     42      directframe(NULL),            decoded_video_frame(NULL),
     43      mpa_codec(0), mpa_ctx(0), directrendering(false),
    4144      lastct('1'), strm(0), buf(0), buf2(0),
    4245      videosizetotal(0), videoframesread(0), setreadahead(false)
    4346{
     
    566569    int width = c->width;
    567570    int height = c->height;
    568571
    569     pic->data[0] = nd->directbuf;
     572    pic->data[0] = nd->directframe->buf;
    570573    pic->data[1] = pic->data[0] + width * height;
    571574    pic->data[2] = pic->data[1] + width * height / 4;
    572575
     
    574577    pic->linesize[1] = width / 2;
    575578    pic->linesize[2] = width / 2;
    576579
    577     pic->opaque = nd;
     580    pic->opaque = nd->directframe;
    578581    pic->type = FF_BUFFER_TYPE_USER;
    579582
    580583    pic->age = 256 * 256 * 256 * 64;
     
    587590    (void)c;
    588591    assert(pic->type == FF_BUFFER_TYPE_USER);
    589592
     593    NuppelDecoder *nd = (NuppelDecoder *)(c->opaque);
     594    if (nd && nd->GetNVP() && nd->GetNVP()->getVideoOutput())
     595        nd->GetNVP()->getVideoOutput()->DeLimboFrame((VideoFrame*)pic->opaque);
     596
    590597    int i;
    591598    for (i = 0; i < 4; i++)
    592599        pic->data[i] = NULL;
     
    683690    int compoff = 0;
    684691
    685692    unsigned char *outbuf = frame->buf;
     693    directframe = frame;
    686694
    687695    if (!buf2)
    688696    {
     
    759767        int gotpicture = 0;
    760768        pthread_mutex_lock(&avcodeclock);
    761769        // if directrendering, writes into buf
    762         directbuf = outbuf;
    763770        int ret = avcodec_decode_video(mpa_ctx, &mpa_pic, &gotpicture,
    764771                                       lstrm, frameheader->packetlength);
     772        directframe = NULL;
    765773        pthread_mutex_unlock(&avcodeclock);
    766774        if (ret < 0)
    767775        {
     
    896904    bool ret = false;
    897905    int seeklen = 0;
    898906
     907    decoded_video_frame = NULL;
     908
    899909    while (!gotvideo)
    900910    {
    901911        long long currentposition = ringBuffer->GetReadPosition();
     
    10461056
    10471057            buf->frameNumber = framesPlayed;
    10481058            GetNVP()->ReleaseNextVideoFrame(buf, frameheader.timecode);
     1059           
     1060            // We need to make the frame available ourselves
     1061            // if we are not using ffmpeg/avlib.
     1062            if (directframe)
     1063                GetNVP()->getVideoOutput()->DeLimboFrame(buf);
     1064
     1065            decoded_video_frame = buf;
    10491066            gotvideo = 1;
    10501067            if (getrawframes && getrawvideo)
    10511068                StoreRawData(strm);
     
    11391156}
    11401157
    11411158void NuppelDecoder::SeekReset(long long newKey, uint skipFrames,
    1142                               bool needFlush, bool discardFrames)
     1159                              bool doFlush, bool discardFrames)
    11431160{
    1144     DecoderBase::SeekReset(newKey, skipFrames, needFlush, discardFrames);
     1161    VERBOSE(VB_PLAYBACK, LOC +
     1162            QString("SeekReset(%1, %2, %3 flush, %4 discard)")
     1163            .arg(newKey).arg(skipFrames)
     1164            .arg((doFlush) ? "do" : "don't")
     1165            .arg((discardFrames) ? "do" : "don't"));
     1166   
     1167    DecoderBase::SeekReset(newKey, skipFrames, doFlush, discardFrames);
    11451168
    1146     if (mpa_codec && needFlush)
     1169    if (mpa_codec && doFlush)
    11471170        avcodec_flush_buffers(mpa_ctx);
    11481171
    1149     while (skipFrames > 0)
     1172    if (discardFrames)
     1173        GetNVP()->DiscardVideoFrames(doFlush);
     1174
     1175    for (;(skipFrames > 0) && !ateof; skipFrames--)
    11501176    {
    11511177        GetFrame(0);
    1152         if (ateof)
    1153             break;
    1154         skipFrames--;
     1178        if (decoded_video_frame)
     1179            GetNVP()->DiscardVideoFrame(decoded_video_frame);
    11551180    }
    11561181}
    11571182
  • 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

     
    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        }
     
    254325    return  ((lsb - base_ts)&mask);
    255326}
    256327
    257 bool AvFormatDecoder::DoRewind(long long desiredFrame, bool doflush)
     328bool AvFormatDecoder::DoRewind(long long desiredFrame, bool discardFrames)
    258329{
    259330    VERBOSE(VB_PLAYBACK, LOC + "DoRewind("
    260             <<desiredFrame<<", "<<( doflush ? "do" : "don't" )<<" flush)");
     331            <<desiredFrame<<", "
     332            <<( discardFrames ? "do" : "don't" )<<" discard frames)");
    261333
    262334    if (recordingHasPositionMap || livetv)
    263         return DecoderBase::DoRewind(desiredFrame, doflush);
     335        return DecoderBase::DoRewind(desiredFrame, discardFrames);
    264336
    265337    // avformat-based seeking
    266     return DoFastForward(desiredFrame, doflush);
     338    return DoFastForward(desiredFrame, discardFrames);
    267339}
    268340
    269 bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool doflush)
     341bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool discardFrames)
    270342{
    271     VERBOSE(VB_PLAYBACK, LOC + "DoFastForward("
    272             <<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"));
    273347
    274348    if (recordingHasPositionMap || livetv)
    275         return DecoderBase::DoFastForward(desiredFrame, doflush);
     349        return DecoderBase::DoFastForward(desiredFrame, discardFrames);
    276350
    277351    bool oldrawstate = getrawframes;
    278352    getrawframes = false;
     
    333407
    334408    int normalframes = desiredFrame - framesPlayed;
    335409
    336     SeekReset(lastKey, normalframes, doflush, doflush);
     410    SeekReset(lastKey, normalframes, discardFrames, discardFrames);
    337411
    338     if (doflush)
     412    if (discardFrames)
    339413    {
    340414        GetNVP()->SetFramesPlayed(framesPlayed + 1);
    341415        GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed + 1);
     
    349423void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames,
    350424                                bool doflush, bool discardFrames)
    351425{
    352     VERBOSE(VB_PLAYBACK, LOC + QString("SeekReset(%1, %2 flush, %3 discard)")
    353             .arg(skipFrames).arg((doflush) ? "do" : "don't")
     426    VERBOSE(VB_PLAYBACK, LOC +
     427            QString("SeekReset(%1, %2, %3 flush, %4 discard)")
     428            .arg(newKey).arg(skipFrames)
     429            .arg((doflush) ? "do" : "don't")
    354430            .arg((discardFrames) ? "do" : "don't"));
    355431
    356432    DecoderBase::SeekReset(newKey, skipFrames, doflush, discardFrames);
    357433
    358     lastapts = 0;
    359     lastvpts = 0;
    360     lastccptsu = 0;
    361     save_cctc[0] = save_cctc[1] = 0;
     434    if (doflush)
     435    {
     436        lastapts = 0;
     437        lastvpts = 0;
     438        lastccptsu = 0;
     439        save_cctc[0] = save_cctc[1] = 0;
     440        av_read_frame_flush(ic);
    362441
    363     av_read_frame_flush(ic);
    364    
    365     d->ResetMPEG2();
     442        // Only reset the internal state if we're using our seeking,
     443        // not when using libavformat's seeking
     444        if (recordingHasPositionMap || livetv)
     445        {
     446            ic->pb.pos = ringBuffer->GetReadPosition();
     447            ic->pb.buf_ptr = ic->pb.buffer;
     448            ic->pb.buf_end = ic->pb.buffer;
     449            ic->pb.eof_reached = 0;
     450        }
    366451
    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     {
     452        // Flush the avcodec buffers
    380453        VERBOSE(VB_PLAYBACK, LOC + "SeekReset() flushing");
    381454        for (int i = 0; i < ic->nb_streams; i++)
    382455        {
     
    384457            if (enc->codec)
    385458                avcodec_flush_buffers(enc);
    386459        }
     460        d->ResetMPEG2();
    387461    }
    388462
    389463    // Discard all the queued up decoded frames
    390464    if (discardFrames)
    391         GetNVP()->DiscardVideoFrames();
     465        GetNVP()->DiscardVideoFrames(doflush);
    392466
    393     // Free up the stored up packets
    394     while (doflush && storedPackets.count() > 0)
     467    if (doflush)
    395468    {
    396         AVPacket *pkt = storedPackets.first();
    397         storedPackets.removeFirst();
    398         av_free_packet(pkt);
    399         delete pkt;
     469        // Free up the stored up packets
     470        while (storedPackets.count() > 0)
     471        {
     472            AVPacket *pkt = storedPackets.first();
     473            storedPackets.removeFirst();
     474            av_free_packet(pkt);
     475            delete pkt;
     476        }
     477
     478        prevgoppos = 0;
     479        gopset = false;
     480        framesPlayed = lastKey;
     481        framesRead = lastKey;
    400482    }
    401483
    402     prevgoppos = 0;
    403     gopset = false;
    404 
    405      // Skip all the desired number of skipFrames
     484    // Skip all the desired number of skipFrames
    406485    for (;skipFrames > 0 && !ateof; skipFrames--)
    407486    {
    408487        GetFrame(0);
     
    416495    VERBOSE(VB_PLAYBACK, LOC + QString("Reset(%1, %2)")
    417496            .arg(reset_video_data).arg(seek_reset));
    418497    if (seek_reset)
    419         SeekReset(0, 0, true, true);
     498        SeekReset(0, 0, true, false);
    420499
    421500    if (reset_video_data)
    422501    {
     
    24462525                    {
    24472526                        AVPicture tmppicture;
    24482527 
     2528                        VideoFrame *xf = picframe;
    24492529                        picframe = GetNVP()->GetNextVideoFrame(false);
    24502530
    24512531                        tmppicture.data[0] = picframe->buf;
     
    24632543                                    context->pix_fmt,
    24642544                                    context->width,
    24652545                                    context->height);
     2546
     2547                        xf->interlaced_frame = mpa_pic.interlaced_frame;
     2548                        xf->top_field_first = mpa_pic.top_field_first;
     2549                        xf->frameNumber = framesPlayed;
     2550                        GetNVP()->DiscardVideoFrame(xf);
    24662551                    }
    24672552
    24682553                    long long temppts = pts;
     
    24982583
    24992584                    picframe->frameNumber = framesPlayed;
    25002585                    GetNVP()->ReleaseNextVideoFrame(picframe, temppts);
    2501                     if (!directrendering)
    2502                         GetNVP()->DiscardVideoFrame(picframe);
     2586                    if (d->HasMPEG2Dec() && mpa_pic.data[3])
     2587                        context->release_buffer(context, &mpa_pic);
    25032588
    25042589                    decoded_video_frame = picframe;
    25052590                    gotvideo = 1;
  • 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);
     
    106105        long long adjFrame; // keyFrameAdjustTable adjusted frame number
    107106        long long pos;      // position in stream
    108107    } PosMapEntry;
     108    long long GetKey(PosMapEntry &entry) const;
    109109
    110110    NuppelVideoPlayer *m_parent;
    111111    ProgramInfo *m_playbackinfo;
     
    122122    long long framesRead;
    123123    long long lastKey;
    124124    int keyframedist;
     125    long long indexOffset;
    125126
    126127
    127128    bool ateof;
  • 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;
     103    VideoFrame *decoded_video_frame;
    103104
    104105    AVCodec *mpa_codec;
    105106    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
     
    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

     
    2020      current_aspect(1.33333), fps(29.97),
    2121
    2222      framesPlayed(0), framesRead(0), lastKey(0), keyframedist(-1),
     23      indexOffset(0),
    2324
    2425      ateof(false), exitafterdecoded(false), transcoding(false),
    2526
     
    156157    {
    157158        VERBOSE(VB_PLAYBACK, QString("Position map filled from DB to: %1")
    158159                .arg((long int) m_positionMap[m_positionMap.size()-1].index));
     160        indexOffset = m_positionMap[0].index;
    159161    }
    160162
    161163    return true;
     
    342344                               int &lower_bound, int &upper_bound)
    343345{
    344346    // Binary search
    345     int upper = m_positionMap.size(), lower = -1;
     347    long long upper = m_positionMap.size(), lower = -1;
    346348    if (!search_adjusted && keyframedist > 0)
    347349        desired_value /= keyframedist;
    348350
    349351    while (upper - 1 > lower)
    350352    {
    351         int i = (upper + lower) / 2;
     353        long long i = (upper + lower) / 2;
    352354        long long value;
    353355        if (search_adjusted)
    354356            value = m_positionMap[i].adjFrame;
    355357        else
    356             value = m_positionMap[i].index;
     358            value = m_positionMap[i].index - indexOffset;
    357359        if (value == desired_value)
    358360        {
    359361            // found it
     
    368370    }
    369371    // Did not find it exactly -- return bounds
    370372
    371     if (search_adjusted) 
     373    if (search_adjusted)
    372374    {
    373375        while (lower >= 0 && m_positionMap[lower].adjFrame > desired_value)
    374376            lower--;
    375         while (upper < (int)m_positionMap.size() &&
     377        while (upper < m_positionMap.size() &&
    376378               m_positionMap[upper].adjFrame > desired_value)
    377379            upper++;
    378380    }
    379381    else
    380382    {
    381         while (lower >= 0 &&m_positionMap[lower].index > desired_value)
     383        while (lower >= 0 &&
     384               (m_positionMap[lower].index - indexOffset) > desired_value)
    382385            lower--;
    383         while (upper < (int)m_positionMap.size() &&
    384                m_positionMap[upper].index < desired_value)
     386        while (upper < m_positionMap.size() &&
     387               (m_positionMap[upper].index - indexOffset) < desired_value)
    385388            upper++;
    386389    }
    387390    // keep in bounds
    388     if (lower < 0)
    389         lower = 0;
    390     if (upper >= (int)m_positionMap.size())
    391         upper = (int)m_positionMap.size() - 1;
     391    lower = max(lower, 0LL);
     392    upper = min(upper, m_positionMap.size() - 1LL);
    392393
    393394    upper_bound = upper;
    394395    lower_bound = lower;
     
    407408    }
    408409}
    409410
    410 bool DecoderBase::DoRewind(long long desiredFrame, bool doflush)
     411bool DecoderBase::DoRewind(long long desiredFrame, bool discardFrames)
    411412{
    412     VERBOSE(VB_PLAYBACK, LOC + "DoRewind("
    413             <<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"));
    414417
    415418    if (m_positionMap.empty())
    416419        return false;
    417420
    418     {
    419         bool ok = true;
    420         if (ringBuffer->isDVD())
    421             ok = DoRewindDVD(desiredFrame);
    422         else
    423             ok = DoRewindNormal(desiredFrame);
     421    if (!DoRewindSeek(desiredFrame))
     422        return false;
    424423
    425         if (!ok)
    426             return false;
    427     }
    428 
    429424    framesPlayed = lastKey;
    430425    framesRead = lastKey;
    431426
    432427    // Do any Extra frame-by-frame seeking for exactseeks mode
    433428    // And flush pre-seek frame if we are allowed to and need to..
    434429    int normalframes = (exactseeks) ? desiredFrame - framesPlayed : 0;
     430    normalframes = max(normalframes, 0);
     431    SeekReset(lastKey, normalframes, true, discardFrames);
    435432
    436     // This shouldn't happen, but it's nasty if it does so prevent it
    437     if (normalframes < 0)
    438         normalframes = 0;
    439 
    440     SeekReset(lastKey, normalframes, true, doflush);
    441 
    442     // ???
    443     if (doflush)
     433    if (discardFrames)
    444434    {
     435        // We need to tell the NVP and VideoOutput what frame we're on.
    445436        GetNVP()->SetFramesPlayed(framesPlayed+1);
    446437        GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed+1);
    447438    }
     
    449440    return true;
    450441}
    451442
    452 bool DecoderBase::DoRewindDVD(long long desiredFrame)
     443long long DecoderBase::GetKey(PosMapEntry &e) const
    453444{
    454     long long pos = DVDFindPosition(desiredFrame);
    455     ringBuffer->Seek(pos, SEEK_SET);
    456     lastKey = desiredFrame + 1;
    457     return true;
     445    long long kf  = (ringBuffer->isDVD()) ? 1LL : keyframedist;
     446    return (hasKeyFrameAdjustTable) ? e.adjFrame :(e.index - indexOffset) * kf;
    458447}
    459448
    460 bool DecoderBase::DoRewindNormal(long long desiredFrame)
     449bool DecoderBase::DoRewindSeek(long long desiredFrame)
    461450{
     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    }
     458
    462459    // Find keyframe <= desiredFrame, store in lastKey (frames)
    463460    int pre_idx, post_idx;
    464461    FindPosition(desiredFrame, hasKeyFrameAdjustTable, pre_idx, post_idx);
    465462
    466     bool useAdj   = hasKeyFrameAdjustTable;
    467463    uint pos_idx  = min(pre_idx, post_idx);
    468464    PosMapEntry e = m_positionMap[pos_idx];
    469     lastKey = (useAdj) ? e.adjFrame : (e.index - 1) * keyframedist;
     465    lastKey = GetKey(e);
    470466
    471467    // ??? Don't rewind past the beginning of the file
    472468    while (e.pos < 0)
     
    476472            return false;
    477473
    478474        e = m_positionMap[pos_idx];
    479         lastKey = (useAdj) ? e.adjFrame : (e.index - 1) * keyframedist;
     475        lastKey = GetKey(e);
    480476    }
    481477
    482478    ringBuffer->Seek(e.pos, SEEK_SET);
     
    487483long long DecoderBase::GetLastFrameInPosMap(long long desiredFrame)
    488484{
    489485    long long last_frame = 0;
    490     uint mult = (uint) (ringBuffer->isDVD()) ? 1 : keyframedist;
    491486    if (!m_positionMap.empty())
    492         last_frame = mult * m_positionMap.back().index;
     487        last_frame = GetKey(m_positionMap.back());
    493488
    494489    // Resync keyframe map if we are trying to seek to a frame
    495490    // not yet in out map and then check for last frame again.
     
    503498        SyncPositionMap();
    504499
    505500        if (!m_positionMap.empty())
    506             last_frame = mult * m_positionMap.back().index;
     501            last_frame = GetKey(m_positionMap.back());
    507502
    508503        if (desiredFrame > last_frame)
    509504        {
     
    533528            .arg(desiredFrame).arg(framesPlayed)
    534529            .arg((discardFrames) ? "do" : "don't"));
    535530
    536     // Rewind if we have already played the desiredFrame.
    537     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)
    538537        return DoRewind(desiredFrame, discardFrames);
     538    desiredFrame = max(desiredFrame, framesPlayed);
    539539
    540540    // Save rawframe state, for later restoration...
    541541    bool oldrawstate = getrawframes;
     
    629629    uint pos_idx = (exactseeks) ? pre_idx : max(pre_idx, post_idx);
    630630
    631631    PosMapEntry e = m_positionMap[pos_idx];
    632     lastKey = (hasKeyFrameAdjustTable) ? e.adjFrame : e.index * keyframedist;
     632    lastKey = GetKey(e);
    633633
    634     // if commented out as a temporary fix for #868.
    635     //if (framesPlayed < lastKey)
     634    if (framesPlayed < lastKey)
    636635    {
    637636        ringBuffer->Seek(e.pos, SEEK_SET);
    638637        needflush    = true;
  • 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);
     
    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
     
    441448    frame_queue_t *q = queue(type);
    442449    if (q)
    443450    {
    444         global_lock.lock();
    445         VideoFrame *frame = q->head();
    446         global_lock.unlock();
    447         return frame;
     451        QMutexLocker locker(&global_lock);
     452        if (q->size())
     453            return q->head();
    448454    }
    449455    return NULL;
    450456}
     
    454460    frame_queue_t *q = queue(type);
    455461    if (q)
    456462    {
    457         global_lock.lock();
    458         VideoFrame *frame = q->tail();
    459         global_lock.unlock();
    460         return frame;
     463        QMutexLocker locker(&global_lock);
     464        if (q->size())
     465            return q->tail();
    461466    }
    462467    return NULL;
    463468}
     
    592597}
    593598
    594599/**
    595  * \fn VideoBuffers::DiscardFrames(void)
     600 * \fn VideoBuffers::DiscardFrames(bool)
    596601 *  Mark all used frames as ready to be reused, this is for seek.
    597602 */
    598 void VideoBuffers::DiscardFrames(void)
     603void VideoBuffers::DiscardFrames(bool next_frame_keyframe)
    599604{
    600     global_lock.lock();
    601     VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(): %1")
    602             .arg(GetStatus()));
     605    QMutexLocker locker(&global_lock);
     606    VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(%1): %2")
     607            .arg(next_frame_keyframe).arg(GetStatus()));
    603608
     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
    604632    // Remove inheritence of all frames not in displayed or pause
    605633    frame_queue_t ula(used);
    606634    ula.insert(ula.end(), limbo.begin(), limbo.end());
     
    634662        }
    635663    }
    636664
    637     VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(): %1 -- done()")
    638             .arg(GetStatus()));
     665    // Make sure frames used by decoder are last...
     666    // This is for libmpeg2 which still uses the frames after a reset.
     667    for (it = decode.begin(); it != decode.end(); ++it)
     668        remove(kVideoBuffer_all, *it);
     669    for (it = decode.begin(); it != decode.end(); ++it)
     670        available.enqueue(*it);
     671    decode.clear();
    639672
    640     global_lock.unlock();
     673    VERBOSE(VB_PLAYBACK,
     674            QString("VideoBuffers::DiscardFrames(%1): %2 -- done")
     675            .arg(next_frame_keyframe).arg(GetStatus()));
    641676}
    642677
    643678void VideoBuffers::ClearAfterSeek(void)
     
    11851220        unsigned long long d = to_bitmap(displayed);
    11861221        unsigned long long l = to_bitmap(limbo);
    11871222        unsigned long long p = to_bitmap(pause);
     1223        unsigned long long x = to_bitmap(decode);
    11881224        for (uint i=0; i<(uint)n; i++)
    11891225        {
    11901226            unsigned long long mask = 1<<i;
     1227            QString tmp("");
    11911228            if (a & mask)
    1192                 str += "A";
    1193             else if (u & mask)
    1194                 str += "U";
    1195             else if (d & mask)
    1196                 str += "d";
    1197             else if (l & mask)
    1198                 str += "L";
    1199             else if (p & mask)
    1200                 str += "p";
     1229                tmp += (x & mask) ? "a" : "A";
     1230            if (u & mask)
     1231                tmp += (x & mask) ? "u" : "U";
     1232            if (d & mask)
     1233                tmp += (x & mask) ? "d" : "D";
     1234            if (l & mask)
     1235                tmp += (x & mask) ? "l" : "L";
     1236            if (p & mask)
     1237                tmp += (x & mask) ? "p" : "P";
     1238
     1239            if (0 == tmp.length())
     1240                str += " ";
     1241            else if (1 == tmp.length())
     1242                str += tmp;
    12011243            else
    1202                 str += " ";
     1244                str += "(" + tmp + ")";
    12031245        }
    12041246        global_lock.unlock();
    12051247    }