Ticket #868: 868-v1.patch
File 868-v1.patch, 29.9 KB (added by , 18 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
37 37 #endif 38 38 ffmpeg_extradatasize(0), ffmpeg_extradata(0), usingextradata(false), 39 39 disablevideo(false), totalLength(0), totalFrames(0), effdsp(0), 40 direct buf(0), mpa_codec(0), mpa_ctx(0), directrendering(false),40 directframe(NULL), mpa_codec(0), mpa_ctx(0), directrendering(false), 41 41 lastct('1'), strm(0), buf(0), buf2(0), 42 42 videosizetotal(0), videoframesread(0), setreadahead(false) 43 43 { … … 566 566 int width = c->width; 567 567 int height = c->height; 568 568 569 pic->data[0] = nd->direct buf;569 pic->data[0] = nd->directframe->buf; 570 570 pic->data[1] = pic->data[0] + width * height; 571 571 pic->data[2] = pic->data[1] + width * height / 4; 572 572 … … 574 574 pic->linesize[1] = width / 2; 575 575 pic->linesize[2] = width / 2; 576 576 577 pic->opaque = nd ;577 pic->opaque = nd->directframe; 578 578 pic->type = FF_BUFFER_TYPE_USER; 579 579 580 580 pic->age = 256 * 256 * 256 * 64; … … 587 587 (void)c; 588 588 assert(pic->type == FF_BUFFER_TYPE_USER); 589 589 590 NuppelDecoder *nd = (NuppelDecoder *)(c->opaque); 591 if (nd && nd->GetNVP() && nd->GetNVP()->getVideoOutput()) 592 nd->GetNVP()->getVideoOutput()->DeLimboFrame((VideoFrame*)pic->opaque); 593 590 594 int i; 591 595 for (i = 0; i < 4; i++) 592 596 pic->data[i] = NULL; … … 683 687 int compoff = 0; 684 688 685 689 unsigned char *outbuf = frame->buf; 690 directframe = frame; 686 691 687 692 if (!buf2) 688 693 { … … 759 764 int gotpicture = 0; 760 765 pthread_mutex_lock(&avcodeclock); 761 766 // if directrendering, writes into buf 762 directbuf = outbuf;763 767 int ret = avcodec_decode_video(mpa_ctx, &mpa_pic, &gotpicture, 764 768 lstrm, frameheader->packetlength); 769 directframe = NULL; 765 770 pthread_mutex_unlock(&avcodeclock); 766 771 if (ret < 0) 767 772 { … … 1046 1051 1047 1052 buf->frameNumber = framesPlayed; 1048 1053 GetNVP()->ReleaseNextVideoFrame(buf, frameheader.timecode); 1054 if (directframe) 1055 GetNVP()->getVideoOutput()->DeLimboFrame(buf); 1049 1056 gotvideo = 1; 1050 1057 if (getrawframes && getrawvideo) 1051 1058 StoreRawData(strm); … … 1146 1153 if (mpa_codec && needFlush) 1147 1154 avcodec_flush_buffers(mpa_ctx); 1148 1155 1156 if (discardFrames) 1157 GetNVP()->DiscardVideoFrames(needFlush); 1158 1149 1159 while (skipFrames > 0) 1150 1160 { 1151 1161 GetFrame(0); -
libs/libmythtv/NuppelVideoPlayer.cpp
803 803 MAXTBUFFER - 1. */ 804 804 } 805 805 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 */ 806 819 VideoFrame *NuppelVideoPlayer::GetNextVideoFrame(bool allow_unsafe) 807 820 { 808 821 return videoOutput->GetNextFreeFrame(false, allow_unsafe); 809 822 } 810 823 824 /** \fn NuppelVideoPlayer::ReleaseNextVideoFrame(VideoFrame*,long long) 825 * \brief Places frame on the queue of frames ready for display. 826 */ 811 827 void NuppelVideoPlayer::ReleaseNextVideoFrame(VideoFrame *buffer, 812 828 long long timecode) 813 829 { … … 817 833 videoOutput->ReleaseFrame(buffer); 818 834 } 819 835 836 /** \fn NuppelVideoPlayer::DiscardVideoFrame(VideoFrame*) 837 * \brief Places frame in the available frames queue. 838 */ 820 839 void NuppelVideoPlayer::DiscardVideoFrame(VideoFrame *buffer) 821 840 { 822 841 if (videoOutput) 823 842 videoOutput->DiscardFrame(buffer); 824 843 } 825 844 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 */ 856 void NuppelVideoPlayer::DiscardVideoFrames(bool next_frame_keyframe) 827 857 { 828 858 if (videoOutput) 829 videoOutput->DiscardFrames( );859 videoOutput->DiscardFrames(next_frame_keyframe); 830 860 } 831 861 832 862 void NuppelVideoPlayer::DrawSlice(VideoFrame *frame, int x, int y, int w, int h) … … 1658 1688 VERBOSE(VB_IMPORTANT, LOC + "Prebuffer wait timed out, and" 1659 1689 "\n\t\t\tthere are not enough free frames. " 1660 1690 "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); 1662 1694 } 1663 1695 prebuffer_tries = 0; 1664 1696 } … … 3014 3046 /** \fn NuppelVideoPlayer::ClearAfterSeek(void) 3015 3047 * \brief This is to support seeking... 3016 3048 * 3017 * It can be very dangerous as it removes all frames from3018 * 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. 3019 3051 * 3020 3052 * Note: caller should not hold any locks 3021 3053 */ -
libs/libmythtv/avformatdecoder.cpp
65 65 height = (height + 15) & (~0xf); 66 66 } 67 67 68 typedef MythDeque<AVFrame*> avframe_q; 69 68 70 class AvFormatDecoderPrivate 69 71 { 70 72 public: … … 83 85 private: 84 86 mpeg2dec_t *mpeg2dec; 85 87 bool allow_mpeg2dec; 88 avframe_q partialFrames; 86 89 }; 87 90 88 91 bool AvFormatDecoderPrivate::InitMPEG2() … … 103 106 void AvFormatDecoderPrivate::DestroyMPEG2() 104 107 { 105 108 if (mpeg2dec) 109 { 106 110 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 } 108 118 } 109 119 110 120 void AvFormatDecoderPrivate::ResetMPEG2() 111 121 { 112 122 if (mpeg2dec) 123 { 113 124 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 } 114 131 } 115 132 116 133 int AvFormatDecoderPrivate::DecodeMPEG2Video(AVCodecContext *avctx, … … 145 162 mpeg2_set_buf(mpeg2dec, picture->data, picture->opaque); 146 163 break; 147 164 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()) 153 167 { 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(); 158 169 *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 163 181 } 164 182 return buf_size; 165 183 case STATE_INVALID: 166 184 // This is the error state. The decoder must be 167 185 // reset on an error. 168 mpeg2_reset(mpeg2dec, 0);186 ResetMPEG2(); 169 187 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; 170 241 default: 171 242 break; 172 243 } … … 266 337 return DoFastForward(desiredFrame, doflush); 267 338 } 268 339 269 bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool d oflush)340 bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool discardFrames) 270 341 { 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")); 273 346 274 347 if (recordingHasPositionMap || livetv) 275 return DecoderBase::DoFastForward(desiredFrame, d oflush);348 return DecoderBase::DoFastForward(desiredFrame, discardFrames); 276 349 277 350 bool oldrawstate = getrawframes; 278 351 getrawframes = false; … … 333 406 334 407 int normalframes = desiredFrame - framesPlayed; 335 408 336 SeekReset(lastKey, normalframes, d oflush, doflush);409 SeekReset(lastKey, normalframes, discardFrames, discardFrames); 337 410 338 if (d oflush)411 if (discardFrames) 339 412 { 340 413 GetNVP()->SetFramesPlayed(framesPlayed + 1); 341 414 GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed + 1); … … 355 428 356 429 DecoderBase::SeekReset(newKey, skipFrames, doflush, discardFrames); 357 430 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); 362 438 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 } 366 448 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 380 450 VERBOSE(VB_PLAYBACK, LOC + "SeekReset() flushing"); 381 451 for (int i = 0; i < ic->nb_streams; i++) 382 452 { … … 384 454 if (enc->codec) 385 455 avcodec_flush_buffers(enc); 386 456 } 457 d->ResetMPEG2(); 387 458 } 388 459 389 460 // Discard all the queued up decoded frames 390 461 if (discardFrames) 391 GetNVP()->DiscardVideoFrames( );462 GetNVP()->DiscardVideoFrames(doflush); 392 463 393 // Free up the stored up packets 394 while (doflush && storedPackets.count() > 0) 464 if (doflush) 395 465 { 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; 400 477 } 401 478 402 prevgoppos = 0; 403 gopset = false; 404 405 // Skip all the desired number of skipFrames 479 // Skip all the desired number of skipFrames 406 480 for (;skipFrames > 0 && !ateof; skipFrames--) 407 481 { 408 482 GetFrame(0); … … 416 490 VERBOSE(VB_PLAYBACK, LOC + QString("Reset(%1, %2)") 417 491 .arg(reset_video_data).arg(seek_reset)); 418 492 if (seek_reset) 419 SeekReset(0, 0, true, true);493 SeekReset(0, 0, true, false); 420 494 421 495 if (reset_video_data) 422 496 { … … 2498 2572 2499 2573 picframe->frameNumber = framesPlayed; 2500 2574 GetNVP()->ReleaseNextVideoFrame(picframe, temppts); 2575 if (d->HasMPEG2Dec() && mpa_pic.data[3]) 2576 context->release_buffer(context, &mpa_pic); 2501 2577 if (!directrendering) 2502 2578 GetNVP()->DiscardVideoFrame(picframe); 2503 2579 -
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/nuppeldecoder.h
99 99 100 100 int effdsp; 101 101 102 unsigned char *directbuf;102 VideoFrame *directframe; 103 103 104 104 AVCodec *mpa_codec; 105 105 AVCodecContext *mpa_ctx; -
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 … … 2948 2948 frame_queue_t children = vbuffers.Children(pframe); 2949 2949 if (!children.empty()) 2950 2950 { 2951 #if 0 2951 2952 VERBOSE(VB_PLAYBACK, LOC + QString( 2952 2953 "Frame %1 w/children: %2 is being held for later " 2953 2954 "discarding.") 2954 2955 .arg(DebugString(pframe, true)) 2955 2956 .arg(DebugString(children))); 2956 2957 #endif 2957 2958 frame_queue_t::iterator cit; 2958 2959 for (cit = children.begin(); cit != children.end(); ++cit) 2959 2960 { -
libs/libmythtv/decoderbase.cpp
407 407 } 408 408 } 409 409 410 bool DecoderBase::DoRewind(long long desiredFrame, bool d oflush)410 bool DecoderBase::DoRewind(long long desiredFrame, bool discardFrames) 411 411 { 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")); 414 416 415 417 if (m_positionMap.empty()) 416 418 return false; 417 419 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; 424 422 425 if (!ok)426 return false;427 }428 429 423 framesPlayed = lastKey; 430 424 framesRead = lastKey; 431 425 432 426 // Do any Extra frame-by-frame seeking for exactseeks mode 433 427 // And flush pre-seek frame if we are allowed to and need to.. 434 428 int normalframes = (exactseeks) ? desiredFrame - framesPlayed : 0; 435 SeekReset(lastKey, normalframes, true, d oflush);429 SeekReset(lastKey, normalframes, true, discardFrames); 436 430 437 // ??? 438 if (doflush) 431 if (discardFrames) 439 432 { 433 // We need to tell the NVP and VideoOutput what frame we're on. 440 434 GetNVP()->SetFramesPlayed(framesPlayed+1); 441 435 GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed+1); 442 436 } … … 444 438 return true; 445 439 } 446 440 447 bool DecoderBase::DoRewind DVD(long long desiredFrame)441 bool DecoderBase::DoRewindSeek(long long desiredFrame) 448 442 { 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 } 454 450 455 bool DecoderBase::DoRewindNormal(long long desiredFrame)456 {457 451 // Find keyframe <= desiredFrame, store in lastKey (frames) 458 452 int pre_idx, post_idx; 459 453 FindPosition(desiredFrame, hasKeyFrameAdjustTable, pre_idx, post_idx); … … 528 522 .arg(desiredFrame).arg(framesPlayed) 529 523 .arg((discardFrames) ? "do" : "don't")); 530 524 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) 533 531 return DoRewind(desiredFrame, discardFrames); 532 desiredFrame = max(desiredFrame, framesPlayed); 534 533 535 534 // Save rawframe state, for later restoration... 536 535 bool oldrawstate = getrawframes; … … 627 626 lastKey = (hasKeyFrameAdjustTable) ? e.adjFrame : e.index * keyframedist; 628 627 629 628 // if commented out as a temporary fix for #868. 630 //if (framesPlayed < lastKey)629 if (framesPlayed < lastKey) 631 630 { 632 631 ringBuffer->Seek(e.pos, SEEK_SET); 633 632 needflush = true; -
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); … … 137 137 frame_queue_t *queue(BufferType type); 138 138 const frame_queue_t *queue(BufferType type) const; 139 139 140 frame_queue_t available, used, limbo, pause, displayed ;140 frame_queue_t available, used, limbo, pause, displayed, decode; 141 141 vbuffer_map_t vbufferMap; // videobuffers to buffer's index 142 142 frame_vector_t buffers; 143 143 uchar_vector_t allocated_structs; // for DeleteBuffers -
libs/libmythtv/videobuffers.cpp
221 221 success = false; 222 222 global_lock.lock(); 223 223 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 224 233 while (frame && used.contains(frame)) 225 234 { 226 235 VERBOSE(VB_IMPORTANT, … … 243 252 } 244 253 if (frame) 245 254 { 246 frame_queue_t *q = queue(enqueue_to); 247 if (q) 248 q->enqueue(frame); 255 safeEnqueue(enqueue_to, frame); 256 249 257 success = true; 250 258 if (with_lock) 251 259 success = TryLockFrame(frame, "GetNextFreeFrame"); 252 260 if (!success) 253 { 254 available.enqueue(frame); 255 q->remove(frame); 256 } 261 safeEnqueue(kVideoBuffer_avail, frame); 257 262 } 258 263 259 264 global_lock.unlock(); … … 283 288 QString("GetNextFreeFrame() unable to " 284 289 "lock frame %1 times. Discarding Frames.") 285 290 .arg(TRY_LOCK_SPINS)); 286 DiscardFrames( );291 DiscardFrames(true); 287 292 } 288 293 } 289 294 } … … 302 307 global_lock.lock(); 303 308 vpos = vbufferMap[frame]; 304 309 limbo.remove(frame); 310 decode.enqueue(frame); 305 311 used.enqueue(frame); 306 312 global_lock.unlock(); 307 313 } … … 319 325 limbo.remove(frame); 320 326 available.enqueue(frame); 321 327 } 328 decode.remove(frame); 322 329 global_lock.unlock(); 323 330 } 324 331 … … 592 599 } 593 600 594 601 /** 595 * \fn VideoBuffers::DiscardFrames( void)602 * \fn VideoBuffers::DiscardFrames(bool) 596 603 * Mark all used frames as ready to be reused, this is for seek. 597 604 */ 598 void VideoBuffers::DiscardFrames( void)605 void VideoBuffers::DiscardFrames(bool next_frame_keyframe) 599 606 { 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())); 603 610 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 604 634 // Remove inheritence of all frames not in displayed or pause 605 635 frame_queue_t ula(used); 606 636 ula.insert(ula.end(), limbo.begin(), limbo.end()); … … 634 664 } 635 665 } 636 666 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(); 639 674 640 global_lock.unlock(); 675 VERBOSE(VB_PLAYBACK, 676 QString("VideoBuffers::DiscardFrames(%1): %2 -- done") 677 .arg(next_frame_keyframe).arg(GetStatus())); 641 678 } 642 679 643 680 void VideoBuffers::ClearAfterSeek(void) … … 1185 1222 unsigned long long d = to_bitmap(displayed); 1186 1223 unsigned long long l = to_bitmap(limbo); 1187 1224 unsigned long long p = to_bitmap(pause); 1225 unsigned long long x = to_bitmap(decode); 1188 1226 for (uint i=0; i<(uint)n; i++) 1189 1227 { 1190 1228 unsigned long long mask = 1<<i; 1191 1229 if (a & mask) 1192 str += "A";1230 str += (x & mask) ? "a" : "A"; 1193 1231 else if (u & mask) 1194 str += "U";1232 str += (x & mask) ? "u" : "U"; 1195 1233 else if (d & mask) 1196 str += "d";1234 str += (x & mask) ? "d" : "D"; 1197 1235 else if (l & mask) 1198 str += "L";1236 str += (x & mask) ? "l" : "L"; 1199 1237 else if (p & mask) 1200 str += "p";1238 str += (x & mask) ? "p" : "P"; 1201 1239 else 1202 1240 str += " "; 1203 1241 }