2 * gstvaapidecoder_h265.c - H.265 decoder
4 * Copyright (C) 2015 Intel Corporation
5 * Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1
10 * of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA
24 * SECTION:gstvaapidecoder_h265
25 * @short_description: H.265 decoder
30 #include <gst/base/gstadapter.h>
31 #include <gst/codecparsers/gsth265parser.h>
32 #include "gstvaapidecoder_h265.h"
33 #include "gstvaapidecoder_objects.h"
34 #include "gstvaapidecoder_priv.h"
35 #include "gstvaapidisplay_priv.h"
36 #include "gstvaapiobject_priv.h"
37 #include "gstvaapiutils_h265_priv.h"
40 #include "gstvaapidebug.h"
42 /* Defined to 1 if strict ordering of DPB is needed. Only useful for debug */
43 #define USE_STRICT_DPB_ORDERING 0
45 typedef struct _GstVaapiDecoderH265Private GstVaapiDecoderH265Private;
46 typedef struct _GstVaapiDecoderH265Class GstVaapiDecoderH265Class;
47 typedef struct _GstVaapiFrameStore GstVaapiFrameStore;
48 typedef struct _GstVaapiFrameStoreClass GstVaapiFrameStoreClass;
49 typedef struct _GstVaapiParserInfoH265 GstVaapiParserInfoH265;
50 typedef struct _GstVaapiPictureH265 GstVaapiPictureH265;
52 static gboolean nal_is_slice (guint8 nal_type);
54 /* ------------------------------------------------------------------------- */
55 /* --- H.265 Parser Info --- */
56 /* ------------------------------------------------------------------------- */
59 * Extended decoder unit flags:
61 * @GST_VAAPI_DECODER_UNIT_AU_START: marks the start of an access unit.
62 * @GST_VAAPI_DECODER_UNIT_AU_END: marks the end of an access unit.
66 GST_VAAPI_DECODER_UNIT_FLAG_AU_START =
67 (GST_VAAPI_DECODER_UNIT_FLAG_LAST << 0),
68 GST_VAAPI_DECODER_UNIT_FLAG_AU_END = (GST_VAAPI_DECODER_UNIT_FLAG_LAST << 1),
70 GST_VAAPI_DECODER_UNIT_FLAGS_AU = (GST_VAAPI_DECODER_UNIT_FLAG_AU_START |
71 GST_VAAPI_DECODER_UNIT_FLAG_AU_END),
74 #define GST_VAAPI_PARSER_INFO_H265(obj) \
75 ((GstVaapiParserInfoH265 *)(obj))
77 struct _GstVaapiParserInfoH265
79 GstVaapiMiniObject parent_instance;
86 /* Fix SEI parsing in codecparser, have to use GArry like h264parser */
87 GstH265SEIMessage sei;
88 GstH265SliceHdr slice_hdr;
91 guint flags; // Same as decoder unit flags (persistent)
95 gst_vaapi_parser_info_h265_finalize (GstVaapiParserInfoH265 * pi)
97 if (nal_is_slice (pi->nalu.type))
98 gst_h265_slice_hdr_free (&pi->data.slice_hdr);
100 switch (pi->nalu.type) {
101 case GST_H265_NAL_VPS:
102 case GST_H265_NAL_SPS:
103 case GST_H265_NAL_PPS:
105 case GST_H265_NAL_PREFIX_SEI:
106 case GST_H265_NAL_SUFFIX_SEI:
107 gst_h265_sei_free (&pi->data.sei);
113 static inline const GstVaapiMiniObjectClass *
114 gst_vaapi_parser_info_h265_class (void)
116 static const GstVaapiMiniObjectClass GstVaapiParserInfoH265Class = {
117 .size = sizeof (GstVaapiParserInfoH265),
118 .finalize = (GDestroyNotify) gst_vaapi_parser_info_h265_finalize
120 return &GstVaapiParserInfoH265Class;
123 static inline GstVaapiParserInfoH265 *
124 gst_vaapi_parser_info_h265_new (void)
126 return (GstVaapiParserInfoH265 *)
127 gst_vaapi_mini_object_new (gst_vaapi_parser_info_h265_class ());
130 #define gst_vaapi_parser_info_h265_ref(pi) \
131 gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(pi))
133 #define gst_vaapi_parser_info_h265_unref(pi) \
134 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(pi))
136 #define gst_vaapi_parser_info_h265_replace(old_pi_ptr, new_pi) \
137 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_pi_ptr), \
138 (GstVaapiMiniObject *)(new_pi))
140 /* ------------------------------------------------------------------------- */
141 /* --- H.265 Pictures --- */
142 /* ------------------------------------------------------------------------- */
145 * Extended picture flags:
147 * @GST_VAAPI_PICTURE_FLAG_IDR: flag that specifies an IDR picture
148 * @GST_VAAPI_PICTURE_FLAG_AU_START: flag that marks the start of an
150 * @GST_VAAPI_PICTURE_FLAG_AU_END: flag that marks the end of an
152 * @GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_BEFORE: flag indicate the inclusion
153 * of picture in RefPicSetStCurrBefore reference list
154 * @GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_AFTER: flag indicate the inclusion
155 * of picture in RefPictSetStCurrAfter reference list
156 * @GST_VAAPI_PICTURE_FLAG_RPS_ST_FOLL: flag indicate the inclusion
157 * of picture in RefPicSetStFoll reference list
158 * @GST_VAAPI_PICTURE_FLAG_RPS_LT_CURR: flag indicate the inclusion
159 * of picture in RefPicSetLtCurr reference list
160 * @GST_VAAPI_PICTURE_FLAG_RPS_LT_FOLL: flag indicate the inclusion
161 * of picture in RefPicSetLtFoll reference list
162 * @GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE: flag that specifies
163 * "used for short-term reference"
164 * @GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE: flag that specifies
165 * "used for long-term reference"
166 * @GST_VAAPI_PICTURE_FLAGS_REFERENCE: mask covering any kind of
167 * reference picture (short-term reference or long-term reference)
171 GST_VAAPI_PICTURE_FLAG_IDR = (GST_VAAPI_PICTURE_FLAG_LAST << 0),
172 GST_VAAPI_PICTURE_FLAG_REFERENCE2 = (GST_VAAPI_PICTURE_FLAG_LAST << 1),
173 GST_VAAPI_PICTURE_FLAG_AU_START = (GST_VAAPI_PICTURE_FLAG_LAST << 4),
174 GST_VAAPI_PICTURE_FLAG_AU_END = (GST_VAAPI_PICTURE_FLAG_LAST << 5),
175 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_BEFORE =
176 (GST_VAAPI_PICTURE_FLAG_LAST << 6),
177 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_AFTER = (GST_VAAPI_PICTURE_FLAG_LAST << 7),
178 GST_VAAPI_PICTURE_FLAG_RPS_ST_FOLL = (GST_VAAPI_PICTURE_FLAG_LAST << 8),
179 GST_VAAPI_PICTURE_FLAG_RPS_LT_CURR = (GST_VAAPI_PICTURE_FLAG_LAST << 9),
180 GST_VAAPI_PICTURE_FLAG_RPS_LT_FOLL = (GST_VAAPI_PICTURE_FLAG_LAST << 10),
182 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE =
183 (GST_VAAPI_PICTURE_FLAG_REFERENCE),
184 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE =
185 (GST_VAAPI_PICTURE_FLAG_REFERENCE | GST_VAAPI_PICTURE_FLAG_REFERENCE2),
186 GST_VAAPI_PICTURE_FLAGS_REFERENCE =
187 (GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
188 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE),
190 GST_VAAPI_PICTURE_FLAGS_RPS_ST =
191 (GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_BEFORE |
192 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_AFTER |
193 GST_VAAPI_PICTURE_FLAG_RPS_ST_FOLL),
194 GST_VAAPI_PICTURE_FLAGS_RPS_LT =
195 (GST_VAAPI_PICTURE_FLAG_RPS_LT_CURR | GST_VAAPI_PICTURE_FLAG_RPS_LT_FOLL),
198 #define GST_VAAPI_PICTURE_IS_IDR(picture) \
199 (GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_IDR))
201 #define GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture) \
202 ((GST_VAAPI_PICTURE_FLAGS(picture) & \
203 GST_VAAPI_PICTURE_FLAGS_REFERENCE) == \
204 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE)
206 #define GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture) \
207 ((GST_VAAPI_PICTURE_FLAGS(picture) & \
208 GST_VAAPI_PICTURE_FLAGS_REFERENCE) == \
209 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE)
211 #define GST_VAAPI_PICTURE_H265(picture) \
212 ((GstVaapiPictureH265 *)(picture))
214 struct _GstVaapiPictureH265
216 GstVaapiPicture base;
217 GstH265SliceHdr *last_slice_hdr;
219 gint32 poc; // PicOrderCntVal (8.3.1)
220 gint32 poc_lsb; // slice_pic_order_cnt_lsb
221 guint32 pic_latency_cnt; // PicLatencyCount
223 guint output_needed:1;
224 guint NoRaslOutputFlag:1;
225 guint NoOutputOfPriorPicsFlag:1;
226 guint RapPicFlag:1; // nalu type between 16 and 21
227 guint IntraPicFlag:1; // Intra pic (only Intra slices)
230 GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiPictureH265, gst_vaapi_picture_h265);
233 gst_vaapi_picture_h265_destroy (GstVaapiPictureH265 * picture)
235 gst_vaapi_picture_destroy (GST_VAAPI_PICTURE (picture));
239 gst_vaapi_picture_h265_create (GstVaapiPictureH265 * picture,
240 const GstVaapiCodecObjectConstructorArgs * args)
242 if (!gst_vaapi_picture_create (GST_VAAPI_PICTURE (picture), args))
245 picture->poc = G_MAXINT32;
246 picture->output_needed = FALSE;
250 static inline GstVaapiPictureH265 *
251 gst_vaapi_picture_h265_new (GstVaapiDecoderH265 * decoder)
253 return (GstVaapiPictureH265 *)
254 gst_vaapi_codec_object_new (&GstVaapiPictureH265Class,
255 GST_VAAPI_CODEC_BASE (decoder), NULL,
256 sizeof (VAPictureParameterBufferHEVC), NULL, 0, 0);
260 gst_vaapi_picture_h265_set_reference (GstVaapiPictureH265 * picture,
261 guint reference_flags)
265 GST_VAAPI_PICTURE_FLAG_UNSET (picture,
266 GST_VAAPI_PICTURE_FLAGS_RPS_ST | GST_VAAPI_PICTURE_FLAGS_RPS_LT);
267 GST_VAAPI_PICTURE_FLAG_UNSET (picture, GST_VAAPI_PICTURE_FLAGS_REFERENCE);
268 GST_VAAPI_PICTURE_FLAG_SET (picture, reference_flags);
271 /* ------------------------------------------------------------------------- */
272 /* --- Frame Buffers (DPB) --- */
273 /* ------------------------------------------------------------------------- */
275 struct _GstVaapiFrameStore
278 GstVaapiMiniObject parent_instance;
280 GstVaapiPictureH265 *buffer;
284 gst_vaapi_frame_store_finalize (gpointer object)
286 GstVaapiFrameStore *const fs = object;
288 gst_vaapi_picture_replace (&fs->buffer, NULL);
291 static GstVaapiFrameStore *
292 gst_vaapi_frame_store_new (GstVaapiPictureH265 * picture)
294 GstVaapiFrameStore *fs;
296 static const GstVaapiMiniObjectClass GstVaapiFrameStoreClass = {
297 sizeof (GstVaapiFrameStore),
298 gst_vaapi_frame_store_finalize
301 fs = (GstVaapiFrameStore *)
302 gst_vaapi_mini_object_new (&GstVaapiFrameStoreClass);
306 fs->buffer = gst_vaapi_picture_ref (picture);
311 static inline gboolean
312 gst_vaapi_frame_store_has_reference (GstVaapiFrameStore * fs)
314 if (GST_VAAPI_PICTURE_IS_REFERENCE (fs->buffer))
319 #define gst_vaapi_frame_store_ref(fs) \
320 gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(fs))
322 #define gst_vaapi_frame_store_unref(fs) \
323 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(fs))
325 #define gst_vaapi_frame_store_replace(old_fs_p, new_fs) \
326 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_fs_p), \
327 (GstVaapiMiniObject *)(new_fs))
329 /* ------------------------------------------------------------------------- */
330 /* --- H.265 Decoder --- */
331 /* ------------------------------------------------------------------------- */
333 #define GST_VAAPI_DECODER_H265_CAST(decoder) \
334 ((GstVaapiDecoderH265 *)(decoder))
338 GST_H265_VIDEO_STATE_GOT_VPS = 1 << 0,
339 GST_H265_VIDEO_STATE_GOT_SPS = 1 << 1,
340 GST_H265_VIDEO_STATE_GOT_PPS = 1 << 2,
341 GST_H265_VIDEO_STATE_GOT_SLICE = 1 << 3,
343 GST_H265_VIDEO_STATE_VALID_PICTURE_HEADERS =
344 (GST_H265_VIDEO_STATE_GOT_SPS | GST_H265_VIDEO_STATE_GOT_PPS),
345 GST_H265_VIDEO_STATE_VALID_PICTURE =
346 (GST_H265_VIDEO_STATE_VALID_PICTURE_HEADERS |
347 GST_H265_VIDEO_STATE_GOT_SLICE)
350 struct _GstVaapiDecoderH265Private
352 GstH265Parser *parser;
355 GstVaapiStreamAlignH265 stream_alignment;
356 GstVaapiPictureH265 *current_picture;
357 GstVaapiParserInfoH265 *vps[GST_H265_MAX_VPS_COUNT];
358 GstVaapiParserInfoH265 *active_vps;
359 GstVaapiParserInfoH265 *sps[GST_H265_MAX_SPS_COUNT];
360 GstVaapiParserInfoH265 *active_sps;
361 GstVaapiParserInfoH265 *pps[GST_H265_MAX_PPS_COUNT];
362 GstVaapiParserInfoH265 *active_pps;
363 GstVaapiParserInfoH265 *prev_pi;
364 GstVaapiParserInfoH265 *prev_slice_pi;
365 GstVaapiParserInfoH265 *prev_independent_slice_pi;
366 GstVaapiFrameStore **dpb;
370 GstVaapiProfile profile;
371 GstVaapiEntrypoint entrypoint;
372 GstVaapiChromaType chroma_type;
374 GstVaapiPictureH265 *RefPicSetStCurrBefore[16];
375 GstVaapiPictureH265 *RefPicSetStCurrAfter[16];
376 GstVaapiPictureH265 *RefPicSetStFoll[16];
377 GstVaapiPictureH265 *RefPicSetLtCurr[16];
378 GstVaapiPictureH265 *RefPicSetLtFoll[16];
380 GstVaapiPictureH265 *RefPicList0[16];
381 guint RefPicList0_count;
382 GstVaapiPictureH265 *RefPicList1[16];
383 guint RefPicList1_count;
385 guint32 SpsMaxLatencyPictures;
387 guint nal_length_size;
389 guint pic_width_in_luma_samples; //sps->pic_width_in_luma_samples
390 guint pic_height_in_luma_samples; //sps->pic_height_in_luma_samples
391 guint pic_structure; // pic_struct (from SEI pic_timing() or inferred)
392 gint32 poc; // PicOrderCntVal
393 gint32 poc_msb; // PicOrderCntMsb
394 gint32 poc_lsb; // pic_order_cnt_lsb (from slice_header())
395 gint32 prev_poc_msb; // prevPicOrderCntMsb
396 gint32 prev_poc_lsb; // prevPicOrderCntLsb
397 gint32 prev_tid0pic_poc_lsb;
398 gint32 prev_tid0pic_poc_msb;
399 gint32 PocStCurrBefore[16];
400 gint32 PocStCurrAfter[16];
401 gint32 PocStFoll[16];
402 gint32 PocLtCurr[16];
403 gint32 PocLtFoll[16];
404 guint NumPocStCurrBefore;
405 guint NumPocStCurrAfter;
409 guint NumPocTotalCurr;
413 guint progressive_sequence:1;
417 * GstVaapiDecoderH265:
419 * A decoder based on H265.
421 struct _GstVaapiDecoderH265
424 GstVaapiDecoder parent_instance;
425 GstVaapiDecoderH265Private priv;
429 * GstVaapiDecoderH265Class:
431 * A decoder class based on H265.
433 struct _GstVaapiDecoderH265Class
436 GstVaapiDecoderClass parent_class;
439 #define RSV_VCL_N10 10
440 #define RSV_VCL_N12 12
441 #define RSV_VCL_N14 14
444 nal_is_idr (guint8 nal_type)
446 if ((nal_type == GST_H265_NAL_SLICE_IDR_W_RADL) ||
447 (nal_type == GST_H265_NAL_SLICE_IDR_N_LP))
453 nal_is_irap (guint8 nal_type)
455 if ((nal_type >= GST_H265_NAL_SLICE_BLA_W_LP) &&
456 (nal_type <= RESERVED_IRAP_NAL_TYPE_MAX))
462 nal_is_bla (guint8 nal_type)
464 if ((nal_type >= GST_H265_NAL_SLICE_BLA_W_LP) &&
465 (nal_type <= GST_H265_NAL_SLICE_BLA_N_LP))
471 nal_is_radl (guint8 nal_type)
473 if ((nal_type >= GST_H265_NAL_SLICE_RADL_N) &&
474 (nal_type <= GST_H265_NAL_SLICE_RADL_R))
480 nal_is_rasl (guint8 nal_type)
482 if ((nal_type >= GST_H265_NAL_SLICE_RASL_N) &&
483 (nal_type <= GST_H265_NAL_SLICE_RASL_R))
489 nal_is_slice (guint8 nal_type)
491 if ((nal_type >= GST_H265_NAL_SLICE_TRAIL_N) &&
492 (nal_type <= GST_H265_NAL_SLICE_CRA_NUT))
498 nal_is_ref (guint8 nal_type)
500 gboolean ret = FALSE;
502 case GST_H265_NAL_SLICE_TRAIL_N:
503 case GST_H265_NAL_SLICE_TSA_N:
504 case GST_H265_NAL_SLICE_STSA_N:
505 case GST_H265_NAL_SLICE_RADL_N:
506 case GST_H265_NAL_SLICE_RASL_N:
519 /* Activates the supplied PPS */
521 ensure_pps (GstVaapiDecoderH265 * decoder, GstH265PPS * pps)
523 GstVaapiDecoderH265Private *const priv = &decoder->priv;
524 GstVaapiParserInfoH265 *const pi = priv->pps[pps->id];
525 gst_vaapi_parser_info_h265_replace (&priv->active_pps, pi);
526 return pi ? &pi->data.pps : NULL;
529 /* Returns the active PPS */
530 static inline GstH265PPS *
531 get_pps (GstVaapiDecoderH265 * decoder)
533 GstVaapiParserInfoH265 *const pi = decoder->priv.active_pps;
534 return pi ? &pi->data.pps : NULL;
537 /* Activate the supplied SPS */
539 ensure_sps (GstVaapiDecoderH265 * decoder, GstH265SPS * sps)
541 GstVaapiDecoderH265Private *const priv = &decoder->priv;
542 GstVaapiParserInfoH265 *const pi = priv->sps[sps->id];
543 gst_vaapi_parser_info_h265_replace (&priv->active_sps, pi);
544 return pi ? &pi->data.sps : NULL;
547 /* Returns the active SPS */
548 static inline GstH265SPS *
549 get_sps (GstVaapiDecoderH265 * decoder)
551 GstVaapiParserInfoH265 *const pi = decoder->priv.active_sps;
552 return pi ? &pi->data.sps : NULL;
555 /* Activate the supplied VPS */
557 ensure_vps (GstVaapiDecoderH265 * decoder, GstH265VPS * vps)
559 GstVaapiDecoderH265Private *const priv = &decoder->priv;
560 GstVaapiParserInfoH265 *const pi = priv->vps[vps->id];
561 gst_vaapi_parser_info_h265_replace (&priv->active_vps, pi);
562 return pi ? &pi->data.vps : NULL;
565 /* Returns the active VPS */
566 static inline GstH265VPS *
567 get_vps (GstVaapiDecoderH265 * decoder)
569 GstVaapiParserInfoH265 *const pi = decoder->priv.active_vps;
570 return pi ? &pi->data.vps : NULL;
573 /* Get number of reference frames to use */
575 get_max_dec_frame_buffering (GstH265SPS * sps)
577 guint max_dec_frame_buffering;
578 GstVaapiLevelH265 level;
579 const GstVaapiH265LevelLimits *level_limits;
580 level = gst_vaapi_utils_h265_get_level (sps->profile_tier_level.level_idc);
581 level_limits = gst_vaapi_utils_h265_get_level_limits (level);
582 if (G_UNLIKELY (!level_limits)) {
583 GST_FIXME ("unsupported level_idc value (%d)",
584 sps->profile_tier_level.level_idc);
585 max_dec_frame_buffering = 16;
587 /* Fixme: Add limit check based on Annex A */
588 return MAX (1, (sps->max_dec_pic_buffering_minus1[0] + 1));
592 dpb_remove_index (GstVaapiDecoderH265 * decoder, gint index)
594 GstVaapiDecoderH265Private *const priv = &decoder->priv;
595 guint i, num_frames = --priv->dpb_count;
596 if (USE_STRICT_DPB_ORDERING) {
597 for (i = index; i < num_frames; i++)
598 gst_vaapi_frame_store_replace (&priv->dpb[i], priv->dpb[i + 1]);
599 } else if (index != num_frames)
600 gst_vaapi_frame_store_replace (&priv->dpb[index], priv->dpb[num_frames]);
601 gst_vaapi_frame_store_replace (&priv->dpb[num_frames], NULL);
605 dpb_output (GstVaapiDecoderH265 * decoder, GstVaapiFrameStore * fs)
607 GstVaapiPictureH265 *picture;
608 g_return_val_if_fail (fs != NULL, FALSE);
610 picture = fs->buffer;
611 g_return_val_if_fail (picture != NULL, FALSE);
613 picture->output_needed = FALSE;
614 return gst_vaapi_picture_output (GST_VAAPI_PICTURE_CAST (picture));
617 /* Get the dpb picture having the specifed poc or poc_lsb */
618 static GstVaapiPictureH265 *
619 dpb_get_picture (GstVaapiDecoderH265 * decoder, gint poc, gboolean match_lsb)
621 GstVaapiDecoderH265Private *const priv = &decoder->priv;
622 GstVaapiPictureH265 *picture = NULL;
625 for (i = 0; i < priv->dpb_count; i++) {
626 GstVaapiFrameStore *const fs = priv->dpb[i];
627 picture = fs->buffer;
629 if (picture && GST_VAAPI_PICTURE_FLAG_IS_SET (picture,
630 GST_VAAPI_PICTURE_FLAGS_REFERENCE)) {
632 if (picture->poc_lsb == poc)
635 if (picture->poc == poc)
643 /* Get the dpb picture having the specifed poc and shor/long ref flags */
644 static GstVaapiPictureH265 *
645 dpb_get_ref_picture (GstVaapiDecoderH265 * decoder, gint poc, gboolean is_short)
647 GstVaapiDecoderH265Private *const priv = &decoder->priv;
648 GstVaapiPictureH265 *picture = NULL;
651 for (i = 0; i < priv->dpb_count; i++) {
652 GstVaapiFrameStore *const fs = priv->dpb[i];
653 picture = fs->buffer;
655 if (picture && picture->poc == poc) {
656 if (is_short && GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE (picture))
659 else if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE (picture))
667 /* Finds the picture with the lowest POC that needs to be output */
669 dpb_find_lowest_poc (GstVaapiDecoderH265 * decoder,
670 GstVaapiPictureH265 ** found_picture_ptr)
672 GstVaapiDecoderH265Private *const priv = &decoder->priv;
673 GstVaapiPictureH265 *found_picture = NULL;
674 GstVaapiPictureH265 *tmp_picture = NULL;
675 guint i, found_index;
677 for (i = 0; i < priv->dpb_count; i++) {
678 GstVaapiFrameStore *const fs = priv->dpb[i];
679 tmp_picture = fs->buffer;
680 if (tmp_picture && !tmp_picture->output_needed)
682 if (!found_picture) {
683 found_picture = tmp_picture;
686 if (found_picture->poc > tmp_picture->poc) {
687 found_picture = tmp_picture;
692 if (found_picture_ptr)
693 *found_picture_ptr = found_picture;
694 return found_picture ? found_index : -1;
698 dpb_bump (GstVaapiDecoderH265 * decoder, GstVaapiPictureH265 * picture)
700 GstVaapiDecoderH265Private *const priv = &decoder->priv;
701 GstVaapiPictureH265 *found_picture;
705 found_index = dpb_find_lowest_poc (decoder, &found_picture);
709 success = dpb_output (decoder, priv->dpb[found_index]);
711 if (!gst_vaapi_frame_store_has_reference (priv->dpb[found_index]))
712 dpb_remove_index (decoder, found_index);
718 dpb_clear (GstVaapiDecoderH265 * decoder, gboolean hard_flush)
720 GstVaapiDecoderH265Private *const priv = &decoder->priv;
721 GstVaapiPictureH265 *pic;
725 for (i = 0; i < priv->dpb_count; i++)
726 dpb_remove_index (decoder, i);
729 /* Remove unused pictures from DPB */
731 while (i < priv->dpb_count) {
732 GstVaapiFrameStore *const fs = priv->dpb[i];
734 if (!pic->output_needed && !gst_vaapi_frame_store_has_reference (fs))
735 dpb_remove_index (decoder, i);
743 dpb_flush (GstVaapiDecoderH265 * decoder)
745 /* Output any frame remaining in DPB */
746 while (dpb_bump (decoder, NULL));
747 dpb_clear (decoder, TRUE);
751 dpb_get_num_need_output (GstVaapiDecoderH265 * decoder)
753 GstVaapiDecoderH265Private *const priv = &decoder->priv;
754 guint i = 0, n_output_needed = 0;
756 while (i < priv->dpb_count) {
757 GstVaapiFrameStore *const fs = priv->dpb[i];
758 if (fs->buffer->output_needed)
763 return n_output_needed;
767 check_latency_cnt (GstVaapiDecoderH265 * decoder)
769 GstVaapiPictureH265 *tmp_pic;
771 GstVaapiDecoderH265Private *const priv = &decoder->priv;
773 while (i < priv->dpb_count) {
774 GstVaapiFrameStore *const fs = priv->dpb[i];
775 tmp_pic = fs->buffer;
776 if (tmp_pic->output_needed) {
777 if (tmp_pic->pic_latency_cnt >= priv->SpsMaxLatencyPictures)
787 dpb_add (GstVaapiDecoderH265 * decoder, GstVaapiPictureH265 * picture)
789 GstVaapiFrameStore *fs;
790 GstVaapiPictureH265 *tmp_pic;
792 GstVaapiDecoderH265Private *const priv = &decoder->priv;
793 GstH265SPS *const sps = get_sps (decoder);
796 while (i < priv->dpb_count) {
797 GstVaapiFrameStore *const fs = priv->dpb[i];
798 tmp_pic = fs->buffer;
799 if (tmp_pic->output_needed)
800 tmp_pic->pic_latency_cnt += 1;
804 if (picture->output_flag) {
805 picture->output_needed = 1;
806 picture->pic_latency_cnt = 0;
808 picture->output_needed = 0;
810 /* set pic as short_term_ref */
811 gst_vaapi_picture_h265_set_reference (picture,
812 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE);
814 /* C.5.2.4 "Bumping" process */
815 while ((dpb_get_num_need_output (decoder) >
816 sps->max_num_reorder_pics[sps->max_sub_layers_minus1])
817 || (sps->max_latency_increase_plus1[sps->max_sub_layers_minus1]
818 && check_latency_cnt (decoder)))
819 dpb_bump (decoder, picture);
821 /* Create new frame store */
822 fs = gst_vaapi_frame_store_new (picture);
825 gst_vaapi_frame_store_replace (&priv->dpb[priv->dpb_count++], fs);
826 gst_vaapi_frame_store_unref (fs);
833 dpb_init (GstVaapiDecoderH265 * decoder, GstVaapiPictureH265 * picture,
834 GstVaapiParserInfoH265 * pi)
836 GstVaapiDecoderH265Private *const priv = &decoder->priv;
837 GstH265SPS *const sps = get_sps (decoder);
839 /* Fixme: Not required?? */
840 if (nal_is_idr (pi->nalu.type))
841 while (dpb_bump (decoder, picture));
844 if (picture->IntraPicFlag &&
845 picture->NoRaslOutputFlag /*&& Fixme: Not picture0 */ ) {
846 if (picture->NoOutputOfPriorPicsFlag)
847 dpb_clear (decoder, TRUE);
849 dpb_clear (decoder, FALSE);
851 dpb_clear (decoder, FALSE);
852 while ((dpb_get_num_need_output (decoder) >
853 sps->max_num_reorder_pics[sps->max_sub_layers_minus1])
854 || (sps->max_latency_increase_plus1[sps->max_sub_layers_minus1]
855 && check_latency_cnt (decoder))
856 || (priv->dpb_count >=
857 (sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1] +
859 dpb_bump (decoder, picture);
867 dpb_reset (GstVaapiDecoderH265 * decoder, guint dpb_size)
869 GstVaapiDecoderH265Private *const priv = &decoder->priv;
870 if (dpb_size > priv->dpb_size_max) {
871 priv->dpb = g_try_realloc_n (priv->dpb, dpb_size, sizeof (*priv->dpb));
874 memset (&priv->dpb[priv->dpb_size_max], 0,
875 (dpb_size - priv->dpb_size_max) * sizeof (*priv->dpb));
876 priv->dpb_size_max = dpb_size;
878 priv->dpb_size = dpb_size;
879 GST_DEBUG ("DPB size %u", priv->dpb_size);
883 static GstVaapiDecoderStatus
884 get_status (GstH265ParserResult result)
886 GstVaapiDecoderStatus status;
888 case GST_H265_PARSER_OK:
889 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
891 case GST_H265_PARSER_NO_NAL_END:
892 status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
894 case GST_H265_PARSER_ERROR:
895 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
898 status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
905 gst_vaapi_decoder_h265_close (GstVaapiDecoderH265 * decoder)
907 GstVaapiDecoderH265Private *const priv = &decoder->priv;
908 gst_vaapi_picture_replace (&priv->current_picture, NULL);
909 gst_vaapi_parser_info_h265_replace (&priv->prev_slice_pi, NULL);
910 gst_vaapi_parser_info_h265_replace (&priv->prev_independent_slice_pi, NULL);
911 gst_vaapi_parser_info_h265_replace (&priv->prev_pi, NULL);
913 dpb_clear (decoder, TRUE);
916 gst_h265_parser_free (priv->parser);
922 gst_vaapi_decoder_h265_open (GstVaapiDecoderH265 * decoder)
924 GstVaapiDecoderH265Private *const priv = &decoder->priv;
925 gst_vaapi_decoder_h265_close (decoder);
926 priv->parser = gst_h265_parser_new ();
933 gst_vaapi_decoder_h265_destroy (GstVaapiDecoder * base_decoder)
935 GstVaapiDecoderH265 *const decoder =
936 GST_VAAPI_DECODER_H265_CAST (base_decoder);
937 GstVaapiDecoderH265Private *const priv = &decoder->priv;
939 gst_vaapi_decoder_h265_close (decoder);
943 for (i = 0; i < G_N_ELEMENTS (priv->pps); i++)
944 gst_vaapi_parser_info_h265_replace (&priv->pps[i], NULL);
945 gst_vaapi_parser_info_h265_replace (&priv->active_pps, NULL);
946 for (i = 0; i < G_N_ELEMENTS (priv->sps); i++)
947 gst_vaapi_parser_info_h265_replace (&priv->sps[i], NULL);
948 gst_vaapi_parser_info_h265_replace (&priv->active_sps, NULL);
949 for (i = 0; i < G_N_ELEMENTS (priv->vps); i++)
950 gst_vaapi_parser_info_h265_replace (&priv->vps[i], NULL);
951 gst_vaapi_parser_info_h265_replace (&priv->active_vps, NULL);
955 gst_vaapi_decoder_h265_create (GstVaapiDecoder * base_decoder)
957 GstVaapiDecoderH265 *const decoder =
958 GST_VAAPI_DECODER_H265_CAST (base_decoder);
959 GstVaapiDecoderH265Private *const priv = &decoder->priv;
960 priv->profile = GST_VAAPI_PROFILE_UNKNOWN;
961 priv->entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
962 priv->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
963 priv->progressive_sequence = TRUE;
969 fill_profiles (GstVaapiProfile profiles[16], guint * n_profiles_ptr,
970 GstVaapiProfile profile)
972 guint n_profiles = *n_profiles_ptr;
973 profiles[n_profiles++] = profile;
975 case GST_VAAPI_PROFILE_H265_MAIN:
976 profiles[n_profiles++] = GST_VAAPI_PROFILE_H265_MAIN10;
978 case GST_VAAPI_PROFILE_H265_MAIN_STILL_PICTURE:
979 profiles[n_profiles++] = GST_VAAPI_PROFILE_H265_MAIN;
980 profiles[n_profiles++] = GST_VAAPI_PROFILE_H265_MAIN10;
985 *n_profiles_ptr = n_profiles;
988 static GstVaapiProfile
989 get_profile (GstVaapiDecoderH265 * decoder, GstH265SPS * sps, guint dpb_size)
991 GstVaapiDecoderH265Private *const priv = &decoder->priv;
992 GstVaapiDisplay *const display = GST_VAAPI_DECODER_DISPLAY (decoder);
993 GstVaapiProfile profile, profiles[3];
994 guint i, n_profiles = 0;
996 gst_vaapi_utils_h265_get_profile (sps->profile_tier_level.profile_idc);
998 return GST_VAAPI_PROFILE_UNKNOWN;
999 fill_profiles (profiles, &n_profiles, profile);
1001 case GST_VAAPI_PROFILE_H265_MAIN10:
1002 if (sps->profile_tier_level.profile_compatibility_flag[1]) { // A.2.3.2 (main profile)
1003 fill_profiles (profiles, &n_profiles, GST_VAAPI_PROFILE_H265_MAIN);
1010 /* If the preferred profile (profiles[0]) matches one that we already
1011 found, then just return it now instead of searching for it again */
1012 if (profiles[0] == priv->profile)
1013 return priv->profile;
1014 for (i = 0; i < n_profiles; i++) {
1015 if (gst_vaapi_display_has_decoder (display, profiles[i], priv->entrypoint))
1018 return GST_VAAPI_PROFILE_UNKNOWN;
1021 static GstVaapiDecoderStatus
1022 ensure_context (GstVaapiDecoderH265 * decoder, GstH265SPS * sps)
1024 GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER_CAST (decoder);
1025 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1026 GstVaapiContextInfo info;
1027 GstVaapiProfile profile;
1028 GstVaapiChromaType chroma_type;
1029 gboolean reset_context = FALSE;
1032 dpb_size = get_max_dec_frame_buffering (sps);
1033 if (priv->dpb_size < dpb_size) {
1034 GST_DEBUG ("DPB size increased");
1035 reset_context = TRUE;
1038 profile = get_profile (decoder, sps, dpb_size);
1040 GST_ERROR ("unsupported profile_idc %u",
1041 sps->profile_tier_level.profile_idc);
1042 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
1045 if (!priv->profile || (priv->profile != profile)) {
1046 GST_DEBUG ("profile changed");
1047 reset_context = TRUE;
1048 priv->profile = profile;
1051 chroma_type = gst_vaapi_utils_h265_get_chroma_type (sps->chroma_format_idc);
1053 GST_ERROR ("unsupported chroma_format_idc %u", sps->chroma_format_idc);
1054 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
1057 if (priv->chroma_type != chroma_type) {
1058 GST_DEBUG ("chroma format changed");
1059 reset_context = TRUE;
1060 priv->chroma_type = chroma_type;
1063 if (priv->pic_width_in_luma_samples != sps->pic_width_in_luma_samples ||
1064 priv->pic_height_in_luma_samples != sps->pic_height_in_luma_samples) {
1065 GST_DEBUG ("size changed");
1066 reset_context = TRUE;
1067 priv->pic_width_in_luma_samples = sps->pic_width_in_luma_samples;
1068 priv->pic_height_in_luma_samples = sps->pic_height_in_luma_samples;
1071 priv->progressive_sequence = 1; /*Fixme */
1072 gst_vaapi_decoder_set_interlaced (base_decoder, !priv->progressive_sequence);
1073 gst_vaapi_decoder_set_pixel_aspect_ratio (base_decoder,
1074 sps->vui_params.par_n, sps->vui_params.par_d);
1075 if (!reset_context && priv->has_context)
1076 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1078 /* XXX: fix surface size when cropping is implemented */
1079 info.profile = priv->profile;
1080 info.entrypoint = priv->entrypoint;
1081 info.chroma_type = priv->chroma_type;
1082 info.width = sps->width;
1083 info.height = sps->height;
1084 info.ref_frames = dpb_size;
1086 if (!gst_vaapi_decoder_ensure_context (GST_VAAPI_DECODER (decoder), &info))
1087 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1088 priv->has_context = TRUE;
1091 if (!dpb_reset (decoder, dpb_size))
1092 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1094 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1098 fill_iq_matrix_4x4 (VAIQMatrixBufferHEVC * iq_matrix,
1099 GstH265ScalingList * scaling_list)
1102 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList4x4) == 6);
1103 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList4x4[0]) == 16);
1104 for (i = 0; i < G_N_ELEMENTS (iq_matrix->ScalingList4x4); i++) {
1105 gst_h265_quant_matrix_4x4_get_raster_from_zigzag (iq_matrix->ScalingList4x4
1106 [i], scaling_list->scaling_lists_4x4[i]);
1111 fill_iq_matrix_8x8 (VAIQMatrixBufferHEVC * iq_matrix,
1112 GstH265ScalingList * scaling_list)
1115 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList8x8) == 6);
1116 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList8x8[0]) == 64);
1117 for (i = 0; i < G_N_ELEMENTS (iq_matrix->ScalingList8x8); i++) {
1118 gst_h265_quant_matrix_8x8_get_raster_from_zigzag (iq_matrix->ScalingList8x8
1119 [i], scaling_list->scaling_lists_8x8[i]);
1124 fill_iq_matrix_16x16 (VAIQMatrixBufferHEVC * iq_matrix,
1125 GstH265ScalingList * scaling_list)
1128 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList16x16) == 6);
1129 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList16x16[0]) == 64);
1130 for (i = 0; i < G_N_ELEMENTS (iq_matrix->ScalingList16x16); i++) {
1131 gst_h265_quant_matrix_16x16_get_raster_from_zigzag
1132 (iq_matrix->ScalingList16x16[i], scaling_list->scaling_lists_16x16[i]);
1137 fill_iq_matrix_32x32 (VAIQMatrixBufferHEVC * iq_matrix,
1138 GstH265ScalingList * scaling_list)
1141 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList32x32) == 2);
1142 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList32x32[0]) == 64);
1143 for (i = 0; i < G_N_ELEMENTS (iq_matrix->ScalingList32x32); i++) {
1144 gst_h265_quant_matrix_32x32_get_raster_from_zigzag
1145 (iq_matrix->ScalingList32x32[i], scaling_list->scaling_lists_32x32[i]);
1150 fill_iq_matrix_dc_16x16 (VAIQMatrixBufferHEVC * iq_matrix,
1151 GstH265ScalingList * scaling_list)
1154 for (i = 0; i < 6; i++)
1155 iq_matrix->ScalingListDC16x16[i] =
1156 scaling_list->scaling_list_dc_coef_minus8_16x16[i] + 8;
1160 fill_iq_matrix_dc_32x32 (VAIQMatrixBufferHEVC * iq_matrix,
1161 GstH265ScalingList * scaling_list)
1164 for (i = 0; i < 2; i++)
1165 iq_matrix->ScalingListDC32x32[i] =
1166 scaling_list->scaling_list_dc_coef_minus8_32x32[i] + 8;
1169 static GstVaapiDecoderStatus
1170 ensure_quant_matrix (GstVaapiDecoderH265 * decoder,
1171 GstVaapiPictureH265 * picture)
1173 GstVaapiPicture *const base_picture = &picture->base;
1174 GstH265PPS *const pps = get_pps (decoder);
1175 GstH265SPS *const sps = get_sps (decoder);
1176 GstH265ScalingList *scaling_list = NULL;
1177 VAIQMatrixBufferHEVC *iq_matrix;
1180 (pps->scaling_list_data_present_flag ||
1181 (sps->scaling_list_enabled_flag
1182 && !sps->scaling_list_data_present_flag)))
1183 scaling_list = &pps->scaling_list;
1184 else if (sps && sps->scaling_list_enabled_flag
1185 && sps->scaling_list_data_present_flag)
1186 scaling_list = &sps->scaling_list;
1188 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1190 base_picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW (HEVC, decoder);
1191 if (!base_picture->iq_matrix) {
1192 GST_ERROR ("failed to allocate IQ matrix");
1193 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1195 iq_matrix = base_picture->iq_matrix->param;
1197 /* Only supporting 4:2:0 */
1198 if (sps->chroma_format_idc != 1)
1199 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
1201 fill_iq_matrix_4x4 (iq_matrix, scaling_list);
1202 fill_iq_matrix_8x8 (iq_matrix, scaling_list);
1203 fill_iq_matrix_16x16 (iq_matrix, scaling_list);
1204 fill_iq_matrix_32x32 (iq_matrix, scaling_list);
1205 fill_iq_matrix_dc_16x16 (iq_matrix, scaling_list);
1206 fill_iq_matrix_dc_32x32 (iq_matrix, scaling_list);
1208 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1211 static inline gboolean
1212 is_valid_state (guint state, guint ref_state)
1214 return (state & ref_state) == ref_state;
1217 static GstVaapiDecoderStatus
1218 decode_current_picture (GstVaapiDecoderH265 * decoder)
1220 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1221 GstVaapiPictureH265 *const picture = priv->current_picture;
1223 if (!is_valid_state (priv->decoder_state, GST_H265_VIDEO_STATE_VALID_PICTURE)) {
1227 priv->decoder_state = 0;
1228 /*Fixme: Use SEI header values */
1229 priv->pic_structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1232 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1234 if (!gst_vaapi_picture_decode (GST_VAAPI_PICTURE_CAST (picture)))
1237 if (!dpb_add (decoder, picture))
1240 gst_vaapi_picture_replace (&priv->current_picture, NULL);
1241 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1244 gst_vaapi_picture_replace (&priv->current_picture, NULL);
1245 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1247 priv->decoder_state = 0;
1248 priv->pic_structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1249 return (GstVaapiDecoderStatus) GST_VAAPI_DECODER_STATUS_DROP_FRAME;
1252 static GstVaapiDecoderStatus
1253 parse_vps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1255 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1256 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1257 GstH265VPS *const vps = &pi->data.vps;
1258 GstH265ParserResult result;
1260 GST_DEBUG ("parse VPS");
1261 priv->parser_state = 0;
1263 memset (vps, 0, sizeof (GstH265VPS));
1265 result = gst_h265_parser_parse_vps (priv->parser, &pi->nalu, vps);
1266 if (result != GST_H265_PARSER_OK)
1267 return get_status (result);
1269 priv->parser_state |= GST_H265_VIDEO_STATE_GOT_VPS;
1270 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1273 static GstVaapiDecoderStatus
1274 parse_sps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1276 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1277 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1278 GstH265SPS *const sps = &pi->data.sps;
1279 GstH265ParserResult result;
1281 GST_DEBUG ("parse SPS");
1282 priv->parser_state = 0;
1284 memset (sps, 0, sizeof (GstH265SPS));
1286 result = gst_h265_parser_parse_sps (priv->parser, &pi->nalu, sps, TRUE);
1287 if (result != GST_H265_PARSER_OK)
1288 return get_status (result);
1290 priv->parser_state |= GST_H265_VIDEO_STATE_GOT_SPS;
1291 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1295 static GstVaapiDecoderStatus
1296 parse_pps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1298 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1299 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1300 GstH265PPS *const pps = &pi->data.pps;
1301 GstH265ParserResult result;
1303 GST_DEBUG ("parse PPS");
1304 priv->parser_state &= GST_H265_VIDEO_STATE_GOT_SPS;
1306 memset (pps, 0, sizeof (GstH265PPS));
1308 result = gst_h265_parser_parse_pps (priv->parser, &pi->nalu, pps);
1309 if (result != GST_H265_PARSER_OK)
1310 return get_status (result);
1312 priv->parser_state |= GST_H265_VIDEO_STATE_GOT_PPS;
1313 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1316 static GstVaapiDecoderStatus
1317 parse_sei (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1319 GST_FIXME ("Parse SEI, Not implemented !");
1321 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1322 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1323 GstH265SEIMessage *sei = &pi->data.sei;
1324 GstH265ParserResult result;
1325 GST_DEBUG ("parse SEI");
1326 result = gst_h265_parser_parse_sei (priv->parser, &pi->nalu, sei);
1327 if (result != GST_H265_PARSER_OK) {
1328 GST_WARNING ("failed to parse SEI messages");
1329 return get_status (result);
1332 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1335 static GstVaapiDecoderStatus
1336 parse_slice (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1338 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1339 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1340 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
1341 GstH265ParserResult result;
1343 GST_DEBUG ("parse slice");
1344 priv->parser_state &= (GST_H265_VIDEO_STATE_GOT_SPS |
1345 GST_H265_VIDEO_STATE_GOT_PPS);
1347 slice_hdr->short_term_ref_pic_set_idx = 0;
1349 memset (slice_hdr, 0, sizeof (GstH265SliceHdr));
1351 result = gst_h265_parser_parse_slice_hdr (priv->parser, &pi->nalu, slice_hdr);
1352 if (result != GST_H265_PARSER_OK)
1353 return get_status (result);
1355 priv->parser_state |= GST_H265_VIDEO_STATE_GOT_SLICE;
1356 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1359 static GstVaapiDecoderStatus
1360 decode_vps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1362 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1363 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1364 GstH265VPS *const vps = &pi->data.vps;
1366 GST_DEBUG ("decode VPS");
1368 gst_vaapi_parser_info_h265_replace (&priv->vps[vps->id], pi);
1370 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1373 static GstVaapiDecoderStatus
1374 decode_sps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1376 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1377 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1378 GstH265SPS *const sps = &pi->data.sps;
1380 GST_DEBUG ("decode SPS");
1382 if (sps->max_latency_increase_plus1[sps->max_sub_layers_minus1])
1383 priv->SpsMaxLatencyPictures =
1384 sps->max_num_reorder_pics[sps->max_sub_layers_minus1] +
1385 sps->max_latency_increase_plus1[sps->max_sub_layers_minus1] - 1;
1387 gst_vaapi_parser_info_h265_replace (&priv->sps[sps->id], pi);
1389 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1392 static GstVaapiDecoderStatus
1393 decode_pps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1395 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1396 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1397 GstH265PPS *const pps = &pi->data.pps;
1399 GST_DEBUG ("decode PPS");
1401 gst_vaapi_parser_info_h265_replace (&priv->pps[pps->id], pi);
1403 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1406 static GstVaapiDecoderStatus
1407 decode_sei (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1409 GST_FIXME ("Decode SEI, Not implemented!");
1411 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1412 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1413 GstH265SEIMessage *sei = &pi->data.sei;
1415 GST_DEBUG ("decode SEI messages");
1416 switch (sei->payloadType) {
1417 case GST_H265_SEI_PIC_TIMING:{
1418 GstH265PicTiming *pic_timing = &sei->payload.pic_timing;
1419 /* Fix: only if vps->frame_field_info_present_flag */
1420 priv->pic_structure = pic_timing->pic_struct;
1427 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1430 static GstVaapiDecoderStatus
1431 decode_sequence_end (GstVaapiDecoderH265 * decoder)
1433 GstVaapiDecoderStatus status;
1434 GST_DEBUG ("decode sequence-end");
1435 status = decode_current_picture (decoder);
1436 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1438 dpb_flush (decoder);
1439 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1442 /* 8.3.1 - Decoding process for picture order count */
1444 init_picture_poc (GstVaapiDecoderH265 * decoder,
1445 GstVaapiPictureH265 * picture, GstVaapiParserInfoH265 * pi)
1447 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1448 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
1449 GstH265SPS *const sps = get_sps (decoder);
1450 const gint32 MaxPicOrderCntLsb =
1451 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
1452 guint8 nal_type = pi->nalu.type;
1453 guint8 temporal_id = pi->nalu.temporal_id_plus1 - 1;
1455 GST_DEBUG ("decode PicOrderCntVal");
1457 priv->prev_poc_lsb = priv->poc_lsb;
1458 priv->prev_poc_msb = priv->poc_msb;
1460 if (!nal_is_irap (nal_type) && picture->NoRaslOutputFlag) {
1461 priv->prev_poc_lsb = priv->prev_tid0pic_poc_lsb;
1462 priv->prev_poc_msb = priv->prev_tid0pic_poc_msb;
1465 /* Finding PicOrderCntMsb */
1466 if (nal_is_irap (nal_type) && picture->NoRaslOutputFlag)
1470 if ((slice_hdr->pic_order_cnt_lsb < priv->prev_poc_lsb) &&
1471 ((priv->prev_poc_lsb - slice_hdr->pic_order_cnt_lsb) >=
1472 (MaxPicOrderCntLsb / 2)))
1473 priv->poc_msb = priv->prev_poc_msb + MaxPicOrderCntLsb;
1475 else if ((slice_hdr->pic_order_cnt_lsb > priv->prev_poc_lsb) &&
1476 ((slice_hdr->pic_order_cnt_lsb - priv->prev_poc_lsb) >
1477 (MaxPicOrderCntLsb / 2)))
1478 priv->poc_msb = priv->prev_poc_msb - MaxPicOrderCntLsb;
1481 priv->poc_msb = priv->prev_poc_msb;
1485 priv->poc = picture->poc = priv->poc_msb + slice_hdr->pic_order_cnt_lsb;
1486 priv->poc_lsb = picture->poc_lsb = slice_hdr->pic_order_cnt_lsb;
1488 if (nal_is_idr (nal_type)) {
1490 picture->poc_lsb = 0;
1493 priv->prev_poc_lsb = 0;
1494 priv->prev_poc_msb = 0;
1495 priv->prev_tid0pic_poc_lsb = 0;
1496 priv->prev_tid0pic_poc_msb = 0;
1499 picture->base.poc = picture->poc;
1500 GST_DEBUG ("PicOrderCntVal %d", picture->base.poc);
1502 if (!temporal_id && !nal_is_rasl (nal_type) &&
1503 !nal_is_radl (nal_type) && nal_is_ref (nal_type)) {
1504 priv->prev_tid0pic_poc_lsb = slice_hdr->pic_order_cnt_lsb;
1505 priv->prev_tid0pic_poc_msb = priv->poc_msb;
1510 init_picture_refs (GstVaapiDecoderH265 * decoder,
1511 GstVaapiPictureH265 * picture, GstH265SliceHdr * slice_hdr)
1513 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1514 guint32 NumRpsCurrTempList0 = 0, NumRpsCurrTempList1 = 0;
1515 GstVaapiPictureH265 *RefPicListTemp0[16] = { NULL, }, *RefPicListTemp1[16] = {
1518 guint num_ref_idx_l0_active_minus1 = 0;
1519 guint num_ref_idx_l1_active_minus1 = 0;
1520 GstH265RefPicListModification *ref_pic_list_modification;
1523 memset (priv->RefPicList0, 0, sizeof (GstVaapiPictureH265 *) * 16);
1524 memset (priv->RefPicList1, 0, sizeof (GstVaapiPictureH265 *) * 16);
1525 priv->RefPicList0_count = priv->RefPicList1_count = 0;
1527 if ((slice_hdr->type != GST_H265_B_SLICE) &&
1528 (slice_hdr->type != GST_H265_P_SLICE))
1531 if (slice_hdr->dependent_slice_segment_flag) {
1532 GstH265SliceHdr *tmp = &priv->prev_independent_slice_pi->data.slice_hdr;
1533 num_ref_idx_l0_active_minus1 = tmp->num_ref_idx_l0_active_minus1;
1534 num_ref_idx_l1_active_minus1 = tmp->num_ref_idx_l1_active_minus1;
1535 ref_pic_list_modification = &tmp->ref_pic_list_modification;
1538 num_ref_idx_l0_active_minus1 = slice_hdr->num_ref_idx_l0_active_minus1;
1539 num_ref_idx_l1_active_minus1 = slice_hdr->num_ref_idx_l1_active_minus1;
1540 ref_pic_list_modification = &slice_hdr->ref_pic_list_modification;
1541 type = slice_hdr->type;
1544 NumRpsCurrTempList0 =
1545 MAX ((num_ref_idx_l0_active_minus1 + 1), priv->NumPocTotalCurr);
1546 NumRpsCurrTempList1 =
1547 MAX ((num_ref_idx_l1_active_minus1 + 1), priv->NumPocTotalCurr);
1550 while (rIdx < NumRpsCurrTempList0) {
1551 for (i = 0; i < priv->NumPocStCurrBefore && rIdx < NumRpsCurrTempList0;
1553 RefPicListTemp0[rIdx] = priv->RefPicSetStCurrBefore[i];
1554 for (i = 0; i < priv->NumPocStCurrAfter && rIdx < NumRpsCurrTempList0;
1556 RefPicListTemp0[rIdx] = priv->RefPicSetStCurrAfter[i];
1557 for (i = 0; i < priv->NumPocLtCurr && rIdx < NumRpsCurrTempList0;
1559 RefPicListTemp0[rIdx] = priv->RefPicSetLtCurr[i];
1562 /* construct RefPicList0 (8-9) */
1563 for (rIdx = 0; rIdx <= num_ref_idx_l0_active_minus1; rIdx++)
1564 priv->RefPicList0[rIdx] =
1565 ref_pic_list_modification->ref_pic_list_modification_flag_l0 ?
1566 RefPicListTemp0[ref_pic_list_modification->list_entry_l0[rIdx]] :
1567 RefPicListTemp0[rIdx];
1568 priv->RefPicList0_count = rIdx;
1570 if (type == GST_H265_B_SLICE) {
1574 while (rIdx < NumRpsCurrTempList1) {
1575 for (i = 0; i < priv->NumPocStCurrAfter && rIdx < NumRpsCurrTempList1;
1577 RefPicListTemp1[rIdx] = priv->RefPicSetStCurrAfter[i];
1578 for (i = 0; i < priv->NumPocStCurrBefore && rIdx < NumRpsCurrTempList1;
1580 RefPicListTemp1[rIdx] = priv->RefPicSetStCurrBefore[i];
1581 for (i = 0; i < priv->NumPocLtCurr && rIdx < NumRpsCurrTempList1;
1583 RefPicListTemp1[rIdx] = priv->RefPicSetLtCurr[i];
1586 /* construct RefPicList1 (8-10) */
1587 for (rIdx = 0; rIdx <= num_ref_idx_l1_active_minus1; rIdx++)
1588 priv->RefPicList1[rIdx] =
1589 ref_pic_list_modification->ref_pic_list_modification_flag_l1 ?
1590 RefPicListTemp1[ref_pic_list_modification->list_entry_l1
1591 [rIdx]] : RefPicListTemp1[rIdx];
1592 priv->RefPicList1_count = rIdx;
1597 init_picture (GstVaapiDecoderH265 * decoder,
1598 GstVaapiPictureH265 * picture, GstVaapiParserInfoH265 * pi)
1600 GstVaapiPicture *const base_picture = &picture->base;
1601 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
1603 base_picture->pts = GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts;
1604 base_picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
1606 if (nal_is_idr (pi->nalu.type)) {
1607 GST_DEBUG ("<IDR>");
1608 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_IDR);
1611 if (nal_is_irap (pi->nalu.type))
1612 picture->IntraPicFlag = TRUE;
1614 if (pi->nalu.type >= GST_H265_NAL_SLICE_BLA_W_LP &&
1615 pi->nalu.type <= GST_H265_NAL_SLICE_CRA_NUT)
1616 picture->RapPicFlag = TRUE;
1618 /*Fixme: Use SEI header values */
1619 base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1620 picture->structure = base_picture->structure;
1622 /*NoRaslOutputFlag ==1 if the current picture is
1625 3) a CRA picture that is the first access unit in the bitstream (Fixme: Not yet added)
1626 4) first picture that follows an end of sequence NAL unit in decoding order (Fixme: Not yet added)
1627 5) has HandleCraAsBlaFlag == 1 (Fixme: Not yet added)
1629 if (nal_is_idr (pi->nalu.type) || nal_is_bla (pi->nalu.type) ||
1630 pi->nalu.type == GST_H265_NAL_SLICE_CRA_NUT) {
1631 picture->NoRaslOutputFlag = 1;
1634 if (nal_is_rasl (pi->
1635 nalu.type) /* Fixme: || NoRaslOutPutFlag of asso irap=1 */ )
1636 picture->output_flag = FALSE;
1638 picture->output_flag = slice_hdr->pic_output_flag;
1640 init_picture_poc (decoder, picture, pi);
1643 if (nal_is_irap (pi->nalu.type)
1644 && picture->NoRaslOutputFlag && picture->poc /*&& Fixme: Not picture0 */ ) {
1646 if (pi->nalu.type == GST_H265_NAL_SLICE_CRA_NUT)
1647 picture->NoOutputOfPriorPicsFlag = 1;
1649 picture->NoOutputOfPriorPicsFlag =
1650 slice_hdr->no_output_of_prior_pics_flag;
1657 vaapi_init_picture (VAPictureHEVC * pic)
1659 pic->picture_id = VA_INVALID_SURFACE;
1660 pic->pic_order_cnt = 0;
1661 pic->flags = VA_PICTURE_HEVC_INVALID;
1665 vaapi_fill_picture (VAPictureHEVC * pic, GstVaapiPictureH265 * picture,
1666 guint picture_structure)
1669 if (!picture_structure)
1670 picture_structure = picture->structure;
1672 pic->picture_id = picture->base.surface_id;
1673 pic->pic_order_cnt = picture->poc;
1676 /* Set the VAPictureHEVC flags */
1677 if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE (picture))
1678 pic->flags |= VA_PICTURE_HEVC_LONG_TERM_REFERENCE;
1680 if (GST_VAAPI_PICTURE_FLAG_IS_SET (picture,
1681 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_BEFORE))
1682 pic->flags |= VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE;
1684 else if (GST_VAAPI_PICTURE_FLAG_IS_SET (picture,
1685 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_AFTER))
1686 pic->flags |= VA_PICTURE_HEVC_RPS_ST_CURR_AFTER;
1688 else if (GST_VAAPI_PICTURE_FLAG_IS_SET (picture,
1689 GST_VAAPI_PICTURE_FLAG_RPS_LT_CURR))
1690 pic->flags |= VA_PICTURE_HEVC_RPS_LT_CURR;
1692 switch (picture_structure) {
1693 case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
1695 case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
1696 pic->flags |= VA_PICTURE_HEVC_FIELD_PIC;
1698 case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
1699 pic->flags |= VA_PICTURE_HEVC_FIELD_PIC;
1700 pic->flags |= VA_PICTURE_HEVC_BOTTOM_FIELD;
1708 get_index_for_RefPicListX (VAPictureHEVC * ReferenceFrames,
1709 GstVaapiPictureH265 * pic)
1713 for (i = 0; i < 15; i++) {
1714 if ((ReferenceFrames[i].picture_id != VA_INVALID_ID) && pic) {
1715 if ((ReferenceFrames[i].pic_order_cnt == pic->poc) &&
1716 (ReferenceFrames[i].picture_id == pic->base.surface_id)) {
1725 fill_picture (GstVaapiDecoderH265 * decoder, GstVaapiPictureH265 * picture)
1727 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1728 GstVaapiPicture *const base_picture = &picture->base;
1729 GstH265PPS *const pps = get_pps (decoder);
1730 GstH265SPS *const sps = get_sps (decoder);
1731 VAPictureParameterBufferHEVC *const pic_param = base_picture->param;
1734 pic_param->pic_fields.value = 0;
1735 pic_param->slice_parsing_fields.value = 0;
1737 /* Fill in VAPictureHEVC */
1738 vaapi_fill_picture (&pic_param->CurrPic, picture, 0);
1739 /* Fill in ReferenceFrames */
1740 for (i = 0, n = 0; i < priv->dpb_count; i++) {
1741 GstVaapiFrameStore *const fs = priv->dpb[i];
1742 if ((gst_vaapi_frame_store_has_reference (fs)))
1743 vaapi_fill_picture (&pic_param->ReferenceFrames[n++], fs->buffer,
1744 fs->buffer->structure);
1745 if (n >= G_N_ELEMENTS (pic_param->ReferenceFrames))
1748 for (; n < G_N_ELEMENTS (pic_param->ReferenceFrames); n++)
1749 vaapi_init_picture (&pic_param->ReferenceFrames[n]);
1752 #define COPY_FIELD(s, f) \
1753 pic_param->f = (s)->f
1754 #define COPY_BFM(a, s, f) \
1755 pic_param->a.bits.f = (s)->f
1757 COPY_FIELD (sps, pic_width_in_luma_samples);
1758 COPY_FIELD (sps, pic_height_in_luma_samples);
1759 COPY_BFM (pic_fields, sps, chroma_format_idc);
1760 COPY_BFM (pic_fields, sps, separate_colour_plane_flag);
1761 COPY_BFM (pic_fields, sps, pcm_enabled_flag);
1762 COPY_BFM (pic_fields, sps, scaling_list_enabled_flag);
1763 COPY_BFM (pic_fields, pps, transform_skip_enabled_flag);
1764 COPY_BFM (pic_fields, sps, amp_enabled_flag);
1765 COPY_BFM (pic_fields, sps, strong_intra_smoothing_enabled_flag);
1766 COPY_BFM (pic_fields, pps, sign_data_hiding_enabled_flag);
1767 COPY_BFM (pic_fields, pps, constrained_intra_pred_flag);
1768 COPY_BFM (pic_fields, pps, cu_qp_delta_enabled_flag);
1769 COPY_BFM (pic_fields, pps, weighted_pred_flag);
1770 COPY_BFM (pic_fields, pps, weighted_bipred_flag);
1771 COPY_BFM (pic_fields, pps, transquant_bypass_enabled_flag);
1772 COPY_BFM (pic_fields, pps, tiles_enabled_flag);
1773 COPY_BFM (pic_fields, pps, entropy_coding_sync_enabled_flag);
1774 pic_param->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag =
1775 pps->loop_filter_across_slices_enabled_flag;
1776 COPY_BFM (pic_fields, pps, loop_filter_across_tiles_enabled_flag);
1777 COPY_BFM (pic_fields, sps, pcm_loop_filter_disabled_flag);
1778 /* Fix: Assign value based on sps_max_num_reorder_pics */
1779 pic_param->pic_fields.bits.NoPicReorderingFlag = 0;
1780 /* Fix: Enable if picture has no B slices */
1781 pic_param->pic_fields.bits.NoBiPredFlag = 0;
1783 pic_param->sps_max_dec_pic_buffering_minus1 =
1784 sps->max_dec_pic_buffering_minus1[0];
1785 COPY_FIELD (sps, bit_depth_luma_minus8);
1786 COPY_FIELD (sps, bit_depth_chroma_minus8);
1787 COPY_FIELD (sps, pcm_sample_bit_depth_luma_minus1);
1788 COPY_FIELD (sps, pcm_sample_bit_depth_chroma_minus1);
1789 COPY_FIELD (sps, log2_min_luma_coding_block_size_minus3);
1790 COPY_FIELD (sps, log2_diff_max_min_luma_coding_block_size);
1791 COPY_FIELD (sps, log2_min_transform_block_size_minus2);
1792 COPY_FIELD (sps, log2_diff_max_min_transform_block_size);
1793 COPY_FIELD (sps, log2_min_pcm_luma_coding_block_size_minus3);
1794 COPY_FIELD (sps, log2_diff_max_min_pcm_luma_coding_block_size);
1795 COPY_FIELD (sps, max_transform_hierarchy_depth_intra);
1796 COPY_FIELD (sps, max_transform_hierarchy_depth_inter);
1797 COPY_FIELD (pps, init_qp_minus26);
1798 COPY_FIELD (pps, diff_cu_qp_delta_depth);
1799 pic_param->pps_cb_qp_offset = pps->cb_qp_offset;
1800 pic_param->pps_cr_qp_offset = pps->cr_qp_offset;
1801 COPY_FIELD (pps, log2_parallel_merge_level_minus2);
1802 COPY_FIELD (pps, num_tile_columns_minus1);
1803 COPY_FIELD (pps, num_tile_rows_minus1);
1804 for (i = 0; i < 19; i++)
1805 pic_param->column_width_minus1[i] = pps->column_width_minus1[i];
1806 for (i = 0; i < 21; i++)
1807 pic_param->row_height_minus1[i] = pps->row_height_minus1[i];
1809 COPY_BFM (slice_parsing_fields, pps, lists_modification_present_flag);
1810 COPY_BFM (slice_parsing_fields, sps, long_term_ref_pics_present_flag);
1811 pic_param->slice_parsing_fields.bits.sps_temporal_mvp_enabled_flag =
1812 sps->temporal_mvp_enabled_flag;
1813 COPY_BFM (slice_parsing_fields, pps, cabac_init_present_flag);
1814 COPY_BFM (slice_parsing_fields, pps, output_flag_present_flag);
1815 COPY_BFM (slice_parsing_fields, pps, dependent_slice_segments_enabled_flag);
1816 pic_param->slice_parsing_fields.
1817 bits.pps_slice_chroma_qp_offsets_present_flag =
1818 pps->slice_chroma_qp_offsets_present_flag;
1819 COPY_BFM (slice_parsing_fields, sps, sample_adaptive_offset_enabled_flag);
1820 COPY_BFM (slice_parsing_fields, pps, deblocking_filter_override_enabled_flag);
1821 pic_param->slice_parsing_fields.bits.pps_disable_deblocking_filter_flag =
1822 pps->deblocking_filter_disabled_flag;
1823 COPY_BFM (slice_parsing_fields, pps,
1824 slice_segment_header_extension_present_flag);
1825 pic_param->slice_parsing_fields.bits.RapPicFlag = picture->RapPicFlag;
1826 pic_param->slice_parsing_fields.bits.IdrPicFlag =
1827 GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_IDR);
1828 pic_param->slice_parsing_fields.bits.IntraPicFlag = picture->IntraPicFlag;
1830 COPY_FIELD (sps, log2_max_pic_order_cnt_lsb_minus4);
1831 COPY_FIELD (sps, num_short_term_ref_pic_sets);
1832 pic_param->num_long_term_ref_pic_sps = sps->num_long_term_ref_pics_sps;
1833 COPY_FIELD (pps, num_ref_idx_l0_default_active_minus1);
1834 COPY_FIELD (pps, num_ref_idx_l1_default_active_minus1);
1835 pic_param->pps_beta_offset_div2 = pps->beta_offset_div2;
1836 pic_param->pps_tc_offset_div2 = pps->tc_offset_div2;
1837 COPY_FIELD (pps, num_extra_slice_header_bits);
1839 /*Fixme: Set correct value as mentioned in va_dec_hevc.h */
1840 pic_param->st_rps_bits = 0;
1844 /* Detection of the first VCL NAL unit of a coded picture (7.4.2.4.5 ) */
1846 is_new_picture (GstVaapiParserInfoH265 * pi, GstVaapiParserInfoH265 * prev_pi)
1848 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
1853 if (slice_hdr->first_slice_segment_in_pic_flag)
1859 /* Detection of a new access unit, assuming we are already in presence
1861 static inline gboolean
1862 is_new_access_unit (GstVaapiParserInfoH265 * pi,
1863 GstVaapiParserInfoH265 * prev_pi)
1872 has_entry_in_rps (GstVaapiPictureH265 * dpb_pic,
1873 GstVaapiPictureH265 ** rps_list, guint rps_list_length)
1877 if (!dpb_pic || !rps_list || !rps_list_length)
1880 for (i = 0; i < rps_list_length; i++) {
1881 if (rps_list[i]->poc == dpb_pic->poc)
1887 /* the derivation process for the RPS and the picture marking */
1889 derive_and_mark_rps (GstVaapiDecoderH265 * decoder,
1890 GstVaapiPictureH265 * picture, GstVaapiParserInfoH265 * pi,
1891 gint32 * CurrDeltaPocMsbPresentFlag, gint32 * FollDeltaPocMsbPresentFlag)
1894 GstVaapiPictureH265 *dpb_pic = NULL;
1895 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1897 memset (priv->RefPicSetLtCurr, 0, sizeof (GstVaapiPictureH265 *) * 16);
1898 memset (priv->RefPicSetLtFoll, 0, sizeof (GstVaapiPictureH265 *) * 16);
1899 memset (priv->RefPicSetStCurrBefore, 0, sizeof (GstVaapiPictureH265 *) * 16);
1900 memset (priv->RefPicSetStCurrAfter, 0, sizeof (GstVaapiPictureH265 *) * 16);
1901 memset (priv->RefPicSetStFoll, 0, sizeof (GstVaapiPictureH265 *) * 16);
1904 for (i = 0; i < priv->NumPocLtCurr; i++) {
1905 if (!CurrDeltaPocMsbPresentFlag[i]) {
1906 dpb_pic = dpb_get_picture (decoder, priv->PocLtCurr[i], TRUE);
1908 priv->RefPicSetLtCurr[i] = dpb_pic;
1910 priv->RefPicSetLtCurr[i] = NULL;
1912 dpb_pic = dpb_get_picture (decoder, priv->PocLtCurr[i], FALSE);
1914 priv->RefPicSetLtCurr[i] = dpb_pic;
1916 priv->RefPicSetLtCurr[i] = NULL;
1920 priv->RefPicSetLtCurr[i] = NULL;
1922 for (i = 0; i < priv->NumPocLtFoll; i++) {
1923 if (!FollDeltaPocMsbPresentFlag[i]) {
1924 dpb_pic = dpb_get_picture (decoder, priv->PocLtFoll[i], TRUE);
1926 priv->RefPicSetLtFoll[i] = dpb_pic;
1928 priv->RefPicSetLtFoll[i] = NULL;
1930 dpb_pic = dpb_get_picture (decoder, priv->PocLtFoll[i], FALSE);
1932 priv->RefPicSetLtFoll[i] = dpb_pic;
1934 priv->RefPicSetLtFoll[i] = NULL;
1938 priv->RefPicSetLtFoll[i] = NULL;
1940 /* Mark all ref pics in RefPicSetLtCurr and RefPicSetLtFol as long_term_refs */
1941 for (i = 0; i < priv->NumPocLtCurr; i++) {
1942 if (priv->RefPicSetLtCurr[i])
1943 gst_vaapi_picture_h265_set_reference (priv->RefPicSetLtCurr[i],
1944 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE |
1945 GST_VAAPI_PICTURE_FLAG_RPS_LT_CURR);
1947 for (i = 0; i < priv->NumPocLtFoll; i++) {
1948 if (priv->RefPicSetLtFoll[i])
1949 gst_vaapi_picture_h265_set_reference (priv->RefPicSetLtFoll[i],
1950 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE |
1951 GST_VAAPI_PICTURE_FLAG_RPS_LT_FOLL);
1955 for (i = 0; i < priv->NumPocStCurrBefore; i++) {
1956 dpb_pic = dpb_get_ref_picture (decoder, priv->PocStCurrBefore[i], TRUE);
1958 gst_vaapi_picture_h265_set_reference (dpb_pic,
1959 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
1960 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_BEFORE);
1961 priv->RefPicSetStCurrBefore[i] = dpb_pic;
1963 priv->RefPicSetStCurrBefore[i] = NULL;
1966 priv->RefPicSetStCurrBefore[i] = NULL;
1968 for (i = 0; i < priv->NumPocStCurrAfter; i++) {
1969 dpb_pic = dpb_get_ref_picture (decoder, priv->PocStCurrAfter[i], TRUE);
1971 gst_vaapi_picture_h265_set_reference (dpb_pic,
1972 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
1973 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_AFTER);
1974 priv->RefPicSetStCurrAfter[i] = dpb_pic;
1976 priv->RefPicSetStCurrAfter[i] = NULL;
1979 priv->RefPicSetStCurrAfter[i] = NULL;
1981 for (i = 0; i < priv->NumPocStFoll; i++) {
1982 dpb_pic = dpb_get_ref_picture (decoder, priv->PocStFoll[i], TRUE);
1984 gst_vaapi_picture_h265_set_reference (dpb_pic,
1985 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
1986 GST_VAAPI_PICTURE_FLAG_RPS_ST_FOLL);
1987 priv->RefPicSetStFoll[i] = dpb_pic;
1989 priv->RefPicSetStFoll[i] = NULL;
1992 priv->RefPicSetStFoll[i] = NULL;
1994 /* Mark all dpb pics not beloging to RefPicSet*[] as unused for ref */
1995 for (i = 0; i < priv->dpb_count; i++) {
1996 dpb_pic = priv->dpb[i]->buffer;
1998 !has_entry_in_rps (dpb_pic, priv->RefPicSetLtCurr, priv->NumPocLtCurr)
1999 && !has_entry_in_rps (dpb_pic, priv->RefPicSetLtFoll,
2001 && !has_entry_in_rps (dpb_pic, priv->RefPicSetStCurrAfter,
2002 priv->NumPocStCurrAfter)
2003 && !has_entry_in_rps (dpb_pic, priv->RefPicSetStCurrBefore,
2004 priv->NumPocStCurrBefore)
2005 && !has_entry_in_rps (dpb_pic, priv->RefPicSetStFoll,
2006 priv->NumPocStFoll))
2007 gst_vaapi_picture_h265_set_reference (dpb_pic, 0);
2011 /* Decoding process for reference picture set (8.3.2) */
2013 decode_ref_pic_set (GstVaapiDecoderH265 * decoder,
2014 GstVaapiPictureH265 * picture, GstVaapiParserInfoH265 * pi)
2017 gint32 CurrDeltaPocMsbPresentFlag[16] = { 0, };
2018 gint32 FollDeltaPocMsbPresentFlag[16] = { 0, };
2019 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2020 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
2021 GstH265SPS *const sps = get_sps (decoder);
2022 const gint32 MaxPicOrderCntLsb =
2023 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
2025 /* if it is an irap pic, set all ref pics in dpb as unused for ref */
2026 if (nal_is_irap (pi->nalu.type) && picture->NoRaslOutputFlag) {
2027 for (i = 0; i < priv->dpb_count; i++) {
2028 GstVaapiFrameStore *const fs = priv->dpb[i];
2029 gst_vaapi_picture_h265_set_reference (fs->buffer, 0);
2033 /* Reset everything for IDR */
2034 if (nal_is_idr (pi->nalu.type)) {
2035 memset (priv->PocStCurrBefore, 0, sizeof (guint) * 16);
2036 memset (priv->PocStCurrAfter, 0, sizeof (guint) * 16);
2037 memset (priv->PocStFoll, 0, sizeof (guint) * 16);
2038 memset (priv->PocLtCurr, 0, sizeof (guint) * 16);
2039 memset (priv->PocLtFoll, 0, sizeof (guint) * 16);
2040 priv->NumPocStCurrBefore = priv->NumPocStCurrAfter = priv->NumPocStFoll = 0;
2041 priv->NumPocLtCurr = priv->NumPocLtFoll = 0;
2043 GstH265ShortTermRefPicSet *stRefPic = NULL;
2044 gint32 num_lt_pics, pocLt, PocLsbLt[16] = { 0, }
2045 , UsedByCurrPicLt[16] = {
2047 gint32 DeltaPocMsbCycleLt[16] = { 0, };
2048 gint numtotalcurr = 0;
2050 /* this is based on CurrRpsIdx described in spec */
2051 if (!slice_hdr->short_term_ref_pic_set_sps_flag)
2052 stRefPic = &slice_hdr->short_term_ref_pic_sets;
2053 else if (sps->num_short_term_ref_pic_sets)
2055 &sps->short_term_ref_pic_set[slice_hdr->short_term_ref_pic_set_idx];
2057 g_assert (stRefPic != NULL);
2059 for (i = 0, j = 0, k = 0; i < stRefPic->NumNegativePics; i++) {
2060 if (stRefPic->UsedByCurrPicS0[i]) {
2061 priv->PocStCurrBefore[j++] = picture->poc + stRefPic->DeltaPocS0[i];
2064 priv->PocStFoll[k++] = picture->poc + stRefPic->DeltaPocS0[i];
2066 priv->NumPocStCurrBefore = j;
2067 for (i = 0, j = 0; i < stRefPic->NumPositivePics; i++) {
2068 if (stRefPic->UsedByCurrPicS1[i]) {
2069 priv->PocStCurrAfter[j++] = picture->poc + stRefPic->DeltaPocS1[i];
2072 priv->PocStFoll[k++] = picture->poc + stRefPic->DeltaPocS1[i];
2074 priv->NumPocStCurrAfter = j;
2075 priv->NumPocStFoll = k;
2076 num_lt_pics = slice_hdr->num_long_term_sps + slice_hdr->num_long_term_pics;
2077 /* The variables PocLsbLt[i] and UsedByCurrPicLt[i] are derived as follows: */
2078 for (i = 0; i < num_lt_pics; i++) {
2079 if (i < slice_hdr->num_long_term_sps) {
2080 PocLsbLt[i] = sps->lt_ref_pic_poc_lsb_sps[slice_hdr->lt_idx_sps[i]];
2081 UsedByCurrPicLt[i] =
2082 sps->used_by_curr_pic_lt_sps_flag[slice_hdr->lt_idx_sps[i]];
2084 PocLsbLt[i] = slice_hdr->poc_lsb_lt[i];
2085 UsedByCurrPicLt[i] = slice_hdr->used_by_curr_pic_lt_flag[i];
2087 if (UsedByCurrPicLt[i])
2091 priv->NumPocTotalCurr = numtotalcurr;
2093 /* The variable DeltaPocMsbCycleLt[i] is derived as follows: (7-38) */
2094 for (i = 0; i < num_lt_pics; i++) {
2095 if (i == 0 || i == slice_hdr->num_long_term_sps)
2096 DeltaPocMsbCycleLt[i] = slice_hdr->delta_poc_msb_cycle_lt[i];
2098 DeltaPocMsbCycleLt[i] =
2099 slice_hdr->delta_poc_msb_cycle_lt[i] + DeltaPocMsbCycleLt[i - 1];
2103 for (i = 0, j = 0, k = 0; i < num_lt_pics; i++) {
2104 pocLt = PocLsbLt[i];
2105 if (slice_hdr->delta_poc_msb_present_flag[i])
2107 picture->poc - DeltaPocMsbCycleLt[i] * MaxPicOrderCntLsb -
2108 slice_hdr->pic_order_cnt_lsb;
2109 if (UsedByCurrPicLt[i]) {
2110 priv->PocLtCurr[j] = pocLt;
2111 CurrDeltaPocMsbPresentFlag[j++] =
2112 slice_hdr->delta_poc_msb_present_flag[i];
2114 priv->PocLtFoll[k] = pocLt;
2115 FollDeltaPocMsbPresentFlag[k++] =
2116 slice_hdr->delta_poc_msb_present_flag[i];
2119 priv->NumPocLtCurr = j;
2120 priv->NumPocLtFoll = k;
2124 /* the derivation process for the RPS and the picture marking */
2125 derive_and_mark_rps (decoder, picture, pi, CurrDeltaPocMsbPresentFlag,
2126 FollDeltaPocMsbPresentFlag);
2131 static GstVaapiDecoderStatus
2132 decode_picture (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
2134 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2135 GstVaapiParserInfoH265 *pi = unit->parsed_info;
2136 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
2137 GstH265PPS *const pps = ensure_pps (decoder, slice_hdr->pps);
2138 GstH265SPS *const sps = ensure_sps (decoder, slice_hdr->pps->sps);
2139 GstVaapiPictureH265 *picture;
2140 GstVaapiDecoderStatus status;
2142 g_return_val_if_fail (pps != NULL, GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN);
2143 g_return_val_if_fail (sps != NULL, GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN);
2145 status = ensure_context (decoder, sps);
2146 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2149 priv->decoder_state = 0;
2151 /* Create new picture */
2152 picture = gst_vaapi_picture_h265_new (decoder);
2154 GST_ERROR ("failed to allocate picture");
2155 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2158 gst_vaapi_picture_replace (&priv->current_picture, picture);
2159 gst_vaapi_picture_unref (picture);
2161 /* Update cropping rectangle */
2162 /* Fixme: Add cropping rectangle, fix needed in codecparser */
2164 status = ensure_quant_matrix (decoder, picture);
2165 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
2166 GST_ERROR ("failed to reset quantizer matrix");
2170 if (!init_picture (decoder, picture, pi))
2171 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2173 if (!decode_ref_pic_set (decoder, picture, pi))
2174 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2176 /* Fixme: if pic is BLA or CRA,and have NoRaslOutputFlag == 1,
2177 invoke 8.3.3 as described in specification for generating
2178 unavailable reference pictures */
2180 if (!dpb_init (decoder, picture, pi))
2181 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2183 if (!fill_picture (decoder, picture))
2184 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2186 priv->decoder_state = pi->state;
2187 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2191 get_slice_data_byte_offset (GstH265SliceHdr * slice_hdr, guint nal_header_bytes)
2194 epb_count = slice_hdr->n_emulation_prevention_bytes;
2195 return nal_header_bytes + (slice_hdr->header_size + 7) / 8 - epb_count;
2199 clip3 (gint x, gint y, gint z)
2209 fill_pred_weight_table (GstVaapiDecoderH265 * decoder,
2210 GstVaapiSlice * slice, GstH265SliceHdr * slice_hdr)
2212 VASliceParameterBufferHEVC *const slice_param = slice->param;
2213 GstH265PPS *const pps = get_pps (decoder);
2214 GstH265SPS *const sps = get_sps (decoder);
2215 GstH265PredWeightTable *const w = &slice_hdr->pred_weight_table;
2216 gint chroma_weight, chroma_log2_weight_denom;
2219 slice_param->luma_log2_weight_denom = 0;
2220 slice_param->delta_chroma_log2_weight_denom = 0;
2222 if ((pps->weighted_pred_flag && GST_H265_IS_P_SLICE (slice_hdr)) ||
2223 (pps->weighted_bipred_flag && GST_H265_IS_B_SLICE (slice_hdr))) {
2225 slice_param->luma_log2_weight_denom = w->luma_log2_weight_denom;
2226 if (!sps->chroma_format_idc)
2227 slice_param->delta_chroma_log2_weight_denom =
2228 w->delta_chroma_log2_weight_denom;
2230 chroma_log2_weight_denom =
2231 slice_param->luma_log2_weight_denom +
2232 slice_param->delta_chroma_log2_weight_denom;
2234 for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
2235 if (slice_hdr->pred_weight_table.luma_weight_l0_flag[i]) {
2236 slice_param->delta_luma_weight_l0[i] = w->delta_luma_weight_l0[i];
2237 slice_param->luma_offset_l0[i] = w->luma_offset_l0[i];
2239 if (slice_hdr->pred_weight_table.chroma_weight_l0_flag[i]) {
2240 for (j = 0; j < 2; j++) {
2241 slice_param->delta_chroma_weight_l0[i][j] =
2242 w->delta_chroma_weight_l0[i][j];
2243 /* Find ChromaWeightL0 */
2245 (1 << chroma_log2_weight_denom) + w->delta_chroma_weight_l0[i][j];
2247 slice_param->ChromaOffsetL0[i][j] = clip3 (-128, 127,
2248 (w->delta_chroma_offset_l0[i][j] -
2249 ((128 * chroma_weight) >> chroma_log2_weight_denom)));
2254 if (GST_H265_IS_B_SLICE (slice_hdr)) {
2255 for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
2256 if (slice_hdr->pred_weight_table.luma_weight_l1_flag[i]) {
2257 slice_param->delta_luma_weight_l1[i] = w->delta_luma_weight_l1[i];
2258 slice_param->luma_offset_l1[i] = w->luma_offset_l1[i];
2260 if (slice_hdr->pred_weight_table.chroma_weight_l1_flag[i]) {
2261 for (j = 0; j < 2; j++) {
2262 slice_param->delta_chroma_weight_l1[i][j] =
2263 w->delta_chroma_weight_l1[i][j];
2264 /* Find ChromaWeightL1 */
2266 (1 << chroma_log2_weight_denom) +
2267 w->delta_chroma_weight_l1[i][j];
2268 slice_param->ChromaOffsetL1[i][j] =
2270 (w->delta_chroma_offset_l1[i][j] -
2271 ((128 * chroma_weight) >> chroma_log2_weight_denom)));
2277 /* Fixme: Optimize */
2279 for (i = 0; i < 15; i++) {
2280 slice_param->delta_luma_weight_l0[i] = 0;
2281 slice_param->luma_offset_l0[i] = 0;
2282 slice_param->delta_luma_weight_l1[i] = 0;
2283 slice_param->luma_offset_l1[i] = 0;
2285 for (i = 0; i < 15; i++) {
2286 for (j = 0; j < 2; j++) {
2287 slice_param->delta_chroma_weight_l0[i][j] = 0;
2288 slice_param->ChromaOffsetL0[i][j] = 0;
2289 slice_param->delta_chroma_weight_l1[i][j] = 0;
2290 slice_param->ChromaOffsetL1[i][j] = 0;
2298 fill_RefPicList (GstVaapiDecoderH265 * decoder,
2299 GstVaapiPictureH265 * picture, GstVaapiSlice * slice,
2300 GstH265SliceHdr * slice_hdr)
2302 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2303 VASliceParameterBufferHEVC *const slice_param = slice->param;
2304 GstVaapiPicture *const base_picture = &picture->base;
2305 VAPictureParameterBufferHEVC *const pic_param = base_picture->param;
2306 guint i, num_ref_lists = 0, j;
2308 slice_param->num_ref_idx_l0_active_minus1 = 0;
2309 slice_param->num_ref_idx_l1_active_minus1 = 0;
2310 for (j = 0; j < 2; j++)
2311 for (i = 0; i < 15; i++)
2312 slice_param->RefPicList[j][i] = 0xFF;
2314 if (GST_H265_IS_B_SLICE (slice_hdr))
2316 else if (GST_H265_IS_I_SLICE (slice_hdr))
2321 if (num_ref_lists < 1)
2324 slice_param->num_ref_idx_l0_active_minus1 =
2325 slice_hdr->num_ref_idx_l0_active_minus1;
2326 slice_param->num_ref_idx_l1_active_minus1 =
2327 slice_hdr->num_ref_idx_l1_active_minus1;
2329 for (i = 0; i < priv->RefPicList0_count; i++)
2330 slice_param->RefPicList[0][i] =
2331 get_index_for_RefPicListX (pic_param->ReferenceFrames,
2332 priv->RefPicList0[i]);
2334 slice_param->RefPicList[0][i] = 0xFF;
2336 if (num_ref_lists < 2)
2339 for (i = 0; i < priv->RefPicList1_count; i++)
2340 slice_param->RefPicList[1][i] =
2341 get_index_for_RefPicListX (pic_param->ReferenceFrames,
2342 priv->RefPicList1[i]);
2344 slice_param->RefPicList[1][i] = 0xFF;
2350 fill_slice (GstVaapiDecoderH265 * decoder,
2351 GstVaapiPictureH265 * picture, GstVaapiSlice * slice,
2352 GstVaapiParserInfoH265 * pi, GstVaapiDecoderUnit * unit)
2354 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2355 VASliceParameterBufferHEVC *const slice_param = slice->param;
2356 GstH265SliceHdr *slice_hdr = &pi->data.slice_hdr;
2358 /* Fill in VASliceParameterBufferH265 */
2359 slice_param->LongSliceFlags.value = 0;
2360 slice_param->slice_data_byte_offset =
2361 get_slice_data_byte_offset (slice_hdr, pi->nalu.header_bytes);
2363 slice_param->slice_segment_address = slice_hdr->segment_address;
2365 #define COPY_LFF(f) \
2366 slice_param->LongSliceFlags.fields.f = (slice_hdr)->f
2368 if (GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_AU_END))
2369 slice_param->LongSliceFlags.fields.LastSliceOfPic = 1;
2371 slice_param->LongSliceFlags.fields.LastSliceOfPic = 0;
2373 COPY_LFF (dependent_slice_segment_flag);
2375 /* use most recent independent slice segment header syntax elements
2376 * for filling the missing fields in dependent slice segment header */
2377 if (slice_hdr->dependent_slice_segment_flag)
2378 slice_hdr = &priv->prev_independent_slice_pi->data.slice_hdr;
2380 COPY_LFF (mvd_l1_zero_flag);
2381 COPY_LFF (cabac_init_flag);
2382 COPY_LFF (collocated_from_l0_flag);
2383 slice_param->LongSliceFlags.fields.color_plane_id =
2384 slice_hdr->colour_plane_id;
2385 slice_param->LongSliceFlags.fields.slice_type = slice_hdr->type;
2386 slice_param->LongSliceFlags.fields.slice_sao_luma_flag =
2387 slice_hdr->sao_luma_flag;
2388 slice_param->LongSliceFlags.fields.slice_sao_chroma_flag =
2389 slice_hdr->sao_chroma_flag;
2390 slice_param->LongSliceFlags.fields.slice_temporal_mvp_enabled_flag =
2391 slice_hdr->temporal_mvp_enabled_flag;
2392 slice_param->LongSliceFlags.fields.slice_deblocking_filter_disabled_flag =
2393 slice_hdr->deblocking_filter_disabled_flag;
2394 slice_param->LongSliceFlags.
2395 fields.slice_loop_filter_across_slices_enabled_flag =
2396 slice_hdr->loop_filter_across_slices_enabled_flag;
2398 if (!slice_hdr->temporal_mvp_enabled_flag)
2399 slice_param->collocated_ref_idx = 0xFF;
2401 slice_param->collocated_ref_idx = slice_hdr->collocated_ref_idx;
2403 slice_param->num_ref_idx_l0_active_minus1 =
2404 slice_hdr->num_ref_idx_l0_active_minus1;
2405 slice_param->num_ref_idx_l1_active_minus1 =
2406 slice_hdr->num_ref_idx_l1_active_minus1;
2407 slice_param->slice_qp_delta = slice_hdr->qp_delta;
2408 slice_param->slice_cb_qp_offset = slice_hdr->cb_qp_offset;
2409 slice_param->slice_cr_qp_offset = slice_hdr->cr_qp_offset;
2410 slice_param->slice_beta_offset_div2 = slice_hdr->beta_offset_div2;
2411 slice_param->slice_tc_offset_div2 = slice_hdr->tc_offset_div2;
2412 slice_param->five_minus_max_num_merge_cand =
2413 slice_hdr->five_minus_max_num_merge_cand;
2415 if (!fill_RefPicList (decoder, picture, slice, slice_hdr))
2418 if (!fill_pred_weight_table (decoder, slice, slice_hdr))
2424 static GstVaapiDecoderStatus
2425 decode_slice (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
2427 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2428 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
2429 GstVaapiPictureH265 *const picture = priv->current_picture;
2430 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
2431 GstVaapiSlice *slice;
2432 GstBuffer *const buffer =
2433 GST_VAAPI_DECODER_CODEC_FRAME (decoder)->input_buffer;
2434 GstMapInfo map_info;
2436 GST_DEBUG ("slice (%u bytes)", pi->nalu.size);
2437 if (!is_valid_state (pi->state, GST_H265_VIDEO_STATE_VALID_PICTURE_HEADERS)) {
2438 GST_WARNING ("failed to receive enough headers to decode slice");
2439 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2442 if (!ensure_pps (decoder, slice_hdr->pps)) {
2443 GST_ERROR ("failed to activate PPS");
2444 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2447 if (!ensure_sps (decoder, slice_hdr->pps->sps)) {
2448 GST_ERROR ("failed to activate SPS");
2449 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2452 if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) {
2453 GST_ERROR ("failed to map buffer");
2454 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2457 /* Check wether this is the first/last slice in the current access unit */
2458 if (pi->flags & GST_VAAPI_DECODER_UNIT_FLAG_AU_START)
2459 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_AU_START);
2461 if (pi->flags & GST_VAAPI_DECODER_UNIT_FLAG_AU_END)
2462 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_AU_END);
2464 slice = GST_VAAPI_SLICE_NEW (HEVC, decoder,
2465 (map_info.data + unit->offset + pi->nalu.offset), pi->nalu.size);
2467 gst_buffer_unmap (buffer, &map_info);
2469 GST_ERROR ("failed to allocate slice");
2470 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2473 init_picture_refs (decoder, picture, slice_hdr);
2475 if (!fill_slice (decoder, picture, slice, pi, unit)) {
2476 gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (slice));
2477 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2480 gst_vaapi_picture_add_slice (GST_VAAPI_PICTURE_CAST (picture), slice);
2481 picture->last_slice_hdr = slice_hdr;
2482 priv->decoder_state |= GST_H265_VIDEO_STATE_GOT_SLICE;
2483 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2487 scan_for_start_code (GstAdapter * adapter, guint ofs, guint size, guint32 * scp)
2489 return (gint) gst_adapter_masked_scan_uint32_peek (adapter,
2490 0xffffff00, 0x00000100, ofs, size, scp);
2493 static GstVaapiDecoderStatus
2494 decode_unit (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
2496 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2497 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
2498 GstVaapiDecoderStatus status;
2499 priv->decoder_state |= pi->state;
2500 switch (pi->nalu.type) {
2501 case GST_H265_NAL_VPS:
2502 status = decode_vps (decoder, unit);
2504 case GST_H265_NAL_SPS:
2505 status = decode_sps (decoder, unit);
2507 case GST_H265_NAL_PPS:
2508 status = decode_pps (decoder, unit);
2510 case GST_H265_NAL_SLICE_TRAIL_N:
2511 case GST_H265_NAL_SLICE_TRAIL_R:
2512 case GST_H265_NAL_SLICE_TSA_N:
2513 case GST_H265_NAL_SLICE_TSA_R:
2514 case GST_H265_NAL_SLICE_STSA_N:
2515 case GST_H265_NAL_SLICE_STSA_R:
2516 case GST_H265_NAL_SLICE_RADL_N:
2517 case GST_H265_NAL_SLICE_RADL_R:
2518 case GST_H265_NAL_SLICE_RASL_N:
2519 case GST_H265_NAL_SLICE_RASL_R:
2520 case GST_H265_NAL_SLICE_BLA_W_LP:
2521 case GST_H265_NAL_SLICE_BLA_W_RADL:
2522 case GST_H265_NAL_SLICE_BLA_N_LP:
2523 case GST_H265_NAL_SLICE_IDR_W_RADL:
2524 case GST_H265_NAL_SLICE_IDR_N_LP:
2525 case GST_H265_NAL_SLICE_CRA_NUT:
2526 status = decode_slice (decoder, unit);
2528 case GST_H265_NAL_EOS:
2529 case GST_H265_NAL_EOB:
2530 status = decode_sequence_end (decoder);
2532 case GST_H265_NAL_SUFFIX_SEI:
2533 case GST_H265_NAL_PREFIX_SEI:
2534 status = decode_sei (decoder, unit);
2537 GST_WARNING ("unsupported NAL unit type %d", pi->nalu.type);
2538 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
2544 static GstVaapiDecoderStatus
2545 gst_vaapi_decoder_h265_decode_codec_data (GstVaapiDecoder *
2546 base_decoder, const guchar * buf, guint buf_size)
2548 GstVaapiDecoderH265 *const decoder =
2549 GST_VAAPI_DECODER_H265_CAST (base_decoder);
2550 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2551 GstVaapiDecoderStatus status;
2552 GstVaapiDecoderUnit unit;
2553 GstVaapiParserInfoH265 *pi = NULL;
2554 GstH265ParserResult result;
2555 guint num_nal_arrays, num_nals;
2557 unit.parsed_info = NULL;
2559 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2561 GST_ERROR ("failed to decode codec-data, not in hvcC format");
2562 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
2565 priv->nal_length_size = (buf[21] & 0x03) + 1;
2566 GST_DEBUG ("nal length size %u", priv->nal_length_size);
2567 num_nal_arrays = buf[22];
2569 for (i = 0; i < num_nal_arrays; i++) {
2570 num_nals = GST_READ_UINT16_BE (buf + ofs + 1);
2571 for (j = 0; j < num_nals; j++) {
2572 pi = gst_vaapi_parser_info_h265_new ();
2574 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2575 unit.parsed_info = pi;
2576 result = gst_h265_parser_identify_nalu_hevc (priv->parser,
2577 buf, ofs + 3, buf_size, 2, &pi->nalu);
2578 if (result != GST_H265_PARSER_OK) {
2579 status = get_status (result);
2583 switch (pi->nalu.type) {
2584 case GST_H265_NAL_VPS:
2585 status = parse_vps (decoder, &unit);
2586 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2588 status = decode_vps (decoder, &unit);
2589 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2592 case GST_H265_NAL_SPS:
2593 status = parse_sps (decoder, &unit);
2594 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2596 status = decode_sps (decoder, &unit);
2597 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2600 case GST_H265_NAL_PPS:
2601 status = parse_pps (decoder, &unit);
2602 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2604 status = decode_pps (decoder, &unit);
2605 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2609 gst_vaapi_parser_info_h265_replace (&pi, NULL);
2613 priv->is_hvcC = TRUE;
2614 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
2616 gst_vaapi_parser_info_h265_replace (&pi, NULL);
2620 static GstVaapiDecoderStatus
2621 ensure_decoder (GstVaapiDecoderH265 * decoder)
2623 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2624 GstVaapiDecoderStatus status;
2625 if (!priv->is_opened) {
2626 priv->is_opened = gst_vaapi_decoder_h265_open (decoder);
2627 if (!priv->is_opened)
2628 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
2630 gst_vaapi_decoder_decode_codec_data (GST_VAAPI_DECODER_CAST (decoder));
2631 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2634 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2637 static GstVaapiDecoderStatus
2638 gst_vaapi_decoder_h265_parse (GstVaapiDecoder * base_decoder,
2639 GstAdapter * adapter, gboolean at_eos, GstVaapiDecoderUnit * unit)
2641 GstVaapiDecoderH265 *const decoder =
2642 GST_VAAPI_DECODER_H265_CAST (base_decoder);
2643 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2644 GstVaapiParserState *const ps = GST_VAAPI_PARSER_STATE (base_decoder);
2645 GstVaapiParserInfoH265 *pi;
2646 GstVaapiDecoderStatus status;
2647 GstH265ParserResult result;
2649 guint i, size, buf_size, nalu_size, flags;
2652 gboolean at_au_end = FALSE;
2653 status = ensure_decoder (decoder);
2654 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2656 switch (priv->stream_alignment) {
2657 case GST_VAAPI_STREAM_ALIGN_H265_NALU:
2658 case GST_VAAPI_STREAM_ALIGN_H265_AU:
2659 size = gst_adapter_available_fast (adapter);
2662 size = gst_adapter_available (adapter);
2666 if (priv->is_hvcC) {
2667 if (size < priv->nal_length_size)
2668 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2669 buf = (guchar *) & start_code;
2670 g_assert (priv->nal_length_size <= sizeof (start_code));
2671 gst_adapter_copy (adapter, buf, 0, priv->nal_length_size);
2673 for (i = 0; i < priv->nal_length_size; i++)
2674 nalu_size = (nalu_size << 8) | buf[i];
2675 buf_size = priv->nal_length_size + nalu_size;
2676 if (size < buf_size)
2677 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2678 else if (priv->stream_alignment == GST_VAAPI_STREAM_ALIGN_H265_AU)
2679 at_au_end = (buf_size == size);
2682 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2683 if (priv->stream_alignment == GST_VAAPI_STREAM_ALIGN_H265_NALU)
2686 ofs = scan_for_start_code (adapter, 0, size, NULL);
2688 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2690 gst_adapter_flush (adapter, ofs);
2694 ofs2 = ps->input_offset2 - ofs - 4;
2697 ofs = G_UNLIKELY (size < ofs2 + 4) ? -1 :
2698 scan_for_start_code (adapter, ofs2, size - ofs2, NULL);
2700 // Assume the whole NAL unit is present if end-of-stream
2701 // or stream buffers aligned on access unit boundaries
2702 if (priv->stream_alignment == GST_VAAPI_STREAM_ALIGN_H265_AU)
2705 ps->input_offset2 = size;
2706 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2713 ps->input_offset2 = 0;
2714 buf = (guchar *) gst_adapter_map (adapter, buf_size);
2716 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2717 unit->size = buf_size;
2718 pi = gst_vaapi_parser_info_h265_new ();
2720 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2721 gst_vaapi_decoder_unit_set_parsed_info (unit,
2722 pi, (GDestroyNotify) gst_vaapi_mini_object_unref);
2724 result = gst_h265_parser_identify_nalu_hevc (priv->parser,
2725 buf, 0, buf_size, priv->nal_length_size, &pi->nalu);
2727 result = gst_h265_parser_identify_nalu_unchecked (priv->parser,
2728 buf, 0, buf_size, &pi->nalu);
2729 status = get_status (result);
2730 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2732 switch (pi->nalu.type) {
2733 case GST_H265_NAL_VPS:
2734 status = parse_vps (decoder, unit);
2736 case GST_H265_NAL_SPS:
2737 status = parse_sps (decoder, unit);
2739 case GST_H265_NAL_PPS:
2740 status = parse_pps (decoder, unit);
2742 case GST_H265_NAL_PREFIX_SEI:
2743 case GST_H265_NAL_SUFFIX_SEI:
2744 status = parse_sei (decoder, unit);
2746 case GST_H265_NAL_SLICE_TRAIL_N:
2747 case GST_H265_NAL_SLICE_TRAIL_R:
2748 case GST_H265_NAL_SLICE_TSA_N:
2749 case GST_H265_NAL_SLICE_TSA_R:
2750 case GST_H265_NAL_SLICE_STSA_N:
2751 case GST_H265_NAL_SLICE_STSA_R:
2752 case GST_H265_NAL_SLICE_RADL_N:
2753 case GST_H265_NAL_SLICE_RADL_R:
2754 case GST_H265_NAL_SLICE_RASL_N:
2755 case GST_H265_NAL_SLICE_RASL_R:
2756 case GST_H265_NAL_SLICE_BLA_W_LP:
2757 case GST_H265_NAL_SLICE_BLA_W_RADL:
2758 case GST_H265_NAL_SLICE_BLA_N_LP:
2759 case GST_H265_NAL_SLICE_IDR_W_RADL:
2760 case GST_H265_NAL_SLICE_IDR_N_LP:
2761 case GST_H265_NAL_SLICE_CRA_NUT:
2762 status = parse_slice (decoder, unit);
2765 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
2768 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2772 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END |
2773 GST_VAAPI_DECODER_UNIT_FLAG_AU_END;
2775 switch (pi->nalu.type) {
2776 case GST_H265_NAL_AUD:
2777 flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START;
2778 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
2780 case GST_H265_NAL_FD:
2781 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
2783 case GST_H265_NAL_EOB:
2784 flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
2786 case GST_H265_NAL_SUFFIX_SEI:
2787 case GST_H265_NAL_EOS:
2788 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
2789 flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_END;
2791 case GST_H265_NAL_VPS:
2792 case GST_H265_NAL_SPS:
2793 case GST_H265_NAL_PPS:
2794 case GST_H265_NAL_PREFIX_SEI:
2795 flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START;
2796 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
2798 case GST_H265_NAL_SLICE_TRAIL_N:
2799 case GST_H265_NAL_SLICE_TRAIL_R:
2800 case GST_H265_NAL_SLICE_TSA_N:
2801 case GST_H265_NAL_SLICE_TSA_R:
2802 case GST_H265_NAL_SLICE_STSA_N:
2803 case GST_H265_NAL_SLICE_STSA_R:
2804 case GST_H265_NAL_SLICE_RADL_N:
2805 case GST_H265_NAL_SLICE_RADL_R:
2806 case GST_H265_NAL_SLICE_RASL_N:
2807 case GST_H265_NAL_SLICE_RASL_R:
2808 case GST_H265_NAL_SLICE_BLA_W_LP:
2809 case GST_H265_NAL_SLICE_BLA_W_RADL:
2810 case GST_H265_NAL_SLICE_BLA_N_LP:
2811 case GST_H265_NAL_SLICE_IDR_W_RADL:
2812 case GST_H265_NAL_SLICE_IDR_N_LP:
2813 case GST_H265_NAL_SLICE_CRA_NUT:
2814 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
2815 if (priv->prev_pi &&
2816 (priv->prev_pi->flags & GST_VAAPI_DECODER_UNIT_FLAG_AU_END)) {
2817 flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START |
2818 GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
2819 } else if (is_new_picture (pi, priv->prev_slice_pi)) {
2820 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
2821 if (is_new_access_unit (pi, priv->prev_slice_pi))
2822 flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START;
2824 gst_vaapi_parser_info_h265_replace (&priv->prev_slice_pi, pi);
2825 if (!pi->data.slice_hdr.dependent_slice_segment_flag)
2826 gst_vaapi_parser_info_h265_replace (&priv->prev_independent_slice_pi,
2833 if ((flags & GST_VAAPI_DECODER_UNIT_FLAGS_AU) && priv->prev_slice_pi)
2834 priv->prev_slice_pi->flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_END;
2835 GST_VAAPI_DECODER_UNIT_FLAG_SET (unit, flags);
2836 pi->nalu.data = NULL;
2837 pi->state = priv->parser_state;
2839 gst_vaapi_parser_info_h265_replace (&priv->prev_pi, pi);
2840 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2843 static GstVaapiDecoderStatus
2844 gst_vaapi_decoder_h265_decode (GstVaapiDecoder * base_decoder,
2845 GstVaapiDecoderUnit * unit)
2847 GstVaapiDecoderH265 *const decoder =
2848 GST_VAAPI_DECODER_H265_CAST (base_decoder);
2849 GstVaapiDecoderStatus status;
2850 status = ensure_decoder (decoder);
2851 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2853 return decode_unit (decoder, unit);
2856 static GstVaapiDecoderStatus
2857 gst_vaapi_decoder_h265_start_frame (GstVaapiDecoder * base_decoder,
2858 GstVaapiDecoderUnit * unit)
2860 GstVaapiDecoderH265 *const decoder =
2861 GST_VAAPI_DECODER_H265_CAST (base_decoder);
2862 return decode_picture (decoder, unit);
2865 static GstVaapiDecoderStatus
2866 gst_vaapi_decoder_h265_end_frame (GstVaapiDecoder * base_decoder)
2868 GstVaapiDecoderH265 *const decoder =
2869 GST_VAAPI_DECODER_H265_CAST (base_decoder);
2871 return decode_current_picture (decoder);
2874 static GstVaapiDecoderStatus
2875 gst_vaapi_decoder_h265_flush (GstVaapiDecoder * base_decoder)
2877 GstVaapiDecoderH265 *const decoder =
2878 GST_VAAPI_DECODER_H265_CAST (base_decoder);
2879 dpb_flush (decoder);
2880 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2884 gst_vaapi_decoder_h265_class_init (GstVaapiDecoderH265Class * klass)
2886 GstVaapiMiniObjectClass *const object_class =
2887 GST_VAAPI_MINI_OBJECT_CLASS (klass);
2888 GstVaapiDecoderClass *const decoder_class = GST_VAAPI_DECODER_CLASS (klass);
2889 object_class->size = sizeof (GstVaapiDecoderH265);
2890 object_class->finalize = (GDestroyNotify) gst_vaapi_decoder_finalize;
2891 decoder_class->create = gst_vaapi_decoder_h265_create;
2892 decoder_class->destroy = gst_vaapi_decoder_h265_destroy;
2893 decoder_class->parse = gst_vaapi_decoder_h265_parse;
2894 decoder_class->decode = gst_vaapi_decoder_h265_decode;
2895 decoder_class->start_frame = gst_vaapi_decoder_h265_start_frame;
2896 decoder_class->end_frame = gst_vaapi_decoder_h265_end_frame;
2897 decoder_class->flush = gst_vaapi_decoder_h265_flush;
2898 decoder_class->decode_codec_data = gst_vaapi_decoder_h265_decode_codec_data;
2901 static inline const GstVaapiDecoderClass *
2902 gst_vaapi_decoder_h265_class (void)
2904 static GstVaapiDecoderH265Class g_class;
2905 static gsize g_class_init = FALSE;
2906 if (g_once_init_enter (&g_class_init)) {
2907 gst_vaapi_decoder_h265_class_init (&g_class);
2908 g_once_init_leave (&g_class_init, TRUE);
2910 return GST_VAAPI_DECODER_CLASS (&g_class);
2914 * gst_vaapi_decoder_h265_set_alignment:
2915 * @decoder: a #GstVaapiDecoderH265
2916 * @alignment: the #GstVaapiStreamAlignH265
2918 * Specifies how stream buffers are aligned / fed, i.e. the boundaries
2919 * of each buffer that is supplied to the decoder. This could be no
2920 * specific alignment, NAL unit boundaries, or access unit boundaries.
2923 gst_vaapi_decoder_h265_set_alignment (GstVaapiDecoderH265 * decoder,
2924 GstVaapiStreamAlignH265 alignment)
2926 g_return_if_fail (decoder != NULL);
2927 decoder->priv.stream_alignment = alignment;
2931 * gst_vaapi_decoder_h265_new:
2932 * @display: a #GstVaapiDisplay
2933 * @caps: a #GstCaps holding codec information
2935 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
2936 * hold extra information like codec-data and pictured coded size.
2938 * Return value: the newly allocated #GstVaapiDecoder object
2941 gst_vaapi_decoder_h265_new (GstVaapiDisplay * display, GstCaps * caps)
2943 return gst_vaapi_decoder_new (gst_vaapi_decoder_h265_class (), display, caps);