2 * Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
19 * NOTE: some of implementations are copied/modified from Chromium code
21 * Copyright 2015 The Chromium Authors. All rights reserved.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions are
27 * * Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
29 * * Redistributions in binary form must reproduce the above
30 * copyright notice, this list of conditions and the following disclaimer
31 * in the documentation and/or other materials provided with the
33 * * Neither the name of Google Inc. nor the names of its
34 * contributors may be used to endorse or promote products derived from
35 * this software without specific prior written permission.
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
38 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
40 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
41 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 #include "gstd3d11decoder.h"
55 #include "gstd3d11converter.h"
56 #include "gstd3d11pluginutils.h"
64 GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_decoder_debug);
65 #define GST_CAT_DEFAULT gst_d3d11_decoder_debug
67 /* GUID might not be defined in MinGW header */
68 DEFINE_GUID (GST_GUID_D3D11_DECODER_PROFILE_H264_IDCT_FGT, 0x1b81be67, 0xa0c7,
69 0x11d3, 0xb9, 0x84, 0x00, 0xc0, 0x4f, 0x2e, 0x73, 0xc5);
70 DEFINE_GUID (GST_GUID_D3D11_DECODER_PROFILE_H264_VLD_NOFGT, 0x1b81be68, 0xa0c7,
71 0x11d3, 0xb9, 0x84, 0x00, 0xc0, 0x4f, 0x2e, 0x73, 0xc5);
72 DEFINE_GUID (GST_GUID_D3D11_DECODER_PROFILE_H264_VLD_FGT, 0x1b81be69, 0xa0c7,
73 0x11d3, 0xb9, 0x84, 0x00, 0xc0, 0x4f, 0x2e, 0x73, 0xc5);
74 DEFINE_GUID (GST_GUID_D3D11_DECODER_PROFILE_HEVC_VLD_MAIN,
75 0x5b11d51b, 0x2f4c, 0x4452, 0xbc, 0xc3, 0x09, 0xf2, 0xa1, 0x16, 0x0c, 0xc0);
76 DEFINE_GUID (GST_GUID_D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10,
77 0x107af0e0, 0xef1a, 0x4d19, 0xab, 0xa8, 0x67, 0xa1, 0x63, 0x07, 0x3d, 0x13);
78 DEFINE_GUID (GST_GUID_D3D11_DECODER_PROFILE_VP8_VLD,
79 0x90b899ea, 0x3a62, 0x4705, 0x88, 0xb3, 0x8d, 0xf0, 0x4b, 0x27, 0x44, 0xe7);
80 DEFINE_GUID (GST_GUID_D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0,
81 0x463707f8, 0xa1d0, 0x4585, 0x87, 0x6d, 0x83, 0xaa, 0x6d, 0x60, 0xb8, 0x9e);
82 DEFINE_GUID (GST_GUID_D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2,
83 0xa4c749ef, 0x6ecf, 0x48aa, 0x84, 0x48, 0x50, 0xa7, 0xa1, 0x16, 0x5f, 0xf7);
84 DEFINE_GUID (GST_GUID_D3D11_DECODER_PROFILE_MPEG2_VLD, 0xee27417f, 0x5e28,
85 0x4e65, 0xbe, 0xea, 0x1d, 0x26, 0xb5, 0x08, 0xad, 0xc9);
86 DEFINE_GUID (GST_GUID_D3D11_DECODER_PROFILE_MPEG2and1_VLD, 0x86695f12, 0x340e,
87 0x4f04, 0x9f, 0xd3, 0x92, 0x53, 0xdd, 0x32, 0x74, 0x60);
88 DEFINE_GUID (GST_GUID_D3D11_DECODER_PROFILE_AV1_VLD_PROFILE0, 0xb8be4ccb,
89 0xcf53, 0x46ba, 0x8d, 0x59, 0xd6, 0xb8, 0xa6, 0xda, 0x5d, 0x2a);
91 static const GUID *profile_h264_list[] = {
92 &GST_GUID_D3D11_DECODER_PROFILE_H264_IDCT_FGT,
93 &GST_GUID_D3D11_DECODER_PROFILE_H264_VLD_NOFGT,
94 &GST_GUID_D3D11_DECODER_PROFILE_H264_VLD_FGT,
97 static const GUID *profile_hevc_list[] = {
98 &GST_GUID_D3D11_DECODER_PROFILE_HEVC_VLD_MAIN,
101 static const GUID *profile_hevc_10_list[] = {
102 &GST_GUID_D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10,
105 static const GUID *profile_vp8_list[] = {
106 &GST_GUID_D3D11_DECODER_PROFILE_VP8_VLD,
109 static const GUID *profile_vp9_list[] = {
110 &GST_GUID_D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0,
113 static const GUID *profile_vp9_10_list[] = {
114 &GST_GUID_D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2,
117 static const GUID *profile_mpeg2_list[] = {
118 &GST_GUID_D3D11_DECODER_PROFILE_MPEG2_VLD,
119 &GST_GUID_D3D11_DECODER_PROFILE_MPEG2and1_VLD
122 static const GUID *profile_av1_list[] = {
123 &GST_GUID_D3D11_DECODER_PROFILE_AV1_VLD_PROFILE0,
124 /* TODO: add more profile */
133 struct _GstD3D11Decoder
140 GstD3D11Device *device;
142 ID3D11VideoDevice *video_device;
143 ID3D11VideoContext *video_context;
145 ID3D11VideoDecoder *decoder_handle;
148 GstVideoInfo output_info;
152 DXGI_FORMAT decoder_format;
153 gboolean downstream_supports_d3d11;
155 GstVideoCodecState *input_state;
156 GstVideoCodecState *output_state;
158 /* Protect internal pool */
159 GMutex internal_pool_lock;
161 GstBufferPool *internal_pool;
162 /* Internal pool params */
165 gboolean use_array_of_texture;
167 guint downstream_min_buffers;
168 gboolean wait_on_pool_full;
170 /* Used for array-of-texture */
174 ID3D11Texture2D *staging;
175 gsize staging_texture_offset[GST_VIDEO_MAX_PLANES];
176 gint stating_texture_stride[GST_VIDEO_MAX_PLANES];
178 GUID decoder_profile;
180 /* For device specific workaround */
181 gboolean can_direct_rendering;
183 /* For high precision clock */
184 guint timer_resolution;
187 static void gst_d3d11_decoder_constructed (GObject * object);
188 static void gst_d3d11_decoder_set_property (GObject * object, guint prop_id,
189 const GValue * value, GParamSpec * pspec);
190 static void gst_d3d11_decoder_get_property (GObject * object, guint prop_id,
191 GValue * value, GParamSpec * pspec);
192 static void gst_d3d11_decoder_dispose (GObject * obj);
193 static void gst_d3d11_decoder_finalize (GObject * obj);
194 static gboolean gst_d3d11_decoder_can_direct_render (GstD3D11Decoder * decoder,
195 GstVideoDecoder * videodec, GstBuffer * view_buffer,
196 gint display_width, gint display_height);
198 #define parent_class gst_d3d11_decoder_parent_class
199 G_DEFINE_TYPE (GstD3D11Decoder, gst_d3d11_decoder, GST_TYPE_OBJECT);
202 gst_d3d11_decoder_class_init (GstD3D11DecoderClass * klass)
204 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
206 gobject_class->constructed = gst_d3d11_decoder_constructed;
207 gobject_class->set_property = gst_d3d11_decoder_set_property;
208 gobject_class->get_property = gst_d3d11_decoder_get_property;
209 gobject_class->dispose = gst_d3d11_decoder_dispose;
210 gobject_class->finalize = gst_d3d11_decoder_finalize;
212 g_object_class_install_property (gobject_class, PROP_DEVICE,
213 g_param_spec_object ("device", "Device",
214 "D3D11 Devicd to use", GST_TYPE_D3D11_DEVICE,
215 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
216 G_PARAM_STATIC_STRINGS)));
220 gst_d3d11_decoder_init (GstD3D11Decoder * self)
222 g_mutex_init (&self->internal_pool_lock);
226 gst_d3d11_decoder_constructed (GObject * object)
228 GstD3D11Decoder *self = GST_D3D11_DECODER (object);
229 ID3D11VideoDevice *video_device;
230 ID3D11VideoContext *video_context;
233 GST_ERROR_OBJECT (self, "No D3D11Device available");
237 video_device = gst_d3d11_device_get_video_device_handle (self->device);
239 GST_WARNING_OBJECT (self, "ID3D11VideoDevice is not available");
243 video_context = gst_d3d11_device_get_video_context_handle (self->device);
244 if (!video_context) {
245 GST_WARNING_OBJECT (self, "ID3D11VideoContext is not available");
249 self->video_device = video_device;
250 video_device->AddRef ();
252 self->video_context = video_context;
253 video_context->AddRef ();
259 gst_d3d11_decoder_set_property (GObject * object, guint prop_id,
260 const GValue * value, GParamSpec * pspec)
262 GstD3D11Decoder *self = GST_D3D11_DECODER (object);
266 self->device = (GstD3D11Device *) g_value_dup_object (value);
269 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
275 gst_d3d11_decoder_get_property (GObject * object, guint prop_id,
276 GValue * value, GParamSpec * pspec)
278 GstD3D11Decoder *self = GST_D3D11_DECODER (object);
282 g_value_set_object (value, self->device);
285 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
291 gst_d3d11_decoder_clear_resource (GstD3D11Decoder * self)
293 g_mutex_lock (&self->internal_pool_lock);
294 if (self->internal_pool) {
295 gst_buffer_pool_set_active (self->internal_pool, FALSE);
296 gst_clear_object (&self->internal_pool);
298 g_mutex_unlock (&self->internal_pool_lock);
300 GST_D3D11_CLEAR_COM (self->decoder_handle);
301 GST_D3D11_CLEAR_COM (self->staging);
303 memset (self->staging_texture_offset,
304 0, sizeof (self->staging_texture_offset));
305 memset (self->stating_texture_stride,
306 0, sizeof (self->stating_texture_stride));
310 gst_d3d11_decoder_reset (GstD3D11Decoder * self)
312 gst_d3d11_decoder_clear_resource (self);
315 self->downstream_min_buffers = 0;
317 self->configured = FALSE;
318 self->opened = FALSE;
320 self->use_array_of_texture = FALSE;
321 self->downstream_supports_d3d11 = FALSE;
323 g_clear_pointer (&self->output_state, gst_video_codec_state_unref);
324 g_clear_pointer (&self->input_state, gst_video_codec_state_unref);
328 gst_d3d11_decoder_dispose (GObject * obj)
330 GstD3D11Decoder *self = GST_D3D11_DECODER (obj);
332 gst_d3d11_decoder_reset (self);
334 GST_D3D11_CLEAR_COM (self->video_device);
335 GST_D3D11_CLEAR_COM (self->video_context);
337 gst_clear_object (&self->device);
339 G_OBJECT_CLASS (parent_class)->dispose (obj);
343 gst_d3d11_decoder_finalize (GObject * obj)
345 GstD3D11Decoder *self = GST_D3D11_DECODER (obj);
348 /* Restore clock precision */
349 if (self->timer_resolution)
350 timeEndPeriod (self->timer_resolution);
353 g_mutex_clear (&self->internal_pool_lock);
355 G_OBJECT_CLASS (parent_class)->finalize (obj);
359 gst_d3d11_decoder_new (GstD3D11Device * device, GstDXVACodec codec)
361 GstD3D11Decoder *self;
363 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), nullptr);
364 g_return_val_if_fail (codec > GST_DXVA_CODEC_NONE, nullptr);
365 g_return_val_if_fail (codec < GST_DXVA_CODEC_LAST, nullptr);
367 self = (GstD3D11Decoder *)
368 g_object_new (GST_TYPE_D3D11_DECODER, "device", device, NULL);
370 if (!self->video_device || !self->video_context) {
371 gst_object_unref (self);
377 gst_object_ref_sink (self);
383 gst_d3d11_decoder_is_configured (GstD3D11Decoder * decoder)
385 g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
387 return decoder->configured;
391 gst_d3d11_decoder_view_id_quark (void)
393 static gsize id_quark = 0;
395 if (g_once_init_enter (&id_quark)) {
396 GQuark quark = g_quark_from_string ("GstD3D11DecoderViewId");
397 g_once_init_leave (&id_quark, quark);
400 return (GQuark) id_quark;
404 gst_d3d11_decoder_ensure_output_view (GstD3D11Decoder * self,
410 mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0);
411 if (!gst_d3d11_memory_get_decoder_output_view (mem, self->video_device,
412 &self->decoder_profile)) {
413 GST_ERROR_OBJECT (self, "Decoder output view is unavailable");
417 if (!self->use_array_of_texture)
420 val = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
421 gst_d3d11_decoder_view_id_quark ());
423 g_assert (self->next_view_id < 128);
424 g_assert (self->next_view_id > 0);
426 gst_mini_object_set_qdata (GST_MINI_OBJECT (mem),
427 gst_d3d11_decoder_view_id_quark (),
428 GUINT_TO_POINTER (self->next_view_id), NULL);
430 self->next_view_id++;
431 /* valid view range is [0, 126], but 0 is not used to here
432 * (it's NULL as well) */
433 self->next_view_id %= 128;
434 if (self->next_view_id == 0)
435 self->next_view_id = 1;
443 gst_d3d11_decoder_prepare_output_view_pool (GstD3D11Decoder * self)
445 GstD3D11AllocationParams *alloc_params = NULL;
446 GstBufferPool *pool = NULL;
447 GstCaps *caps = NULL;
448 GstVideoAlignment align;
449 GstD3D11AllocationFlags alloc_flags = (GstD3D11AllocationFlags) 0;
450 gint bind_flags = D3D11_BIND_DECODER;
451 GstVideoInfo *info = &self->info;
454 g_mutex_lock (&self->internal_pool_lock);
455 if (self->internal_pool) {
456 gst_buffer_pool_set_active (self->internal_pool, FALSE);
457 gst_clear_object (&self->internal_pool);
459 g_mutex_unlock (&self->internal_pool_lock);
461 if (!self->use_array_of_texture) {
462 alloc_flags = GST_D3D11_ALLOCATION_FLAG_TEXTURE_ARRAY;
464 /* array of texture can have shader resource view */
465 bind_flags |= D3D11_BIND_SHADER_RESOURCE;
468 alloc_params = gst_d3d11_allocation_params_new (self->device, info,
469 alloc_flags, bind_flags);
472 GST_ERROR_OBJECT (self, "Failed to create allocation param");
476 pool_size = self->dpb_size + self->downstream_min_buffers;
477 GST_DEBUG_OBJECT (self,
478 "Configuring internal pool with size %d "
479 "(dpb size: %d, downstream min buffers: %d)", pool_size, self->dpb_size,
480 self->downstream_min_buffers);
482 if (!self->use_array_of_texture) {
483 alloc_params->desc[0].ArraySize = pool_size;
485 /* Valid view id is [0, 126], but we will use [1, 127] range so that
486 * it can be used by qdata, because zero is equal to null */
487 self->next_view_id = 1;
489 /* our pool size can be increased as much as possbile */
493 gst_video_alignment_reset (&align);
495 align.padding_right = self->aligned_width - GST_VIDEO_INFO_WIDTH (info);
496 align.padding_bottom = self->aligned_height - GST_VIDEO_INFO_HEIGHT (info);
497 if (!gst_d3d11_allocation_params_alignment (alloc_params, &align)) {
498 GST_ERROR_OBJECT (self, "Cannot set alignment");
502 caps = gst_video_info_to_caps (info);
504 GST_ERROR_OBJECT (self, "Couldn't convert video info to caps");
508 pool = gst_d3d11_buffer_pool_new_with_options (self->device,
509 caps, alloc_params, 0, pool_size);
510 gst_clear_caps (&caps);
511 g_clear_pointer (&alloc_params, gst_d3d11_allocation_params_free);
514 GST_ERROR_OBJECT (self, "Failed to create buffer pool");
518 if (!gst_buffer_pool_set_active (pool, TRUE)) {
519 GST_ERROR_OBJECT (self, "Couldn't activate pool");
523 g_mutex_lock (&self->internal_pool_lock);
524 self->internal_pool = pool;
525 g_mutex_unlock (&self->internal_pool_lock);
531 gst_d3d11_allocation_params_free (alloc_params);
533 gst_object_unref (pool);
535 gst_caps_unref (caps);
541 gst_dxva_codec_to_string (GstDXVACodec codec)
544 case GST_DXVA_CODEC_NONE:
546 case GST_DXVA_CODEC_H264:
548 case GST_DXVA_CODEC_VP9:
550 case GST_DXVA_CODEC_H265:
552 case GST_DXVA_CODEC_VP8:
554 case GST_DXVA_CODEC_MPEG2:
556 case GST_DXVA_CODEC_AV1:
559 g_assert_not_reached ();
567 gst_d3d11_decoder_get_supported_decoder_profile (GstD3D11Device * device,
568 GstDXVACodec codec, GstVideoFormat format, const GUID ** selected_profile)
570 GUID *guid_list = nullptr;
571 const GUID *profile = nullptr;
572 guint available_profile_count;
575 ID3D11VideoDevice *video_device;
576 const GUID **profile_list = nullptr;
577 guint profile_size = 0;
579 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE);
580 g_return_val_if_fail (selected_profile != nullptr, FALSE);
582 video_device = gst_d3d11_device_get_video_device_handle (device);
587 case GST_DXVA_CODEC_H264:
588 if (format == GST_VIDEO_FORMAT_NV12) {
589 profile_list = profile_h264_list;
590 profile_size = G_N_ELEMENTS (profile_h264_list);
593 case GST_DXVA_CODEC_H265:
594 if (format == GST_VIDEO_FORMAT_NV12) {
595 profile_list = profile_hevc_list;
596 profile_size = G_N_ELEMENTS (profile_hevc_list);
597 } else if (format == GST_VIDEO_FORMAT_P010_10LE) {
598 profile_list = profile_hevc_10_list;
599 profile_size = G_N_ELEMENTS (profile_hevc_10_list);
602 case GST_DXVA_CODEC_VP8:
603 if (format == GST_VIDEO_FORMAT_NV12) {
604 profile_list = profile_vp8_list;
605 profile_size = G_N_ELEMENTS (profile_vp8_list);
608 case GST_DXVA_CODEC_VP9:
609 if (format == GST_VIDEO_FORMAT_NV12) {
610 profile_list = profile_vp9_list;
611 profile_size = G_N_ELEMENTS (profile_vp9_list);
612 } else if (format == GST_VIDEO_FORMAT_P010_10LE) {
613 profile_list = profile_vp9_10_list;
614 profile_size = G_N_ELEMENTS (profile_vp9_10_list);
617 case GST_DXVA_CODEC_MPEG2:
618 if (format == GST_VIDEO_FORMAT_NV12) {
619 profile_list = profile_mpeg2_list;
620 profile_size = G_N_ELEMENTS (profile_mpeg2_list);
623 case GST_DXVA_CODEC_AV1:
624 profile_list = profile_av1_list;
625 profile_size = G_N_ELEMENTS (profile_av1_list);
632 GST_ERROR_OBJECT (device,
633 "Not supported codec (%d) and format (%s) configuration", codec,
634 gst_video_format_to_string (format));
638 available_profile_count = video_device->GetVideoDecoderProfileCount ();
640 if (available_profile_count == 0) {
641 GST_INFO_OBJECT (device, "No available decoder profile");
645 GST_DEBUG_OBJECT (device,
646 "Have %u available decoder profiles", available_profile_count);
647 guid_list = (GUID *) g_alloca (sizeof (GUID) * available_profile_count);
649 for (i = 0; i < available_profile_count; i++) {
650 hr = video_device->GetVideoDecoderProfile (i, &guid_list[i]);
651 if (!gst_d3d11_result (hr, device)) {
652 GST_WARNING_OBJECT (device, "Failed to get %d th decoder profile", i);
657 #ifndef GST_DISABLE_GST_DEBUG
658 GST_LOG_OBJECT (device, "Supported decoder GUID");
659 for (i = 0; i < available_profile_count; i++) {
660 const GUID *guid = &guid_list[i];
662 GST_LOG_OBJECT (device,
663 "\t { %8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x }",
664 (guint) guid->Data1, (guint) guid->Data2, (guint) guid->Data3,
665 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
666 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
669 GST_LOG_OBJECT (device, "Requested decoder GUID");
670 for (i = 0; i < profile_size; i++) {
671 const GUID *guid = profile_list[i];
673 GST_LOG_OBJECT (device,
674 "\t { %8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x }",
675 (guint) guid->Data1, (guint) guid->Data2, (guint) guid->Data3,
676 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
677 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
681 for (i = 0; i < profile_size; i++) {
682 for (j = 0; j < available_profile_count; j++) {
683 if (IsEqualGUID (*profile_list[i], guid_list[j])) {
684 profile = profile_list[i];
691 GST_INFO_OBJECT (device, "No supported decoder profile for %s codec",
692 gst_dxva_codec_to_string (codec));
696 *selected_profile = profile;
698 GST_DEBUG_OBJECT (device,
700 "{ %8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x }",
701 (guint) profile->Data1, (guint) profile->Data2, (guint) profile->Data3,
702 profile->Data4[0], profile->Data4[1], profile->Data4[2],
703 profile->Data4[3], profile->Data4[4], profile->Data4[5],
704 profile->Data4[6], profile->Data4[7]);
711 gst_d3d11_decoder_configure (GstD3D11Decoder * decoder,
712 GstVideoCodecState * input_state, GstVideoInfo * info, gint coded_width,
713 gint coded_height, guint dpb_size)
715 GstD3D11Format d3d11_format;
717 g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
718 g_return_val_if_fail (info != NULL, FALSE);
719 g_return_val_if_fail (input_state != NULL, FALSE);
720 g_return_val_if_fail (coded_width >= GST_VIDEO_INFO_WIDTH (info), FALSE);
721 g_return_val_if_fail (coded_height >= GST_VIDEO_INFO_HEIGHT (info), FALSE);
722 g_return_val_if_fail (dpb_size > 0, FALSE);
724 gst_d3d11_decoder_reset (decoder);
726 if (!gst_d3d11_device_get_format (decoder->device,
727 GST_VIDEO_INFO_FORMAT (info), &d3d11_format) ||
728 d3d11_format.dxgi_format == DXGI_FORMAT_UNKNOWN) {
729 GST_ERROR_OBJECT (decoder, "Could not determine dxgi format from %s",
730 gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (info)));
734 decoder->input_state = gst_video_codec_state_ref (input_state);
735 decoder->info = decoder->output_info = *info;
736 decoder->coded_width = coded_width;
737 decoder->coded_height = coded_height;
738 decoder->dpb_size = dpb_size;
739 decoder->decoder_format = d3d11_format.dxgi_format;
741 decoder->configured = TRUE;
747 gst_d3d11_decoder_ensure_staging_texture (GstD3D11Decoder * self)
749 ID3D11Device *device_handle;
750 D3D11_TEXTURE2D_DESC desc = { 0, };
756 device_handle = gst_d3d11_device_get_device_handle (self->device);
758 /* create stage texture to copy out */
759 desc.Width = self->aligned_width;
760 desc.Height = self->aligned_height;
762 desc.Format = self->decoder_format;
763 desc.SampleDesc.Count = 1;
765 desc.Usage = D3D11_USAGE_STAGING;
766 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
768 hr = device_handle->CreateTexture2D (&desc, NULL, &self->staging);
769 if (!gst_d3d11_result (hr, self->device)) {
770 GST_ERROR_OBJECT (self, "Couldn't create staging texture");
778 gst_d3d11_decoder_enable_high_precision_timer (GstD3D11Decoder * self)
781 GstD3D11DeviceVendor vendor;
783 if (self->timer_resolution)
786 vendor = gst_d3d11_get_device_vendor (self->device);
787 /* Do this only for NVIDIA at the moment, other vendors doesn't seem to be
788 * requiring retry for BeginFrame() */
789 if (vendor == GST_D3D11_DEVICE_VENDOR_NVIDIA) {
791 if (timeGetDevCaps (&time_caps, sizeof (TIMECAPS)) == TIMERR_NOERROR) {
795 resolution = MIN (MAX (time_caps.wPeriodMin, 1), time_caps.wPeriodMax);
797 ret = timeBeginPeriod (resolution);
798 if (ret == TIMERR_NOERROR) {
799 self->timer_resolution = resolution;
800 GST_INFO_OBJECT (self, "Updated timer resolution to %d", resolution);
808 gst_d3d11_decoder_open (GstD3D11Decoder * self)
811 BOOL can_support = FALSE;
813 D3D11_VIDEO_DECODER_CONFIG *config_list;
814 D3D11_VIDEO_DECODER_CONFIG *best_config = NULL;
815 D3D11_VIDEO_DECODER_DESC decoder_desc = { 0, };
816 const GUID *selected_profile = NULL;
818 gint aligned_width, aligned_height;
820 GstD3D11DeviceVendor vendor;
821 ID3D11VideoDevice *video_device;
822 GstVideoInfo *info = &self->info;
827 if (!self->configured) {
828 GST_ERROR_OBJECT (self, "Should configure first");
832 video_device = self->video_device;
834 gst_d3d11_device_lock (self->device);
835 if (!gst_d3d11_decoder_get_supported_decoder_profile (self->device,
836 self->codec, GST_VIDEO_INFO_FORMAT (info), &selected_profile)) {
840 hr = video_device->CheckVideoDecoderFormat (selected_profile,
841 self->decoder_format, &can_support);
842 if (!gst_d3d11_result (hr, self->device) || !can_support) {
843 GST_ERROR_OBJECT (self,
844 "VideoDevice could not support dxgi format %d, hr: 0x%x",
845 self->decoder_format, (guint) hr);
849 gst_d3d11_decoder_clear_resource (self);
850 self->can_direct_rendering = TRUE;
852 vendor = gst_d3d11_get_device_vendor (self->device);
854 case GST_D3D11_DEVICE_VENDOR_XBOX:
855 /* FIXME: Need to figure out Xbox device's behavior
856 * https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/1312
858 self->can_direct_rendering = FALSE;
864 /* NOTE: other dxva implementations (ffmpeg and vlc) do this
865 * and they say the required alignment were mentioned by dxva spec.
866 * See ff_dxva2_common_frame_params() in dxva.c of ffmpeg and
867 * directx_va_Setup() in directx_va.c of vlc.
868 * But... where it is? */
869 switch (self->codec) {
870 case GST_DXVA_CODEC_H265:
871 case GST_DXVA_CODEC_AV1:
872 /* See directx_va_Setup() impl. in vlc */
873 if (vendor != GST_D3D11_DEVICE_VENDOR_XBOX)
878 case GST_DXVA_CODEC_MPEG2:
879 /* XXX: ffmpeg does this */
887 aligned_width = GST_ROUND_UP_N (self->coded_width, alignment);
888 aligned_height = GST_ROUND_UP_N (self->coded_height, alignment);
889 if (aligned_width != self->coded_width ||
890 aligned_height != self->coded_height) {
891 GST_DEBUG_OBJECT (self,
892 "coded resolution %dx%d is not aligned to %d, adjust to %dx%d",
893 self->coded_width, self->coded_height, alignment, aligned_width,
897 self->aligned_width = aligned_width;
898 self->aligned_height = aligned_height;
900 decoder_desc.SampleWidth = aligned_width;
901 decoder_desc.SampleHeight = aligned_height;
902 decoder_desc.OutputFormat = self->decoder_format;
903 decoder_desc.Guid = *selected_profile;
905 hr = video_device->GetVideoDecoderConfigCount (&decoder_desc, &config_count);
906 if (!gst_d3d11_result (hr, self->device) || config_count == 0) {
907 GST_ERROR_OBJECT (self, "Could not get decoder config count, hr: 0x%x",
912 GST_DEBUG_OBJECT (self, "Total %d config available", config_count);
914 config_list = (D3D11_VIDEO_DECODER_CONFIG *)
915 g_alloca (sizeof (D3D11_VIDEO_DECODER_CONFIG) * config_count);
917 for (i = 0; i < config_count; i++) {
918 hr = video_device->GetVideoDecoderConfig (&decoder_desc, i,
920 if (!gst_d3d11_result (hr, self->device)) {
921 GST_ERROR_OBJECT (self, "Could not get decoder %dth config, hr: 0x%x",
926 /* FIXME: need support DXVA_Slice_H264_Long ?? */
927 /* this config uses DXVA_Slice_H264_Short */
928 switch (self->codec) {
929 case GST_DXVA_CODEC_H264:
930 if (config_list[i].ConfigBitstreamRaw == 2)
931 best_config = &config_list[i];
933 case GST_DXVA_CODEC_H265:
934 case GST_DXVA_CODEC_VP9:
935 case GST_DXVA_CODEC_VP8:
936 case GST_DXVA_CODEC_MPEG2:
937 case GST_DXVA_CODEC_AV1:
938 if (config_list[i].ConfigBitstreamRaw == 1)
939 best_config = &config_list[i];
942 g_assert_not_reached ();
950 if (best_config == NULL) {
951 GST_ERROR_OBJECT (self, "Could not determine decoder config");
955 GST_DEBUG_OBJECT (self, "ConfigDecoderSpecific 0x%x",
956 best_config->ConfigDecoderSpecific);
958 /* bit 14 is equal to 1b means this config support array of texture and
959 * it's recommended type as per DXVA spec */
960 if ((best_config->ConfigDecoderSpecific & 0x4000) == 0x4000) {
961 GST_DEBUG_OBJECT (self, "Config support array of texture");
962 self->use_array_of_texture = TRUE;
965 hr = video_device->CreateVideoDecoder (&decoder_desc,
966 best_config, &self->decoder_handle);
967 if (!gst_d3d11_result (hr, self->device) || !self->decoder_handle) {
968 GST_ERROR_OBJECT (self,
969 "Could not create decoder object, hr: 0x%x", (guint) hr);
973 GST_DEBUG_OBJECT (self, "Decoder object %p created", self->decoder_handle);
975 if (!self->downstream_supports_d3d11 &&
976 !gst_d3d11_decoder_ensure_staging_texture (self)) {
977 GST_ERROR_OBJECT (self, "Couldn't prepare staging texture");
981 self->decoder_profile = *selected_profile;
983 /* Store pool related information here, then we will setup internal pool
984 * later once the number of min buffer size required by downstream is known.
985 * Actual buffer pool size will be "dpb_size + downstream_min_buffers"
987 self->downstream_min_buffers = 0;
988 self->wait_on_pool_full = FALSE;
991 gst_d3d11_device_unlock (self->device);
993 gst_d3d11_decoder_enable_high_precision_timer (self);
998 gst_d3d11_decoder_reset (self);
999 gst_d3d11_device_unlock (self->device);
1005 gst_d3d11_decoder_begin_frame (GstD3D11Decoder * decoder,
1006 ID3D11VideoDecoderOutputView * output_view, guint content_key_size,
1007 gconstpointer content_key)
1009 ID3D11VideoContext *video_context;
1010 guint retry_count = 0;
1012 guint retry_threshold = 100;
1014 /* if we have high resolution timer, do more retry */
1015 if (decoder->timer_resolution)
1016 retry_threshold = 500;
1018 video_context = decoder->video_context;
1021 GST_LOG_OBJECT (decoder, "Try begin frame, retry count %d", retry_count);
1022 hr = video_context->DecoderBeginFrame (decoder->decoder_handle,
1023 output_view, content_key_size, content_key);
1025 /* HACK: Do retry with 1ms sleep per failure, since DXVA/D3D11
1026 * doesn't provide API for "GPU-IS-READY-TO-DECODE" like signal.
1028 if (hr == E_PENDING && retry_count < retry_threshold) {
1029 GST_LOG_OBJECT (decoder, "GPU is busy, try again. Retry count %d",
1033 if (gst_d3d11_result (hr, decoder->device))
1034 GST_LOG_OBJECT (decoder, "Succeeded with retry count %d", retry_count);
1041 if (!gst_d3d11_result (hr, decoder->device)) {
1042 GST_ERROR_OBJECT (decoder, "Failed to begin frame, hr: 0x%x", (guint) hr);
1050 gst_d3d11_decoder_end_frame (GstD3D11Decoder * decoder)
1053 ID3D11VideoContext *video_context;
1055 video_context = decoder->video_context;
1056 hr = video_context->DecoderEndFrame (decoder->decoder_handle);
1058 if (!gst_d3d11_result (hr, decoder->device)) {
1059 GST_WARNING_OBJECT (decoder, "EndFrame failed, hr: 0x%x", (guint) hr);
1067 gst_d3d11_decoder_get_decoder_buffer (GstD3D11Decoder * decoder,
1068 D3D11_VIDEO_DECODER_BUFFER_TYPE type, guint * buffer_size,
1072 void *decoder_buffer;
1074 ID3D11VideoContext *video_context;
1076 video_context = decoder->video_context;
1077 hr = video_context->GetDecoderBuffer (decoder->decoder_handle,
1078 type, &size, &decoder_buffer);
1080 if (!gst_d3d11_result (hr, decoder->device)) {
1081 GST_WARNING_OBJECT (decoder, "Getting buffer type %d error, hr: 0x%x",
1086 *buffer_size = size;
1087 *buffer = decoder_buffer;
1093 gst_d3d11_decoder_release_decoder_buffer (GstD3D11Decoder * decoder,
1094 D3D11_VIDEO_DECODER_BUFFER_TYPE type)
1097 ID3D11VideoContext *video_context;
1099 video_context = decoder->video_context;
1100 hr = video_context->ReleaseDecoderBuffer (decoder->decoder_handle, type);
1102 if (!gst_d3d11_result (hr, decoder->device)) {
1103 GST_WARNING_OBJECT (decoder, "ReleaseDecoderBuffer failed, hr: 0x%x",
1112 gst_d3d11_decoder_submit_decoder_buffers (GstD3D11Decoder * decoder,
1113 guint buffer_count, const D3D11_VIDEO_DECODER_BUFFER_DESC * buffers)
1116 ID3D11VideoContext *video_context;
1118 video_context = decoder->video_context;
1119 hr = video_context->SubmitDecoderBuffers (decoder->decoder_handle,
1120 buffer_count, buffers);
1121 if (!gst_d3d11_result (hr, decoder->device)) {
1122 GST_WARNING_OBJECT (decoder, "SubmitDecoderBuffers failed, hr: 0x%x",
1131 gst_d3d11_decoder_decode_frame (GstD3D11Decoder * decoder,
1132 ID3D11VideoDecoderOutputView * output_view,
1133 GstD3D11DecodeInputStreamArgs * input_args)
1135 guint d3d11_buffer_size;
1136 gpointer d3d11_buffer;
1137 D3D11_VIDEO_DECODER_BUFFER_DESC buffer_desc[4];
1138 guint buffer_desc_size;
1140 g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
1141 g_return_val_if_fail (output_view != nullptr, FALSE);
1142 g_return_val_if_fail (input_args != nullptr, FALSE);
1144 memset (buffer_desc, 0, sizeof (buffer_desc));
1146 buffer_desc[0].BufferType = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS;
1147 buffer_desc[0].DataSize = input_args->picture_params_size;
1149 buffer_desc[1].BufferType = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL;
1150 buffer_desc[1].DataSize = input_args->slice_control_size;
1152 buffer_desc[2].BufferType = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM;
1153 buffer_desc[2].DataOffset = 0;
1154 buffer_desc[2].DataSize = input_args->bitstream_size;
1156 buffer_desc_size = 3;
1157 if (input_args->inverse_quantization_matrix &&
1158 input_args->inverse_quantization_matrix_size > 0) {
1159 buffer_desc[3].BufferType =
1160 D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX;
1161 buffer_desc[3].DataSize = input_args->inverse_quantization_matrix_size;
1165 gst_d3d11_device_lock (decoder->device);
1166 if (!gst_d3d11_decoder_begin_frame (decoder, output_view, 0, nullptr)) {
1167 gst_d3d11_device_unlock (decoder->device);
1172 if (!gst_d3d11_decoder_get_decoder_buffer (decoder,
1173 D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS, &d3d11_buffer_size,
1175 GST_ERROR_OBJECT (decoder,
1176 "Failed to get decoder buffer for picture parameters");
1180 if (d3d11_buffer_size < input_args->picture_params_size) {
1181 GST_ERROR_OBJECT (decoder,
1182 "Too small picture param buffer size %d", d3d11_buffer_size);
1184 gst_d3d11_decoder_release_decoder_buffer (decoder,
1185 D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS);
1189 memcpy (d3d11_buffer, input_args->picture_params,
1190 input_args->picture_params_size);
1192 if (!gst_d3d11_decoder_release_decoder_buffer (decoder,
1193 D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS)) {
1194 GST_ERROR_OBJECT (decoder, "Failed to release picture param buffer");
1198 if (!gst_d3d11_decoder_get_decoder_buffer (decoder,
1199 D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL, &d3d11_buffer_size,
1201 GST_ERROR_OBJECT (decoder, "Failed to get slice control buffer");
1205 if (d3d11_buffer_size < input_args->slice_control_size) {
1206 GST_ERROR_OBJECT (decoder,
1207 "Too small slice control buffer size %d", d3d11_buffer_size);
1209 gst_d3d11_decoder_release_decoder_buffer (decoder,
1210 D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL);
1214 memcpy (d3d11_buffer,
1215 input_args->slice_control, input_args->slice_control_size);
1217 if (!gst_d3d11_decoder_release_decoder_buffer (decoder,
1218 D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL)) {
1219 GST_ERROR_OBJECT (decoder, "Failed to release slice control buffer");
1223 if (!gst_d3d11_decoder_get_decoder_buffer (decoder,
1224 D3D11_VIDEO_DECODER_BUFFER_BITSTREAM, &d3d11_buffer_size,
1226 GST_ERROR_OBJECT (decoder, "Failed to get bitstream buffer");
1230 if (d3d11_buffer_size < input_args->bitstream_size) {
1231 GST_ERROR_OBJECT (decoder, "Too small bitstream buffer size %d",
1234 gst_d3d11_decoder_release_decoder_buffer (decoder,
1235 D3D11_VIDEO_DECODER_BUFFER_BITSTREAM);
1239 memcpy (d3d11_buffer, input_args->bitstream, input_args->bitstream_size);
1241 if (!gst_d3d11_decoder_release_decoder_buffer (decoder,
1242 D3D11_VIDEO_DECODER_BUFFER_BITSTREAM)) {
1243 GST_ERROR_OBJECT (decoder, "Failed to release bitstream buffer");
1247 if (input_args->inverse_quantization_matrix_size > 0) {
1248 if (!gst_d3d11_decoder_get_decoder_buffer (decoder,
1249 D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX,
1250 &d3d11_buffer_size, &d3d11_buffer)) {
1251 GST_ERROR_OBJECT (decoder,
1252 "Failed to get inverse quantization matrix buffer");
1256 if (d3d11_buffer_size < input_args->inverse_quantization_matrix_size) {
1257 GST_ERROR_OBJECT (decoder,
1258 "Too small inverse quantization matrix buffer buffer %d",
1261 gst_d3d11_decoder_release_decoder_buffer (decoder,
1262 D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX);
1266 memcpy (d3d11_buffer, input_args->inverse_quantization_matrix,
1267 input_args->inverse_quantization_matrix_size);
1269 if (!gst_d3d11_decoder_release_decoder_buffer (decoder,
1270 D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX)) {
1271 GST_ERROR_OBJECT (decoder,
1272 "Failed to release inverse quantization matrix buffer");
1277 if (!gst_d3d11_decoder_submit_decoder_buffers (decoder,
1278 buffer_desc_size, buffer_desc)) {
1279 GST_ERROR_OBJECT (decoder, "Failed to submit decoder buffers");
1283 if (!gst_d3d11_decoder_end_frame (decoder)) {
1284 gst_d3d11_device_unlock (decoder->device);
1288 gst_d3d11_device_unlock (decoder->device);
1293 gst_d3d11_decoder_end_frame (decoder);
1294 gst_d3d11_device_unlock (decoder->device);
1299 gst_d3d11_decoder_get_output_view_buffer (GstD3D11Decoder * decoder,
1300 GstVideoDecoder * videodec)
1302 GstBuffer *buf = NULL;
1305 g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
1307 if (!decoder->internal_pool) {
1308 /* Try negotiate again whatever the previous negotiation result was.
1309 * There could be updated field(s) in sinkpad caps after we negotiated with
1310 * downstream on new_sequence() call. For example, h264/h265 parse
1311 * will be able to update HDR10 related caps field after parsing
1312 * corresponding SEI messages which are usually placed after the essential
1314 gst_video_decoder_negotiate (videodec);
1316 if (!gst_d3d11_decoder_prepare_output_view_pool (decoder)) {
1317 GST_ERROR_OBJECT (videodec, "Failed to setup internal pool");
1320 } else if (!gst_buffer_pool_set_active (decoder->internal_pool, TRUE)) {
1321 GST_ERROR_OBJECT (videodec, "Couldn't set active internal pool");
1325 ret = gst_buffer_pool_acquire_buffer (decoder->internal_pool, &buf, NULL);
1327 if (ret != GST_FLOW_OK || !buf) {
1328 if (ret != GST_FLOW_FLUSHING) {
1329 GST_ERROR_OBJECT (videodec, "Couldn't get buffer from pool, ret %s",
1330 gst_flow_get_name (ret));
1332 GST_DEBUG_OBJECT (videodec, "We are flusing");
1338 if (!gst_d3d11_decoder_ensure_output_view (decoder, buf)) {
1339 GST_ERROR_OBJECT (videodec, "Output view unavailable");
1340 gst_buffer_unref (buf);
1348 ID3D11VideoDecoderOutputView *
1349 gst_d3d11_decoder_get_output_view_from_buffer (GstD3D11Decoder * decoder,
1350 GstBuffer * buffer, guint8 * index)
1353 GstD3D11Memory *dmem;
1354 ID3D11VideoDecoderOutputView *view;
1356 g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), NULL);
1357 g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
1359 mem = gst_buffer_peek_memory (buffer, 0);
1360 if (!gst_is_d3d11_memory (mem)) {
1361 GST_WARNING_OBJECT (decoder, "Not a d3d11 memory");
1365 dmem = (GstD3D11Memory *) mem;
1366 view = gst_d3d11_memory_get_decoder_output_view (dmem, decoder->video_device,
1367 &decoder->decoder_profile);
1370 GST_ERROR_OBJECT (decoder, "Decoder output view is unavailable");
1375 if (decoder->use_array_of_texture) {
1377 gpointer val = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
1378 gst_d3d11_decoder_view_id_quark ());
1380 GST_ERROR_OBJECT (decoder, "memory has no qdata");
1384 id = (guint8) GPOINTER_TO_UINT (val);
1385 g_assert (id < 128);
1389 *index = gst_d3d11_memory_get_subresource_index (dmem);
1397 gst_d3d11_decoder_process_output (GstD3D11Decoder * decoder,
1398 GstVideoDecoder * videodec, gint display_width, gint display_height,
1399 GstBuffer * decoder_buffer, GstBuffer ** output)
1401 g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
1402 g_return_val_if_fail (GST_IS_VIDEO_DECODER (videodec), FALSE);
1403 g_return_val_if_fail (GST_IS_BUFFER (decoder_buffer), FALSE);
1404 g_return_val_if_fail (output != NULL, FALSE);
1406 if (display_width != GST_VIDEO_INFO_WIDTH (&decoder->output_info) ||
1407 display_height != GST_VIDEO_INFO_HEIGHT (&decoder->output_info)) {
1408 GST_INFO_OBJECT (videodec, "Frame size changed, do renegotiate");
1410 gst_video_info_set_format (&decoder->output_info,
1411 GST_VIDEO_INFO_FORMAT (&decoder->info), display_width, display_height);
1412 GST_VIDEO_INFO_INTERLACE_MODE (&decoder->output_info) =
1413 GST_VIDEO_INFO_INTERLACE_MODE (&decoder->info);
1415 if (!gst_video_decoder_negotiate (videodec)) {
1416 GST_ERROR_OBJECT (videodec, "Failed to re-negotiate with new frame size");
1421 if (gst_d3d11_decoder_can_direct_render (decoder, videodec, decoder_buffer,
1422 display_width, display_height)) {
1425 mem = gst_buffer_peek_memory (decoder_buffer, 0);
1426 GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
1428 *output = gst_buffer_ref (decoder_buffer);
1433 *output = gst_video_decoder_allocate_output_buffer (videodec);
1434 if (*output == NULL) {
1435 GST_ERROR_OBJECT (videodec, "Couldn't allocate output buffer");
1440 return gst_d3d11_buffer_copy_into (*output,
1441 decoder_buffer, &decoder->output_info);
1445 gst_d3d11_decoder_negotiate (GstD3D11Decoder * decoder,
1446 GstVideoDecoder * videodec)
1450 GstVideoCodecState *state = NULL;
1451 gboolean alternate_interlaced;
1452 gboolean alternate_supported = FALSE;
1453 gboolean d3d11_supported = FALSE;
1454 GstVideoCodecState *input_state;
1456 g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
1457 g_return_val_if_fail (GST_IS_VIDEO_DECODER (videodec), FALSE);
1459 info = &decoder->output_info;
1460 input_state = decoder->input_state;
1462 alternate_interlaced =
1463 (GST_VIDEO_INFO_INTERLACE_MODE (info) ==
1464 GST_VIDEO_INTERLACE_MODE_ALTERNATE);
1466 peer_caps = gst_pad_get_allowed_caps (GST_VIDEO_DECODER_SRC_PAD (videodec));
1467 GST_DEBUG_OBJECT (videodec, "Allowed caps %" GST_PTR_FORMAT, peer_caps);
1469 if (!peer_caps || gst_caps_is_any (peer_caps)) {
1470 GST_DEBUG_OBJECT (videodec,
1471 "cannot determine output format, use system memory");
1473 GstCapsFeatures *features;
1474 guint size = gst_caps_get_size (peer_caps);
1477 for (i = 0; i < size; i++) {
1478 features = gst_caps_get_features (peer_caps, i);
1483 if (gst_caps_features_contains (features,
1484 GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
1485 d3d11_supported = TRUE;
1488 /* FIXME: software deinterlace element will not return interlaced caps
1489 * feature... We should fix it */
1490 if (gst_caps_features_contains (features,
1491 GST_CAPS_FEATURE_FORMAT_INTERLACED)) {
1492 alternate_supported = TRUE;
1496 gst_clear_caps (&peer_caps);
1498 GST_DEBUG_OBJECT (videodec,
1499 "Downstream feature support, D3D11 memory: %d, interlaced format %d",
1500 d3d11_supported, alternate_supported);
1502 if (alternate_interlaced) {
1503 /* FIXME: D3D11 cannot support alternating interlaced stream yet */
1504 GST_FIXME_OBJECT (videodec,
1505 "Implement alternating interlaced stream for D3D11");
1507 if (alternate_supported) {
1508 gint height = GST_VIDEO_INFO_HEIGHT (info);
1510 /* Set caps resolution with display size, that's how we designed
1511 * for alternating interlaced stream */
1512 height = 2 * height;
1513 state = gst_video_decoder_set_interlaced_output_state (videodec,
1514 GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_INTERLACE_MODE (info),
1515 GST_VIDEO_INFO_WIDTH (info), height, input_state);
1517 GST_WARNING_OBJECT (videodec,
1518 "Downstream doesn't support alternating interlaced stream");
1520 state = gst_video_decoder_set_output_state (videodec,
1521 GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
1522 GST_VIDEO_INFO_HEIGHT (info), input_state);
1524 /* XXX: adjust PAR, this would produce output similar to that of
1525 * "line doubling" (so called bob deinterlacing) processing.
1526 * apart from missing anchor line (top-field or bottom-field) information.
1527 * Potentially flickering could happen. So this might not be correct.
1528 * But it would be better than negotiation error of half-height squeezed
1530 state->info.par_d *= 2;
1531 state->info.fps_n *= 2;
1534 state = gst_video_decoder_set_interlaced_output_state (videodec,
1535 GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_INTERLACE_MODE (info),
1536 GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), input_state);
1540 GST_ERROR_OBJECT (decoder, "Couldn't set output state");
1544 state->caps = gst_video_info_to_caps (&state->info);
1546 g_clear_pointer (&decoder->output_state, gst_video_codec_state_unref);
1547 decoder->output_state = state;
1549 if (d3d11_supported) {
1550 gst_caps_set_features (state->caps, 0,
1551 gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, NULL));
1554 decoder->downstream_supports_d3d11 = d3d11_supported;
1556 return gst_d3d11_decoder_open (decoder);
1560 gst_d3d11_decoder_decide_allocation (GstD3D11Decoder * decoder,
1561 GstVideoDecoder * videodec, GstQuery * query)
1564 GstBufferPool *pool = NULL;
1565 guint n, size, min = 0, max = 0;
1566 GstVideoInfo vinfo = { 0, };
1567 GstStructure *config;
1568 GstD3D11AllocationParams *d3d11_params;
1569 gboolean use_d3d11_pool;
1570 gboolean has_videometa;
1572 g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
1573 g_return_val_if_fail (GST_IS_VIDEO_DECODER (videodec), FALSE);
1574 g_return_val_if_fail (query != NULL, FALSE);
1576 if (!decoder->opened) {
1577 GST_ERROR_OBJECT (videodec, "Should open decoder first");
1581 gst_query_parse_allocation (query, &outcaps, NULL);
1584 GST_DEBUG_OBJECT (decoder, "No output caps");
1588 has_videometa = gst_query_find_allocation_meta (query,
1589 GST_VIDEO_META_API_TYPE, nullptr);
1591 use_d3d11_pool = decoder->downstream_supports_d3d11;
1593 gst_video_info_from_caps (&vinfo, outcaps);
1594 n = gst_query_get_n_allocation_pools (query);
1596 gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
1598 /* create our own pool */
1600 if (use_d3d11_pool) {
1601 if (!GST_IS_D3D11_BUFFER_POOL (pool)) {
1602 GST_DEBUG_OBJECT (videodec,
1603 "Downstream pool is not d3d11, will create new one");
1604 gst_clear_object (&pool);
1606 GstD3D11BufferPool *dpool = GST_D3D11_BUFFER_POOL (pool);
1607 if (dpool->device != decoder->device) {
1608 GST_DEBUG_OBJECT (videodec, "Different device, will create new one");
1609 gst_clear_object (&pool);
1612 } else if (has_videometa) {
1613 /* We will use d3d11 staging buffer pool */
1614 gst_clear_object (&pool);
1620 pool = gst_d3d11_buffer_pool_new (decoder->device);
1621 else if (has_videometa)
1622 pool = gst_d3d11_staging_buffer_pool_new (decoder->device);
1624 pool = gst_video_buffer_pool_new ();
1626 size = (guint) vinfo.size;
1629 config = gst_buffer_pool_get_config (pool);
1630 gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
1631 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
1633 if (use_d3d11_pool) {
1634 GstVideoAlignment align;
1637 gst_video_alignment_reset (&align);
1639 d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
1641 d3d11_params = gst_d3d11_allocation_params_new (decoder->device, &vinfo,
1642 (GstD3D11AllocationFlags) 0, 0);
1644 width = GST_VIDEO_INFO_WIDTH (&vinfo);
1645 height = GST_VIDEO_INFO_HEIGHT (&vinfo);
1647 /* need alignment to copy decoder output texture to downstream texture */
1648 align.padding_right = GST_ROUND_UP_16 (width) - width;
1649 align.padding_bottom = GST_ROUND_UP_16 (height) - height;
1650 if (!gst_d3d11_allocation_params_alignment (d3d11_params, &align)) {
1651 GST_ERROR_OBJECT (videodec, "Cannot set alignment");
1655 /* Needs render target bind flag so that it can be used for
1656 * output of shader pipeline if internal resizing is required.
1657 * Also, downstream can keep using video processor even if we copy
1658 * some decoded textures into downstream buffer */
1659 d3d11_params->desc[0].BindFlags |= D3D11_BIND_RENDER_TARGET;
1661 gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
1662 gst_d3d11_allocation_params_free (d3d11_params);
1664 /* Store min buffer size. We need to take account of the amount of buffers
1665 * which might be held by downstream in case of zero-copy playback */
1666 if (!decoder->internal_pool) {
1668 GST_DEBUG_OBJECT (videodec, "Downstream proposed pool");
1669 decoder->wait_on_pool_full = TRUE;
1670 /* XXX: hardcoded bound 16, to avoid too large pool size */
1671 decoder->downstream_min_buffers = MIN (min, 16);
1673 GST_DEBUG_OBJECT (videodec, "Downstream didn't propose pool");
1674 decoder->wait_on_pool_full = FALSE;
1675 /* don't know how many buffers would be queued by downstream */
1676 decoder->downstream_min_buffers = 4;
1679 /* We configured our DPB pool already, let's check if our margin can
1681 decoder->wait_on_pool_full = FALSE;
1684 if (decoder->downstream_min_buffers >= min)
1685 decoder->wait_on_pool_full = TRUE;
1687 GST_DEBUG_OBJECT (videodec,
1688 "Pre-allocated margin %d can%s cover downstream min size %d",
1689 decoder->downstream_min_buffers,
1690 decoder->wait_on_pool_full ? "" : "not", min);
1692 GST_DEBUG_OBJECT (videodec, "Downstream min size is unknown");
1696 GST_DEBUG_OBJECT (videodec, "Downstream min buffres: %d", min);
1699 gst_buffer_pool_set_config (pool, config);
1700 /* d3d11 buffer pool will update buffer size based on allocated texture,
1701 * get size from config again */
1702 config = gst_buffer_pool_get_config (pool);
1703 gst_buffer_pool_config_get_params (config, nullptr, &size, nullptr, nullptr);
1704 gst_structure_free (config);
1707 gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
1709 gst_query_add_allocation_pool (query, pool, size, min, max);
1710 gst_object_unref (pool);
1716 gst_d3d11_decoder_set_flushing (GstD3D11Decoder * decoder,
1717 GstVideoDecoder * videodec, gboolean flushing)
1719 g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
1721 g_mutex_lock (&decoder->internal_pool_lock);
1722 if (decoder->internal_pool)
1723 gst_buffer_pool_set_flushing (decoder->internal_pool, flushing);
1724 g_mutex_unlock (&decoder->internal_pool_lock);
1730 gst_d3d11_decoder_can_direct_render (GstD3D11Decoder * decoder,
1731 GstVideoDecoder * videodec, GstBuffer * view_buffer,
1732 gint display_width, gint display_height)
1735 GstD3D11PoolAllocator *alloc;
1736 guint max_size = 0, outstanding_size = 0;
1738 /* We don't support direct render for reverse playback */
1739 if (videodec->input_segment.rate < 0)
1742 if (!decoder->can_direct_rendering || !decoder->downstream_supports_d3d11)
1745 /* different size, need copy */
1746 /* TODO: crop meta */
1747 if (display_width != GST_VIDEO_INFO_WIDTH (&decoder->info) ||
1748 display_height != GST_VIDEO_INFO_HEIGHT (&decoder->info))
1751 /* we can do direct render in this case, since there is no DPB pool size
1753 if (decoder->use_array_of_texture)
1756 /* Let's believe downstream info */
1757 if (decoder->wait_on_pool_full)
1760 /* Check if we are about to full */
1761 mem = gst_buffer_peek_memory (view_buffer, 0);
1763 /* something went wrong */
1764 if (!gst_is_d3d11_memory (mem)) {
1765 GST_ERROR_OBJECT (decoder, "Not a D3D11 memory");
1769 alloc = GST_D3D11_POOL_ALLOCATOR (mem->allocator);
1770 if (!gst_d3d11_pool_allocator_get_pool_size (alloc, &max_size,
1771 &outstanding_size)) {
1772 GST_ERROR_OBJECT (decoder, "Couldn't query pool size");
1776 /* 2 buffer margin */
1777 if (max_size <= outstanding_size + 1) {
1778 GST_DEBUG_OBJECT (decoder, "memory pool is about to full (%u/%u)",
1779 outstanding_size, max_size);
1783 GST_LOG_OBJECT (decoder, "Can do direct rendering");
1788 /* Keep sync with chromium and keep in sorted order.
1789 * See supported_profile_helpers.cc in chromium */
1790 static const guint legacy_amd_list[] = {
1791 0x130f, 0x6700, 0x6701, 0x6702, 0x6703, 0x6704, 0x6705, 0x6706, 0x6707,
1792 0x6708, 0x6709, 0x6718, 0x6719, 0x671c, 0x671d, 0x671f, 0x6720, 0x6721,
1793 0x6722, 0x6723, 0x6724, 0x6725, 0x6726, 0x6727, 0x6728, 0x6729, 0x6738,
1794 0x6739, 0x673e, 0x6740, 0x6741, 0x6742, 0x6743, 0x6744, 0x6745, 0x6746,
1795 0x6747, 0x6748, 0x6749, 0x674a, 0x6750, 0x6751, 0x6758, 0x6759, 0x675b,
1796 0x675d, 0x675f, 0x6760, 0x6761, 0x6762, 0x6763, 0x6764, 0x6765, 0x6766,
1797 0x6767, 0x6768, 0x6770, 0x6771, 0x6772, 0x6778, 0x6779, 0x677b, 0x6798,
1798 0x67b1, 0x6821, 0x683d, 0x6840, 0x6841, 0x6842, 0x6843, 0x6849, 0x6850,
1799 0x6858, 0x6859, 0x6880, 0x6888, 0x6889, 0x688a, 0x688c, 0x688d, 0x6898,
1800 0x6899, 0x689b, 0x689c, 0x689d, 0x689e, 0x68a0, 0x68a1, 0x68a8, 0x68a9,
1801 0x68b0, 0x68b8, 0x68b9, 0x68ba, 0x68be, 0x68bf, 0x68c0, 0x68c1, 0x68c7,
1802 0x68c8, 0x68c9, 0x68d8, 0x68d9, 0x68da, 0x68de, 0x68e0, 0x68e1, 0x68e4,
1803 0x68e5, 0x68e8, 0x68e9, 0x68f1, 0x68f2, 0x68f8, 0x68f9, 0x68fa, 0x68fe,
1804 0x9400, 0x9401, 0x9402, 0x9403, 0x9405, 0x940a, 0x940b, 0x940f, 0x9440,
1805 0x9441, 0x9442, 0x9443, 0x9444, 0x9446, 0x944a, 0x944b, 0x944c, 0x944e,
1806 0x9450, 0x9452, 0x9456, 0x945a, 0x945b, 0x945e, 0x9460, 0x9462, 0x946a,
1807 0x946b, 0x947a, 0x947b, 0x9480, 0x9487, 0x9488, 0x9489, 0x948a, 0x948f,
1808 0x9490, 0x9491, 0x9495, 0x9498, 0x949c, 0x949e, 0x949f, 0x94a0, 0x94a1,
1809 0x94a3, 0x94b1, 0x94b3, 0x94b4, 0x94b5, 0x94b9, 0x94c0, 0x94c1, 0x94c3,
1810 0x94c4, 0x94c5, 0x94c6, 0x94c7, 0x94c8, 0x94c9, 0x94cb, 0x94cc, 0x94cd,
1811 0x9500, 0x9501, 0x9504, 0x9505, 0x9506, 0x9507, 0x9508, 0x9509, 0x950f,
1812 0x9511, 0x9515, 0x9517, 0x9519, 0x9540, 0x9541, 0x9542, 0x954e, 0x954f,
1813 0x9552, 0x9553, 0x9555, 0x9557, 0x955f, 0x9580, 0x9581, 0x9583, 0x9586,
1814 0x9587, 0x9588, 0x9589, 0x958a, 0x958b, 0x958c, 0x958d, 0x958e, 0x958f,
1815 0x9590, 0x9591, 0x9593, 0x9595, 0x9596, 0x9597, 0x9598, 0x9599, 0x959b,
1816 0x95c0, 0x95c2, 0x95c4, 0x95c5, 0x95c6, 0x95c7, 0x95c9, 0x95cc, 0x95cd,
1817 0x95ce, 0x95cf, 0x9610, 0x9611, 0x9612, 0x9613, 0x9614, 0x9615, 0x9616,
1818 0x9640, 0x9641, 0x9642, 0x9643, 0x9644, 0x9645, 0x9647, 0x9648, 0x9649,
1819 0x964a, 0x964b, 0x964c, 0x964e, 0x964f, 0x9710, 0x9711, 0x9712, 0x9713,
1820 0x9714, 0x9715, 0x9802, 0x9803, 0x9804, 0x9805, 0x9806, 0x9807, 0x9808,
1821 0x9809, 0x980a, 0x9830, 0x983d, 0x9850, 0x9851, 0x9874, 0x9900, 0x9901,
1822 0x9903, 0x9904, 0x9905, 0x9906, 0x9907, 0x9908, 0x9909, 0x990a, 0x990b,
1823 0x990c, 0x990d, 0x990e, 0x990f, 0x9910, 0x9913, 0x9917, 0x9918, 0x9919,
1824 0x9990, 0x9991, 0x9992, 0x9993, 0x9994, 0x9995, 0x9996, 0x9997, 0x9998,
1825 0x9999, 0x999a, 0x999b, 0x999c, 0x999d, 0x99a0, 0x99a2, 0x99a4
1828 static const guint legacy_intel_list[] = {
1829 0x102, 0x106, 0x116, 0x126, 0x152, 0x156, 0x166,
1830 0x402, 0x406, 0x416, 0x41e, 0xa06, 0xa16, 0xf31,
1834 binary_search_compare (const guint * a, const guint * b)
1839 /* Certain AMD GPU drivers like R600, R700, Evergreen and Cayman and some second
1840 * generation Intel GPU drivers crash if we create a video device with a
1841 * resolution higher then 1920 x 1088. This function checks if the GPU is in
1842 * this list and if yes returns true. */
1844 gst_d3d11_decoder_util_is_legacy_device (GstD3D11Device * device)
1846 const guint amd_id[] = { 0x1002, 0x1022 };
1847 const guint intel_id = 0x8086;
1848 guint device_id = 0;
1849 guint vendor_id = 0;
1850 guint *match = NULL;
1852 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE);
1854 g_object_get (device, "device-id", &device_id, "vendor-id", &vendor_id, NULL);
1856 if (vendor_id == amd_id[0] || vendor_id == amd_id[1]) {
1858 (guint *) gst_util_array_binary_search ((gpointer) legacy_amd_list,
1859 G_N_ELEMENTS (legacy_amd_list), sizeof (guint),
1860 (GCompareDataFunc) binary_search_compare,
1861 GST_SEARCH_MODE_EXACT, &device_id, NULL);
1862 } else if (vendor_id == intel_id) {
1864 (guint *) gst_util_array_binary_search ((gpointer) legacy_intel_list,
1865 G_N_ELEMENTS (legacy_intel_list), sizeof (guint),
1866 (GCompareDataFunc) binary_search_compare,
1867 GST_SEARCH_MODE_EXACT, &device_id, NULL);
1871 GST_DEBUG_OBJECT (device, "it's legacy device");
1879 gst_d3d11_decoder_supports_format (GstD3D11Device * device,
1880 const GUID * decoder_profile, DXGI_FORMAT format)
1883 BOOL can_support = FALSE;
1884 ID3D11VideoDevice *video_device;
1886 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE);
1887 g_return_val_if_fail (decoder_profile != NULL, FALSE);
1888 g_return_val_if_fail (format != DXGI_FORMAT_UNKNOWN, FALSE);
1890 video_device = gst_d3d11_device_get_video_device_handle (device);
1894 hr = video_device->CheckVideoDecoderFormat (decoder_profile, format,
1896 if (!gst_d3d11_result (hr, device) || !can_support) {
1897 GST_DEBUG_OBJECT (device,
1898 "VideoDevice could not support dxgi format %d, hr: 0x%x",
1899 format, (guint) hr);
1907 /* Don't call this method with legacy device */
1909 gst_d3d11_decoder_supports_resolution (GstD3D11Device * device,
1910 const GUID * decoder_profile, DXGI_FORMAT format, guint width, guint height)
1912 D3D11_VIDEO_DECODER_DESC desc;
1915 ID3D11VideoDevice *video_device;
1917 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE);
1918 g_return_val_if_fail (decoder_profile != NULL, FALSE);
1919 g_return_val_if_fail (format != DXGI_FORMAT_UNKNOWN, FALSE);
1921 video_device = gst_d3d11_device_get_video_device_handle (device);
1925 desc.SampleWidth = width;
1926 desc.SampleHeight = height;
1927 desc.OutputFormat = format;
1928 desc.Guid = *decoder_profile;
1930 hr = video_device->GetVideoDecoderConfigCount (&desc, &config_count);
1931 if (!gst_d3d11_result (hr, device) || config_count == 0) {
1932 GST_DEBUG_OBJECT (device, "Could not get decoder config count, hr: 0x%x",
1942 PROP_DECODER_ADAPTER_LUID = 1,
1943 PROP_DECODER_DEVICE_ID,
1944 PROP_DECODER_VENDOR_ID,
1947 struct _GstD3D11DecoderClassData
1949 GstD3D11DecoderSubClassData subclass_data;
1956 * gst_d3d11_decoder_class_data_new:
1957 * @device: (transfer none): a #GstD3D11Device
1958 * @sink_caps: (transfer full): a #GstCaps
1959 * @src_caps: (transfer full): a #GstCaps
1961 * Create new #GstD3D11DecoderClassData
1963 * Returns: (transfer full): the new #GstD3D11DecoderClassData
1965 GstD3D11DecoderClassData *
1966 gst_d3d11_decoder_class_data_new (GstD3D11Device * device, GstDXVACodec codec,
1967 GstCaps * sink_caps, GstCaps * src_caps)
1969 GstD3D11DecoderClassData *ret;
1971 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1972 g_return_val_if_fail (sink_caps != NULL, NULL);
1973 g_return_val_if_fail (src_caps != NULL, NULL);
1975 ret = g_new0 (GstD3D11DecoderClassData, 1);
1977 /* class data will be leaked if the element never gets instantiated */
1978 GST_MINI_OBJECT_FLAG_SET (sink_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
1979 GST_MINI_OBJECT_FLAG_SET (src_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
1981 ret->subclass_data.codec = codec;
1982 g_object_get (device, "adapter-luid", &ret->subclass_data.adapter_luid,
1983 "device-id", &ret->subclass_data.device_id,
1984 "vendor-id", &ret->subclass_data.vendor_id,
1985 "description", &ret->description, nullptr);
1986 ret->sink_caps = sink_caps;
1987 ret->src_caps = src_caps;
1993 gst_d3d11_decoder_class_data_fill_subclass_data (GstD3D11DecoderClassData *
1994 data, GstD3D11DecoderSubClassData * subclass_data)
1996 g_return_if_fail (data != nullptr);
1997 g_return_if_fail (subclass_data != nullptr);
1999 *subclass_data = data->subclass_data;
2003 gst_d3d11_decoder_class_data_free (GstD3D11DecoderClassData * data)
2008 gst_clear_caps (&data->sink_caps);
2009 gst_clear_caps (&data->src_caps);
2010 g_free (data->description);
2015 gst_d3d11_decoder_proxy_class_init (GstElementClass * klass,
2016 GstD3D11DecoderClassData * data, const gchar * author)
2018 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
2019 GstD3D11DecoderSubClassData *cdata = &data->subclass_data;
2020 std::string long_name;
2021 std::string description;
2022 const gchar *codec_name;
2024 g_object_class_install_property (gobject_class, PROP_DECODER_ADAPTER_LUID,
2025 g_param_spec_int64 ("adapter-luid", "Adapter LUID",
2026 "DXGI Adapter LUID (Locally Unique Identifier) of created device",
2027 G_MININT64, G_MAXINT64, cdata->adapter_luid,
2028 (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
2030 g_object_class_install_property (gobject_class, PROP_DECODER_DEVICE_ID,
2031 g_param_spec_uint ("device-id", "Device Id",
2032 "DXGI Device ID", 0, G_MAXUINT32, 0,
2033 (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
2035 g_object_class_install_property (gobject_class, PROP_DECODER_VENDOR_ID,
2036 g_param_spec_uint ("vendor-id", "Vendor Id",
2037 "DXGI Vendor ID", 0, G_MAXUINT32, 0,
2038 (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
2040 codec_name = gst_dxva_codec_to_string (cdata->codec);
2041 long_name = "Direct3D11/DXVA " + std::string (codec_name) + " " +
2042 std::string (data->description) + " Decoder";
2043 description = "Direct3D11/DXVA based " + std::string (codec_name) +
2046 gst_element_class_set_metadata (klass, long_name.c_str (),
2047 "Codec/Decoder/Video/Hardware", description.c_str (), author);
2049 gst_element_class_add_pad_template (klass,
2050 gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
2052 gst_element_class_add_pad_template (klass,
2053 gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
2056 gst_d3d11_decoder_class_data_free (data);
2060 gst_d3d11_decoder_proxy_get_property (GObject * object, guint prop_id,
2061 GValue * value, GParamSpec * pspec,
2062 GstD3D11DecoderSubClassData * subclass_data)
2065 case PROP_DECODER_ADAPTER_LUID:
2066 g_value_set_int64 (value, subclass_data->adapter_luid);
2068 case PROP_DECODER_DEVICE_ID:
2069 g_value_set_uint (value, subclass_data->device_id);
2071 case PROP_DECODER_VENDOR_ID:
2072 g_value_set_uint (value, subclass_data->vendor_id);
2075 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2081 gst_d3d11_decoder_proxy_open (GstVideoDecoder * videodec,
2082 GstD3D11DecoderSubClassData * subclass_data, GstD3D11Device ** device,
2083 GstD3D11Decoder ** decoder)
2085 GstElement *elem = GST_ELEMENT (videodec);
2087 if (!gst_d3d11_ensure_element_data_for_adapter_luid (elem,
2088 subclass_data->adapter_luid, device)) {
2089 GST_ERROR_OBJECT (elem, "Cannot create d3d11device");
2093 *decoder = gst_d3d11_decoder_new (*device, subclass_data->codec);
2095 if (*decoder == nullptr) {
2096 GST_ERROR_OBJECT (elem, "Cannot create d3d11 decoder");
2097 gst_clear_object (device);