@@ -199,6 +199,68 @@ void CudaDeviceInterface::initializeContext(AVCodecContext* codecContext) {
199199 return ;
200200}
201201
202+ std::unique_ptr<FiltersContext> CudaDeviceInterface::initializeFiltersContext (
203+ const VideoStreamOptions& videoStreamOptions,
204+ const UniqueAVFrame& avFrame,
205+ const AVRational& timeBase) {
206+ enum AVPixelFormat frameFormat =
207+ static_cast <enum AVPixelFormat>(avFrame->format );
208+
209+ if (avFrame->format != AV_PIX_FMT_CUDA) {
210+ auto cpuDevice = torch::Device (torch::kCPU );
211+ auto cpuInterface = createDeviceInterface (cpuDevice);
212+ return cpuInterface->initializeFiltersContext (
213+ videoStreamOptions, avFrame, timeBase);
214+ }
215+
216+ auto frameDims =
217+ getHeightAndWidthFromOptionsOrAVFrame (videoStreamOptions, avFrame);
218+ int height = frameDims.height ;
219+ int width = frameDims.width ;
220+
221+ auto hwFramesCtx =
222+ reinterpret_cast <AVHWFramesContext*>(avFrame->hw_frames_ctx ->data );
223+ AVPixelFormat actualFormat = hwFramesCtx->sw_format ;
224+
225+ if (actualFormat == AV_PIX_FMT_NV12) {
226+ return nullptr ;
227+ }
228+
229+ AVPixelFormat outputFormat;
230+ std::stringstream filters;
231+
232+ unsigned version_int = avfilter_version ();
233+ if (version_int < AV_VERSION_INT (8 , 0 , 103 )) {
234+ // Color conversion support ('format=' option) was added to scale_cuda from
235+ // n5.0. With the earlier version of ffmpeg we have no choice but use CPU
236+ // filters. See:
237+ // https://github.com/FFmpeg/FFmpeg/commit/62dc5df941f5e196164c151691e4274195523e95
238+ outputFormat = AV_PIX_FMT_RGB24;
239+
240+ filters << " hwdownload,format=" << av_pix_fmt_desc_get (actualFormat)->name ;
241+ filters << " ,scale=" << width << " :" << height;
242+ filters << " :sws_flags=bilinear" ;
243+ } else {
244+ // Actual output color format will be set via filter options
245+ outputFormat = AV_PIX_FMT_CUDA;
246+
247+ filters << " scale_cuda=" << width << " :" << height;
248+ filters << " :format=nv12:interp_algo=bilinear" ;
249+ }
250+
251+ return std::make_unique<FiltersContext>(
252+ avFrame->width ,
253+ avFrame->height ,
254+ frameFormat,
255+ avFrame->sample_aspect_ratio ,
256+ width,
257+ height,
258+ outputFormat,
259+ filters.str (),
260+ timeBase,
261+ av_buffer_ref (avFrame->hw_frames_ctx ));
262+ }
263+
202264void CudaDeviceInterface::convertAVFrameToFrameOutput (
203265 const VideoStreamOptions& videoStreamOptions,
204266 [[maybe_unused]] const AVRational& timeBase,
0 commit comments