Ticket #868: 868-v2.patch
| File 868-v2.patch, 41.3 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
25 25 #include "bswap.h" 26 26 #endif 27 27 28 #define LOC QString("NVD: ") 29 #define LOC_ERR QString("NVD Error: ") 28 30 29 31 pthread_mutex_t avcodeclock = PTHREAD_MUTEX_INITIALIZER; 30 32 … … 37 39 #endif 38 40 ffmpeg_extradatasize(0), ffmpeg_extradata(0), usingextradata(false), 39 41 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), 41 44 lastct('1'), strm(0), buf(0), buf2(0), 42 45 videosizetotal(0), videoframesread(0), setreadahead(false) 43 46 { … … 566 569 int width = c->width; 567 570 int height = c->height; 568 571 569 pic->data[0] = nd->direct buf;572 pic->data[0] = nd->directframe->buf; 570 573 pic->data[1] = pic->data[0] + width * height; 571 574 pic->data[2] = pic->data[1] + width * height / 4; 572 575 … … 574 577 pic->linesize[1] = width / 2; 575 578 pic->linesize[2] = width / 2; 576 579 577 pic->opaque = nd ;580 pic->opaque = nd->directframe; 578 581 pic->type = FF_BUFFER_TYPE_USER; 579 582 580 583 pic->age = 256 * 256 * 256 * 64; … … 587 590 (void)c; 588 591 assert(pic->type == FF_BUFFER_TYPE_USER); 589 592 593 NuppelDecoder *nd = (NuppelDecoder *)(c->opaque); 594 if (nd && nd->GetNVP() && nd->GetNVP()->getVideoOutput()) 595 nd->GetNVP()->getVideoOutput()->DeLimboFrame((VideoFrame*)pic->opaque); 596 590 597 int i; 591 598 for (i = 0; i < 4; i++) 592 599 pic->data[i] = NULL; … … 683 690 int compoff = 0; 684 691 685 692 unsigned char *outbuf = frame->buf; 693 directframe = frame; 686 694 687 695 if (!buf2) 688 696 { … … 759 767 int gotpicture = 0; 760 768 pthread_mutex_lock(&avcodeclock); 761 769 // if directrendering, writes into buf 762 directbuf = outbuf;763 770 int ret = avcodec_decode_video(mpa_ctx, &mpa_pic, &gotpicture, 764 771 lstrm, frameheader->packetlength); 772 directframe = NULL; 765 773 pthread_mutex_unlock(&avcodeclock); 766 774 if (ret < 0) 767 775 { … … 896 904 bool ret = false; 897 905 int seeklen = 0; 898 906 907 decoded_video_frame = NULL; 908 899 909 while (!gotvideo) 900 910 { 901 911 long long currentposition = ringBuffer->GetReadPosition(); … … 1046 1056 1047 1057 buf->frameNumber = framesPlayed; 1048 1058 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; 1049 1066 gotvideo = 1; 1050 1067 if (getrawframes && getrawvideo) 1051 1068 StoreRawData(strm); … … 1139 1156 } 1140 1157 1141 1158 void NuppelDecoder::SeekReset(long long newKey, uint skipFrames, 1142 bool needFlush, bool discardFrames)1159 bool doFlush, bool discardFrames) 1143 1160 { 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); 1145 1168 1146 if (mpa_codec && needFlush)1169 if (mpa_codec && doFlush) 1147 1170 avcodec_flush_buffers(mpa_ctx); 1148 1171 1149 while (skipFrames > 0) 1172 if (discardFrames) 1173 GetNVP()->DiscardVideoFrames(doFlush); 1174 1175 for (;(skipFrames > 0) && !ateof; skipFrames--) 1150 1176 { 1151 1177 GetFrame(0); 1152 if (ateof) 1153 break; 1154 skipFrames--; 1178 if (decoded_video_frame) 1179 GetNVP()->DiscardVideoFrame(decoded_video_frame); 1155 1180 } 1156 1181 } 1157 1182 -
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
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 } … … 254 325 return ((lsb - base_ts)&mask); 255 326 } 256 327 257 bool AvFormatDecoder::DoRewind(long long desiredFrame, bool d oflush)328 bool AvFormatDecoder::DoRewind(long long desiredFrame, bool discardFrames) 258 329 { 259 330 VERBOSE(VB_PLAYBACK, LOC + "DoRewind(" 260 <<desiredFrame<<", "<<( doflush ? "do" : "don't" )<<" flush)"); 331 <<desiredFrame<<", " 332 <<( discardFrames ? "do" : "don't" )<<" discard frames)"); 261 333 262 334 if (recordingHasPositionMap || livetv) 263 return DecoderBase::DoRewind(desiredFrame, d oflush);335 return DecoderBase::DoRewind(desiredFrame, discardFrames); 264 336 265 337 // avformat-based seeking 266 return DoFastForward(desiredFrame, d oflush);338 return DoFastForward(desiredFrame, discardFrames); 267 339 } 268 340 269 bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool d oflush)341 bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool discardFrames) 270 342 { 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")); 273 347 274 348 if (recordingHasPositionMap || livetv) 275 return DecoderBase::DoFastForward(desiredFrame, d oflush);349 return DecoderBase::DoFastForward(desiredFrame, discardFrames); 276 350 277 351 bool oldrawstate = getrawframes; 278 352 getrawframes = false; … … 333 407 334 408 int normalframes = desiredFrame - framesPlayed; 335 409 336 SeekReset(lastKey, normalframes, d oflush, doflush);410 SeekReset(lastKey, normalframes, discardFrames, discardFrames); 337 411 338 if (d oflush)412 if (discardFrames) 339 413 { 340 414 GetNVP()->SetFramesPlayed(framesPlayed + 1); 341 415 GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed + 1); … … 349 423 void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames, 350 424 bool doflush, bool discardFrames) 351 425 { 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") 354 430 .arg((discardFrames) ? "do" : "don't")); 355 431 356 432 DecoderBase::SeekReset(newKey, skipFrames, doflush, discardFrames); 357 433 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); 362 441 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 } 366 451 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 380 453 VERBOSE(VB_PLAYBACK, LOC + "SeekReset() flushing"); 381 454 for (int i = 0; i < ic->nb_streams; i++) 382 455 { … … 384 457 if (enc->codec) 385 458 avcodec_flush_buffers(enc); 386 459 } 460 d->ResetMPEG2(); 387 461 } 388 462 389 463 // Discard all the queued up decoded frames 390 464 if (discardFrames) 391 GetNVP()->DiscardVideoFrames( );465 GetNVP()->DiscardVideoFrames(doflush); 392 466 393 // Free up the stored up packets 394 while (doflush && storedPackets.count() > 0) 467 if (doflush) 395 468 { 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; 400 482 } 401 483 402 prevgoppos = 0; 403 gopset = false; 404 405 // Skip all the desired number of skipFrames 484 // Skip all the desired number of skipFrames 406 485 for (;skipFrames > 0 && !ateof; skipFrames--) 407 486 { 408 487 GetFrame(0); … … 416 495 VERBOSE(VB_PLAYBACK, LOC + QString("Reset(%1, %2)") 417 496 .arg(reset_video_data).arg(seek_reset)); 418 497 if (seek_reset) 419 SeekReset(0, 0, true, true);498 SeekReset(0, 0, true, false); 420 499 421 500 if (reset_video_data) 422 501 { … … 2446 2525 { 2447 2526 AVPicture tmppicture; 2448 2527 2528 VideoFrame *xf = picframe; 2449 2529 picframe = GetNVP()->GetNextVideoFrame(false); 2450 2530 2451 2531 tmppicture.data[0] = picframe->buf; … … 2463 2543 context->pix_fmt, 2464 2544 context->width, 2465 2545 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); 2466 2551 } 2467 2552 2468 2553 long long temppts = pts; … … 2498 2583 2499 2584 picframe->frameNumber = framesPlayed; 2500 2585 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); 2503 2588 2504 2589 decoded_video_frame = picframe; 2505 2590 gotvideo = 1; -
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); … … 106 105 long long adjFrame; // keyFrameAdjustTable adjusted frame number 107 106 long long pos; // position in stream 108 107 } PosMapEntry; 108 long long GetKey(PosMapEntry &entry) const; 109 109 110 110 NuppelVideoPlayer *m_parent; 111 111 ProgramInfo *m_playbackinfo; … … 122 122 long long framesRead; 123 123 long long lastKey; 124 124 int keyframedist; 125 long long indexOffset; 125 126 126 127 127 128 bool ateof; -
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 VideoFrame *decoded_video_frame; 103 104 104 105 AVCodec *mpa_codec; 105 106 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 … … 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
20 20 current_aspect(1.33333), fps(29.97), 21 21 22 22 framesPlayed(0), framesRead(0), lastKey(0), keyframedist(-1), 23 indexOffset(0), 23 24 24 25 ateof(false), exitafterdecoded(false), transcoding(false), 25 26 … … 156 157 { 157 158 VERBOSE(VB_PLAYBACK, QString("Position map filled from DB to: %1") 158 159 .arg((long int) m_positionMap[m_positionMap.size()-1].index)); 160 indexOffset = m_positionMap[0].index; 159 161 } 160 162 161 163 return true; … … 342 344 int &lower_bound, int &upper_bound) 343 345 { 344 346 // Binary search 345 intupper = m_positionMap.size(), lower = -1;347 long long upper = m_positionMap.size(), lower = -1; 346 348 if (!search_adjusted && keyframedist > 0) 347 349 desired_value /= keyframedist; 348 350 349 351 while (upper - 1 > lower) 350 352 { 351 inti = (upper + lower) / 2;353 long long i = (upper + lower) / 2; 352 354 long long value; 353 355 if (search_adjusted) 354 356 value = m_positionMap[i].adjFrame; 355 357 else 356 value = m_positionMap[i].index ;358 value = m_positionMap[i].index - indexOffset; 357 359 if (value == desired_value) 358 360 { 359 361 // found it … … 368 370 } 369 371 // Did not find it exactly -- return bounds 370 372 371 if (search_adjusted) 373 if (search_adjusted) 372 374 { 373 375 while (lower >= 0 && m_positionMap[lower].adjFrame > desired_value) 374 376 lower--; 375 while (upper < (int)m_positionMap.size() &&377 while (upper < m_positionMap.size() && 376 378 m_positionMap[upper].adjFrame > desired_value) 377 379 upper++; 378 380 } 379 381 else 380 382 { 381 while (lower >= 0 &&m_positionMap[lower].index > desired_value) 383 while (lower >= 0 && 384 (m_positionMap[lower].index - indexOffset) > desired_value) 382 385 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) 385 388 upper++; 386 389 } 387 390 // 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); 392 393 393 394 upper_bound = upper; 394 395 lower_bound = lower; … … 407 408 } 408 409 } 409 410 410 bool DecoderBase::DoRewind(long long desiredFrame, bool d oflush)411 bool DecoderBase::DoRewind(long long desiredFrame, bool discardFrames) 411 412 { 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")); 414 417 415 418 if (m_positionMap.empty()) 416 419 return false; 417 420 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; 424 423 425 if (!ok)426 return false;427 }428 429 424 framesPlayed = lastKey; 430 425 framesRead = lastKey; 431 426 432 427 // Do any Extra frame-by-frame seeking for exactseeks mode 433 428 // And flush pre-seek frame if we are allowed to and need to.. 434 429 int normalframes = (exactseeks) ? desiredFrame - framesPlayed : 0; 430 normalframes = max(normalframes, 0); 431 SeekReset(lastKey, normalframes, true, discardFrames); 435 432 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) 444 434 { 435 // We need to tell the NVP and VideoOutput what frame we're on. 445 436 GetNVP()->SetFramesPlayed(framesPlayed+1); 446 437 GetNVP()->getVideoOutput()->SetFramesPlayed(framesPlayed+1); 447 438 } … … 449 440 return true; 450 441 } 451 442 452 bool DecoderBase::DoRewindDVD(long long desiredFrame) 443 long long DecoderBase::GetKey(PosMapEntry &e) const 453 444 { 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; 458 447 } 459 448 460 bool DecoderBase::DoRewind Normal(long long desiredFrame)449 bool DecoderBase::DoRewindSeek(long long desiredFrame) 461 450 { 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 462 459 // Find keyframe <= desiredFrame, store in lastKey (frames) 463 460 int pre_idx, post_idx; 464 461 FindPosition(desiredFrame, hasKeyFrameAdjustTable, pre_idx, post_idx); 465 462 466 bool useAdj = hasKeyFrameAdjustTable;467 463 uint pos_idx = min(pre_idx, post_idx); 468 464 PosMapEntry e = m_positionMap[pos_idx]; 469 lastKey = (useAdj) ? e.adjFrame : (e.index - 1) * keyframedist;465 lastKey = GetKey(e); 470 466 471 467 // ??? Don't rewind past the beginning of the file 472 468 while (e.pos < 0) … … 476 472 return false; 477 473 478 474 e = m_positionMap[pos_idx]; 479 lastKey = (useAdj) ? e.adjFrame : (e.index - 1) * keyframedist;475 lastKey = GetKey(e); 480 476 } 481 477 482 478 ringBuffer->Seek(e.pos, SEEK_SET); … … 487 483 long long DecoderBase::GetLastFrameInPosMap(long long desiredFrame) 488 484 { 489 485 long long last_frame = 0; 490 uint mult = (uint) (ringBuffer->isDVD()) ? 1 : keyframedist;491 486 if (!m_positionMap.empty()) 492 last_frame = mult * m_positionMap.back().index;487 last_frame = GetKey(m_positionMap.back()); 493 488 494 489 // Resync keyframe map if we are trying to seek to a frame 495 490 // not yet in out map and then check for last frame again. … … 503 498 SyncPositionMap(); 504 499 505 500 if (!m_positionMap.empty()) 506 last_frame = mult * m_positionMap.back().index;501 last_frame = GetKey(m_positionMap.back()); 507 502 508 503 if (desiredFrame > last_frame) 509 504 { … … 533 528 .arg(desiredFrame).arg(framesPlayed) 534 529 .arg((discardFrames) ? "do" : "don't")); 535 530 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) 538 537 return DoRewind(desiredFrame, discardFrames); 538 desiredFrame = max(desiredFrame, framesPlayed); 539 539 540 540 // Save rawframe state, for later restoration... 541 541 bool oldrawstate = getrawframes; … … 629 629 uint pos_idx = (exactseeks) ? pre_idx : max(pre_idx, post_idx); 630 630 631 631 PosMapEntry e = m_positionMap[pos_idx]; 632 lastKey = (hasKeyFrameAdjustTable) ? e.adjFrame : e.index * keyframedist;632 lastKey = GetKey(e); 633 633 634 // if commented out as a temporary fix for #868. 635 //if (framesPlayed < lastKey) 634 if (framesPlayed < lastKey) 636 635 { 637 636 ringBuffer->Seek(e.pos, SEEK_SET); 638 637 needflush = true; -
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); … … 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 … … 441 448 frame_queue_t *q = queue(type); 442 449 if (q) 443 450 { 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(); 448 454 } 449 455 return NULL; 450 456 } … … 454 460 frame_queue_t *q = queue(type); 455 461 if (q) 456 462 { 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(); 461 466 } 462 467 return NULL; 463 468 } … … 592 597 } 593 598 594 599 /** 595 * \fn VideoBuffers::DiscardFrames( void)600 * \fn VideoBuffers::DiscardFrames(bool) 596 601 * Mark all used frames as ready to be reused, this is for seek. 597 602 */ 598 void VideoBuffers::DiscardFrames( void)603 void VideoBuffers::DiscardFrames(bool next_frame_keyframe) 599 604 { 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())); 603 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 604 632 // Remove inheritence of all frames not in displayed or pause 605 633 frame_queue_t ula(used); 606 634 ula.insert(ula.end(), limbo.begin(), limbo.end()); … … 634 662 } 635 663 } 636 664 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(); 639 672 640 global_lock.unlock(); 673 VERBOSE(VB_PLAYBACK, 674 QString("VideoBuffers::DiscardFrames(%1): %2 -- done") 675 .arg(next_frame_keyframe).arg(GetStatus())); 641 676 } 642 677 643 678 void VideoBuffers::ClearAfterSeek(void) … … 1185 1220 unsigned long long d = to_bitmap(displayed); 1186 1221 unsigned long long l = to_bitmap(limbo); 1187 1222 unsigned long long p = to_bitmap(pause); 1223 unsigned long long x = to_bitmap(decode); 1188 1224 for (uint i=0; i<(uint)n; i++) 1189 1225 { 1190 1226 unsigned long long mask = 1<<i; 1227 QString tmp(""); 1191 1228 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; 1201 1243 else 1202 str += " ";1244 str += "(" + tmp + ")"; 1203 1245 } 1204 1246 global_lock.unlock(); 1205 1247 }
