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;
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;
626 outlink->
w =
s->width;
627 outlink->
h =
s->height;
634 if (!
s->hw_device_ctx) {
637 if (!
s->hw_device_ctx) {
646 s->device = d3d12_hwctx->
device;
654 if (!
s->hw_frames_ctx_out)
673 s->output_format = DXGI_FORMAT_NV12;
676 s->output_format = DXGI_FORMAT_P010;
685 frames_ctx->
width =
s->width;
686 frames_ctx->
height =
s->height;
690 if (
ctx->extra_hw_frames > 0)
699 frames_hwctx->
format =
s->output_format;
700 frames_hwctx->
resource_flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
701 frames_hwctx->
heap_flags = D3D12_HEAP_FLAG_NONE;
714 inlink->
w, inlink->
h, outlink->
w, outlink->
h);
746#define OFFSET(x) offsetof(ScaleD3D12Context, x)
747#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
759 .p.name =
"scale_d3d12",
762 .p.priv_class = &scale_d3d12_class,
static const char *const format[]
const FFFilter ff_vf_scale_d3d12
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
#define i(width, name, range_min, range_max)
@ AV_OPT_TYPE_PIXEL_FMT
Underlying C type is enum AVPixelFormat.
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
#define AVFILTER_FLAG_HWDEVICE
The filter can create hardware frames using AVFilterContext.hw_device_ctx.
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
#define AVERROR_EXTERNAL
Generic error in an external library.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
An API-specific header for AV_HWDEVICE_TYPE_D3D12VA.
static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp)
#define FILTER_INPUTS(array)
#define FILTER_OUTPUTS(array)
#define FF_FILTER_FLAG_HWFRAME_AWARE
The filter is aware of hardware frames, and any hardware frame context should not be automatically pr...
static FilterLink * ff_filter_link(AVFilterLink *link)
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
#define AVFILTER_DEFINE_CLASS(fname)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
#define FFSWAP(type, a, b)
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
@ AV_PIX_FMT_D3D12
Hardware surfaces for Direct3D 12.
AVColorTransferCharacteristic
Color Transfer Characteristic.
@ AVCOL_TRC_SMPTE2084
SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems.
@ AVCOL_TRC_ARIB_STD_B67
ARIB STD-B67, known as "Hybrid log-gamma".
AVColorSpace
YUV colorspace type.
@ AVCOL_SPC_BT470BG
also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
@ AVCOL_SPC_BT2020_CL
ITU-R BT2020 constant luminance system.
@ AVCOL_SPC_BT2020_NCL
ITU-R BT2020 non-constant luminance system.
@ AVCOL_SPC_SMPTE170M
also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
int ff_scale_adjust_dimensions(AVFilterLink *inlink, int *ret_w, int *ret_h, int force_original_aspect_ratio, int force_divisible_by, double w_adj)
Transform evaluated width and height obtained from ff_scale_eval_dimensions into actual target width ...
int ff_scale_eval_dimensions(void *log_ctx, const char *w_expr, const char *h_expr, AVFilterLink *inlink, AVFilterLink *outlink, int *ret_w, int *ret_h)
Parse and evaluate string expressions for width and height.
A reference to a data buffer.
uint8_t * data
The data buffer.
Describe the class of an AVClass context structure.
This struct is allocated as AVHWDeviceContext.hwctx.
ID3D12Device * device
Device used for objects creation and access.
D3D12VA frame descriptor for pool allocation.
ID3D12Resource * texture
The texture in which the frame is located.
AVD3D12VASyncContext sync_ctx
The sync context for the texture.
This struct is allocated as AVHWFramesContext.hwctx.
D3D12_RESOURCE_FLAGS resource_flags
Options for working with resources.
D3D12_HEAP_FLAGS heap_flags
Options for working with heaps allocation when creating resources.
DXGI_FORMAT format
DXGI_FORMAT format.
ID3D12Fence * fence
D3D12 fence object.
uint64_t fence_value
The fence value used for sync.
A link between two filters.
int w
agreed upon image width
int h
agreed upon image height
AVFilterContext * src
source filter
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
AVFilterContext * dst
dest filter
A filter pad used for either input or output.
This structure describes decoded (raw) audio or video data.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
enum AVColorSpace colorspace
YUV colorspace type.
enum AVColorTransferCharacteristic color_trc
int64_t duration
Duration of the frame, in the same units as pts.
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
This struct describes a set or pool of "hardware" frames (i.e.
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
int initial_pool_size
Initial size of the frame pool.
int width
The allocated dimensions of the frames in this pool.
Rational number (pair of numerator and denominator).
Link properties exposed to filter code, but not external callers.
AVBufferRef * hw_frames_ctx
For hwaccel pixel formats, this should be a reference to the AVHWFramesContext describing the frames.
ID3D12VideoProcessor * video_processor
AVBufferRef * hw_device_ctx
ID3D12VideoDevice * video_device
DXGI_FORMAT output_format
enum AVPixelFormat format
ID3D12CommandAllocator * command_allocator
AVRational input_framerate
AVBufferRef * hw_frames_ctx_out
ID3D12VideoProcessCommandList * command_list
D3D12_FEATURE_DATA_VIDEO_PROCESS_SUPPORT process_support
ID3D12CommandQueue * command_queue
DXGI_COLOR_SPACE_TYPE input_colorspace
static AVFormatContext * ctx
static const AVFilterPad scale_d3d12_inputs[]
static int scale_d3d12_filter_frame(AVFilterLink *inlink, AVFrame *in)
static av_cold int scale_d3d12_init(AVFilterContext *ctx)
static AVRational get_input_framerate(AVFilterContext *ctx, AVFilterLink *inlink, AVFrame *in)
static av_cold void scale_d3d12_uninit(AVFilterContext *ctx)
static const AVFilterPad scale_d3d12_outputs[]
static int scale_d3d12_config_props(AVFilterLink *outlink)
static const AVOption scale_d3d12_options[]
static DXGI_COLOR_SPACE_TYPE get_dxgi_colorspace(enum AVColorSpace colorspace, enum AVColorTransferCharacteristic trc, int is_10bit)
static void release_d3d12_resources(ScaleD3D12Context *s)
static int scale_d3d12_configure_processor(ScaleD3D12Context *s, AVFilterContext *ctx)
#define WaitForSingleObject(a, b)