| 848 | } |
| 849 | |
| 850 | FFMS_Frame *FFMS_VideoSource::GetFrame(int n) { |
| 851 | GetFrameCheck(n); |
| 852 | n = Frames.RealFrameNumber(n); |
| 853 | |
| 854 | if (Stage != DecodeStage::INITIALIZE_SOURCE && LastFrameNum == n) |
| 855 | return &LocalFrame; |
| 856 | |
| 857 | int SeekOffset = 0; |
| 858 | bool Seek = true; |
| 859 | bool WasSkipped = false; |
| 860 | |
| 861 | do { |
| 862 | bool HasSeeked = false; |
| 863 | if (Seek) { |
| 864 | HasSeeked = SeekTo(n, SeekOffset); |
| 865 | Seek = false; |
| 866 | WasSkipped = false; |
| 867 | } |
| 868 | |
| 869 | int64_t StartTime = AV_NOPTS_VALUE, FilePos = -1; |
| 870 | bool Skipped = (((unsigned) CurrentFrame < Frames.size()) && Frames[CurrentFrame].Skipped()); |
| 871 | if (HasSeeked || !Skipped) { |
| 872 | if (WasSkipped) |
| 873 | WasSkipped = false; |
| 874 | else |
| 875 | DecodeNextFrame(StartTime, FilePos); |
| 876 | } |
| 877 | |
| 878 | if (!HasSeeked) |
| 879 | continue; |
| 880 | |
| 881 | if (StartTime == AV_NOPTS_VALUE && !Frames.HasTS) { |
| 882 | if (FilePos >= 0) { |
| 883 | CurrentFrame = Frames.FrameFromPos(FilePos); |
| 884 | if (CurrentFrame >= 0) |
| 885 | continue; |
| 886 | } |
| 887 | // If the track doesn't have timestamps or file positions then |
| 888 | // just trust that we got to the right place, since we have no |
| 889 | // way to tell where we are |
| 890 | else { |
| 891 | CurrentFrame = n; |
| 892 | continue; |
| 893 | } |
| 894 | } |
| 895 | |
| 896 | CurrentFrame = Frames.FrameFromPTS(StartTime); |
| 897 | |
| 898 | // Is the seek destination time known? Does it belong to a frame? |
| 899 | if (CurrentFrame < 0) { |
| 900 | if (SeekMode == 1 || StartTime < 0) { |
| 901 | // No idea where we are so go back a bit further |
| 902 | SeekOffset -= 10; |
| 903 | Seek = true; |
| 904 | continue; |
| 905 | } |
| 906 | CurrentFrame = Frames.ClosestFrameFromPTS(StartTime); |
| 907 | } |
no test coverage detected