78 if (
s->command_queue &&
s->fence &&
s->fence_event) {
79 fence_value =
s->fence_value - 1;
80 hr = ID3D12CommandQueue_Signal(
s->command_queue,
s->fence, fence_value);
82 UINT64 completed = ID3D12Fence_GetCompletedValue(
s->fence);
83 if (completed < fence_value) {
84 hr = ID3D12Fence_SetEventOnCompletion(
s->fence, fence_value,
s->fence_event);
93 CloseHandle(
s->fence_event);
94 s->fence_event =
NULL;
98 ID3D12Fence_Release(
s->fence);
102 if (
s->command_list) {
103 ID3D12VideoProcessCommandList_Release(
s->command_list);
104 s->command_list =
NULL;
107 if (
s->command_allocator) {
108 ID3D12CommandAllocator_Release(
s->command_allocator);
109 s->command_allocator =
NULL;
112 if (
s->video_processor) {
113 ID3D12VideoProcessor_Release(
s->video_processor);
114 s->video_processor =
NULL;
117 if (
s->video_device) {
118 ID3D12VideoDevice_Release(
s->video_device);
119 s->video_device =
NULL;
122 if (
s->command_queue) {
123 ID3D12CommandQueue_Release(
s->command_queue);
124 s->command_queue =
NULL;
135 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020;
137 return DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020;
139 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020;
142 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
147 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020;
149 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601;
151 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
168 }
else if (
inlink->time_base.num > 0 &&
inlink->time_base.den > 0) {
185 if (
s->output_format == DXGI_FORMAT_UNKNOWN) {
192 s->device = d3d12_hwctx->device;
195 s->input_width,
s->input_height,
s->width,
s->height);
197 hr = ID3D12Device_QueryInterface(
s->device, &IID_ID3D12VideoDevice, (
void **)&
s->video_device);
203 D3D12_COMMAND_QUEUE_DESC queue_desc = {
204 .Type = D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
205 .Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
206 .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
210 hr = ID3D12Device_CreateCommandQueue(
s->device, &queue_desc, &IID_ID3D12CommandQueue, (
void **)&
s->command_queue);
216 s->process_support.NodeIndex = 0;
218 s->process_support.InputSample.Format.Format =
s->input_format;
219 s->process_support.InputSample.Format.ColorSpace =
s->input_colorspace;
220 s->process_support.InputSample.Width =
s->input_width;
221 s->process_support.InputSample.Height =
s->input_height;
222 s->process_support.InputFrameRate.Numerator =
s->input_framerate.num;
223 s->process_support.InputFrameRate.Denominator =
s->input_framerate.den;
224 s->process_support.InputFieldType = D3D12_VIDEO_FIELD_TYPE_NONE;
225 s->process_support.InputStereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE;
227 s->process_support.OutputFormat.Format =
s->output_format;
228 s->process_support.OutputFormat.ColorSpace =
s->input_colorspace;
229 s->process_support.OutputFrameRate.Numerator =
s->input_framerate.num;
230 s->process_support.OutputFrameRate.Denominator =
s->input_framerate.den;
231 s->process_support.OutputStereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE;
233 hr = ID3D12VideoDevice_CheckFeatureSupport(
235 D3D12_FEATURE_VIDEO_PROCESS_SUPPORT,
237 sizeof(
s->process_support)
245 if (!(
s->process_support.SupportFlags & D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED)) {
250 D3D12_VIDEO_PROCESS_OUTPUT_STREAM_DESC processor_output_desc = {
251 .Format =
s->output_format,
252 .ColorSpace =
s->input_colorspace,
253 .AlphaFillMode = D3D12_VIDEO_PROCESS_ALPHA_FILL_MODE_OPAQUE,
254 .AlphaFillModeSourceStreamIndex = 0,
255 .BackgroundColor = { 0.0f, 0.0f, 0.0f, 1.0f },
256 .FrameRate = {
s->input_framerate.num,
s->input_framerate.den },
257 .EnableStereo = FALSE,
260 D3D12_VIDEO_PROCESS_INPUT_STREAM_DESC processor_input_desc = {
261 .Format =
s->input_format,
262 .ColorSpace =
s->input_colorspace,
263 .SourceAspectRatio = {
s->input_width,
s->input_height },
264 .DestinationAspectRatio = {
s->width,
s->height },
265 .FrameRate = {
s->input_framerate.num,
s->input_framerate.den },
266 .StereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE,
267 .FieldType = D3D12_VIDEO_FIELD_TYPE_NONE,
268 .DeinterlaceMode = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_NONE,
269 .EnableOrientation = FALSE,
270 .FilterFlags = D3D12_VIDEO_PROCESS_FILTER_FLAG_NONE,
272 .MaxWidth =
s->input_width,
273 .MaxHeight =
s->input_height,
274 .MinWidth =
s->input_width,
275 .MinHeight =
s->input_height
277 .DestinationSizeRange = {
278 .MaxWidth =
s->width,
279 .MaxHeight =
s->height,
280 .MinWidth =
s->width,
281 .MinHeight =
s->height
283 .EnableAlphaBlending = FALSE,
284 .LumaKey = { .Enable = FALSE, .Lower = 0.0f, .Upper = 1.0f },
286 .NumFutureFrames = 0,
287 .EnableAutoProcessing = FALSE,
291 if (!(
s->process_support.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_PIXEL_ASPECT_RATIO)) {
292 processor_input_desc.SourceAspectRatio.Numerator = 1;
293 processor_input_desc.SourceAspectRatio.Denominator = 1;
294 processor_input_desc.DestinationAspectRatio.Numerator = 1;
295 processor_input_desc.DestinationAspectRatio.Denominator = 1;
299 hr = ID3D12VideoDevice_CreateVideoProcessor(
302 &processor_output_desc,
304 &processor_input_desc,
305 &IID_ID3D12VideoProcessor,
306 (
void **)&
s->video_processor
314 hr = ID3D12Device_CreateCommandAllocator(
316 D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
317 &IID_ID3D12CommandAllocator,
318 (
void **)&
s->command_allocator
326 hr = ID3D12Device_CreateCommandList(
329 D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
330 s->command_allocator,
332 &IID_ID3D12VideoProcessCommandList,
333 (
void **)&
s->command_list
341 ID3D12VideoProcessCommandList_Close(
s->command_list);
343 hr = ID3D12Device_CreateFence(
s->device, 0, D3D12_FENCE_FLAG_NONE, &IID_ID3D12Fence, (
void **)&
s->fence);
350 s->fence_event = CreateEvent(
NULL, FALSE, FALSE,
NULL);
351 if (!
s->fence_event) {
382 if (!
s->hw_device_ctx) {
391 if (input_device_ctx->
type != filter_device_ctx->type) {
410 if (!
s->video_processor) {
413 s->input_width = input_frames_ctx->
width;
414 s->input_height = input_frames_ctx->
height;
417 s->input_format = input_hwctx->format;
419 if (
s->input_format == DXGI_FORMAT_UNKNOWN) {
422 s->input_format = DXGI_FORMAT_NV12;
425 s->input_format = DXGI_FORMAT_P010;
434 int is_10bit = (
s->input_format == DXGI_FORMAT_P010);
440 s->input_width,
s->input_height,
s->input_format,
s->input_colorspace,
441 s->input_framerate.num,
s->input_framerate.den);
459 ID3D12Resource *input_resource = input_frame->
texture;
460 ID3D12Resource *output_resource =
output_frame->texture;
462 if (!input_resource || !output_resource) {
470 UINT64 completed = ID3D12Fence_GetCompletedValue(input_frame->
sync_ctx.
fence);
471 if (completed < input_frame->sync_ctx.fence_value) {
481 hr = ID3D12CommandAllocator_Reset(
s->command_allocator);
488 hr = ID3D12VideoProcessCommandList_Reset(
s->command_list,
s->command_allocator);
495 D3D12_RESOURCE_BARRIER barriers[2] = {
497 .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
498 .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
500 .pResource = input_resource,
501 .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
502 .StateBefore = D3D12_RESOURCE_STATE_COMMON,
503 .StateAfter = D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ
507 .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
508 .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
510 .pResource = output_resource,
511 .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
512 .StateBefore = D3D12_RESOURCE_STATE_COMMON,
513 .StateAfter = D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE
518 ID3D12VideoProcessCommandList_ResourceBarrier(
s->command_list, 2, barriers);
520 D3D12_VIDEO_PROCESS_INPUT_STREAM_ARGUMENTS input_args = {0};
522 input_args.InputStream[0].pTexture2D = input_resource;
523 input_args.Transform.SourceRectangle.right =
s->input_width;
524 input_args.Transform.SourceRectangle.bottom =
s->input_height;
525 input_args.Transform.DestinationRectangle.right =
s->width;
526 input_args.Transform.DestinationRectangle.bottom =
s->height;
527 input_args.Transform.Orientation = D3D12_VIDEO_PROCESS_ORIENTATION_DEFAULT;
529 input_args.Flags = D3D12_VIDEO_PROCESS_INPUT_STREAM_FLAG_NONE;
531 input_args.RateInfo.OutputIndex = 0;
532 input_args.RateInfo.InputFrameOrField = 0;
534 memset(input_args.FilterLevels, 0,
sizeof(input_args.FilterLevels));
536 input_args.AlphaBlending.Enable = FALSE;
537 input_args.AlphaBlending.Alpha = 1.0f;
539 D3D12_VIDEO_PROCESS_OUTPUT_STREAM_ARGUMENTS output_args = {0};
541 output_args.OutputStream[0].pTexture2D = output_resource;
542 output_args.TargetRectangle.right =
s->width;
543 output_args.TargetRectangle.bottom =
s->height;
545 ID3D12VideoProcessCommandList_ProcessFrames(
553 for (
int i = 0;
i < 2;
i++) {
554 FFSWAP(D3D12_RESOURCE_STATES, barriers[
i].Transition.StateBefore, barriers[
i].Transition.StateAfter);
556 ID3D12VideoProcessCommandList_ResourceBarrier(
s->command_list, 2, barriers);
558 hr = ID3D12VideoProcessCommandList_Close(
s->command_list);
565 ID3D12CommandList *cmd_lists[] = { (ID3D12CommandList *)
s->command_list };
566 ID3D12CommandQueue_ExecuteCommandLists(
s->command_queue, 1, cmd_lists);
568 hr = ID3D12CommandQueue_Signal(
s->command_queue,
s->fence,
s->fence_value);
577 ID3D12Fence_AddRef(
s->fence);
587 out->width =
s->width;
588 out->height =
s->height;
624 outlink->
w =
s->width;
625 outlink->
h =
s->height;
632 if (!
s->hw_device_ctx) {
635 if (!
s->hw_device_ctx) {
644 s->device = d3d12_hwctx->device;
652 if (!
s->hw_frames_ctx_out)
660 frames_ctx->
sw_format = in_frames_ctx->sw_format;
661 s->format = in_frames_ctx->sw_format;
671 s->output_format = DXGI_FORMAT_NV12;
674 s->output_format = DXGI_FORMAT_P010;
683 frames_ctx->
width =
s->width;
684 frames_ctx->
height =
s->height;
688 if (
ctx->extra_hw_frames > 0)
697 frames_hwctx->
format =
s->output_format;
698 frames_hwctx->
resource_flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
699 frames_hwctx->
heap_flags = D3D12_HEAP_FLAG_NONE;
744 #define OFFSET(x) offsetof(ScaleD3D12Context, x)
745 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
757 .
p.
name =
"scale_d3d12",
760 .
p.priv_class = &scale_d3d12_class,