Ticket #7964: mythtv_smoothsync.13-24fixes-p0.patch
File mythtv_smoothsync.13-24fixes-p0.patch, 12.4 KB (added by , 13 years ago) |
---|
-
libs/libmythtv/mythplayer.cpp
old new MythPlayer::MythPlayer(bool muted) 238 238 // Audio and video synchronization stuff 239 239 videosync(NULL), avsync_delay(0), 240 240 avsync_adjustment(0), avsync_avg(0), 241 avsync_predictor(0), avsync_predictor_enabled(false), 241 242 refreshrate(0), 242 243 lastsync(false), repeat_delay(0), 243 244 // Time Code stuff … … void MythPlayer::SetVideoParams(int widt 876 877 video_frame_rate = fps; 877 878 float temp_speed = (play_speed == 0.0f) ? 878 879 audio.GetStretchFactor() : play_speed; 879 frame_interval = (int)(1000000.0f / video_frame_rate / temp_speed);880 SetFrameInterval(kScan_Progressive, 1.0 / (video_frame_rate * temp_speed)); 880 881 } 881 882 882 883 if (videoOutput) … … int MythPlayer::NextCaptionTrack(int mod 1637 1638 return NextCaptionTrack(nextmode); 1638 1639 } 1639 1640 1641 void MythPlayer::SetFrameInterval(FrameScanType scan, double frame_period) 1642 { 1643 frame_interval = (int)(1000000.0f * frame_period + 0.5f); 1644 if (!avsync_predictor_enabled) 1645 avsync_predictor = 0; 1646 avsync_predictor_enabled = false; 1647 1648 VERBOSE(VB_PLAYBACK, LOC + QString("SetFrameInterval ps:%1 scan:%2") 1649 .arg(play_speed).arg(scan) 1650 ); 1651 if (play_speed < 1 || play_speed > 2 || refreshrate <= 0) 1652 return; 1653 1654 avsync_predictor_enabled = ((frame_interval-(frame_interval/200)) < refreshrate); 1655 } 1656 1657 void MythPlayer::ResetAVSync(void) 1658 { 1659 avsync_avg = 0; 1660 if (!avsync_predictor_enabled || avsync_predictor >= refreshrate) 1661 avsync_predictor = 0; 1662 prevtc = 0; 1663 VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V sync reset"); 1664 } 1665 1640 1666 void MythPlayer::InitAVSync(void) 1641 1667 { 1642 1668 videosync->Start(); … … void MythPlayer::InitAVSync(void) 1660 1686 .arg(1000000.0 / frame_interval, 0, 'f', 3); 1661 1687 VERBOSE(VB_PLAYBACK, LOC + msg); 1662 1688 1689 SetFrameInterval(m_scan, 1.0 / (video_frame_rate * play_speed)); 1690 1663 1691 // try to get preferential scheduling, but ignore if we fail to. 1664 1692 myth_nice(-19); 1665 1693 } 1666 1694 } 1667 1695 1696 int64_t MythPlayer::AVSyncGetAudiotime(void) 1697 { 1698 int64_t currentaudiotime = 0; 1699 if (normal_speed) 1700 { 1701 currentaudiotime = audio.GetAudioTime(); 1702 } 1703 return currentaudiotime; 1704 } 1705 1668 1706 #define MAXDIVERGE 3.0f 1669 1707 #define DIVERGELIMIT 30.0f 1670 1708 void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) 1671 1709 { 1672 1710 int repeat_pict = 0; 1673 int64_t timecode = audio.GetAudioTime();1711 int64_t timecode = 0; 1674 1712 1675 1713 if (buffer) 1676 1714 { 1677 1715 repeat_pict = buffer->repeat_pict; 1678 1716 timecode = buffer->timecode; 1679 1717 } 1718 else 1719 timecode = audio.GetAudioTime(); 1680 1720 1681 1721 float diverge = 0.0f; 1682 1722 int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval; 1723 int vsync_delay_clock = 0; 1724 int64_t currentaudiotime = 0; 1683 1725 1684 1726 // attempt to reduce fps for standalone PIP 1685 1727 if (player_ctx->IsPIP() && framesPlayed % 2) … … void MythPlayer::AVSync(VideoFrame *buff 1709 1751 if (kScan_Detect == m_scan || kScan_Ignore == m_scan) 1710 1752 ps = kScan_Progressive; 1711 1753 1754 bool dropframe = false; 1755 QString dbg; 1756 1757 if (avsync_predictor_enabled) // && !prebuffering) 1758 { 1759 avsync_predictor += frame_interval; 1760 if (avsync_predictor >= refreshrate) 1761 { 1762 int refreshperiodsinframe = avsync_predictor/refreshrate; 1763 avsync_predictor -= refreshrate * refreshperiodsinframe; 1764 } 1765 else 1766 { 1767 dropframe = true; 1768 dbg = "A/V predict drop frame, "; 1769 } 1770 } 1771 1712 1772 if (diverge < -MAXDIVERGE) 1713 1773 { 1774 dropframe = true; 1714 1775 // If video is way behind of audio, adjust for it... 1715 QStringdbg = QString("Video is %1 frames behind audio (too slow), ")1776 dbg = QString("Video is %1 frames behind audio (too slow), ") 1716 1777 .arg(-diverge); 1778 } 1717 1779 1780 if (dropframe) 1781 { 1718 1782 // Reset A/V Sync 1719 1783 lastsync = true; 1720 1784 1785 currentaudiotime = AVSyncGetAudiotime(); 1721 1786 if (!using_null_videoout && 1722 1787 videoOutput->hasHWAcceleration() && 1723 1788 !videoOutput->IsSyncLocked()) … … void MythPlayer::AVSync(VideoFrame *buff 1744 1809 osdLock.lock(); 1745 1810 videoOutput->PrepareFrame(buffer, ps, osd); 1746 1811 osdLock.unlock(); 1747 VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2") 1812 VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, 1813 LOC + QString("AVSync waitforframe %1 %2") 1748 1814 .arg(avsync_adjustment).arg(m_double_framerate)); 1749 videosync->WaitForFrame(frameDelay + avsync_adjustment + repeat_delay); 1750 VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show"); 1815 vsync_delay_clock = videosync->WaitForFrame 1816 (frameDelay + avsync_adjustment + repeat_delay); 1817 currentaudiotime = AVSyncGetAudiotime(); 1818 VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + "AVSync show"); 1751 1819 videoOutput->Show(ps); 1752 1820 1753 1821 if (videoOutput->IsErrored()) … … void MythPlayer::AVSync(VideoFrame *buff 1775 1843 videoOutput->PrepareFrame(buffer, ps, osd); 1776 1844 osdLock.unlock(); 1777 1845 // Display the second field 1778 videosync->WaitForFrame(frameDelay + avsync_adjustment); 1846 //videosync->AdvanceTrigger(); 1847 vsync_delay_clock = videosync->WaitForFrame(frameDelay + avsync_adjustment); 1779 1848 videoOutput->Show(ps); 1780 1849 } 1781 1850 1782 1851 repeat_delay = frame_interval * repeat_pict * 0.5; 1783 1852 1784 1853 if (repeat_delay) 1785 VERBOSE(VB_TIMESTAMP, QString("A/V repeat_pict, adding %1 repeat "1854 VERBOSE(VB_TIMESTAMP, LOC + QString("A/V repeat_pict, adding %1 repeat " 1786 1855 "delay").arg(repeat_delay)); 1787 1856 } 1788 1857 else 1789 1858 { 1790 videosync->WaitForFrame(frameDelay); 1859 vsync_delay_clock = videosync->WaitForFrame(frameDelay); 1860 currentaudiotime = AVSyncGetAudiotime(); 1791 1861 } 1792 1862 1793 1863 if (output_jmeter) 1794 output_jmeter->RecordCycleTime(); 1864 { 1865 if (output_jmeter->RecordCycleTime()) 1866 { 1867 VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V avsync_delay: %1, " 1868 "avsync_avg: %2") 1869 .arg(avsync_delay / 1000).arg(avsync_avg / 1000) 1870 ); 1871 } 1872 } 1795 1873 1796 1874 avsync_adjustment = 0; 1797 1875 … … void MythPlayer::AVSync(VideoFrame *buff 1799 1877 { 1800 1878 // If audio is way behind of video, adjust for it... 1801 1879 // by cutting the frame rate in half for the length of this frame 1802 avsync_adjustment = refreshrate; 1880 //avsync_adjustment = refreshrate; 1881 avsync_adjustment = frame_interval; 1803 1882 lastsync = true; 1804 1883 VERBOSE(VB_PLAYBACK, LOC + 1805 1884 QString("Video is %1 frames ahead of audio,\n" … … void MythPlayer::AVSync(VideoFrame *buff 1808 1887 1809 1888 if (audio.HasAudioOut() && normal_speed) 1810 1889 { 1890 // must be sampled here due to Show delays 1811 1891 int64_t currentaudiotime = audio.GetAudioTime(); 1812 VERBOSE(VB_ TIMESTAMP,QString(1892 VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString( 1813 1893 "A/V timecodes audio %1 video %2 frameinterval %3 " 1814 "avdel %4 avg %5 tcoffset %6") 1894 "avdel %4 avg %5 tcoffset %6" 1895 " avp %7 avpen %8" 1896 " avdc %9" 1897 ) 1815 1898 .arg(currentaudiotime) 1816 1899 .arg(timecode) 1817 1900 .arg(frame_interval) 1818 .arg(timecode - currentaudiotime )1901 .arg(timecode - currentaudiotime - (int)(vsync_delay_clock*audio.GetStretchFactor()+500)/1000) 1819 1902 .arg(avsync_avg) 1820 1903 .arg(tc_wrap[TC_AUDIO]) 1904 .arg(avsync_predictor) 1905 .arg(avsync_predictor_enabled) 1906 .arg(vsync_delay_clock) 1821 1907 ); 1822 1908 if (currentaudiotime != 0 && timecode != 0) 1823 1909 { // currentaudiotime == 0 after a seek 1824 1910 // The time at the start of this frame (ie, now) is given by 1825 1911 // last->timecode 1826 int delta = (int)((timecode - prevtc)/play_speed) - (frame_interval / 1000); 1827 prevtc = timecode; 1828 //cerr << delta << " "; 1829 1830 // If the timecode is off by a frame (dropped frame) wait to sync 1831 if (delta > (int) frame_interval / 1200 && 1832 delta < (int) frame_interval / 1000 * 3 && 1833 prevrp == 0) 1912 if (prevtc != 0) 1834 1913 { 1835 // wait an extra frame interval 1836 avsync_adjustment += frame_interval; 1914 int delta = (int)((timecode - prevtc)/play_speed) - (frame_interval / 1000); 1915 // If the timecode is off by a frame (dropped frame) wait to sync 1916 if (delta > (int) frame_interval / 1200 && 1917 delta < (int) frame_interval / 1000 * 3 && 1918 prevrp == 0) 1919 { 1920 // wait an extra frame interval 1921 VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V delay %1").arg(delta)); 1922 avsync_adjustment += frame_interval; 1923 //videosync->AdvanceTrigger(); 1924 //if (m_double_framerate) 1925 // videosync->AdvanceTrigger(); 1926 } 1837 1927 } 1928 prevtc = timecode; 1838 1929 prevrp = repeat_pict; 1839 1930 1840 avsync_delay = (timecode - currentaudiotime) * 1000 ;//usec1931 avsync_delay = (timecode - currentaudiotime) * 1000 - (int)(vsync_delay_clock*audio.GetStretchFactor()); //usec 1841 1932 // prevents major jitter when pts resets during dvd title 1842 1933 if (avsync_delay > 2000000 && limit_delay) 1843 1934 avsync_delay = 90000; 1844 1935 avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4; 1845 1936 1937 int avsync_used = avsync_avg; 1938 if (labs(avsync_used) > labs(avsync_delay)) 1939 avsync_used = avsync_delay; 1940 1846 1941 /* If the audio time codes and video diverge, shift 1847 1942 the video by one interlaced field (1/2 frame) */ 1848 1943 if (!lastsync) 1849 1944 { 1850 if (avsync_ avg > frame_interval * 3 / 2)1945 if (avsync_used > refreshrate) 1851 1946 { 1852 1947 avsync_adjustment += refreshrate; 1853 lastsync = true; 1948 //lastsync = true; 1949 VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V avg high extend"); 1854 1950 } 1855 else if (avsync_ avg < 0 - frame_interval * 3 / 2)1951 else if (avsync_used < 0 - refreshrate) 1856 1952 { 1857 1953 avsync_adjustment -= refreshrate; 1858 lastsync = true; 1954 //lastsync = true; 1955 VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V avg high skip"); 1859 1956 } 1860 1957 } 1861 1958 else … … void MythPlayer::AVSync(VideoFrame *buff 1863 1960 } 1864 1961 else 1865 1962 { 1866 avsync_avg = 0;1963 ResetAVSync(); 1867 1964 } 1868 1965 } 1966 else 1967 { 1968 VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V no sync proc ns:%1").arg(normal_speed)); 1969 } 1869 1970 } 1870 1971 1871 1972 void MythPlayer::RefreshPauseFrame(void) … … void MythPlayer::ClearAfterSeek(bool cle 3500 3601 commBreakMap.SetTracker(framesPlayed); 3501 3602 commBreakMap.ResetLastSkip(); 3502 3603 needNewPauseFrame = true; 3604 ResetAVSync(); 3503 3605 } 3504 3606 3505 3607 void MythPlayer::SetPlayerInfo(TV *tv, QWidget *widget, -
libs/libmythtv/mythplayer.h
old new class MPUBLIC MythPlayer 515 515 void WrapTimecode(int64_t &timecode, TCTypes tc_type); 516 516 void InitAVSync(void); 517 517 virtual void AVSync(VideoFrame *buffer, bool limit_delay = false); 518 void ResetAVSync(void); 519 int64_t AVSyncGetAudiotime(void); 520 void SetFrameInterval(FrameScanType scan, double speed); 518 521 void FallbackDeint(void); 519 522 void CheckExtraAudioDecode(void); 520 523 … … class MPUBLIC MythPlayer 703 706 int avsync_delay; 704 707 int avsync_adjustment; 705 708 int avsync_avg; 709 int avsync_predictor; 710 bool avsync_predictor_enabled; 706 711 int refreshrate; 707 712 bool lastsync; 708 713 bool decode_extra_audio;