Ticket #7964: timestretch-predictive-frame-skip.patch
File timestretch-predictive-frame-skip.patch, 9.5 KB (added by , 14 years ago) |
---|
-
libs/libmythtv/NuppelVideoPlayer.cpp
old new NuppelVideoPlayer::NuppelVideoPlayer(boo 255 255 text_size = 8 * (sizeof(teletextsubtitle) + VT_WIDTH); 256 256 for (int i = 0; i < MAXTBUFFER; i++) 257 257 txtbuffers[i].buffer = new unsigned char[text_size + 1]; 258 259 m_skip_frame_idx = m_skip_frame_extra_idx = 0; 260 m_skip_frame = m_skip_frame_extra = 0; 258 261 } 259 262 260 263 NuppelVideoPlayer::~NuppelVideoPlayer(void) … … bool NuppelVideoPlayer::Play(float speed 500 503 audio_lock.lock(); 501 504 if (audioOutput && unpauseaudio) 502 505 audio_paused = false; 503 506 504 507 audio_lock.unlock(); 505 508 if (player_ctx->buffer) 506 509 player_ctx->buffer->Unpause(); … … bool NuppelVideoPlayer::IsPaused(bool *i 534 537 void NuppelVideoPlayer::PauseVideo(bool wait) 535 538 { 536 539 QMutexLocker locker(&pauseUnpauseLock); 537 540 538 541 if (wait) 539 542 video_actually_paused = false; 540 543 pausevideo = true; 541 544 542 545 for (uint i = 0; wait && !video_actually_paused; i++) 543 546 { 544 547 videoThreadPaused.wait(&pauseUnpauseLock, 250); … … void NuppelVideoPlayer::AutoDeint(VideoF 1023 1026 m_scan_locked = false; 1024 1027 } 1025 1028 1029 void NuppelVideoPlayer::PredictFrameSkip(FrameScanType scan) 1030 { 1031 if (play_speed > 1.0) 1032 { 1033 float skip_frame, extra_skip; 1034 skip_frame = (video_frame_rate / 1035 ((play_speed * video_frame_rate) - 1036 video_frame_rate)); 1037 VERBOSE(VB_PLAYBACK, "skip_frame " << skip_frame); 1038 if (kScan_Progressive != scan) 1039 skip_frame *= 2; 1040 VERBOSE(VB_IMPORTANT, QString("kScan = %1, scan = %2") 1041 .arg(kScan_Progressive).arg(scan)); 1042 VERBOSE(VB_PLAYBACK, "skip_frame " << skip_frame); 1043 m_skip_frame = skip_frame; 1044 VERBOSE(VB_PLAYBACK, "m_skip_frame " << m_skip_frame); 1045 VERBOSE(VB_PLAYBACK, " diff " << skip_frame - m_skip_frame); 1046 if (skip_frame - (float)m_skip_frame < 0.0001) 1047 { 1048 m_skip_frame_extra = 0; 1049 m_skip_frame_extra_idx = 0; 1050 } 1051 else 1052 { 1053 m_skip_frame_extra = (1.0 / 1054 (skip_frame - (float)m_skip_frame)) 1055 * (float)m_skip_frame; 1056 --m_skip_frame_extra; // Seems better to skip to often, than not often enough 1057 VERBOSE(VB_PLAYBACK, "m_skip_frame_extra " << m_skip_frame_extra); 1058 m_skip_frame_extra_idx = -2; 1059 } 1060 1061 m_skip_frame_idx = 0; 1062 ++m_skip_frame; 1063 VERBOSE(VB_PLAYBACK, "m_skip_frame " << m_skip_frame); 1064 1065 VERBOSE(VB_PLAYBACK, LOC + QString("Adjusted play speed %1, " 1066 "skip frame %2 & %3 " 1067 "(rate %4)") 1068 .arg(play_speed).arg(m_skip_frame) 1069 .arg(m_skip_frame_extra).arg(video_frame_rate)); 1070 } 1071 else 1072 { 1073 m_skip_frame_idx = m_skip_frame_extra_idx = 0; 1074 m_skip_frame = m_skip_frame_extra = 0; 1075 } 1076 } 1077 1026 1078 void NuppelVideoPlayer::SetScanType(FrameScanType scan) 1027 1079 { 1028 1080 QMutexLocker locker(&videofiltersLock); … … void NuppelVideoPlayer::SetScanType(Fram 1046 1098 { 1047 1099 m_scan = scan; 1048 1100 videosync->SetFrameInterval(frame_interval, false); 1101 PredictFrameSkip(scan); 1049 1102 return; 1050 1103 } 1051 1104 … … void NuppelVideoPlayer::SetScanType(Fram 1089 1142 if (osd) 1090 1143 { 1091 1144 osd->SetFrameInterval( 1092 (m_double_framerate && m_double_process) ?1093 (frame_interval>>1) : frame_interval);1145 (m_double_framerate && m_double_process) ? 1146 (frame_interval>>1) : frame_interval); 1094 1147 } 1095 1148 1149 if (m_scan != scan) 1150 PredictFrameSkip(scan); 1151 1096 1152 m_scan = scan; 1097 1153 } 1098 1154 … … void NuppelVideoPlayer::OpenDummy(void) 1150 1206 isDummy = true; 1151 1207 1152 1208 float displayAspect = 1153 gContext->GetFloatSettingOnHost("XineramaMonitorAspectRatio", 1209 gContext->GetFloatSettingOnHost("XineramaMonitorAspectRatio", 1154 1210 gContext->GetHostName(), 1.3333); 1155 1211 1156 1212 if (!videoOutput) … … void NuppelVideoPlayer::AVSync(void) 2406 2462 if (kScan_Detect == m_scan || kScan_Ignore == m_scan) 2407 2463 ps = kScan_Progressive; 2408 2464 2409 if (diverge < -MAXDIVERGE) 2465 if (m_skip_frame_extra && ++m_skip_frame_extra_idx == m_skip_frame_extra) 2466 { 2467 m_skip_frame_extra_idx = 0; 2468 2469 /* Copied from (diverge < -MAXDIVERGE), below. Can it be optimized? */ 2470 // Reset A/V Sync 2471 lastsync = true; 2472 2473 if (buffer && !using_null_videoout && 2474 videoOutput->hasHWAcceleration() && 2475 !videoOutput->IsSyncLocked()) 2476 { 2477 // If we are using certain hardware decoders, so we've already done 2478 // the decoding; display the frame, but don't wait for A/V Sync. 2479 // Excludes HW decoder/render methods that are locked to 2480 // the vertical sync (e.g. VDPAU) 2481 videoOutput->PrepareFrame(buffer, kScan_Intr2ndField); 2482 videoOutput->Show(kScan_Intr2ndField); 2483 VERBOSE(VB_PLAYBACK, LOC + "skipping A/V wait."); 2484 } 2485 } 2486 if (m_skip_frame && ++m_skip_frame_idx == m_skip_frame) 2487 { 2488 m_skip_frame_idx = 0; 2489 2490 /* Copied from (diverge < -MAXDIVERGE), below. Can it be optimized? */ 2491 // Reset A/V Sync 2492 lastsync = true; 2493 2494 if (buffer && !using_null_videoout && 2495 videoOutput->hasHWAcceleration() && 2496 !videoOutput->IsSyncLocked()) 2497 { 2498 // If we are using certain hardware decoders, so we've already done 2499 // the decoding; display the frame, but don't wait for A/V Sync. 2500 // Excludes HW decoder/render methods that are locked to 2501 // the vertical sync (e.g. VDPAU) 2502 videoOutput->PrepareFrame(buffer, kScan_Intr2ndField); 2503 videoOutput->Show(kScan_Intr2ndField); 2504 VERBOSE(VB_PLAYBACK, LOC + "skipping A/V wait."); 2505 } 2506 } 2507 else if (diverge < -MAXDIVERGE) 2410 2508 { 2411 2509 // If video is way behind of audio, adjust for it... 2412 2510 QString dbg = QString("Video is %1 frames behind audio (too slow), ") … … void NuppelVideoPlayer::AVSync(void) 2414 2512 2415 2513 // Reset A/V Sync 2416 2514 lastsync = true; 2515 m_skip_frame_idx = 0; 2516 m_skip_frame_extra_idx = -2; 2417 2517 2418 2518 if (buffer && !using_null_videoout && 2419 2519 videoOutput->hasHWAcceleration() && … … void NuppelVideoPlayer::AVSync(void) 2524 2624 VERBOSE(VB_PLAYBACK, LOC + 2525 2625 QString("Video is %1 frames ahead of audio,\n" 2526 2626 "\t\t\tdoubling video frame interval to slow down.").arg(diverge)); 2627 m_skip_frame_idx = 0; 2628 m_skip_frame_extra_idx = -2; 2527 2629 } 2528 2630 2529 2631 audio_lock.lock(); … … void NuppelVideoPlayer::AVSync(void) 2593 2695 avsync_avg = 0; 2594 2696 avsync_oldavg = 0; 2595 2697 } 2596 } 2698 } 2597 2699 else 2598 2700 audio_lock.unlock(); 2599 2701 } … … bool NuppelVideoPlayer::StartPlaying(boo 3595 3697 3596 3698 play_speed = next_play_speed; 3597 3699 normal_speed = next_normal_speed; 3700 3598 3701 VERBOSE(VB_PLAYBACK, LOC + "Changing speed to " << play_speed); 3599 3702 3703 PredictFrameSkip(m_scan); 3704 3600 3705 if (play_speed == 0.0) 3601 3706 { 3602 3707 DoPause(); … … void NuppelVideoPlayer::DoPlay(void) 4442 4547 audio_lock.unlock(); 4443 4548 } 4444 4549 4550 4445 4551 VERBOSE(VB_PLAYBACK, LOC + "DoPlay() -- setting unpaused"); 4446 4552 paused = actuallypaused = false; 4447 4553 } … … int NuppelVideoPlayer::SetTrack(uint typ 6861 6967 if (decoder) 6862 6968 { 6863 6969 msg = decoder->GetTrackDesc(type, GetTrack(type)); 6864 6970 6865 6971 if (player_ctx->buffer->isDVD()) 6866 6972 player_ctx->buffer->DVD()->SetTrack(type, trackNo); 6867 6973 } … … bool NuppelVideoPlayer::GoToDVDMenu(QStr 7592 7698 { 7593 7699 if (!player_ctx->buffer->isDVD()) 7594 7700 return false; 7595 7701 7596 7702 textDisplayMode = kDisplayNone; 7597 7703 bool ret = player_ctx->buffer->DVD()->GoToMenu(str); 7598 7704 7599 7705 if (!ret) 7600 7706 { 7601 7707 if (osd) … … bool NuppelVideoPlayer::GoToDVDMenu(QStr 7603 7709 VERBOSE(VB_GENERAL, "No DVD Menu available."); 7604 7710 return false; 7605 7711 } 7606 7712 7607 7713 return true; 7608 7714 } 7609 7715 … … static unsigned dbg_ident(const NuppelVi 8056 8162 } 8057 8163 8058 8164 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 8165 -
libs/libmythtv/NuppelVideoPlayer.h
old new class MPUBLIC NuppelVideoPlayer : public 151 151 void ClearBookmark(void); 152 152 void SetForcedAspectRatio(int mpeg2_aspect_value, int letterbox_permission); 153 153 154 void PredictFrameSkip(FrameScanType scan); 155 154 156 void NextScanType(void) 155 157 { SetScanType((FrameScanType)(((int)m_scan + 1) & 0x3)); } 156 158 void SetScanType(FrameScanType); … … class MPUBLIC NuppelVideoPlayer : public 803 805 bool decode_extra_audio; 804 806 float m_stored_audio_stretchfactor; 805 807 bool audio_paused; 808 int m_skip_frame_idx; 809 int m_skip_frame; 810 int m_skip_frame_extra; 811 int m_skip_frame_extra_idx; 806 812 807 813 // Audio warping stuff 808 814 bool usevideotimebase;