82 ID3D12CommandAllocator **ppAllocator)
87 if (
av_fifo_peek(
s->allocator_queue, &allocator, 1, 0) >= 0) {
88 UINT64 completed = ID3D12Fence_GetCompletedValue(
s->fence);
96 hr = ID3D12Device_CreateCommandAllocator(
s->device, D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
97 &IID_ID3D12CommandAllocator, (
void **)ppAllocator);
110 .command_allocator = pAllocator,
111 .fence_value = fence_value,
125 if (
s->command_queue &&
s->fence &&
s->fence_event) {
126 fence_value =
s->fence_value - 1;
127 hr = ID3D12CommandQueue_Signal(
s->command_queue,
s->fence, fence_value);
129 UINT64 completed = ID3D12Fence_GetCompletedValue(
s->fence);
130 if (completed < fence_value) {
131 hr = ID3D12Fence_SetEventOnCompletion(
s->fence, fence_value,
s->fence_event);
139 if (
s->fence_event) {
140 CloseHandle(
s->fence_event);
141 s->fence_event =
NULL;
145 ID3D12Fence_Release(
s->fence);
149 if (
s->command_list) {
150 ID3D12VideoProcessCommandList_Release(
s->command_list);
151 s->command_list =
NULL;
154 if (
s->allocator_queue) {
160 if (
s->video_processor) {
161 ID3D12VideoProcessor_Release(
s->video_processor);
162 s->video_processor =
NULL;
165 if (
s->video_device) {
166 ID3D12VideoDevice_Release(
s->video_device);
167 s->video_device =
NULL;
170 if (
s->command_queue) {
171 ID3D12CommandQueue_Release(
s->command_queue);
172 s->command_queue =
NULL;
183 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020;
185 return DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020;
187 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020;
190 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
195 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020;
197 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601;
199 return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
233 ID3D12CommandAllocator *command_allocator =
NULL;
235 if (
s->output_format == DXGI_FORMAT_UNKNOWN) {
242 s->device = d3d12_hwctx->
device;
245 s->input_width,
s->input_height,
s->width,
s->height);
247 hr = ID3D12Device_QueryInterface(
s->device, &IID_ID3D12VideoDevice, (
void **)&
s->video_device);
253 D3D12_COMMAND_QUEUE_DESC queue_desc = {
254 .Type = D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
255 .Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
256 .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
260 hr = ID3D12Device_CreateCommandQueue(
s->device, &queue_desc, &IID_ID3D12CommandQueue, (
void **)&
s->command_queue);
266 s->process_support.NodeIndex = 0;
268 s->process_support.InputSample.Format.Format =
s->input_format;
269 s->process_support.InputSample.Format.ColorSpace =
s->input_colorspace;
270 s->process_support.InputSample.Width =
s->input_width;
271 s->process_support.InputSample.Height =
s->input_height;
272 s->process_support.InputFrameRate.Numerator =
s->input_framerate.num;
273 s->process_support.InputFrameRate.Denominator =
s->input_framerate.den;
274 s->process_support.InputFieldType = D3D12_VIDEO_FIELD_TYPE_NONE;
275 s->process_support.InputStereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE;
277 s->process_support.OutputFormat.Format =
s->output_format;
278 s->process_support.OutputFormat.ColorSpace =
s->input_colorspace;
279 s->process_support.OutputFrameRate.Numerator =
s->input_framerate.num;
280 s->process_support.OutputFrameRate.Denominator =
s->input_framerate.den;
281 s->process_support.OutputStereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE;
283 hr = ID3D12VideoDevice_CheckFeatureSupport(
285 D3D12_FEATURE_VIDEO_PROCESS_SUPPORT,
287 sizeof(
s->process_support)
295 if (!(
s->process_support.SupportFlags & D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED)) {
300 D3D12_VIDEO_PROCESS_OUTPUT_STREAM_DESC processor_output_desc = {
301 .Format =
s->output_format,
302 .ColorSpace =
s->input_colorspace,
303 .AlphaFillMode = D3D12_VIDEO_PROCESS_ALPHA_FILL_MODE_OPAQUE,
304 .AlphaFillModeSourceStreamIndex = 0,
305 .BackgroundColor = { 0.0f, 0.0f, 0.0f, 1.0f },
306 .FrameRate = {
s->input_framerate.num,
s->input_framerate.den },
307 .EnableStereo = FALSE,
310 D3D12_VIDEO_PROCESS_INPUT_STREAM_DESC processor_input_desc = {
311 .Format =
s->input_format,
312 .ColorSpace =
s->input_colorspace,
313 .SourceAspectRatio = {
s->input_width,
s->input_height },
314 .DestinationAspectRatio = {
s->width,
s->height },
315 .FrameRate = {
s->input_framerate.num,
s->input_framerate.den },
316 .StereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE,
317 .FieldType = D3D12_VIDEO_FIELD_TYPE_NONE,
318 .DeinterlaceMode = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_NONE,
319 .EnableOrientation = FALSE,
320 .FilterFlags = D3D12_VIDEO_PROCESS_FILTER_FLAG_NONE,
322 .MaxWidth =
s->input_width,
323 .MaxHeight =
s->input_height,
324 .MinWidth =
s->input_width,
325 .MinHeight =
s->input_height
327 .DestinationSizeRange = {
328 .MaxWidth =
s->width,
329 .MaxHeight =
s->height,
330 .MinWidth =
s->width,
331 .MinHeight =
s->height
333 .EnableAlphaBlending = FALSE,
334 .LumaKey = { .Enable = FALSE, .Lower = 0.0f, .Upper = 1.0f },
336 .NumFutureFrames = 0,
337 .EnableAutoProcessing = FALSE,
341 if (!(
s->process_support.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_PIXEL_ASPECT_RATIO)) {
342 processor_input_desc.SourceAspectRatio.Numerator = 1;
343 processor_input_desc.SourceAspectRatio.Denominator = 1;
344 processor_input_desc.DestinationAspectRatio.Numerator = 1;
345 processor_input_desc.DestinationAspectRatio.Denominator = 1;
349 hr = ID3D12VideoDevice_CreateVideoProcessor(
352 &processor_output_desc,
354 &processor_input_desc,
355 &IID_ID3D12VideoProcessor,
356 (
void **)&
s->video_processor
364 hr = ID3D12Device_CreateFence(
s->device, 0, D3D12_FENCE_FLAG_NONE, &IID_ID3D12Fence, (
void **)&
s->fence);
371 s->fence_event = CreateEvent(
NULL, FALSE, FALSE,
NULL);
372 if (!
s->fence_event) {
378 if (!
s->allocator_queue)
385 hr = ID3D12Device_CreateCommandList(
388 D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
391 &IID_ID3D12VideoProcessCommandList,
392 (
void **)&
s->command_list
397 ID3D12CommandAllocator_Release(command_allocator);
401 ID3D12VideoProcessCommandList_Close(
s->command_list);
419 ID3D12CommandAllocator *command_allocator =
NULL;
434 if (!
s->hw_device_ctx) {
443 if (input_device_ctx->
type != filter_device_ctx->
type) {
462 if (!
s->video_processor) {
465 s->input_width = input_frames_ctx->
width;
466 s->input_height = input_frames_ctx->
height;
469 s->input_format = input_hwctx->
format;
471 if (
s->input_format == DXGI_FORMAT_UNKNOWN) {
474 s->input_format = DXGI_FORMAT_NV12;
477 s->input_format = DXGI_FORMAT_P010;
486 int is_10bit = (
s->input_format == DXGI_FORMAT_P010);
492 s->input_width,
s->input_height,
s->input_format,
s->input_colorspace,
493 s->input_framerate.num,
s->input_framerate.den);
511 ID3D12Resource *input_resource = input_frame->
texture;
512 ID3D12Resource *output_resource =
output_frame->texture;
514 if (!input_resource || !output_resource) {
522 UINT64 completed = ID3D12Fence_GetCompletedValue(input_frame->
sync_ctx.
fence);
523 if (completed < input_frame->sync_ctx.fence_value) {
537 hr = ID3D12CommandAllocator_Reset(command_allocator);
544 hr = ID3D12VideoProcessCommandList_Reset(
s->command_list, command_allocator);
551 D3D12_RESOURCE_BARRIER barriers[2] = {
553 .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
554 .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
556 .pResource = input_resource,
557 .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
558 .StateBefore = D3D12_RESOURCE_STATE_COMMON,
559 .StateAfter = D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ
563 .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
564 .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
566 .pResource = output_resource,
567 .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
568 .StateBefore = D3D12_RESOURCE_STATE_COMMON,
569 .StateAfter = D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE
574 ID3D12VideoProcessCommandList_ResourceBarrier(
s->command_list, 2, barriers);
576 D3D12_VIDEO_PROCESS_INPUT_STREAM_ARGUMENTS input_args = {0};
578 input_args.InputStream[0].pTexture2D = input_resource;
579 input_args.Transform.SourceRectangle.right =
s->input_width;
580 input_args.Transform.SourceRectangle.bottom =
s->input_height;
581 input_args.Transform.DestinationRectangle.right =
s->width;
582 input_args.Transform.DestinationRectangle.bottom =
s->height;
583 input_args.Transform.Orientation = D3D12_VIDEO_PROCESS_ORIENTATION_DEFAULT;
585 input_args.Flags = D3D12_VIDEO_PROCESS_INPUT_STREAM_FLAG_NONE;
587 input_args.RateInfo.OutputIndex = 0;
588 input_args.RateInfo.InputFrameOrField = 0;
590 memset(input_args.FilterLevels, 0,
sizeof(input_args.FilterLevels));
592 input_args.AlphaBlending.Enable = FALSE;
593 input_args.AlphaBlending.Alpha = 1.0f;
595 D3D12_VIDEO_PROCESS_OUTPUT_STREAM_ARGUMENTS output_args = {0};
597 output_args.OutputStream[0].pTexture2D = output_resource;
598 output_args.TargetRectangle.right =
s->width;
599 output_args.TargetRectangle.bottom =
s->height;
601 ID3D12VideoProcessCommandList_ProcessFrames(
609 for (
int i = 0;
i < 2;
i++) {
610 FFSWAP(D3D12_RESOURCE_STATES, barriers[
i].Transition.StateBefore, barriers[
i].Transition.StateAfter);
612 ID3D12VideoProcessCommandList_ResourceBarrier(
s->command_list, 2, barriers);
614 hr = ID3D12VideoProcessCommandList_Close(
s->command_list);
621 ID3D12CommandList *cmd_lists[] = { (ID3D12CommandList *)
s->command_list };
622 ID3D12CommandQueue_ExecuteCommandLists(
s->command_queue, 1, cmd_lists);
624 hr = ID3D12CommandQueue_Signal(
s->command_queue,
s->fence,
s->fence_value);
633 ID3D12Fence_AddRef(
s->fence);
636 command_allocator =
NULL;
648 out->width =
s->width;
649 out->height =
s->height;
657 if (command_allocator)
689 outlink->
w =
s->width;
690 outlink->
h =
s->height;
697 if (!
s->hw_device_ctx) {
700 if (!
s->hw_device_ctx) {
709 s->device = d3d12_hwctx->
device;
717 if (!
s->hw_frames_ctx_out)
736 s->output_format = DXGI_FORMAT_NV12;
739 s->output_format = DXGI_FORMAT_P010;
748 frames_ctx->
width =
s->width;
749 frames_ctx->
height =
s->height;
753 if (
ctx->extra_hw_frames > 0)
762 frames_hwctx->
format =
s->output_format;
763 frames_hwctx->
resource_flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
764 frames_hwctx->
heap_flags = D3D12_HEAP_FLAG_NONE;
777 inlink->
w, inlink->
h, outlink->
w, outlink->
h);
809#define OFFSET(x) offsetof(ScaleD3D12Context, x)
810#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
822 .p.name =
"scale_d3d12",
825 .p.priv_class = &scale_d3d12_class,
static const char *const format[]
const FFFilter ff_vf_scale_d3d12
static AVFormatContext * ctx
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.
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
int av_fifo_peek(const AVFifo *f, void *buf, size_t nb_elems, size_t offset)
Read data from a FIFO without modifying FIFO state.
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
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).
ID3D12CommandAllocator * command_allocator
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
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 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 int scale_d3d12_get_valid_command_allocator(ScaleD3D12Context *s, AVFilterContext *ctx, ID3D12CommandAllocator **ppAllocator)
static DXGI_COLOR_SPACE_TYPE get_dxgi_colorspace(enum AVColorSpace colorspace, enum AVColorTransferCharacteristic trc, int is_10bit)
static int scale_d3d12_discard_command_allocator(ScaleD3D12Context *s, ID3D12CommandAllocator *pAllocator, UINT64 fence_value)
static void release_d3d12_resources(ScaleD3D12Context *s)
static int scale_d3d12_configure_processor(ScaleD3D12Context *s, AVFilterContext *ctx)
#define WaitForSingleObject(a, b)