Check the current seek position and determine if we need to seek again
| 1768 | |
| 1769 | // Check the current seek position and determine if we need to seek again |
| 1770 | bool FFmpegReader::CheckSeek() { |
| 1771 | // Are we seeking for a specific frame? |
| 1772 | if (is_seeking) { |
| 1773 | const int64_t kSeekRetryMax = 5; |
| 1774 | const int kSeekStagnantMax = 2; |
| 1775 | |
| 1776 | // Determine if both an audio and video packet have been decoded since the seek happened. |
| 1777 | // If not, allow the ReadStream method to keep looping |
| 1778 | if ((is_video_seek && !seek_video_frame_found) || (!is_video_seek && !seek_audio_frame_found)) |
| 1779 | return false; |
| 1780 | |
| 1781 | // Check for both streams |
| 1782 | if ((info.has_video && !seek_video_frame_found) || (info.has_audio && !seek_audio_frame_found)) |
| 1783 | return false; |
| 1784 | |
| 1785 | // Determine max seeked frame |
| 1786 | int64_t max_seeked_frame = std::max(seek_audio_frame_found, seek_video_frame_found); |
| 1787 | // Track stagnant seek results (no progress between retries) |
| 1788 | if (max_seeked_frame == last_seek_max_frame) { |
| 1789 | seek_stagnant_count++; |
| 1790 | } else { |
| 1791 | last_seek_max_frame = max_seeked_frame; |
| 1792 | seek_stagnant_count = 0; |
| 1793 | } |
| 1794 | |
| 1795 | // determine if we are "before" the requested frame |
| 1796 | if (max_seeked_frame >= seeking_frame) { |
| 1797 | // SEEKED TOO FAR |
| 1798 | ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckSeek (Too far, seek again)", |
| 1799 | "is_video_seek", is_video_seek, |
| 1800 | "max_seeked_frame", max_seeked_frame, |
| 1801 | "seeking_frame", seeking_frame, |
| 1802 | "seeking_pts", seeking_pts, |
| 1803 | "seek_video_frame_found", seek_video_frame_found, |
| 1804 | "seek_audio_frame_found", seek_audio_frame_found); |
| 1805 | |
| 1806 | // Seek again... to the nearest Keyframe |
| 1807 | if (seek_count < kSeekRetryMax) { |
| 1808 | Seek(seeking_frame - (10 * seek_count * seek_count)); |
| 1809 | } else if (seek_stagnant_count >= kSeekStagnantMax) { |
| 1810 | // Stagnant seek: force a much earlier target and keep seeking. |
| 1811 | Seek(seeking_frame - (10 * kSeekRetryMax * kSeekRetryMax)); |
| 1812 | } else { |
| 1813 | // Retry budget exhausted: keep seeking from a conservative offset. |
| 1814 | Seek(seeking_frame - (10 * seek_count * seek_count)); |
| 1815 | } |
| 1816 | } else { |
| 1817 | // SEEK WORKED |
| 1818 | ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckSeek (Successful)", |
| 1819 | "is_video_seek", is_video_seek, |
| 1820 | "packet->pts", GetPacketPTS(), |
| 1821 | "seeking_pts", seeking_pts, |
| 1822 | "seeking_frame", seeking_frame, |
| 1823 | "seek_video_frame_found", seek_video_frame_found, |
| 1824 | "seek_audio_frame_found", seek_audio_frame_found); |
| 1825 | |
| 1826 | // Seek worked, and we are "before" the requested frame |
| 1827 | is_seeking = false; |
nothing calls this directly
no test coverage detected