diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
index 702abc0..a7b7a74 100644
a
|
b
|
const double MythPlayer::kInaccuracyNone = 0; |
79 | 79 | // By default, when seeking, snap to a keyframe if the keyframe's |
80 | 80 | // distance from the target frame is less than 10% of the total seek |
81 | 81 | // distance. |
82 | | const double MythPlayer::kInaccuracyDefault = 0.1; |
| 82 | const double MythPlayer::kInaccuracyDefault = 0.2; |
83 | 83 | |
84 | 84 | // Allow greater inaccuracy (50%) in the cutlist editor (unless the |
85 | 85 | // editor seek distance is set to 1 frame or 1 keyframe). |
… |
… |
MythPlayer::MythPlayer(PlayerFlags flags) |
202 | 202 | decoder_lock(QMutex::Recursive), |
203 | 203 | next_play_speed(1.0f), next_normal_speed(true), |
204 | 204 | play_speed(1.0f), normal_speed(true), |
205 | | frame_interval((int)(1000000.0f / 30)), m_frame_interval(0), |
| 205 | frame_interval((int)(1000000.0f / 25)), m_frame_interval(0), |
206 | 206 | ffrew_skip(1),ffrew_adjust(0), |
207 | 207 | // Audio and video synchronization stuff |
208 | 208 | videosync(NULL), avsync_delay(0), |
209 | 209 | avsync_adjustment(0), avsync_avg(0), |
210 | 210 | avsync_predictor(0), avsync_predictor_enabled(false), |
211 | | refreshrate(0), |
| 211 | refreshinterval(0), |
212 | 212 | lastsync(false), repeat_delay(0), |
213 | 213 | disp_timecode(0), avsync_audiopaused(false), |
214 | 214 | // AVSync for Raspberry Pi digital streams |
… |
… |
void MythPlayer::PauseVideo(void) |
424 | 424 | needNewPauseFrame = true; |
425 | 425 | videoPaused = true; |
426 | 426 | videoPauseLock.unlock(); |
| 427 | first_time = true; |
427 | 428 | } |
428 | 429 | |
429 | 430 | void MythPlayer::UnpauseVideo(void) |
… |
… |
FrameScanType MythPlayer::detectInterlace(FrameScanType newScan, |
666 | 667 | // isn't, we have to guess. |
667 | 668 | |
668 | 669 | scan = kScan_Interlaced; // default to interlaced |
669 | | if (720 == video_height) // ATSC 720p |
670 | | scan = kScan_Progressive; |
671 | | else if (fps > 45) // software deinterlacing |
| 670 | if (fps > 45) // software deinterlacing |
672 | 671 | scan = kScan_Progressive; |
673 | 672 | |
674 | 673 | if (kScan_Detect != newScan) |
… |
… |
int MythPlayer::NextCaptionTrack(int mode) |
1773 | 1772 | void MythPlayer::SetFrameInterval(FrameScanType scan, double frame_period) |
1774 | 1773 | { |
1775 | 1774 | frame_interval = (int)(1000000.0f * frame_period + 0.5f); |
| 1775 | // int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval; |
| 1776 | |
1776 | 1777 | if (!avsync_predictor_enabled) |
1777 | 1778 | avsync_predictor = 0; |
1778 | 1779 | avsync_predictor_enabled = false; |
1779 | 1780 | |
1780 | 1781 | LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("SetFrameInterval ps:%1 scan:%2") |
1781 | 1782 | .arg(play_speed).arg(scan)); |
1782 | | if (play_speed < 1 || play_speed > 2 || refreshrate <= 0) |
| 1783 | if (play_speed < 1 || play_speed > 2 || refreshinterval <= 0) |
1783 | 1784 | return; |
1784 | 1785 | |
1785 | 1786 | avsync_predictor_enabled = ((frame_interval-(frame_interval/200)) < |
1786 | | refreshrate); |
| 1787 | refreshinterval); |
1787 | 1788 | } |
1788 | 1789 | |
1789 | 1790 | void MythPlayer::ResetAVSync(void) |
1790 | 1791 | { |
1791 | 1792 | avsync_avg = 0; |
1792 | | if (!avsync_predictor_enabled || avsync_predictor >= refreshrate) |
| 1793 | if (!avsync_predictor_enabled || avsync_predictor >= refreshinterval) |
1793 | 1794 | avsync_predictor = 0; |
1794 | 1795 | prevtc = 0; |
1795 | 1796 | avsync_next = avsync_interval; // Frames till next sync check |
… |
… |
void MythPlayer::InitAVSync(void) |
1804 | 1805 | |
1805 | 1806 | repeat_delay = 0; |
1806 | 1807 | |
1807 | | refreshrate = MythDisplay::GetDisplayInfo(frame_interval).Rate(); |
| 1808 | refreshinterval = MythDisplay::GetDisplayInfo(frame_interval).Rate(); |
1808 | 1809 | |
1809 | 1810 | // Number of frames over which to average time divergence |
1810 | 1811 | avsync_averaging=4; |
… |
… |
void MythPlayer::InitAVSync(void) |
1831 | 1832 | QString msg = QString("Video timing method: %1").arg(timing_type); |
1832 | 1833 | LOG(VB_GENERAL, LOG_INFO, LOC + msg); |
1833 | 1834 | msg = QString("Display Refresh Rate: %1 Video Frame Rate: %2") |
1834 | | .arg(1000000.0 / refreshrate, 0, 'f', 3) |
| 1835 | .arg(1000000.0 / refreshinterval, 0, 'f', 3) |
1835 | 1836 | .arg(1000000.0 / frame_interval, 0, 'f', 3); |
1836 | 1837 | LOG(VB_PLAYBACK, LOG_INFO, LOC + msg); |
1837 | 1838 | |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
1865 | 1866 | } |
1866 | 1867 | |
1867 | 1868 | float diverge = 0.0f; |
1868 | | int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval; |
1869 | 1869 | int vsync_delay_clock = 0; |
1870 | 1870 | //int64_t currentaudiotime = 0; |
1871 | 1871 | |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
1891 | 1891 | avsync_next = avsync_interval/divisor; |
1892 | 1892 | } |
1893 | 1893 | |
1894 | | FrameScanType ps = m_scan; |
1895 | | if (kScan_Detect == m_scan || kScan_Ignore == m_scan) |
1896 | | ps = kScan_Progressive; |
1897 | | |
1898 | 1894 | bool max_video_behind = diverge < -max_diverge; |
1899 | 1895 | bool dropframe = false; |
1900 | 1896 | QString dbg; |
1901 | 1897 | |
| 1898 | dropframe = !m_double_framerate && drop_field; |
| 1899 | |
1902 | 1900 | if (avsync_predictor_enabled) |
1903 | 1901 | { |
1904 | 1902 | avsync_predictor += frame_interval; |
1905 | | if (avsync_predictor >= refreshrate) |
| 1903 | if (avsync_predictor >= refreshinterval) |
1906 | 1904 | { |
1907 | | int refreshperiodsinframe = avsync_predictor/refreshrate; |
1908 | | avsync_predictor -= refreshrate * refreshperiodsinframe; |
| 1905 | int refreshperiodsinframe = avsync_predictor/refreshinterval; |
| 1906 | avsync_predictor -= refreshinterval * refreshperiodsinframe; |
1909 | 1907 | } |
1910 | 1908 | else |
1911 | 1909 | { |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
1914 | 1912 | } |
1915 | 1913 | } |
1916 | 1914 | |
| 1915 | int frameDelay = frame_interval + avsync_adjustment + repeat_delay; |
| 1916 | frameDelay = m_double_framerate ? frameDelay / 2 : frameDelay; |
| 1917 | |
1917 | 1918 | if (max_video_behind) |
1918 | 1919 | { |
1919 | 1920 | dropframe = true; |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
1928 | 1929 | audio.Pause(false); |
1929 | 1930 | } |
1930 | 1931 | |
| 1932 | FrameScanType ps = m_scan; |
| 1933 | if (kScan_Detect == m_scan || kScan_Ignore == m_scan) |
| 1934 | ps = kScan_Progressive; |
| 1935 | |
1931 | 1936 | if (!dropframe) |
1932 | 1937 | { |
1933 | 1938 | // PGB this was orignally in the calling methods |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
1967 | 1972 | LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, |
1968 | 1973 | LOC + QString("AVSync waitforframe %1 %2") |
1969 | 1974 | .arg(avsync_adjustment).arg(m_double_framerate)); |
1970 | | vsync_delay_clock = videosync->WaitForFrame |
1971 | | (frameDelay + avsync_adjustment + repeat_delay); |
| 1975 | vsync_delay_clock = videosync->WaitForFrame(frameDelay); |
1972 | 1976 | } |
1973 | 1977 | else |
1974 | 1978 | { |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
1976 | 1980 | lastsync = true; |
1977 | 1981 | } |
1978 | 1982 | //currentaudiotime = AVSyncGetAudiotime(); |
1979 | | LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC + "AVSync show"); |
| 1983 | // LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC + "AVSync show"); |
1980 | 1984 | videoOutput->Show(ps); |
1981 | 1985 | |
1982 | 1986 | if (videoOutput->IsErrored()) |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
1987 | 1991 | return; |
1988 | 1992 | } |
1989 | 1993 | |
1990 | | if (m_double_framerate) |
| 1994 | if (!drop_field && m_double_framerate) |
1991 | 1995 | { |
1992 | 1996 | //second stage of deinterlacer processing |
1993 | 1997 | ps = (kScan_Intr2ndField == ps) ? |
1994 | 1998 | kScan_Interlaced : kScan_Intr2ndField; |
1995 | 1999 | osdLock.lock(); |
| 2000 | |
1996 | 2001 | if (m_double_process && ps != kScan_Progressive) |
1997 | 2002 | { |
1998 | 2003 | videofiltersLock.lock(); |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
2005 | 2010 | osdLock.unlock(); |
2006 | 2011 | // Display the second field |
2007 | 2012 | if (!player_ctx->IsPBP() || player_ctx->IsPrimaryPBP()) |
2008 | | vsync_delay_clock = videosync->WaitForFrame(frameDelay + |
2009 | | avsync_adjustment); |
| 2013 | vsync_delay_clock += videosync->WaitForFrame(repeat_field ? (frameDelay * 2) : frameDelay); |
2010 | 2014 | videoOutput->Show(ps); |
2011 | 2015 | } |
2012 | 2016 | |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
2019 | 2023 | } |
2020 | 2024 | else |
2021 | 2025 | { |
2022 | | vsync_delay_clock = videosync->WaitForFrame(frameDelay); |
| 2026 | vsync_delay_clock = videosync->WaitForFrame(frame_interval); |
2023 | 2027 | //currentaudiotime = AVSyncGetAudiotime(); |
2024 | 2028 | } |
2025 | 2029 | |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
2049 | 2053 | // must be sampled here due to Show delays |
2050 | 2054 | int64_t currentaudiotime = audio.GetAudioTime(); |
2051 | 2055 | LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC + |
2052 | | QString("A/V timecodes audio %1 video %2 frameinterval %3 " |
| 2056 | QString("A/V timecodes audio %1 video %2 framedelay %3 " |
2053 | 2057 | "avdel %4 avg %5 tcoffset %6 avp %7 avpen %8 avdc %9 " |
2054 | 2058 | "diverge %10") |
2055 | 2059 | .arg(currentaudiotime) |
2056 | 2060 | .arg(timecode) |
2057 | | .arg(frame_interval) |
| 2061 | .arg(frameDelay) |
2058 | 2062 | .arg(timecode - currentaudiotime - |
2059 | 2063 | (int)(vsync_delay_clock*audio.GetStretchFactor()+500)/1000) |
2060 | 2064 | .arg(avsync_avg) |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
2099 | 2103 | |
2100 | 2104 | // prevents major jitter when pts resets during dvd title |
2101 | 2105 | if (avsync_delay > 2000000 && limit_delay) |
| 2106 | { |
2102 | 2107 | avsync_delay = 90000; |
| 2108 | avsync_avg = 0; |
| 2109 | } |
2103 | 2110 | avsync_avg = (avsync_delay + (avsync_avg * (avsync_averaging-1))) / avsync_averaging; |
2104 | 2111 | |
2105 | 2112 | int avsync_used = avsync_avg; |
… |
… |
void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) |
2108 | 2115 | |
2109 | 2116 | /* If the audio time codes and video diverge, shift |
2110 | 2117 | the video by one interlaced field (1/2 frame) */ |
2111 | | if (!lastsync) |
| 2118 | if (true) //(!lastsync) |
2112 | 2119 | { |
2113 | | if (avsync_used > refreshrate) |
| 2120 | diverge = (float)avsync_avg / (float)refreshinterval; |
| 2121 | // limit damage to spread any AV shift |
| 2122 | if (diverge > 3) |
| 2123 | diverge = 3; |
| 2124 | if (diverge < -3) |
| 2125 | diverge = -3; |
| 2126 | // target +/- 0.5 * refreshinterval |
| 2127 | |
| 2128 | frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval; |
| 2129 | repeat_field = false; |
| 2130 | drop_field = false; |
| 2131 | avsync_adjustment = refreshinterval - frameDelay; |
| 2132 | avsync_adjustment = (refreshinterval > frameDelay) ? frameDelay : avsync_adjustment; |
| 2133 | |
| 2134 | if (avsync_used > frameDelay) |
2114 | 2135 | { |
2115 | | avsync_adjustment += refreshrate; |
| 2136 | avsync_adjustment = 0; |
| 2137 | repeat_field = true; |
2116 | 2138 | } |
2117 | | else if (avsync_used < 0 - refreshrate) |
| 2139 | else if (avsync_used < 0 - frameDelay) |
2118 | 2140 | { |
2119 | | avsync_adjustment -= refreshrate; |
| 2141 | // drop field or frame |
| 2142 | avsync_adjustment = 0; |
| 2143 | drop_field = true; |
2120 | 2144 | } |
| 2145 | |
| 2146 | LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC + |
| 2147 | QString("avsync_used(us) %1 av_adj %2").arg(avsync_used).arg(avsync_adjustment)); |
| 2148 | |
2121 | 2149 | } |
2122 | 2150 | else |
2123 | 2151 | lastsync = false; |
… |
… |
void MythPlayer::DisplayPauseFrame(void) |
2175 | 2203 | RefreshPauseFrame(); |
2176 | 2204 | PreProcessNormalFrame(); // Allow interactiveTV to draw on pause frame |
2177 | 2205 | |
| 2206 | // retrieve the next frame |
| 2207 | videoOutput->StartDisplayingFrame(); |
| 2208 | VideoFrame *frame = videoOutput->GetLastShownFrame(); |
| 2209 | |
| 2210 | FrameScanType ps = m_scan; |
| 2211 | if (kScan_Detect == m_scan || kScan_Ignore == m_scan) |
| 2212 | ps = kScan_Progressive; |
| 2213 | |
| 2214 | if (m_double_process && ps != kScan_Progressive) |
| 2215 | { |
| 2216 | //second stage of deinterlacer processing |
| 2217 | ps = kScan_Intr2ndField; |
| 2218 | } |
| 2219 | |
| 2220 | // ps = kScan_Ignore; |
| 2221 | |
2178 | 2222 | osdLock.lock(); |
2179 | 2223 | videofiltersLock.lock(); |
2180 | | videoOutput->ProcessFrame(NULL, osd, videoFilters, pip_players); |
| 2224 | videoOutput->ProcessFrame(frame, osd, videoFilters, pip_players, ps); |
2181 | 2225 | videofiltersLock.unlock(); |
2182 | | videoOutput->PrepareFrame(NULL, kScan_Ignore, osd); |
| 2226 | videoOutput->PrepareFrame(frame, ps, osd); |
2183 | 2227 | osdLock.unlock(); |
2184 | | videoOutput->Show(kScan_Ignore); |
| 2228 | videoOutput->Show(ps); |
2185 | 2229 | videosync->Start(); |
2186 | 2230 | } |
2187 | 2231 | |
… |
… |
void MythPlayer::DisplayNormalFrame(bool check_prebuffer) |
2316 | 2360 | AutoDeint(frame); |
2317 | 2361 | detect_letter_box->SwitchTo(frame); |
2318 | 2362 | |
2319 | | FrameScanType ps = m_scan; |
2320 | | if (kScan_Detect == m_scan || kScan_Ignore == m_scan) |
2321 | | ps = kScan_Progressive; |
2322 | | |
2323 | 2363 | AVSync(frame, 0); |
2324 | 2364 | // If PiP then keep this frame for MythPlayer::GetCurrentFrame |
2325 | 2365 | if (!player_ctx->IsPIP()) |
… |
… |
void MythPlayer::VideoStart(void) |
2444 | 2484 | avsync_delay = 0; |
2445 | 2485 | avsync_avg = 0; |
2446 | 2486 | avsync_next = avsync_interval; // Frames till next sync check |
2447 | | refreshrate = 0; |
| 2487 | refreshinterval = 0; |
2448 | 2488 | lastsync = false; |
2449 | 2489 | |
2450 | 2490 | EnableFrameRateMonitor(); |
2451 | | refreshrate = frame_interval; |
| 2491 | refreshinterval = frame_interval; |
2452 | 2492 | |
2453 | 2493 | float temp_speed = (play_speed == 0.0) ? audio.GetStretchFactor() : play_speed; |
2454 | 2494 | int fr_int = (1000000.0 / video_frame_rate / temp_speed); |
… |
… |
void MythPlayer::ChangeSpeed(void) |
3787 | 3827 | |
3788 | 3828 | // If using bob deinterlace, turn on or off if we |
3789 | 3829 | // changed to or from synchronous playback speed. |
3790 | | bool play_1 = play_speed > 0.99f && play_speed < 1.01f && normal_speed; |
| 3830 | bool play_1 = true; //play_speed > 0.99f && play_speed < 1.01f && normal_speed; |
3791 | 3831 | bool inter = (kScan_Interlaced == m_scan || |
3792 | 3832 | kScan_Intr2ndField == m_scan); |
3793 | 3833 | |
diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
index 1a23e2f..9c9fb64 100644
a
|
b
|
class MTV_PUBLIC MythPlayer |
656 | 656 | int64_t decoderSeek; |
657 | 657 | bool decodeOneFrame; |
658 | 658 | bool needNewPauseFrame; |
| 659 | bool first_time; |
659 | 660 | mutable QMutex bufferPauseLock; |
660 | 661 | mutable QMutex videoPauseLock; |
661 | 662 | mutable QMutex pauseLock; |
… |
… |
class MTV_PUBLIC MythPlayer |
809 | 810 | |
810 | 811 | float play_speed; |
811 | 812 | bool normal_speed; |
812 | | int frame_interval;///< always adjusted for play_speed |
813 | | int m_frame_interval;///< used to detect changes to frame_interval |
| 813 | int frame_interval; ///< always adjusted for play_speed |
| 814 | int m_frame_interval; ///< used to detect changes to frame_interval |
814 | 815 | |
815 | 816 | int ffrew_skip; |
816 | 817 | int ffrew_adjust; |
… |
… |
class MTV_PUBLIC MythPlayer |
822 | 823 | int avsync_avg; |
823 | 824 | int avsync_predictor; |
824 | 825 | bool avsync_predictor_enabled; |
825 | | int refreshrate; |
| 826 | int refreshinterval; // time (us) |
826 | 827 | bool lastsync; |
827 | 828 | bool decode_extra_audio; |
828 | 829 | int repeat_delay; |
| 830 | bool drop_field; |
| 831 | bool repeat_field; |
829 | 832 | int64_t disp_timecode; |
830 | 833 | bool avsync_audiopaused; |
831 | 834 | float max_diverge; // from setting PlayerMaxDiverge default 2 |
diff --git a/mythtv/libs/libmythtv/videoout_vdpau.cpp b/mythtv/libs/libmythtv/videoout_vdpau.cpp
index 07f6e6d..fd8fa59 100644
a
|
b
|
void VideoOutputVDPAU::PrepareFrame(VideoFrame *frame, FrameScanType scan, |
505 | 505 | VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : |
506 | 506 | VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; |
507 | 507 | } |
508 | | else if (!frame && m_deinterlacing) |
| 508 | else if (m_deinterlacing && !frame) |
509 | 509 | { |
510 | | field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; |
| 510 | field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD; |
511 | 511 | } |
512 | 512 | |
513 | 513 | m_render->WaitForFlip(); |