Ticket #868: 868-v3.patch
| File 868-v3.patch, 19.8 KB (added by , 20 years ago) |
|---|
-
libs/libmythtv/NuppelVideoPlayer.h
210 210 { videoOutput->ReleaseFrame(GetNextVideoFrame(false)); } 211 211 void ReleaseCurrentFrame(VideoFrame *frame); 212 212 void DiscardVideoFrame(VideoFrame *buffer); 213 void DiscardVideoFrames( void);213 void DiscardVideoFrames(bool next_frame_keyframe); 214 214 void DrawSlice(VideoFrame *frame, int x, int y, int w, int h); 215 215 216 216 // Reinit -
libs/libmythtv/nuppeldecoder.cpp
1170 1170 avcodec_flush_buffers(mpa_ctx); 1171 1171 1172 1172 if (discardFrames) 1173 GetNVP()->DiscardVideoFrames( );1173 GetNVP()->DiscardVideoFrames(doFlush); 1174 1174 1175 1175 for (;(skipFrames > 0) && !ateof; skipFrames--) 1176 1176 { -
libs/libmythtv/NuppelVideoPlayer.cpp
804 804 MAXTBUFFER - 1. */ 805 805 } 806 806 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 */ 807 820 VideoFrame *NuppelVideoPlayer::GetNextVideoFrame(bool allow_unsafe) 808 821 { 809 822 return videoOutput->GetNextFreeFrame(false, allow_unsafe); 810 823 } 811 824 825 /** \fn NuppelVideoPlayer::ReleaseNextVideoFrame(VideoFrame*,long long) 826 * \brief Places frame on the queue of frames ready for display. 827 */ 812 828 void NuppelVideoPlayer::ReleaseNextVideoFrame(VideoFrame *buffer, 813 829 long long timecode) 814 830 { … … 818 834 videoOutput->ReleaseFrame(buffer); 819 835 } 820 836 837 /** \fn NuppelVideoPlayer::DiscardVideoFrame(VideoFrame*) 838 * \brief Places frame in the available frames queue. 839 */ 821 840 void NuppelVideoPlayer::DiscardVideoFrame(VideoFrame *buffer) 822 841 { 823 842 if (videoOutput) 824 843 videoOutput->DiscardFrame(buffer); 825 844 } 826 845 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 */ 857 void NuppelVideoPlayer::DiscardVideoFrames(bool next_frame_keyframe) 828 858 { 829 859 if (videoOutput) 830 videoOutput->DiscardFrames( );860 videoOutput->DiscardFrames(next_frame_keyframe); 831 861 } 832 862 833 863 void NuppelVideoPlayer::DrawSlice(VideoFrame *frame, int x, int y, int w, int h) … … 1659 1689 VERBOSE(VB_IMPORTANT, LOC + "Prebuffer wait timed out, and" 1660 1690 "\n\t\t\tthere are not enough free frames. " 1661 1691 "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); 1663 1695 } 1664 1696 prebuffer_tries = 0; 1665 1697 } … … 3013 3045 /** \fn NuppelVideoPlayer::ClearAfterSeek(void) 3014 3046 * \brief This is to support seeking... 3015 3047 * 3016 * It can be very dangerous as it removes all frames from3017 * 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. 3018 3050 * 3019 3051 * Note: caller should not hold any locks 3020 3052 */ -
libs/libmythtv/avformatdecoder.cpp
169 169 *got_picture_ptr = 1; 170 170 *picture = *frm; 171 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 172 181 } 173 182 return buf_size; 174 183 case STATE_INVALID: … … 316 325 return ((lsb - base_ts)&mask); 317 326 } 318 327 319 bool AvFormatDecoder::DoRewind(long long desiredFrame, bool d oflush)328 bool AvFormatDecoder::DoRewind(long long desiredFrame, bool discardFrames) 320 329 { 321 330 VERBOSE(VB_PLAYBACK, LOC + "DoRewind(" 322 <<desiredFrame<<", "<<( doflush ? "do" : "don't" )<<" flush)"); 331 <<desiredFrame<<", " 332 <<( discardFrames ? "do" : "don't" )<<" discard frames)"); 323 333 324 334 if (recordingHasPositionMap || livetv) 325 return DecoderBase::DoRewind(desiredFrame, d oflush);335 return DecoderBase::DoRewind(desiredFrame, discardFrames); 326 336 327 337 // avformat-based seeking 328 return DoFastForward(desiredFrame, d oflush);338 return DoFastForward(desiredFrame, discardFrames); 329 339 } 330 340 331 bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool d oflush)341 bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool discardFrames) 332 342 { 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")); 335 347 336 348 if (recordingHasPositionMap || livetv) 337 return DecoderBase::DoFastForward(desiredFrame, d oflush);349 return DecoderBase::DoFastForward(desiredFrame, discardFrames); 338 350 339 351 bool oldrawstate = getrawframes; 340 352 getrawframes = false; … … 395 407 396 408 int normalframes = desiredFrame - framesPlayed; 397 409 398 SeekReset(lastKey, normalframes, d oflush, doflush);410 SeekReset(lastKey, normalframes, discardFrames, discardFrames); 399 411 400 if (d oflush)412 if (discardFrames) 401 413 { 402 414 GetNVP()->SetFramesPlayed(framesPlayed + 1); 403 415 GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed + 1); … … 450 462 451 463 // Discard all the queued up decoded frames 452 464 if (discardFrames) 453 GetNVP()->DiscardVideoFrames( );465 GetNVP()->DiscardVideoFrames(doflush); 454 466 455 467 if (doflush) 456 468 { -
libs/libmythtv/decoderbase.h
94 94 protected: 95 95 void FileChanged(void); 96 96 97 bool DoRewindDVD(long long desiredFrame); 98 bool DoRewindNormal(long long desiredFrame); 97 bool DoRewindSeek(long long desiredFrame); 99 98 void DoFastForwardSeek(long long desiredFrame, bool &needflush); 100 99 101 100 long long GetLastFrameInPosMap(long long desiredFrame); -
libs/libmythtv/videooutbase.cpp
422 422 XJ_height = height; 423 423 SetVideoAspectRatio(aspect); 424 424 425 DiscardFrames( );425 DiscardFrames(true); 426 426 } 427 427 428 428 /** -
libs/libmythtv/videoout_xv.h
103 103 104 104 VideoFrame *GetNextFreeFrame(bool allow_unsafe); 105 105 void DiscardFrame(VideoFrame*); 106 void DiscardFrames( void);106 void DiscardFrames(bool kf); 107 107 void DoneDisplayingFrame(void); 108 108 109 109 void ProcessFrameXvMC(VideoFrame *frame, OSD *osd); -
libs/libmythtv/videoout_xv.cpp
1642 1642 void VideoOutputXv::DeleteBuffers(VOSType subtype, bool delete_pause_frame) 1643 1643 { 1644 1644 (void) subtype; 1645 DiscardFrames( );1645 DiscardFrames(true); 1646 1646 1647 1647 #ifdef USING_XVMC 1648 1648 // XvMC buffers … … 1651 1651 xvmc_vo_surf_t *surf = (xvmc_vo_surf_t*) xvmc_surfs[i]; 1652 1652 X11S(XvMCHideSurface(XJ_disp, &(surf->surface))); 1653 1653 } 1654 DiscardFrames( );1654 DiscardFrames(true); 1655 1655 for (uint i=0; i<xvmc_surfs.size(); i++) 1656 1656 { 1657 1657 xvmc_vo_surf_t *surf = (xvmc_vo_surf_t*) xvmc_surfs[i]; … … 1824 1824 void VideoOutputXv::ClearAfterSeek(void) 1825 1825 { 1826 1826 VERBOSE(VB_PLAYBACK, LOC + "ClearAfterSeek()"); 1827 DiscardFrames( );1827 DiscardFrames(false); 1828 1828 #ifdef USING_XVMC 1829 1829 if (VideoOutputSubType() > XVideo) 1830 1830 { … … 1833 1833 xvmc_vo_surf_t *surf = (xvmc_vo_surf_t*) xvmc_surfs[i]; 1834 1834 X11S(XvMCHideSurface(XJ_disp, &(surf->surface))); 1835 1835 } 1836 DiscardFrames( );1836 DiscardFrames(true); 1837 1837 } 1838 1838 #endif 1839 1839 } … … 1844 1844 vbuffers.end_lock(); \ 1845 1845 } while (0) 1846 1846 1847 void VideoOutputXv::DiscardFrames( void)1847 void VideoOutputXv::DiscardFrames(bool next_frame_keyframe) 1848 1848 { 1849 1849 if (VideoOutputSubType() <= XVideo) 1850 1850 { 1851 vbuffers.DiscardFrames( );1851 vbuffers.DiscardFrames(next_frame_keyframe); 1852 1852 return; 1853 1853 } 1854 1854 … … 2010 2010 void VideoOutputXv::PrepareFrameXv(VideoFrame *frame) 2011 2011 { 2012 2012 if (!frame) 2013 { 2013 2014 frame = vbuffers.GetScratchFrame(); 2015 vbuffers.GetScratchFrame()->frameNumber = framesPlayed - 1LL; 2016 } 2014 2017 2015 2018 XvImage *image = NULL; 2016 2019 { … … 2049 2052 void VideoOutputXv::PrepareFrameMem(VideoFrame *buffer, FrameScanType /*scan*/) 2050 2053 { 2051 2054 if (!buffer) 2055 { 2052 2056 buffer = vbuffers.GetScratchFrame(); 2057 vbuffers.GetScratchFrame()->frameNumber = framesPlayed - 1LL; 2058 } 2053 2059 2054 2060 vbuffers.LockFrame(buffer, "PrepareFrameMem"); 2055 2061 … … 2532 2538 vbuffers.TryLockFrame(vbuffers.GetScratchFrame(), 2533 2539 "UpdatePauseFrame -- scratch")) 2534 2540 { 2541 vbuffers.GetScratchFrame()->frameNumber = framesPlayed - 1; 2535 2542 CopyFrame(&av_pause_frame, vbuffers.GetScratchFrame()); 2536 2543 vbuffers.UnlockFrame(vbuffers.GetScratchFrame(), 2537 2544 "UpdatePauseFrame -- scratch"); … … 2789 2796 if (!frame) 2790 2797 { 2791 2798 frame = vbuffers.GetScratchFrame(); 2799 frame->frameNumber = framesPlayed - 1LL; 2792 2800 vector<const VideoFrame*> locks; 2793 2801 locks.push_back(frame); 2794 2802 locks.push_back(&av_pause_frame); … … 2948 2956 frame_queue_t children = vbuffers.Children(pframe); 2949 2957 if (!children.empty()) 2950 2958 { 2959 #if 0 2951 2960 VERBOSE(VB_PLAYBACK, LOC + QString( 2952 2961 "Frame %1 w/children: %2 is being held for later " 2953 2962 "discarding.") 2954 2963 .arg(DebugString(pframe, true)) 2955 2964 .arg(DebugString(children))); 2956 2965 #endif 2957 2966 frame_queue_t::iterator cit; 2958 2967 for (cit = children.begin(); cit != children.end(); ++cit) 2959 2968 { -
libs/libmythtv/decoderbase.cpp
408 408 } 409 409 } 410 410 411 bool DecoderBase::DoRewind(long long desiredFrame, bool d oflush)411 bool DecoderBase::DoRewind(long long desiredFrame, bool discardFrames) 412 412 { 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")); 415 417 416 418 if (m_positionMap.empty()) 417 419 return false; 418 420 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; 425 423 426 if (!ok)427 return false;428 }429 430 424 framesPlayed = lastKey; 431 425 framesRead = lastKey; 432 426 433 427 // Do any Extra frame-by-frame seeking for exactseeks mode 434 428 // And flush pre-seek frame if we are allowed to and need to.. 435 429 int normalframes = (exactseeks) ? desiredFrame - framesPlayed : 0; 430 normalframes = max(normalframes, 0); 431 SeekReset(lastKey, normalframes, true, discardFrames); 436 432 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) 445 434 { 435 // We need to tell the NVP and VideoOutput what frame we're on. 446 436 GetNVP()->SetFramesPlayed(framesPlayed+1); 447 437 GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed+1); 448 438 } … … 456 446 return (hasKeyFrameAdjustTable) ? e.adjFrame :(e.index - indexOffset) * kf; 457 447 } 458 448 459 bool DecoderBase::DoRewind DVD(long long desiredFrame)449 bool DecoderBase::DoRewindSeek(long long desiredFrame) 460 450 { 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 } 466 458 467 bool DecoderBase::DoRewindNormal(long long desiredFrame)468 {469 459 // Find keyframe <= desiredFrame, store in lastKey (frames) 470 460 int pre_idx, post_idx; 471 461 FindPosition(desiredFrame, hasKeyFrameAdjustTable, pre_idx, post_idx); … … 538 528 .arg(desiredFrame).arg(framesPlayed) 539 529 .arg((discardFrames) ? "do" : "don't")); 540 530 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) 543 537 return DoRewind(desiredFrame, discardFrames); 538 desiredFrame = max(desiredFrame, framesPlayed); 544 539 545 540 // Save rawframe state, for later restoration... 546 541 bool oldrawstate = getrawframes; -
libs/libmythtv/ivtvdecoder.cpp
20 20 #include "videoout_ivtv.h" 21 21 #include "videodev_myth.h" 22 22 23 #define LOC QString("IVD: ") 24 #define LOC_ERR QString("IVD Error: ") 25 23 26 bool IvtvDecoder::ntsc = true; 24 27 25 28 IvtvDecoder::IvtvDecoder(NuppelVideoPlayer *parent, ProgramInfo *pginfo) … … 53 56 void IvtvDecoder::SeekReset(long long newkey, uint skipframes, 54 57 bool needFlush, bool discardFrames) 55 58 { 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 56 63 DecoderBase::SeekReset(newkey, skipframes, needFlush, discardFrames); 57 64 58 65 if (!exactseeks) … … 77 84 vidframes = 0; 78 85 queuedlist.clear(); 79 86 80 videoout->Stop(false );87 videoout->Stop(false /* hide */); 81 88 videoout->Flush(); 82 89 83 90 videoout->Start(0, skipframes+5); -
libs/libmythtv/videooutbase.h
253 253 virtual void DiscardFrame(VideoFrame *frame) { vbuffers.DiscardFrame(frame); } 254 254 /// \brief Releases all frames not being actively displayed from any queue 255 255 /// 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); } 257 257 258 258 /// \bug not implemented correctly. vpos is not updated. 259 259 VideoFrame *GetLastDecodedFrame(void) { return vbuffers.GetLastDecodedFrame(); } -
libs/libmythtv/videobuffers.h
59 59 void DeleteBuffers(void); 60 60 61 61 void Reset(void); 62 void DiscardFrames( void);62 void DiscardFrames(bool next_frame_keyframe); 63 63 void ClearAfterSeek(void); 64 64 65 65 void SetPrebuffering(bool normal); -
libs/libmythtv/videobuffers.cpp
288 288 QString("GetNextFreeFrame() unable to " 289 289 "lock frame %1 times. Discarding Frames.") 290 290 .arg(TRY_LOCK_SPINS)); 291 DiscardFrames( );291 DiscardFrames(true); 292 292 } 293 293 } 294 294 } … … 597 597 } 598 598 599 599 /** 600 * \fn VideoBuffers::DiscardFrames( void)600 * \fn VideoBuffers::DiscardFrames(bool) 601 601 * Mark all used frames as ready to be reused, this is for seek. 602 602 */ 603 void VideoBuffers::DiscardFrames( void)603 void VideoBuffers::DiscardFrames(bool next_frame_keyframe) 604 604 { 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())); 608 608 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 609 632 // Remove inheritence of all frames not in displayed or pause 610 633 frame_queue_t ula(used); 611 634 ula.insert(ula.end(), limbo.begin(), limbo.end()); … … 650 673 VERBOSE(VB_PLAYBACK, QString("VideoBuffers::DiscardFrames(): %1 -- done()") 651 674 .arg(GetStatus())); 652 675 653 global_lock.unlock(); 676 VERBOSE(VB_PLAYBACK, 677 QString("VideoBuffers::DiscardFrames(%1): %2 -- done") 678 .arg(next_frame_keyframe).arg(GetStatus())); 654 679 } 655 680 656 681 void VideoBuffers::ClearAfterSeek(void)
