@@ -199,6 +199,68 @@ void CudaDeviceInterface::initializeContext(AVCodecContext* codecContext) {
199
199
return ;
200
200
}
201
201
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
+
202
264
void CudaDeviceInterface::convertAVFrameToFrameOutput (
203
265
const VideoStreamOptions& videoStreamOptions,
204
266
[[maybe_unused]] const AVRational& timeBase,
0 commit comments