Process a video packet
| 1836 | |
| 1837 | // Process a video packet |
| 1838 | void FFmpegReader::ProcessVideoPacket(int64_t requested_frame) { |
| 1839 | // Get the AVFrame from the current packet |
| 1840 | // This sets the video_pts to the correct timestamp |
| 1841 | int frame_finished = GetAVFrame(); |
| 1842 | |
| 1843 | // Check if the AVFrame is finished and set it |
| 1844 | if (!frame_finished) { |
| 1845 | // No AVFrame decoded yet, bail out |
| 1846 | if (pFrame) { |
| 1847 | RemoveAVFrame(pFrame); |
| 1848 | } |
| 1849 | return; |
| 1850 | } |
| 1851 | |
| 1852 | // Calculate current frame # |
| 1853 | int64_t current_frame = ConvertVideoPTStoFrame(video_pts); |
| 1854 | |
| 1855 | // Track 1st video packet after a successful seek |
| 1856 | if (!seek_video_frame_found && is_seeking) |
| 1857 | seek_video_frame_found = current_frame; |
| 1858 | |
| 1859 | // Create or get the existing frame object. Requested frame needs to be created |
| 1860 | // in working_cache at least once. Seek can clear the working_cache, so we must |
| 1861 | // add the requested frame back to the working_cache here. If it already exists, |
| 1862 | // it will be moved to the top of the working_cache. |
| 1863 | working_cache.Add(CreateFrame(requested_frame)); |
| 1864 | |
| 1865 | // Debug output |
| 1866 | ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessVideoPacket (Before)", "requested_frame", requested_frame, "current_frame", current_frame); |
| 1867 | |
| 1868 | // Init some things local (for OpenMP) |
| 1869 | AVPixelFormat decoded_pix_fmt = (pFrame && pFrame->format != AV_PIX_FMT_NONE) |
| 1870 | ? static_cast<AVPixelFormat>(pFrame->format) |
| 1871 | : AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx); |
| 1872 | bool src_full_range = (pFrame && pFrame->color_range == AVCOL_RANGE_JPEG); |
| 1873 | AVPixelFormat src_pix_fmt = NormalizeDeprecatedPixFmt(decoded_pix_fmt, src_full_range); |
| 1874 | int src_width = (pFrame && pFrame->width > 0) ? pFrame->width : info.width; |
| 1875 | int src_height = (pFrame && pFrame->height > 0) ? pFrame->height : info.height; |
| 1876 | int height = src_height; |
| 1877 | int width = src_width; |
| 1878 | // Create or reuse a RGB Frame (since most videos are not in RGB, we must convert it) |
| 1879 | AVFrame *pFrameRGB = pFrameRGB_cached; |
| 1880 | if (!pFrameRGB) { |
| 1881 | pFrameRGB = AV_ALLOCATE_FRAME(); |
| 1882 | if (pFrameRGB == nullptr) |
| 1883 | throw OutOfMemory("Failed to allocate frame buffer", path); |
| 1884 | pFrameRGB_cached = pFrameRGB; |
| 1885 | } |
| 1886 | AV_RESET_FRAME(pFrameRGB); |
| 1887 | uint8_t *buffer = nullptr; |
| 1888 | |
| 1889 | // Determine the max size of this source image (based on the timeline's size, the scaling mode, |
| 1890 | // and the scaling keyframes). This is a performance improvement, to keep the images as small as possible, |
| 1891 | // without losing quality. NOTE: We cannot go smaller than the timeline itself, or the add_layer timeline |
| 1892 | // method will scale it back to timeline size before scaling it smaller again. This needs to be fixed in |
| 1893 | // the future. |
| 1894 | int max_width = info.width; |
| 1895 | int max_height = info.height; |
nothing calls this directly
no test coverage detected