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.
21 * SECTION:element-d3d11h265dec
22 * @title: d3d11h265dec
24 * A Direct3D11/DXVA based H.265 video decoder
26 * ## Example launch line
28 * gst-launch-1.0 filesrc location=/path/to/hevc/file ! parsebin ! d3d11h265dec ! d3d11videosink
39 #include "gstd3d11h265dec.h"
41 #include <gst/codecs/gsth265decoder.h>
45 /* HACK: to expose dxva data structure on UWP */
46 #ifdef WINAPI_PARTITION_DESKTOP
47 #undef WINAPI_PARTITION_DESKTOP
49 #define WINAPI_PARTITION_DESKTOP 1
53 GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_h265_dec_debug);
54 #define GST_CAT_DEFAULT gst_d3d11_h265_dec_debug
57 typedef struct _GstD3D11H265DecInner
59 GstD3D11Device *device = nullptr;
60 GstD3D11Decoder *d3d11_decoder = nullptr;
62 DXVA_PicParams_HEVC pic_params;
63 DXVA_Qmatrix_HEVC iq_matrix;
65 std::vector<DXVA_Slice_HEVC_Short> slice_list;
66 std::vector<guint8> bitstream_buffer;
68 gboolean submit_iq_data;
73 gint coded_height = 0;
75 guint8 chroma_format_idc = 0;
76 GstVideoFormat out_format = GST_VIDEO_FORMAT_UNKNOWN;
77 GstVideoInterlaceMode interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
78 } GstD3D11H265DecInner;
81 typedef struct _GstD3D11H265Dec
83 GstH265Decoder parent;
84 GstD3D11H265DecInner *inner;
87 typedef struct _GstD3D11H265DecClass
89 GstH265DecoderClass parent_class;
90 GstD3D11DecoderSubClassData class_data;
91 } GstD3D11H265DecClass;
93 static GstElementClass *parent_class = NULL;
95 #define GST_D3D11_H265_DEC(object) ((GstD3D11H265Dec *) (object))
96 #define GST_D3D11_H265_DEC_GET_CLASS(object) \
97 (G_TYPE_INSTANCE_GET_CLASS ((object),G_TYPE_FROM_INSTANCE (object),GstD3D11H265DecClass))
99 static void gst_d3d11_h265_dec_get_property (GObject * object,
100 guint prop_id, GValue * value, GParamSpec * pspec);
101 static void gst_d3d11_h265_dec_finalize (GObject * object);
102 static void gst_d3d11_h265_dec_set_context (GstElement * element,
103 GstContext * context);
105 static gboolean gst_d3d11_h265_dec_open (GstVideoDecoder * decoder);
106 static gboolean gst_d3d11_h265_dec_close (GstVideoDecoder * decoder);
107 static gboolean gst_d3d11_h265_dec_negotiate (GstVideoDecoder * decoder);
108 static gboolean gst_d3d11_h265_dec_decide_allocation (GstVideoDecoder *
109 decoder, GstQuery * query);
110 static gboolean gst_d3d11_h265_dec_src_query (GstVideoDecoder * decoder,
112 static gboolean gst_d3d11_h265_dec_sink_event (GstVideoDecoder * decoder,
116 static gboolean gst_d3d11_h265_dec_new_sequence (GstH265Decoder * decoder,
117 const GstH265SPS * sps, gint max_dpb_size);
118 static gboolean gst_d3d11_h265_dec_new_picture (GstH265Decoder * decoder,
119 GstVideoCodecFrame * cframe, GstH265Picture * picture);
120 static GstFlowReturn gst_d3d11_h265_dec_output_picture (GstH265Decoder *
121 decoder, GstVideoCodecFrame * frame, GstH265Picture * picture);
122 static gboolean gst_d3d11_h265_dec_start_picture (GstH265Decoder * decoder,
123 GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb);
124 static gboolean gst_d3d11_h265_dec_decode_slice (GstH265Decoder * decoder,
125 GstH265Picture * picture, GstH265Slice * slice,
126 GArray * ref_pic_list0, GArray * ref_pic_list1);
127 static gboolean gst_d3d11_h265_dec_end_picture (GstH265Decoder * decoder,
128 GstH265Picture * picture);
131 gst_d3d11_h265_dec_class_init (GstD3D11H265DecClass * klass, gpointer data)
133 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
134 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
135 GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
136 GstH265DecoderClass *h265decoder_class = GST_H265_DECODER_CLASS (klass);
137 GstD3D11DecoderClassData *cdata = (GstD3D11DecoderClassData *) data;
139 gobject_class->get_property = gst_d3d11_h265_dec_get_property;
140 gobject_class->finalize = gst_d3d11_h265_dec_finalize;
142 element_class->set_context =
143 GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_set_context);
145 parent_class = (GstElementClass *) g_type_class_peek_parent (klass);
146 gst_d3d11_decoder_class_data_fill_subclass_data (cdata, &klass->class_data);
147 gst_d3d11_decoder_proxy_class_init (element_class, cdata,
148 "Seungha Yang <seungha.yang@navercorp.com>");
150 decoder_class->open = GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_open);
151 decoder_class->close = GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_close);
152 decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_negotiate);
153 decoder_class->decide_allocation =
154 GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_decide_allocation);
155 decoder_class->src_query = GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_src_query);
156 decoder_class->sink_event = GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_sink_event);
158 h265decoder_class->new_sequence =
159 GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_new_sequence);
160 h265decoder_class->new_picture =
161 GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_new_picture);
162 h265decoder_class->output_picture =
163 GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_output_picture);
164 h265decoder_class->start_picture =
165 GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_start_picture);
166 h265decoder_class->decode_slice =
167 GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_decode_slice);
168 h265decoder_class->end_picture =
169 GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_end_picture);
173 gst_d3d11_h265_dec_init (GstD3D11H265Dec * self)
175 self->inner = new GstD3D11H265DecInner ();
179 gst_d3d11_h265_dec_get_property (GObject * object, guint prop_id,
180 GValue * value, GParamSpec * pspec)
182 GstD3D11H265DecClass *klass = GST_D3D11_H265_DEC_GET_CLASS (object);
183 GstD3D11DecoderSubClassData *cdata = &klass->class_data;
185 gst_d3d11_decoder_proxy_get_property (object, prop_id, value, pspec, cdata);
189 gst_d3d11_h265_dec_finalize (GObject * object)
191 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (object);
195 G_OBJECT_CLASS (parent_class)->finalize (object);
199 gst_d3d11_h265_dec_set_context (GstElement * element, GstContext * context)
201 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (element);
202 GstD3D11H265DecInner *inner = self->inner;
203 GstD3D11H265DecClass *klass = GST_D3D11_H265_DEC_GET_CLASS (self);
204 GstD3D11DecoderSubClassData *cdata = &klass->class_data;
206 gst_d3d11_handle_set_context (element, context, cdata->adapter,
209 GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
213 gst_d3d11_h265_dec_open (GstVideoDecoder * decoder)
215 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
216 GstD3D11H265DecInner *inner = self->inner;
217 GstD3D11H265DecClass *klass = GST_D3D11_H265_DEC_GET_CLASS (self);
218 GstD3D11DecoderSubClassData *cdata = &klass->class_data;
220 if (!gst_d3d11_ensure_element_data (GST_ELEMENT_CAST (self), cdata->adapter,
222 GST_ERROR_OBJECT (self, "Cannot create d3d11device");
226 inner->d3d11_decoder = gst_d3d11_decoder_new (inner->device,
227 GST_DXVA_CODEC_H265);
229 if (!inner->d3d11_decoder) {
230 GST_ERROR_OBJECT (self, "Cannot create d3d11 decoder");
231 gst_clear_object (&inner->device);
239 gst_d3d11_h265_dec_close (GstVideoDecoder * decoder)
241 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
242 GstD3D11H265DecInner *inner = self->inner;
244 gst_clear_object (&inner->d3d11_decoder);
245 gst_clear_object (&inner->device);
251 gst_d3d11_h265_dec_negotiate (GstVideoDecoder * decoder)
253 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
254 GstD3D11H265DecInner *inner = self->inner;
256 if (!gst_d3d11_decoder_negotiate (inner->d3d11_decoder, decoder))
259 return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
263 gst_d3d11_h265_dec_decide_allocation (GstVideoDecoder * decoder,
266 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
267 GstD3D11H265DecInner *inner = self->inner;
269 if (!gst_d3d11_decoder_decide_allocation (inner->d3d11_decoder,
274 return GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation
279 gst_d3d11_h265_dec_src_query (GstVideoDecoder * decoder, GstQuery * query)
281 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
282 GstD3D11H265DecInner *inner = self->inner;
284 switch (GST_QUERY_TYPE (query)) {
285 case GST_QUERY_CONTEXT:
286 if (gst_d3d11_handle_context_query (GST_ELEMENT (decoder),
287 query, inner->device)) {
295 return GST_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query);
299 gst_d3d11_h265_dec_sink_event (GstVideoDecoder * decoder, GstEvent * event)
301 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
302 GstD3D11H265DecInner *inner = self->inner;
304 switch (GST_EVENT_TYPE (event)) {
305 case GST_EVENT_FLUSH_START:
306 if (inner->d3d11_decoder)
307 gst_d3d11_decoder_set_flushing (inner->d3d11_decoder, decoder, TRUE);
309 case GST_EVENT_FLUSH_STOP:
310 if (inner->d3d11_decoder)
311 gst_d3d11_decoder_set_flushing (inner->d3d11_decoder, decoder, FALSE);
316 return GST_VIDEO_DECODER_CLASS (parent_class)->sink_event (decoder, event);
320 gst_d3d11_h265_dec_new_sequence (GstH265Decoder * decoder,
321 const GstH265SPS * sps, gint max_dpb_size)
323 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
324 GstD3D11H265DecInner *inner = self->inner;
325 gint crop_width, crop_height;
326 gboolean modified = FALSE;
327 GstVideoInterlaceMode interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
329 GST_LOG_OBJECT (self, "new sequence");
331 if (sps->conformance_window_flag) {
332 crop_width = sps->crop_rect_width;
333 crop_height = sps->crop_rect_height;
335 crop_width = sps->width;
336 crop_height = sps->height;
339 if (inner->width != crop_width || inner->height != crop_height ||
340 inner->coded_width != sps->width || inner->coded_height != sps->height) {
341 GST_INFO_OBJECT (self, "resolution changed %dx%d -> %dx%d",
342 crop_width, crop_height, sps->width, sps->height);
343 inner->width = crop_width;
344 inner->height = crop_height;
345 inner->coded_width = sps->width;
346 inner->coded_height = sps->height;
350 if (inner->bitdepth != (guint) sps->bit_depth_luma_minus8 + 8) {
351 GST_INFO_OBJECT (self, "bitdepth changed");
352 inner->bitdepth = sps->bit_depth_luma_minus8 + 8;
356 if (sps->vui_parameters_present_flag && sps->vui_params.field_seq_flag) {
357 interlace_mode = GST_VIDEO_INTERLACE_MODE_ALTERNATE;
359 /* 7.4.4 Profile, tier and level sementics */
360 if (sps->profile_tier_level.progressive_source_flag &&
361 !sps->profile_tier_level.interlaced_source_flag) {
362 interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
364 interlace_mode = GST_VIDEO_INTERLACE_MODE_MIXED;
368 if (inner->interlace_mode != interlace_mode) {
369 GST_INFO_OBJECT (self, "Interlace mode change %d -> %d",
370 inner->interlace_mode, interlace_mode);
371 inner->interlace_mode = interlace_mode;
375 if (inner->chroma_format_idc != sps->chroma_format_idc) {
376 GST_INFO_OBJECT (self, "chroma format changed");
377 inner->chroma_format_idc = sps->chroma_format_idc;
381 if (modified || !gst_d3d11_decoder_is_configured (inner->d3d11_decoder)) {
384 inner->out_format = GST_VIDEO_FORMAT_UNKNOWN;
386 if (inner->bitdepth == 8) {
387 if (inner->chroma_format_idc == 1) {
388 inner->out_format = GST_VIDEO_FORMAT_NV12;
390 GST_FIXME_OBJECT (self, "Could not support 8bits non-4:2:0 format");
392 } else if (inner->bitdepth == 10) {
393 if (inner->chroma_format_idc == 1) {
394 inner->out_format = GST_VIDEO_FORMAT_P010_10LE;
396 GST_FIXME_OBJECT (self, "Could not support 10bits non-4:2:0 format");
400 if (inner->out_format == GST_VIDEO_FORMAT_UNKNOWN) {
401 GST_ERROR_OBJECT (self, "Could not support bitdepth/chroma format");
405 gst_video_info_set_format (&info,
406 inner->out_format, inner->width, inner->height);
407 GST_VIDEO_INFO_INTERLACE_MODE (&info) = inner->interlace_mode;
409 if (!gst_d3d11_decoder_configure (inner->d3d11_decoder,
410 decoder->input_state, &info,
411 inner->coded_width, inner->coded_height,
412 /* Additional 4 views margin for zero-copy rendering */
414 GST_ERROR_OBJECT (self, "Failed to create decoder");
418 if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
419 GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
428 gst_d3d11_h265_dec_new_picture (GstH265Decoder * decoder,
429 GstVideoCodecFrame * cframe, GstH265Picture * picture)
431 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
432 GstD3D11H265DecInner *inner = self->inner;
433 GstBuffer *view_buffer;
435 view_buffer = gst_d3d11_decoder_get_output_view_buffer (inner->d3d11_decoder,
436 GST_VIDEO_DECODER (decoder));
438 GST_DEBUG_OBJECT (self, "No available output view buffer");
442 GST_LOG_OBJECT (self, "New output view buffer %" GST_PTR_FORMAT, view_buffer);
444 gst_h265_picture_set_user_data (picture,
445 view_buffer, (GDestroyNotify) gst_buffer_unref);
447 GST_LOG_OBJECT (self, "New h265picture %p", picture);
453 gst_d3d11_h265_dec_picture_params_from_sps (GstD3D11H265Dec * self,
454 const GstH265SPS * sps, DXVA_PicParams_HEVC * params)
456 #define COPY_FIELD(f) \
457 (params)->f = (sps)->f
458 #define COPY_FIELD_WITH_PREFIX(f) \
459 (params)->G_PASTE(sps_,f) = (sps)->f
461 params->PicWidthInMinCbsY =
462 sps->width >> (sps->log2_min_luma_coding_block_size_minus3 + 3);
463 params->PicHeightInMinCbsY =
464 sps->height >> (sps->log2_min_luma_coding_block_size_minus3 + 3);
465 params->sps_max_dec_pic_buffering_minus1 =
466 sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1];
468 COPY_FIELD (chroma_format_idc);
469 COPY_FIELD (separate_colour_plane_flag);
470 COPY_FIELD (bit_depth_luma_minus8);
471 COPY_FIELD (bit_depth_chroma_minus8);
472 COPY_FIELD (log2_max_pic_order_cnt_lsb_minus4);
473 COPY_FIELD (log2_min_luma_coding_block_size_minus3);
474 COPY_FIELD (log2_diff_max_min_luma_coding_block_size);
475 COPY_FIELD (log2_min_transform_block_size_minus2);
476 COPY_FIELD (log2_diff_max_min_transform_block_size);
477 COPY_FIELD (max_transform_hierarchy_depth_inter);
478 COPY_FIELD (max_transform_hierarchy_depth_intra);
479 COPY_FIELD (num_short_term_ref_pic_sets);
480 COPY_FIELD (num_long_term_ref_pics_sps);
481 COPY_FIELD (scaling_list_enabled_flag);
482 COPY_FIELD (amp_enabled_flag);
483 COPY_FIELD (sample_adaptive_offset_enabled_flag);
484 COPY_FIELD (pcm_enabled_flag);
486 if (sps->pcm_enabled_flag) {
487 COPY_FIELD (pcm_sample_bit_depth_luma_minus1);
488 COPY_FIELD (pcm_sample_bit_depth_chroma_minus1);
489 COPY_FIELD (log2_min_pcm_luma_coding_block_size_minus3);
490 COPY_FIELD (log2_diff_max_min_pcm_luma_coding_block_size);
493 COPY_FIELD (pcm_loop_filter_disabled_flag);
494 COPY_FIELD (long_term_ref_pics_present_flag);
495 COPY_FIELD_WITH_PREFIX (temporal_mvp_enabled_flag);
496 COPY_FIELD (strong_intra_smoothing_enabled_flag);
499 #undef COPY_FIELD_WITH_PREFIX
503 gst_d3d11_h265_dec_picture_params_from_pps (GstD3D11H265Dec * self,
504 const GstH265PPS * pps, DXVA_PicParams_HEVC * params)
508 #define COPY_FIELD(f) \
509 (params)->f = (pps)->f
510 #define COPY_FIELD_WITH_PREFIX(f) \
511 (params)->G_PASTE(pps_,f) = (pps)->f
513 COPY_FIELD (num_ref_idx_l0_default_active_minus1);
514 COPY_FIELD (num_ref_idx_l1_default_active_minus1);
515 COPY_FIELD (init_qp_minus26);
516 COPY_FIELD (dependent_slice_segments_enabled_flag);
517 COPY_FIELD (output_flag_present_flag);
518 COPY_FIELD (num_extra_slice_header_bits);
519 COPY_FIELD (sign_data_hiding_enabled_flag);
520 COPY_FIELD (cabac_init_present_flag);
521 COPY_FIELD (constrained_intra_pred_flag);
522 COPY_FIELD (transform_skip_enabled_flag);
523 COPY_FIELD (cu_qp_delta_enabled_flag);
524 COPY_FIELD_WITH_PREFIX (slice_chroma_qp_offsets_present_flag);
525 COPY_FIELD (weighted_pred_flag);
526 COPY_FIELD (weighted_bipred_flag);
527 COPY_FIELD (transquant_bypass_enabled_flag);
528 COPY_FIELD (tiles_enabled_flag);
529 COPY_FIELD (entropy_coding_sync_enabled_flag);
530 COPY_FIELD (uniform_spacing_flag);
532 if (pps->tiles_enabled_flag)
533 COPY_FIELD (loop_filter_across_tiles_enabled_flag);
535 COPY_FIELD_WITH_PREFIX (loop_filter_across_slices_enabled_flag);
536 COPY_FIELD (deblocking_filter_override_enabled_flag);
537 COPY_FIELD_WITH_PREFIX (deblocking_filter_disabled_flag);
538 COPY_FIELD (lists_modification_present_flag);
539 COPY_FIELD (slice_segment_header_extension_present_flag);
540 COPY_FIELD_WITH_PREFIX (cb_qp_offset);
541 COPY_FIELD_WITH_PREFIX (cr_qp_offset);
543 if (pps->tiles_enabled_flag) {
544 COPY_FIELD (num_tile_columns_minus1);
545 COPY_FIELD (num_tile_rows_minus1);
546 if (!pps->uniform_spacing_flag) {
547 for (i = 0; i < pps->num_tile_columns_minus1 &&
548 i < G_N_ELEMENTS (params->column_width_minus1); i++)
549 COPY_FIELD (column_width_minus1[i]);
551 for (i = 0; i < pps->num_tile_rows_minus1 &&
552 i < G_N_ELEMENTS (params->row_height_minus1); i++)
553 COPY_FIELD (row_height_minus1[i]);
557 COPY_FIELD (diff_cu_qp_delta_depth);
558 COPY_FIELD_WITH_PREFIX (beta_offset_div2);
559 COPY_FIELD_WITH_PREFIX (tc_offset_div2);
560 COPY_FIELD (log2_parallel_merge_level_minus2);
563 #undef COPY_FIELD_WITH_PREFIX
567 gst_d3d11_h265_dec_picture_params_from_slice_header (GstD3D11H265Dec *
568 self, const GstH265SliceHdr * slice_header, DXVA_PicParams_HEVC * params)
570 if (slice_header->short_term_ref_pic_set_sps_flag == 0) {
571 params->ucNumDeltaPocsOfRefRpsIdx =
572 slice_header->short_term_ref_pic_sets.NumDeltaPocsOfRefRpsIdx;
573 params->wNumBitsForShortTermRPSInSlice =
574 slice_header->short_term_ref_pic_set_size;
579 gst_d3d11_h265_dec_fill_picture_params (GstD3D11H265Dec * self,
580 const GstH265SliceHdr * slice_header, DXVA_PicParams_HEVC * params)
582 const GstH265SPS *sps;
583 const GstH265PPS *pps;
585 g_return_val_if_fail (slice_header->pps != NULL, FALSE);
586 g_return_val_if_fail (slice_header->pps->sps != NULL, FALSE);
588 pps = slice_header->pps;
591 /* not related to hevc syntax */
592 params->NoPicReorderingFlag = 0;
593 params->NoBiPredFlag = 0;
594 params->ReservedBits1 = 0;
595 params->StatusReportFeedbackNumber = 1;
597 gst_d3d11_h265_dec_picture_params_from_sps (self, sps, params);
598 gst_d3d11_h265_dec_picture_params_from_pps (self, pps, params);
599 gst_d3d11_h265_dec_picture_params_from_slice_header (self,
600 slice_header, params);
605 static ID3D11VideoDecoderOutputView *
606 gst_d3d11_h265_dec_get_output_view_from_picture (GstD3D11H265Dec * self,
607 GstH265Picture * picture, guint8 * view_id)
609 GstD3D11H265DecInner *inner = self->inner;
610 GstBuffer *view_buffer;
611 ID3D11VideoDecoderOutputView *view;
613 view_buffer = (GstBuffer *) gst_h265_picture_get_user_data (picture);
615 GST_DEBUG_OBJECT (self, "current picture does not have output view buffer");
619 view = gst_d3d11_decoder_get_output_view_from_buffer (inner->d3d11_decoder,
620 view_buffer, view_id);
622 GST_DEBUG_OBJECT (self, "current picture does not have output view handle");
630 gst_d3d11_h265_dec_get_ref_index (const DXVA_PicParams_HEVC * pic_params,
633 for (UCHAR i = 0; i < G_N_ELEMENTS (pic_params->RefPicList); i++) {
634 if (pic_params->RefPicList[i].Index7Bits == view_id)
642 init_pic_params (DXVA_PicParams_HEVC * params)
644 memset (params, 0, sizeof (DXVA_PicParams_HEVC));
645 for (guint i = 0; i < G_N_ELEMENTS (params->RefPicList); i++)
646 params->RefPicList[i].bPicEntry = 0xff;
648 for (guint i = 0; i < G_N_ELEMENTS (params->RefPicSetStCurrBefore); i++) {
649 params->RefPicSetStCurrBefore[i] = 0xff;
650 params->RefPicSetStCurrAfter[i] = 0xff;
651 params->RefPicSetLtCurr[i] = 0xff;
656 gst_d3d11_h265_dec_start_picture (GstH265Decoder * decoder,
657 GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb)
659 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
660 GstD3D11H265DecInner *inner = self->inner;
661 DXVA_PicParams_HEVC *pic_params = &inner->pic_params;
662 DXVA_Qmatrix_HEVC *iq_matrix = &inner->iq_matrix;
663 ID3D11VideoDecoderOutputView *view;
664 guint8 view_id = 0xff;
669 GstH265ScalingList *scaling_list = nullptr;
671 pps = slice->header.pps;
674 view = gst_d3d11_h265_dec_get_output_view_from_picture (self, picture,
677 GST_ERROR_OBJECT (self, "current picture does not have output view handle");
681 init_pic_params (pic_params);
682 gst_d3d11_h265_dec_fill_picture_params (self, &slice->header, pic_params);
684 pic_params->CurrPic.Index7Bits = view_id;
685 pic_params->IrapPicFlag = GST_H265_IS_NAL_TYPE_IRAP (slice->nalu.type);
686 pic_params->IdrPicFlag = GST_H265_IS_NAL_TYPE_IDR (slice->nalu.type);
687 pic_params->IntraPicFlag = GST_H265_IS_NAL_TYPE_IRAP (slice->nalu.type);
688 pic_params->CurrPicOrderCntVal = picture->pic_order_cnt;
690 dpb_array = gst_h265_dpb_get_pictures_all (dpb);
692 i < dpb_array->len && j < G_N_ELEMENTS (pic_params->RefPicList); i++) {
693 GstH265Picture *other = g_array_index (dpb_array, GstH265Picture *, i);
697 GST_LOG_OBJECT (self, "%dth picture in dpb is not reference, skip", i);
701 gst_d3d11_h265_dec_get_output_view_from_picture (self, other, &id);
702 pic_params->RefPicList[j].Index7Bits = id;
703 pic_params->RefPicList[j].AssociatedFlag = other->long_term;
704 pic_params->PicOrderCntValList[j] = other->pic_order_cnt;
707 g_array_unref (dpb_array);
709 for (i = 0, j = 0; i < G_N_ELEMENTS (pic_params->RefPicSetStCurrBefore); i++) {
710 GstH265Picture *other = nullptr;
711 guint8 other_view_id = 0xff;
714 while (!other && j < decoder->NumPocStCurrBefore)
715 other = decoder->RefPicSetStCurrBefore[j++];
718 ID3D11VideoDecoderOutputView *other_view;
720 other_view = gst_d3d11_h265_dec_get_output_view_from_picture (self,
721 other, &other_view_id);
724 id = gst_d3d11_h265_dec_get_ref_index (pic_params, other_view_id);
727 pic_params->RefPicSetStCurrBefore[i] = id;
730 for (i = 0, j = 0; i < G_N_ELEMENTS (pic_params->RefPicSetStCurrAfter); i++) {
731 GstH265Picture *other = nullptr;
732 guint8 other_view_id = 0xff;
735 while (!other && j < decoder->NumPocStCurrAfter)
736 other = decoder->RefPicSetStCurrAfter[j++];
739 ID3D11VideoDecoderOutputView *other_view;
741 other_view = gst_d3d11_h265_dec_get_output_view_from_picture (self,
742 other, &other_view_id);
745 id = gst_d3d11_h265_dec_get_ref_index (pic_params, other_view_id);
748 pic_params->RefPicSetStCurrAfter[i] = id;
751 for (i = 0, j = 0; i < G_N_ELEMENTS (pic_params->RefPicSetLtCurr); i++) {
752 GstH265Picture *other = nullptr;
753 guint8 other_view_id = 0xff;
756 while (!other && j < decoder->NumPocLtCurr)
757 other = decoder->RefPicSetLtCurr[j++];
760 ID3D11VideoDecoderOutputView *other_view;
762 other_view = gst_d3d11_h265_dec_get_output_view_from_picture (self,
763 other, &other_view_id);
766 id = gst_d3d11_h265_dec_get_ref_index (pic_params, other_view_id);
769 pic_params->RefPicSetLtCurr[i] = id;
772 if (pps->scaling_list_data_present_flag ||
773 (sps->scaling_list_enabled_flag
774 && !sps->scaling_list_data_present_flag)) {
775 scaling_list = &pps->scaling_list;
776 } else if (sps->scaling_list_enabled_flag &&
777 sps->scaling_list_data_present_flag) {
778 scaling_list = &sps->scaling_list;
782 G_STATIC_ASSERT (sizeof (iq_matrix->ucScalingLists0) ==
783 sizeof (scaling_list->scaling_lists_4x4));
784 G_STATIC_ASSERT (sizeof (iq_matrix->ucScalingLists1) ==
785 sizeof (scaling_list->scaling_lists_8x8));
786 G_STATIC_ASSERT (sizeof (iq_matrix->ucScalingLists2) ==
787 sizeof (scaling_list->scaling_lists_16x16));
788 G_STATIC_ASSERT (sizeof (iq_matrix->ucScalingLists3) ==
789 sizeof (scaling_list->scaling_lists_32x32));
791 memcpy (iq_matrix->ucScalingLists0, scaling_list->scaling_lists_4x4,
792 sizeof (iq_matrix->ucScalingLists0));
793 memcpy (iq_matrix->ucScalingLists1, scaling_list->scaling_lists_8x8,
794 sizeof (iq_matrix->ucScalingLists1));
795 memcpy (iq_matrix->ucScalingLists2, scaling_list->scaling_lists_16x16,
796 sizeof (iq_matrix->ucScalingLists2));
797 memcpy (iq_matrix->ucScalingLists3, scaling_list->scaling_lists_32x32,
798 sizeof (iq_matrix->ucScalingLists3));
800 for (i = 0; i < G_N_ELEMENTS (iq_matrix->ucScalingListDCCoefSizeID2); i++) {
801 iq_matrix->ucScalingListDCCoefSizeID2[i] =
802 scaling_list->scaling_list_dc_coef_minus8_16x16[i] + 8;
805 for (i = 0; i < G_N_ELEMENTS (iq_matrix->ucScalingListDCCoefSizeID3); i++) {
806 iq_matrix->ucScalingListDCCoefSizeID3[i] =
807 scaling_list->scaling_list_dc_coef_minus8_32x32[i] + 8;
810 inner->submit_iq_data = TRUE;
812 inner->submit_iq_data = FALSE;
815 inner->slice_list.resize (0);
816 inner->bitstream_buffer.resize (0);
822 gst_d3d11_h265_dec_decode_slice (GstH265Decoder * decoder,
823 GstH265Picture * picture, GstH265Slice * slice,
824 GArray * ref_pic_list0, GArray * ref_pic_list1)
826 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
827 GstD3D11H265DecInner *inner = self->inner;
828 DXVA_Slice_HEVC_Short dxva_slice;
829 static const guint8 start_code[] = { 0, 0, 1 };
830 const size_t start_code_size = sizeof (start_code);
832 dxva_slice.BSNALunitDataLocation = inner->bitstream_buffer.size ();
833 /* Includes 3 bytes start code prefix */
834 dxva_slice.SliceBytesInBuffer = slice->nalu.size + start_code_size;
835 dxva_slice.wBadSliceChopping = 0;
837 inner->slice_list.push_back (dxva_slice);
839 size_t pos = inner->bitstream_buffer.size ();
840 inner->bitstream_buffer.resize (pos + start_code_size + slice->nalu.size);
842 /* Fill start code prefix */
843 memcpy (&inner->bitstream_buffer[0] + pos, start_code, start_code_size);
846 memcpy (&inner->bitstream_buffer[0] + pos + start_code_size,
847 slice->nalu.data + slice->nalu.offset, slice->nalu.size);
853 gst_d3d11_h265_dec_end_picture (GstH265Decoder * decoder,
854 GstH265Picture * picture)
856 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
857 GstD3D11H265DecInner *inner = self->inner;
858 ID3D11VideoDecoderOutputView *view;
859 guint8 view_id = 0xff;
860 size_t bitstream_buffer_size;
861 size_t bitstream_pos;
862 GstD3D11DecodeInputStreamArgs input_args;
864 GST_LOG_OBJECT (self, "end picture %p, (poc %d)",
865 picture, picture->pic_order_cnt);
867 if (inner->bitstream_buffer.empty () || inner->slice_list.empty ()) {
868 GST_ERROR_OBJECT (self, "No bitstream buffer to submit");
872 view = gst_d3d11_h265_dec_get_output_view_from_picture (self, picture,
875 GST_ERROR_OBJECT (self, "current picture does not have output view handle");
879 memset (&input_args, 0, sizeof (GstD3D11DecodeInputStreamArgs));
881 bitstream_pos = inner->bitstream_buffer.size ();
882 bitstream_buffer_size = GST_ROUND_UP_128 (bitstream_pos);
884 if (bitstream_buffer_size > bitstream_pos) {
885 size_t padding = bitstream_buffer_size - bitstream_pos;
887 /* As per DXVA spec, total amount of bitstream buffer size should be
888 * 128 bytes aligned. If actual data is not multiple of 128 bytes,
889 * the last slice data needs to be zero-padded */
890 inner->bitstream_buffer.resize (bitstream_buffer_size, 0);
892 DXVA_Slice_HEVC_Short & slice = inner->slice_list.back ();
893 slice.SliceBytesInBuffer += padding;
896 input_args.picture_params = &inner->pic_params;
897 input_args.picture_params_size = sizeof (DXVA_PicParams_HEVC);
898 input_args.slice_control = &inner->slice_list[0];
899 input_args.slice_control_size =
900 sizeof (DXVA_Slice_HEVC_Short) * inner->slice_list.size ();
901 input_args.bitstream = &inner->bitstream_buffer[0];
902 input_args.bitstream_size = inner->bitstream_buffer.size ();
904 if (inner->submit_iq_data) {
905 input_args.inverse_quantization_matrix = &inner->iq_matrix;
906 input_args.inverse_quantization_matrix_size = sizeof (DXVA_Qmatrix_HEVC);
909 return gst_d3d11_decoder_decode_frame (inner->d3d11_decoder,
914 gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
915 GstVideoCodecFrame * frame, GstH265Picture * picture)
917 GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
918 GstD3D11H265DecInner *inner = self->inner;
919 GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
920 GstBuffer *view_buffer;
922 GST_LOG_OBJECT (self, "Outputting picture %p, poc %d, picture_struct %d, "
923 "buffer flags 0x%x", picture, picture->pic_order_cnt, picture->pic_struct,
924 picture->buffer_flags);
926 view_buffer = (GstBuffer *) gst_h265_picture_get_user_data (picture);
929 GST_ERROR_OBJECT (self, "Could not get output view");
933 if (!gst_d3d11_decoder_process_output (inner->d3d11_decoder, vdec,
934 inner->width, inner->height, view_buffer, &frame->output_buffer)) {
935 GST_ERROR_OBJECT (self, "Failed to copy buffer");
939 GST_BUFFER_FLAG_SET (frame->output_buffer, picture->buffer_flags);
940 gst_h265_picture_unref (picture);
942 return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
945 gst_h265_picture_unref (picture);
946 gst_video_decoder_release_frame (vdec, frame);
948 return GST_FLOW_ERROR;
952 gst_d3d11_h265_dec_register (GstPlugin * plugin, GstD3D11Device * device,
960 const GUID *profile = NULL;
961 GTypeInfo type_info = {
962 sizeof (GstD3D11H265DecClass),
965 (GClassInitFunc) gst_d3d11_h265_dec_class_init,
968 sizeof (GstD3D11H265Dec),
970 (GInstanceInitFunc) gst_d3d11_h265_dec_init,
972 const GUID *main_10_guid = NULL;
973 const GUID *main_guid = NULL;
974 GstCaps *sink_caps = NULL;
975 GstCaps *src_caps = NULL;
976 GstCaps *src_caps_copy;
978 GstCapsFeatures *caps_features;
980 guint max_height = 0;
982 gboolean have_main10 = FALSE;
983 gboolean have_main = FALSE;
984 DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
986 have_main10 = gst_d3d11_decoder_get_supported_decoder_profile (device,
987 GST_DXVA_CODEC_H265, GST_VIDEO_FORMAT_P010_10LE, &main_10_guid);
989 GST_DEBUG_OBJECT (device, "decoder does not support HEVC_VLD_MAIN10");
992 gst_d3d11_decoder_supports_format (device, main_10_guid,
995 GST_FIXME_OBJECT (device, "device does not support P010 format");
999 have_main = gst_d3d11_decoder_get_supported_decoder_profile (device,
1000 GST_DXVA_CODEC_H265, GST_VIDEO_FORMAT_NV12, &main_guid);
1002 GST_DEBUG_OBJECT (device, "decoder does not support HEVC_VLD_MAIN");
1005 gst_d3d11_decoder_supports_format (device, main_guid, DXGI_FORMAT_NV12);
1007 GST_FIXME_OBJECT (device, "device does not support NV12 format");
1011 if (!have_main10 && !have_main) {
1012 GST_INFO_OBJECT (device, "device does not support h.265 decoding");
1017 profile = main_guid;
1018 format = DXGI_FORMAT_NV12;
1020 profile = main_10_guid;
1021 format = DXGI_FORMAT_P010;
1024 for (i = 0; i < G_N_ELEMENTS (gst_dxva_resolutions); i++) {
1025 if (gst_d3d11_decoder_supports_resolution (device, profile,
1026 format, gst_dxva_resolutions[i].width,
1027 gst_dxva_resolutions[i].height)) {
1028 max_width = gst_dxva_resolutions[i].width;
1029 max_height = gst_dxva_resolutions[i].height;
1031 GST_DEBUG_OBJECT (device,
1032 "device support resolution %dx%d", max_width, max_height);
1038 if (max_width == 0 || max_height == 0) {
1039 GST_WARNING_OBJECT (device, "Couldn't query supported resolution");
1043 sink_caps = gst_caps_from_string ("video/x-h265, "
1044 "stream-format=(string) { hev1, hvc1, byte-stream }, "
1045 "alignment= (string) au");
1046 src_caps = gst_caps_new_empty_simple ("video/x-raw");
1049 /* main10 profile covers main and main10 */
1050 GValue profile_list = G_VALUE_INIT;
1051 GValue profile_value = G_VALUE_INIT;
1052 GValue format_list = G_VALUE_INIT;
1053 GValue format_value = G_VALUE_INIT;
1055 g_value_init (&profile_list, GST_TYPE_LIST);
1057 g_value_init (&profile_value, G_TYPE_STRING);
1058 g_value_set_string (&profile_value, "main");
1059 gst_value_list_append_and_take_value (&profile_list, &profile_value);
1061 g_value_init (&profile_value, G_TYPE_STRING);
1062 g_value_set_string (&profile_value, "main-10");
1063 gst_value_list_append_and_take_value (&profile_list, &profile_value);
1066 g_value_init (&format_list, GST_TYPE_LIST);
1068 g_value_init (&format_value, G_TYPE_STRING);
1069 g_value_set_string (&format_value, "NV12");
1070 gst_value_list_append_and_take_value (&format_list, &format_value);
1072 g_value_init (&format_value, G_TYPE_STRING);
1073 g_value_set_string (&format_value, "P010_10LE");
1074 gst_value_list_append_and_take_value (&format_list, &format_value);
1076 gst_caps_set_value (sink_caps, "profile", &profile_list);
1077 gst_caps_set_value (src_caps, "format", &format_list);
1078 g_value_unset (&profile_list);
1079 g_value_unset (&format_list);
1081 gst_caps_set_simple (sink_caps, "profile", G_TYPE_STRING, "main", NULL);
1082 gst_caps_set_simple (src_caps, "format", G_TYPE_STRING, "NV12", NULL);
1085 /* To cover both landscape and portrait, select max value */
1086 resolution = MAX (max_width, max_height);
1087 gst_caps_set_simple (sink_caps,
1088 "width", GST_TYPE_INT_RANGE, 1, resolution,
1089 "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
1090 gst_caps_set_simple (src_caps,
1091 "width", GST_TYPE_INT_RANGE, 1, resolution,
1092 "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
1094 /* Copy src caps to append other capsfeatures */
1095 src_caps_copy = gst_caps_copy (src_caps);
1097 /* System memory with alternate interlace-mode */
1098 tmp = gst_caps_copy (src_caps_copy);
1099 caps_features = gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED,
1101 gst_caps_set_features_simple (tmp, caps_features);
1102 gst_caps_set_simple (tmp, "interlace-mode", G_TYPE_STRING, "alternate", NULL);
1103 gst_caps_append (src_caps, tmp);
1105 /* D3D11 memory feature */
1106 tmp = gst_caps_copy (src_caps_copy);
1107 caps_features = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY,
1109 gst_caps_set_features_simple (tmp, caps_features);
1110 gst_caps_append (src_caps, tmp);
1112 /* FIXME: D3D11 deinterlace element is not prepared, so this D3D11 with
1113 * interlaced caps feature is pointless at the moment */
1115 /* D3D11 memory with alternate interlace-mode */
1116 tmp = gst_caps_copy (src_caps_copy);
1117 caps_features = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY,
1118 GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL);
1119 gst_caps_set_features_simple (tmp, caps_features);
1120 gst_caps_set_simple (tmp, "interlace-mode", G_TYPE_STRING, "alternate", NULL);
1121 gst_caps_append (src_caps, tmp);
1124 gst_caps_unref (src_caps_copy);
1126 type_info.class_data =
1127 gst_d3d11_decoder_class_data_new (device, GST_DXVA_CODEC_H265,
1128 sink_caps, src_caps);
1130 type_name = g_strdup ("GstD3D11H265Dec");
1131 feature_name = g_strdup ("d3d11h265dec");
1133 while (g_type_from_name (type_name)) {
1136 g_free (feature_name);
1137 type_name = g_strdup_printf ("GstD3D11H265Device%dDec", index);
1138 feature_name = g_strdup_printf ("d3d11h265device%ddec", index);
1141 type = g_type_register_static (GST_TYPE_H265_DECODER,
1142 type_name, &type_info, (GTypeFlags) 0);
1144 /* make lower rank than default device */
1145 if (rank > 0 && index != 0)
1148 if (!gst_element_register (plugin, feature_name, rank, type))
1149 GST_WARNING ("Failed to register plugin '%s'", type_name);
1152 g_free (feature_name);