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
31 #include <gst/base/gstadapter.h>
32 #include <gst/codecparsers/gsth265parser.h>
33 #include "gstvaapicompat.h"
34 #include "gstvaapidecoder_h265.h"
35 #include "gstvaapidecoder_objects.h"
36 #include "gstvaapidecoder_priv.h"
37 #include "gstvaapidisplay_priv.h"
38 #include "gstvaapiobject_priv.h"
39 #include "gstvaapiutils_h265_priv.h"
42 #include "gstvaapidebug.h"
44 /* Defined to 1 if strict ordering of DPB is needed. Only useful for debug */
45 #define USE_STRICT_DPB_ORDERING 0
47 typedef struct _GstVaapiDecoderH265Private GstVaapiDecoderH265Private;
48 typedef struct _GstVaapiDecoderH265Class GstVaapiDecoderH265Class;
49 typedef struct _GstVaapiFrameStore GstVaapiFrameStore;
50 typedef struct _GstVaapiFrameStoreClass GstVaapiFrameStoreClass;
51 typedef struct _GstVaapiParserInfoH265 GstVaapiParserInfoH265;
52 typedef struct _GstVaapiPictureH265 GstVaapiPictureH265;
54 static gboolean nal_is_slice (guint8 nal_type);
56 /* ------------------------------------------------------------------------- */
57 /* --- H.265 Parser Info --- */
58 /* ------------------------------------------------------------------------- */
61 * Extended decoder unit flags:
63 * @GST_VAAPI_DECODER_UNIT_AU_START: marks the start of an access unit.
64 * @GST_VAAPI_DECODER_UNIT_AU_END: marks the end of an access unit.
68 GST_VAAPI_DECODER_UNIT_FLAG_AU_START =
69 (GST_VAAPI_DECODER_UNIT_FLAG_LAST << 0),
70 GST_VAAPI_DECODER_UNIT_FLAG_AU_END = (GST_VAAPI_DECODER_UNIT_FLAG_LAST << 1),
72 GST_VAAPI_DECODER_UNIT_FLAGS_AU = (GST_VAAPI_DECODER_UNIT_FLAG_AU_START |
73 GST_VAAPI_DECODER_UNIT_FLAG_AU_END),
76 #define GST_VAAPI_PARSER_INFO_H265(obj) \
77 ((GstVaapiParserInfoH265 *)(obj))
79 struct _GstVaapiParserInfoH265
81 GstVaapiMiniObject parent_instance;
89 GstH265SliceHdr slice_hdr;
92 guint flags; // Same as decoder unit flags (persistent)
96 gst_vaapi_parser_info_h265_finalize (GstVaapiParserInfoH265 * pi)
98 if (nal_is_slice (pi->nalu.type))
99 gst_h265_slice_hdr_free (&pi->data.slice_hdr);
101 switch (pi->nalu.type) {
102 case GST_H265_NAL_VPS:
103 case GST_H265_NAL_SPS:
104 case GST_H265_NAL_PPS:
106 case GST_H265_NAL_PREFIX_SEI:
107 case GST_H265_NAL_SUFFIX_SEI:
109 g_array_unref (pi->data.sei);
117 static inline const GstVaapiMiniObjectClass *
118 gst_vaapi_parser_info_h265_class (void)
120 static const GstVaapiMiniObjectClass GstVaapiParserInfoH265Class = {
121 .size = sizeof (GstVaapiParserInfoH265),
122 .finalize = (GDestroyNotify) gst_vaapi_parser_info_h265_finalize
124 return &GstVaapiParserInfoH265Class;
127 static inline GstVaapiParserInfoH265 *
128 gst_vaapi_parser_info_h265_new (void)
130 return (GstVaapiParserInfoH265 *)
131 gst_vaapi_mini_object_new (gst_vaapi_parser_info_h265_class ());
134 #define gst_vaapi_parser_info_h265_ref(pi) \
135 gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(pi))
137 #define gst_vaapi_parser_info_h265_unref(pi) \
138 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(pi))
140 #define gst_vaapi_parser_info_h265_replace(old_pi_ptr, new_pi) \
141 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_pi_ptr), \
142 (GstVaapiMiniObject *)(new_pi))
144 /* ------------------------------------------------------------------------- */
145 /* --- H.265 Pictures --- */
146 /* ------------------------------------------------------------------------- */
149 * Extended picture flags:
151 * @GST_VAAPI_PICTURE_FLAG_IDR: flag that specifies an IDR picture
152 * @GST_VAAPI_PICTURE_FLAG_AU_START: flag that marks the start of an
154 * @GST_VAAPI_PICTURE_FLAG_AU_END: flag that marks the end of an
156 * @GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_BEFORE: flag indicate the inclusion
157 * of picture in RefPicSetStCurrBefore reference list
158 * @GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_AFTER: flag indicate the inclusion
159 * of picture in RefPictSetStCurrAfter reference list
160 * @GST_VAAPI_PICTURE_FLAG_RPS_ST_FOLL: flag indicate the inclusion
161 * of picture in RefPicSetStFoll reference list
162 * @GST_VAAPI_PICTURE_FLAG_RPS_LT_CURR: flag indicate the inclusion
163 * of picture in RefPicSetLtCurr reference list
164 * @GST_VAAPI_PICTURE_FLAG_RPS_LT_FOLL: flag indicate the inclusion
165 * of picture in RefPicSetLtFoll reference list
166 * @GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE: flag that specifies
167 * "used for short-term reference"
168 * @GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE: flag that specifies
169 * "used for long-term reference"
170 * @GST_VAAPI_PICTURE_FLAGS_REFERENCE: mask covering any kind of
171 * reference picture (short-term reference or long-term reference)
175 GST_VAAPI_PICTURE_FLAG_IDR = (GST_VAAPI_PICTURE_FLAG_LAST << 0),
176 GST_VAAPI_PICTURE_FLAG_REFERENCE2 = (GST_VAAPI_PICTURE_FLAG_LAST << 1),
177 GST_VAAPI_PICTURE_FLAG_AU_START = (GST_VAAPI_PICTURE_FLAG_LAST << 4),
178 GST_VAAPI_PICTURE_FLAG_AU_END = (GST_VAAPI_PICTURE_FLAG_LAST << 5),
179 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_BEFORE =
180 (GST_VAAPI_PICTURE_FLAG_LAST << 6),
181 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_AFTER = (GST_VAAPI_PICTURE_FLAG_LAST << 7),
182 GST_VAAPI_PICTURE_FLAG_RPS_ST_FOLL = (GST_VAAPI_PICTURE_FLAG_LAST << 8),
183 GST_VAAPI_PICTURE_FLAG_RPS_LT_CURR = (GST_VAAPI_PICTURE_FLAG_LAST << 9),
184 GST_VAAPI_PICTURE_FLAG_RPS_LT_FOLL = (GST_VAAPI_PICTURE_FLAG_LAST << 10),
186 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE =
187 (GST_VAAPI_PICTURE_FLAG_REFERENCE),
188 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE =
189 (GST_VAAPI_PICTURE_FLAG_REFERENCE | GST_VAAPI_PICTURE_FLAG_REFERENCE2),
190 GST_VAAPI_PICTURE_FLAGS_REFERENCE =
191 (GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
192 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE),
194 GST_VAAPI_PICTURE_FLAGS_RPS_ST =
195 (GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_BEFORE |
196 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_AFTER |
197 GST_VAAPI_PICTURE_FLAG_RPS_ST_FOLL),
198 GST_VAAPI_PICTURE_FLAGS_RPS_LT =
199 (GST_VAAPI_PICTURE_FLAG_RPS_LT_CURR | GST_VAAPI_PICTURE_FLAG_RPS_LT_FOLL),
202 #define GST_VAAPI_PICTURE_IS_IDR(picture) \
203 (GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_IDR))
205 #define GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture) \
206 ((GST_VAAPI_PICTURE_FLAGS(picture) & \
207 GST_VAAPI_PICTURE_FLAGS_REFERENCE) == \
208 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE)
210 #define GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture) \
211 ((GST_VAAPI_PICTURE_FLAGS(picture) & \
212 GST_VAAPI_PICTURE_FLAGS_REFERENCE) == \
213 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE)
215 #define GST_VAAPI_PICTURE_H265(picture) \
216 ((GstVaapiPictureH265 *)(picture))
218 struct _GstVaapiPictureH265
220 GstVaapiPicture base;
221 GstH265SliceHdr *last_slice_hdr;
223 gint32 poc; // PicOrderCntVal (8.3.1)
224 gint32 poc_lsb; // slice_pic_order_cnt_lsb
225 guint32 pic_latency_cnt; // PicLatencyCount
227 guint output_needed:1;
228 guint NoRaslOutputFlag:1;
229 guint NoOutputOfPriorPicsFlag:1;
230 guint RapPicFlag:1; // nalu type between 16 and 21
231 guint IntraPicFlag:1; // Intra pic (only Intra slices)
234 GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiPictureH265, gst_vaapi_picture_h265);
237 gst_vaapi_picture_h265_destroy (GstVaapiPictureH265 * picture)
239 gst_vaapi_picture_destroy (GST_VAAPI_PICTURE (picture));
243 gst_vaapi_picture_h265_create (GstVaapiPictureH265 * picture,
244 const GstVaapiCodecObjectConstructorArgs * args)
246 if (!gst_vaapi_picture_create (GST_VAAPI_PICTURE (picture), args))
249 picture->structure = picture->base.structure;
250 picture->poc = G_MAXINT32;
251 picture->output_needed = FALSE;
255 static inline GstVaapiPictureH265 *
256 gst_vaapi_picture_h265_new (GstVaapiDecoderH265 * decoder)
258 return (GstVaapiPictureH265 *)
259 gst_vaapi_codec_object_new (&GstVaapiPictureH265Class,
260 GST_VAAPI_CODEC_BASE (decoder), NULL,
261 sizeof (VAPictureParameterBufferHEVC), NULL, 0, 0);
265 gst_vaapi_picture_h265_set_reference (GstVaapiPictureH265 * picture,
266 guint reference_flags)
270 GST_VAAPI_PICTURE_FLAG_UNSET (picture,
271 GST_VAAPI_PICTURE_FLAGS_RPS_ST | GST_VAAPI_PICTURE_FLAGS_RPS_LT);
272 GST_VAAPI_PICTURE_FLAG_UNSET (picture, GST_VAAPI_PICTURE_FLAGS_REFERENCE);
273 GST_VAAPI_PICTURE_FLAG_SET (picture, reference_flags);
276 /* ------------------------------------------------------------------------- */
277 /* --- Frame Buffers (DPB) --- */
278 /* ------------------------------------------------------------------------- */
280 struct _GstVaapiFrameStore
283 GstVaapiMiniObject parent_instance;
285 GstVaapiPictureH265 *buffer;
289 gst_vaapi_frame_store_finalize (gpointer object)
291 GstVaapiFrameStore *const fs = object;
293 gst_vaapi_picture_replace (&fs->buffer, NULL);
296 static GstVaapiFrameStore *
297 gst_vaapi_frame_store_new (GstVaapiPictureH265 * picture)
299 GstVaapiFrameStore *fs;
301 static const GstVaapiMiniObjectClass GstVaapiFrameStoreClass = {
302 sizeof (GstVaapiFrameStore),
303 gst_vaapi_frame_store_finalize
306 fs = (GstVaapiFrameStore *)
307 gst_vaapi_mini_object_new (&GstVaapiFrameStoreClass);
311 fs->buffer = gst_vaapi_picture_ref (picture);
316 static inline gboolean
317 gst_vaapi_frame_store_has_reference (GstVaapiFrameStore * fs)
319 if (GST_VAAPI_PICTURE_IS_REFERENCE (fs->buffer))
324 #define gst_vaapi_frame_store_ref(fs) \
325 gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(fs))
327 #define gst_vaapi_frame_store_unref(fs) \
328 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(fs))
330 #define gst_vaapi_frame_store_replace(old_fs_p, new_fs) \
331 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_fs_p), \
332 (GstVaapiMiniObject *)(new_fs))
334 /* ------------------------------------------------------------------------- */
335 /* --- H.265 Decoder --- */
336 /* ------------------------------------------------------------------------- */
338 #define GST_VAAPI_DECODER_H265_CAST(decoder) \
339 ((GstVaapiDecoderH265 *)(decoder))
343 GST_H265_VIDEO_STATE_GOT_VPS = 1 << 0,
344 GST_H265_VIDEO_STATE_GOT_SPS = 1 << 1,
345 GST_H265_VIDEO_STATE_GOT_PPS = 1 << 2,
346 GST_H265_VIDEO_STATE_GOT_SLICE = 1 << 3,
348 GST_H265_VIDEO_STATE_VALID_PICTURE_HEADERS =
349 (GST_H265_VIDEO_STATE_GOT_SPS | GST_H265_VIDEO_STATE_GOT_PPS),
350 GST_H265_VIDEO_STATE_VALID_PICTURE =
351 (GST_H265_VIDEO_STATE_VALID_PICTURE_HEADERS |
352 GST_H265_VIDEO_STATE_GOT_SLICE)
355 struct _GstVaapiDecoderH265Private
357 GstH265Parser *parser;
360 GstVaapiStreamAlignH265 stream_alignment;
361 GstVaapiPictureH265 *current_picture;
362 GstVaapiParserInfoH265 *vps[GST_H265_MAX_VPS_COUNT];
363 GstVaapiParserInfoH265 *active_vps;
364 GstVaapiParserInfoH265 *sps[GST_H265_MAX_SPS_COUNT];
365 GstVaapiParserInfoH265 *active_sps;
366 GstVaapiParserInfoH265 *pps[GST_H265_MAX_PPS_COUNT];
367 GstVaapiParserInfoH265 *active_pps;
368 GstVaapiParserInfoH265 *prev_pi;
369 GstVaapiParserInfoH265 *prev_slice_pi;
370 GstVaapiParserInfoH265 *prev_independent_slice_pi;
371 GstVaapiFrameStore **dpb;
375 GstVaapiProfile profile;
376 GstVaapiEntrypoint entrypoint;
377 GstVaapiChromaType chroma_type;
379 GstVaapiPictureH265 *RefPicSetStCurrBefore[16];
380 GstVaapiPictureH265 *RefPicSetStCurrAfter[16];
381 GstVaapiPictureH265 *RefPicSetStFoll[16];
382 GstVaapiPictureH265 *RefPicSetLtCurr[16];
383 GstVaapiPictureH265 *RefPicSetLtFoll[16];
385 GstVaapiPictureH265 *RefPicList0[16];
386 guint RefPicList0_count;
387 GstVaapiPictureH265 *RefPicList1[16];
388 guint RefPicList1_count;
390 guint32 SpsMaxLatencyPictures;
391 gint32 WpOffsetHalfRangeC;
393 guint nal_length_size;
395 guint pic_width_in_luma_samples; //sps->pic_width_in_luma_samples
396 guint pic_height_in_luma_samples; //sps->pic_height_in_luma_samples
397 guint pic_structure; // pic_struct (from SEI pic_timing() or inferred)
398 gint32 poc; // PicOrderCntVal
399 gint32 poc_msb; // PicOrderCntMsb
400 gint32 poc_lsb; // pic_order_cnt_lsb (from slice_header())
401 gint32 prev_poc_msb; // prevPicOrderCntMsb
402 gint32 prev_poc_lsb; // prevPicOrderCntLsb
403 gint32 prev_tid0pic_poc_lsb;
404 gint32 prev_tid0pic_poc_msb;
405 gint32 PocStCurrBefore[16];
406 gint32 PocStCurrAfter[16];
407 gint32 PocStFoll[16];
408 gint32 PocLtCurr[16];
409 gint32 PocLtFoll[16];
410 guint NumPocStCurrBefore;
411 guint NumPocStCurrAfter;
415 guint NumPocTotalCurr;
419 guint progressive_sequence:1;
420 guint new_bitstream:1;
421 guint prev_nal_is_eos:1; /*previous nal type is EOS */
422 guint associated_irap_NoRaslOutputFlag:1;
426 * GstVaapiDecoderH265:
428 * A decoder based on H265.
430 struct _GstVaapiDecoderH265
433 GstVaapiDecoder parent_instance;
434 GstVaapiDecoderH265Private priv;
438 * GstVaapiDecoderH265Class:
440 * A decoder class based on H265.
442 struct _GstVaapiDecoderH265Class
445 GstVaapiDecoderClass parent_class;
448 #define RSV_VCL_N10 10
449 #define RSV_VCL_N12 12
450 #define RSV_VCL_N14 14
453 nal_is_idr (guint8 nal_type)
455 if ((nal_type == GST_H265_NAL_SLICE_IDR_W_RADL) ||
456 (nal_type == GST_H265_NAL_SLICE_IDR_N_LP))
462 nal_is_irap (guint8 nal_type)
464 if ((nal_type >= GST_H265_NAL_SLICE_BLA_W_LP) &&
465 (nal_type <= RESERVED_IRAP_NAL_TYPE_MAX))
471 nal_is_bla (guint8 nal_type)
473 if ((nal_type >= GST_H265_NAL_SLICE_BLA_W_LP) &&
474 (nal_type <= GST_H265_NAL_SLICE_BLA_N_LP))
480 nal_is_cra (guint8 nal_type)
482 if (nal_type == GST_H265_NAL_SLICE_CRA_NUT)
488 nal_is_radl (guint8 nal_type)
490 if ((nal_type >= GST_H265_NAL_SLICE_RADL_N) &&
491 (nal_type <= GST_H265_NAL_SLICE_RADL_R))
497 nal_is_rasl (guint8 nal_type)
499 if ((nal_type >= GST_H265_NAL_SLICE_RASL_N) &&
500 (nal_type <= GST_H265_NAL_SLICE_RASL_R))
506 nal_is_slice (guint8 nal_type)
508 if ((nal_type >= GST_H265_NAL_SLICE_TRAIL_N) &&
509 (nal_type <= GST_H265_NAL_SLICE_CRA_NUT))
515 nal_is_ref (guint8 nal_type)
517 gboolean ret = FALSE;
519 case GST_H265_NAL_SLICE_TRAIL_N:
520 case GST_H265_NAL_SLICE_TSA_N:
521 case GST_H265_NAL_SLICE_STSA_N:
522 case GST_H265_NAL_SLICE_RADL_N:
523 case GST_H265_NAL_SLICE_RASL_N:
536 /* Activates the supplied PPS */
538 ensure_pps (GstVaapiDecoderH265 * decoder, GstH265PPS * pps)
540 GstVaapiDecoderH265Private *const priv = &decoder->priv;
541 GstVaapiParserInfoH265 *const pi = priv->pps[pps->id];
543 gst_vaapi_parser_info_h265_replace (&priv->active_pps, pi);
544 return pi ? &pi->data.pps : NULL;
547 /* Returns the active PPS */
548 static inline GstH265PPS *
549 get_pps (GstVaapiDecoderH265 * decoder)
551 GstVaapiParserInfoH265 *const pi = decoder->priv.active_pps;
553 return pi ? &pi->data.pps : NULL;
556 /* Activate the supplied SPS */
558 ensure_sps (GstVaapiDecoderH265 * decoder, GstH265SPS * sps)
560 GstVaapiDecoderH265Private *const priv = &decoder->priv;
561 GstVaapiParserInfoH265 *const pi = priv->sps[sps->id];
563 gst_vaapi_parser_info_h265_replace (&priv->active_sps, pi);
564 return pi ? &pi->data.sps : NULL;
567 /* Returns the active SPS */
568 static inline GstH265SPS *
569 get_sps (GstVaapiDecoderH265 * decoder)
571 GstVaapiParserInfoH265 *const pi = decoder->priv.active_sps;
573 return pi ? &pi->data.sps : NULL;
576 /* Activate the supplied VPS */
578 ensure_vps (GstVaapiDecoderH265 * decoder, GstH265VPS * vps)
580 GstVaapiDecoderH265Private *const priv = &decoder->priv;
581 GstVaapiParserInfoH265 *const pi = priv->vps[vps->id];
583 gst_vaapi_parser_info_h265_replace (&priv->active_vps, pi);
584 return pi ? &pi->data.vps : NULL;
587 /* Returns the active VPS */
588 static inline GstH265VPS *
589 get_vps (GstVaapiDecoderH265 * decoder)
591 GstVaapiParserInfoH265 *const pi = decoder->priv.active_vps;
592 return pi ? &pi->data.vps : NULL;
595 /* Get number of reference frames to use */
597 get_max_dec_frame_buffering (GstH265SPS * sps)
599 guint max_dec_frame_buffering;
600 GstVaapiLevelH265 level;
601 const GstVaapiH265LevelLimits *level_limits;
603 level = gst_vaapi_utils_h265_get_level (sps->profile_tier_level.level_idc);
604 level_limits = gst_vaapi_utils_h265_get_level_limits (level);
605 if (G_UNLIKELY (!level_limits)) {
606 GST_FIXME ("unsupported level_idc value (%d)",
607 sps->profile_tier_level.level_idc);
608 max_dec_frame_buffering = 16;
611 /* Fixme: Add limit check based on Annex A */
613 /* Assuming HighestTid as sps_max_sub_layers_minus1 */
615 (sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1] + 1));
619 dpb_remove_index (GstVaapiDecoderH265 * decoder, gint index)
621 GstVaapiDecoderH265Private *const priv = &decoder->priv;
622 guint i, num_frames = --priv->dpb_count;
624 if (USE_STRICT_DPB_ORDERING) {
625 for (i = index; i < num_frames; i++)
626 gst_vaapi_frame_store_replace (&priv->dpb[i], priv->dpb[i + 1]);
627 } else if (index != num_frames)
628 gst_vaapi_frame_store_replace (&priv->dpb[index], priv->dpb[num_frames]);
629 gst_vaapi_frame_store_replace (&priv->dpb[num_frames], NULL);
633 dpb_output (GstVaapiDecoderH265 * decoder, GstVaapiFrameStore * fs)
635 GstVaapiPictureH265 *picture;
637 g_return_val_if_fail (fs != NULL, FALSE);
639 picture = fs->buffer;
640 g_return_val_if_fail (picture != NULL, FALSE);
642 picture->output_needed = FALSE;
643 return gst_vaapi_picture_output (GST_VAAPI_PICTURE_CAST (picture));
646 /* Get the dpb picture having the specifed poc or poc_lsb */
647 static GstVaapiPictureH265 *
648 dpb_get_picture (GstVaapiDecoderH265 * decoder, gint poc, gboolean match_lsb)
650 GstVaapiDecoderH265Private *const priv = &decoder->priv;
653 for (i = 0; i < priv->dpb_count; i++) {
654 GstVaapiPictureH265 *const picture = priv->dpb[i]->buffer;
656 if (picture && GST_VAAPI_PICTURE_FLAG_IS_SET (picture,
657 GST_VAAPI_PICTURE_FLAGS_REFERENCE)) {
659 if (picture->poc_lsb == poc)
662 if (picture->poc == poc)
670 /* Get the dpb picture having the specifed poc and shor/long ref flags */
671 static GstVaapiPictureH265 *
672 dpb_get_ref_picture (GstVaapiDecoderH265 * decoder, gint poc, gboolean is_short)
674 GstVaapiDecoderH265Private *const priv = &decoder->priv;
677 for (i = 0; i < priv->dpb_count; i++) {
678 GstVaapiPictureH265 *const picture = priv->dpb[i]->buffer;
680 if (picture && picture->poc == poc) {
681 if (is_short && GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE (picture))
683 else if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE (picture))
691 /* Finds the picture with the lowest POC that needs to be output */
693 dpb_find_lowest_poc (GstVaapiDecoderH265 * decoder,
694 GstVaapiPictureH265 ** found_picture_ptr)
696 GstVaapiDecoderH265Private *const priv = &decoder->priv;
697 GstVaapiPictureH265 *found_picture = NULL;
698 guint i, found_index;
700 for (i = 0; i < priv->dpb_count; i++) {
701 GstVaapiPictureH265 *const picture = priv->dpb[i]->buffer;
702 if (picture && !picture->output_needed)
704 if (!found_picture || found_picture->poc > picture->poc)
705 found_picture = picture, found_index = i;
708 if (found_picture_ptr)
709 *found_picture_ptr = found_picture;
710 return found_picture ? found_index : -1;
714 dpb_bump (GstVaapiDecoderH265 * decoder, GstVaapiPictureH265 * picture)
716 GstVaapiDecoderH265Private *const priv = &decoder->priv;
717 GstVaapiPictureH265 *found_picture;
721 found_index = dpb_find_lowest_poc (decoder, &found_picture);
725 success = dpb_output (decoder, priv->dpb[found_index]);
727 if (!gst_vaapi_frame_store_has_reference (priv->dpb[found_index]))
728 dpb_remove_index (decoder, found_index);
734 dpb_clear (GstVaapiDecoderH265 * decoder, gboolean hard_flush)
736 GstVaapiDecoderH265Private *const priv = &decoder->priv;
737 GstVaapiPictureH265 *pic;
741 for (i = 0; i < priv->dpb_count; i++)
742 dpb_remove_index (decoder, i);
745 /* Remove unused pictures from DPB */
747 while (i < priv->dpb_count) {
748 GstVaapiFrameStore *const fs = priv->dpb[i];
750 if (!pic->output_needed && !gst_vaapi_frame_store_has_reference (fs))
751 dpb_remove_index (decoder, i);
759 dpb_flush (GstVaapiDecoderH265 * decoder)
761 /* Output any frame remaining in DPB */
762 while (dpb_bump (decoder, NULL));
763 dpb_clear (decoder, TRUE);
767 dpb_get_num_need_output (GstVaapiDecoderH265 * decoder)
769 GstVaapiDecoderH265Private *const priv = &decoder->priv;
770 guint i = 0, n_output_needed = 0;
772 while (i < priv->dpb_count) {
773 GstVaapiFrameStore *const fs = priv->dpb[i];
774 if (fs->buffer->output_needed)
779 return n_output_needed;
783 check_latency_cnt (GstVaapiDecoderH265 * decoder)
785 GstVaapiDecoderH265Private *const priv = &decoder->priv;
786 GstVaapiPictureH265 *tmp_pic;
789 while (i < priv->dpb_count) {
790 GstVaapiFrameStore *const fs = priv->dpb[i];
791 tmp_pic = fs->buffer;
792 if (tmp_pic->output_needed) {
793 if (tmp_pic->pic_latency_cnt >= priv->SpsMaxLatencyPictures)
803 dpb_add (GstVaapiDecoderH265 * decoder, GstVaapiPictureH265 * picture)
805 GstVaapiDecoderH265Private *const priv = &decoder->priv;
806 GstH265SPS *const sps = get_sps (decoder);
807 GstVaapiFrameStore *fs;
808 GstVaapiPictureH265 *tmp_pic;
812 while (i < priv->dpb_count) {
813 GstVaapiFrameStore *const fs = priv->dpb[i];
814 tmp_pic = fs->buffer;
815 if (tmp_pic->output_needed)
816 tmp_pic->pic_latency_cnt += 1;
820 if (picture->output_flag) {
821 picture->output_needed = 1;
822 picture->pic_latency_cnt = 0;
824 picture->output_needed = 0;
826 /* set pic as short_term_ref */
827 gst_vaapi_picture_h265_set_reference (picture,
828 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE);
830 /* C.5.2.4 "Bumping" process */
831 while ((dpb_get_num_need_output (decoder) >
832 sps->max_num_reorder_pics[sps->max_sub_layers_minus1])
833 || (sps->max_latency_increase_plus1[sps->max_sub_layers_minus1]
834 && check_latency_cnt (decoder)))
835 dpb_bump (decoder, picture);
837 /* Create new frame store */
838 fs = gst_vaapi_frame_store_new (picture);
841 gst_vaapi_frame_store_replace (&priv->dpb[priv->dpb_count++], fs);
842 gst_vaapi_frame_store_unref (fs);
850 dpb_init (GstVaapiDecoderH265 * decoder, GstVaapiPictureH265 * picture,
851 GstVaapiParserInfoH265 * pi)
853 GstVaapiDecoderH265Private *const priv = &decoder->priv;
854 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
855 GstH265SPS *const sps = get_sps (decoder);
857 if (nal_is_irap (pi->nalu.type)
858 && picture->NoRaslOutputFlag && !priv->new_bitstream) {
860 if (pi->nalu.type == GST_H265_NAL_SLICE_CRA_NUT)
861 picture->NoOutputOfPriorPicsFlag = 1;
863 picture->NoOutputOfPriorPicsFlag =
864 slice_hdr->no_output_of_prior_pics_flag;
866 if (picture->NoOutputOfPriorPicsFlag)
867 dpb_clear (decoder, TRUE);
869 dpb_clear (decoder, FALSE);
870 while (dpb_bump (decoder, NULL));
873 dpb_clear (decoder, FALSE);
874 while ((dpb_get_num_need_output (decoder) >
875 sps->max_num_reorder_pics[sps->max_sub_layers_minus1])
876 || (sps->max_latency_increase_plus1[sps->max_sub_layers_minus1]
877 && check_latency_cnt (decoder))
878 || (priv->dpb_count >=
879 (sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1] +
881 dpb_bump (decoder, picture);
889 dpb_reset (GstVaapiDecoderH265 * decoder, guint dpb_size)
891 GstVaapiDecoderH265Private *const priv = &decoder->priv;
893 if (dpb_size > priv->dpb_size_max) {
894 priv->dpb = g_try_realloc_n (priv->dpb, dpb_size, sizeof (*priv->dpb));
897 memset (&priv->dpb[priv->dpb_size_max], 0,
898 (dpb_size - priv->dpb_size_max) * sizeof (*priv->dpb));
899 priv->dpb_size_max = dpb_size;
901 priv->dpb_size = dpb_size;
902 GST_DEBUG ("DPB size %u", priv->dpb_size);
906 static GstVaapiDecoderStatus
907 get_status (GstH265ParserResult result)
909 GstVaapiDecoderStatus status;
912 case GST_H265_PARSER_OK:
913 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
915 case GST_H265_PARSER_NO_NAL_END:
916 status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
918 case GST_H265_PARSER_ERROR:
919 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
922 status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
929 gst_vaapi_decoder_h265_close (GstVaapiDecoderH265 * decoder)
931 GstVaapiDecoderH265Private *const priv = &decoder->priv;
933 gst_vaapi_picture_replace (&priv->current_picture, NULL);
934 gst_vaapi_parser_info_h265_replace (&priv->prev_slice_pi, NULL);
935 gst_vaapi_parser_info_h265_replace (&priv->prev_independent_slice_pi, NULL);
936 gst_vaapi_parser_info_h265_replace (&priv->prev_pi, NULL);
938 dpb_clear (decoder, TRUE);
941 gst_h265_parser_free (priv->parser);
947 gst_vaapi_decoder_h265_open (GstVaapiDecoderH265 * decoder)
949 GstVaapiDecoderH265Private *const priv = &decoder->priv;
951 gst_vaapi_decoder_h265_close (decoder);
952 priv->parser = gst_h265_parser_new ();
959 gst_vaapi_decoder_h265_destroy (GstVaapiDecoder * base_decoder)
961 GstVaapiDecoderH265 *const decoder =
962 GST_VAAPI_DECODER_H265_CAST (base_decoder);
963 GstVaapiDecoderH265Private *const priv = &decoder->priv;
966 gst_vaapi_decoder_h265_close (decoder);
970 for (i = 0; i < G_N_ELEMENTS (priv->pps); i++)
971 gst_vaapi_parser_info_h265_replace (&priv->pps[i], NULL);
972 gst_vaapi_parser_info_h265_replace (&priv->active_pps, NULL);
973 for (i = 0; i < G_N_ELEMENTS (priv->sps); i++)
974 gst_vaapi_parser_info_h265_replace (&priv->sps[i], NULL);
975 gst_vaapi_parser_info_h265_replace (&priv->active_sps, NULL);
976 for (i = 0; i < G_N_ELEMENTS (priv->vps); i++)
977 gst_vaapi_parser_info_h265_replace (&priv->vps[i], NULL);
978 gst_vaapi_parser_info_h265_replace (&priv->active_vps, NULL);
982 gst_vaapi_decoder_h265_create (GstVaapiDecoder * base_decoder)
984 GstVaapiDecoderH265 *const decoder =
985 GST_VAAPI_DECODER_H265_CAST (base_decoder);
986 GstVaapiDecoderH265Private *const priv = &decoder->priv;
988 priv->profile = GST_VAAPI_PROFILE_UNKNOWN;
989 priv->entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
990 priv->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
991 priv->progressive_sequence = TRUE;
992 priv->new_bitstream = TRUE;
993 priv->prev_nal_is_eos = FALSE;
999 fill_profiles (GstVaapiProfile profiles[16], guint * n_profiles_ptr,
1000 GstVaapiProfile profile)
1002 guint n_profiles = *n_profiles_ptr;
1004 profiles[n_profiles++] = profile;
1006 case GST_VAAPI_PROFILE_H265_MAIN:
1007 profiles[n_profiles++] = GST_VAAPI_PROFILE_H265_MAIN10;
1009 case GST_VAAPI_PROFILE_H265_MAIN_STILL_PICTURE:
1010 profiles[n_profiles++] = GST_VAAPI_PROFILE_H265_MAIN;
1011 profiles[n_profiles++] = GST_VAAPI_PROFILE_H265_MAIN10;
1016 *n_profiles_ptr = n_profiles;
1019 static GstVaapiProfile
1020 get_profile (GstVaapiDecoderH265 * decoder, GstH265SPS * sps, guint dpb_size)
1022 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1023 GstVaapiDisplay *const display = GST_VAAPI_DECODER_DISPLAY (decoder);
1024 GstVaapiProfile profile, profiles[3];
1025 guint i, n_profiles = 0;
1028 gst_vaapi_utils_h265_get_profile (sps->profile_tier_level.profile_idc);
1030 /* HACK: This is a work-around to identify some main profile streams having wrong profile_idc.
1031 * There are some wrongly encoded main profile streams(eg: ENTP_C_LG_3.bin) which doesn't
1032 * have any of the profile_idc values mentioned in Annex-A, instead general_profile_idc
1033 * has been set as zero and having general_profile_compatibility_flag[general_profile_idc]
1034 * is TRUE. Assuming them as MAIN profile for now */
1035 if (sps->profile_tier_level.profile_space == 0 &&
1036 sps->profile_tier_level.profile_idc == 0 &&
1037 sps->profile_tier_level.profile_compatibility_flag[0] == 1) {
1038 GST_WARNING ("Wrong profile_idc, blindly setting it as main profile !!");
1039 profile = GST_VAAPI_PROFILE_H265_MAIN;
1041 return GST_VAAPI_PROFILE_UNKNOWN;
1044 fill_profiles (profiles, &n_profiles, profile);
1046 case GST_VAAPI_PROFILE_H265_MAIN10:
1047 if (sps->profile_tier_level.profile_compatibility_flag[1]) { // A.2.3.2 (main profile)
1048 fill_profiles (profiles, &n_profiles, GST_VAAPI_PROFILE_H265_MAIN);
1055 /* If the preferred profile (profiles[0]) matches one that we already
1056 found, then just return it now instead of searching for it again */
1057 if (profiles[0] == priv->profile)
1058 return priv->profile;
1059 for (i = 0; i < n_profiles; i++) {
1060 if (gst_vaapi_display_has_decoder (display, profiles[i], priv->entrypoint))
1063 return GST_VAAPI_PROFILE_UNKNOWN;
1066 static GstVaapiDecoderStatus
1067 ensure_context (GstVaapiDecoderH265 * decoder, GstH265SPS * sps)
1069 GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER_CAST (decoder);
1070 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1071 GstVaapiContextInfo info;
1072 GstVaapiProfile profile;
1073 GstVaapiChromaType chroma_type;
1074 gboolean reset_context = FALSE;
1077 dpb_size = get_max_dec_frame_buffering (sps);
1078 if (priv->dpb_size < dpb_size) {
1079 GST_DEBUG ("DPB size increased");
1080 reset_context = TRUE;
1083 profile = get_profile (decoder, sps, dpb_size);
1085 GST_ERROR ("unsupported profile_idc %u",
1086 sps->profile_tier_level.profile_idc);
1087 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
1090 if (!priv->profile || (priv->profile != profile)) {
1091 GST_DEBUG ("profile changed");
1092 reset_context = TRUE;
1093 priv->profile = profile;
1096 chroma_type = gst_vaapi_utils_h265_get_chroma_type (sps->chroma_format_idc);
1098 GST_ERROR ("unsupported chroma_format_idc %u", sps->chroma_format_idc);
1099 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
1102 if (priv->chroma_type != chroma_type) {
1103 GST_DEBUG ("chroma format changed");
1104 reset_context = TRUE;
1105 priv->chroma_type = chroma_type;
1108 if (priv->pic_width_in_luma_samples != sps->pic_width_in_luma_samples ||
1109 priv->pic_height_in_luma_samples != sps->pic_height_in_luma_samples) {
1110 GST_DEBUG ("size changed");
1111 reset_context = TRUE;
1112 priv->pic_width_in_luma_samples = sps->pic_width_in_luma_samples;
1113 priv->pic_height_in_luma_samples = sps->pic_height_in_luma_samples;
1116 priv->progressive_sequence = 1; /*Fixme */
1117 gst_vaapi_decoder_set_interlaced (base_decoder, !priv->progressive_sequence);
1118 gst_vaapi_decoder_set_pixel_aspect_ratio (base_decoder,
1119 sps->vui_params.par_n, sps->vui_params.par_d);
1120 if (!reset_context && priv->has_context)
1121 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1123 /* XXX: fix surface size when cropping is implemented */
1124 info.profile = priv->profile;
1125 info.entrypoint = priv->entrypoint;
1126 info.chroma_type = priv->chroma_type;
1127 info.width = sps->width;
1128 info.height = sps->height;
1129 info.ref_frames = dpb_size;
1131 if (!gst_vaapi_decoder_ensure_context (GST_VAAPI_DECODER (decoder), &info))
1132 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1133 priv->has_context = TRUE;
1136 if (!dpb_reset (decoder, dpb_size))
1137 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1139 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1143 fill_iq_matrix_4x4 (VAIQMatrixBufferHEVC * iq_matrix,
1144 GstH265ScalingList * scaling_list)
1148 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList4x4) == 6);
1149 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList4x4[0]) == 16);
1150 for (i = 0; i < G_N_ELEMENTS (iq_matrix->ScalingList4x4); i++) {
1151 gst_h265_quant_matrix_4x4_get_raster_from_zigzag (iq_matrix->ScalingList4x4
1152 [i], scaling_list->scaling_lists_4x4[i]);
1157 fill_iq_matrix_8x8 (VAIQMatrixBufferHEVC * iq_matrix,
1158 GstH265ScalingList * scaling_list)
1162 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList8x8) == 6);
1163 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList8x8[0]) == 64);
1164 for (i = 0; i < G_N_ELEMENTS (iq_matrix->ScalingList8x8); i++) {
1165 gst_h265_quant_matrix_8x8_get_raster_from_zigzag (iq_matrix->ScalingList8x8
1166 [i], scaling_list->scaling_lists_8x8[i]);
1171 fill_iq_matrix_16x16 (VAIQMatrixBufferHEVC * iq_matrix,
1172 GstH265ScalingList * scaling_list)
1176 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList16x16) == 6);
1177 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList16x16[0]) == 64);
1178 for (i = 0; i < G_N_ELEMENTS (iq_matrix->ScalingList16x16); i++) {
1179 gst_h265_quant_matrix_16x16_get_raster_from_zigzag
1180 (iq_matrix->ScalingList16x16[i], scaling_list->scaling_lists_16x16[i]);
1185 fill_iq_matrix_32x32 (VAIQMatrixBufferHEVC * iq_matrix,
1186 GstH265ScalingList * scaling_list)
1190 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList32x32) == 2);
1191 g_assert (G_N_ELEMENTS (iq_matrix->ScalingList32x32[0]) == 64);
1192 for (i = 0; i < G_N_ELEMENTS (iq_matrix->ScalingList32x32); i++) {
1193 gst_h265_quant_matrix_32x32_get_raster_from_zigzag
1194 (iq_matrix->ScalingList32x32[i], scaling_list->scaling_lists_32x32[i]);
1199 fill_iq_matrix_dc_16x16 (VAIQMatrixBufferHEVC * iq_matrix,
1200 GstH265ScalingList * scaling_list)
1204 for (i = 0; i < 6; i++)
1205 iq_matrix->ScalingListDC16x16[i] =
1206 scaling_list->scaling_list_dc_coef_minus8_16x16[i] + 8;
1210 fill_iq_matrix_dc_32x32 (VAIQMatrixBufferHEVC * iq_matrix,
1211 GstH265ScalingList * scaling_list)
1215 for (i = 0; i < 2; i++)
1216 iq_matrix->ScalingListDC32x32[i] =
1217 scaling_list->scaling_list_dc_coef_minus8_32x32[i] + 8;
1220 static GstVaapiDecoderStatus
1221 ensure_quant_matrix (GstVaapiDecoderH265 * decoder,
1222 GstVaapiPictureH265 * picture)
1224 GstVaapiPicture *const base_picture = &picture->base;
1225 GstH265PPS *const pps = get_pps (decoder);
1226 GstH265SPS *const sps = get_sps (decoder);
1227 GstH265ScalingList *scaling_list = NULL;
1228 VAIQMatrixBufferHEVC *iq_matrix;
1231 (pps->scaling_list_data_present_flag ||
1232 (sps->scaling_list_enabled_flag
1233 && !sps->scaling_list_data_present_flag)))
1234 scaling_list = &pps->scaling_list;
1235 else if (sps && sps->scaling_list_enabled_flag
1236 && sps->scaling_list_data_present_flag)
1237 scaling_list = &sps->scaling_list;
1239 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1241 base_picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW (HEVC, decoder);
1242 if (!base_picture->iq_matrix) {
1243 GST_ERROR ("failed to allocate IQ matrix");
1244 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1246 iq_matrix = base_picture->iq_matrix->param;
1248 /* Only supporting 4:2:0 */
1249 if (sps->chroma_format_idc != 1)
1250 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
1252 fill_iq_matrix_4x4 (iq_matrix, scaling_list);
1253 fill_iq_matrix_8x8 (iq_matrix, scaling_list);
1254 fill_iq_matrix_16x16 (iq_matrix, scaling_list);
1255 fill_iq_matrix_32x32 (iq_matrix, scaling_list);
1256 fill_iq_matrix_dc_16x16 (iq_matrix, scaling_list);
1257 fill_iq_matrix_dc_32x32 (iq_matrix, scaling_list);
1259 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1262 static inline gboolean
1263 is_valid_state (guint state, guint ref_state)
1265 return (state & ref_state) == ref_state;
1268 static GstVaapiDecoderStatus
1269 decode_current_picture (GstVaapiDecoderH265 * decoder)
1271 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1272 GstVaapiPictureH265 *const picture = priv->current_picture;
1274 if (!is_valid_state (priv->decoder_state, GST_H265_VIDEO_STATE_VALID_PICTURE)) {
1278 priv->decoder_state = 0;
1279 /*Fixme: Use SEI header values */
1280 priv->pic_structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1283 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1285 if (!gst_vaapi_picture_decode (GST_VAAPI_PICTURE_CAST (picture)))
1288 if (!dpb_add (decoder, picture))
1291 gst_vaapi_picture_replace (&priv->current_picture, NULL);
1292 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1295 gst_vaapi_picture_replace (&priv->current_picture, NULL);
1296 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1298 priv->decoder_state = 0;
1299 priv->pic_structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1300 return (GstVaapiDecoderStatus) GST_VAAPI_DECODER_STATUS_DROP_FRAME;
1303 static GstVaapiDecoderStatus
1304 parse_vps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1306 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1307 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1308 GstH265VPS *const vps = &pi->data.vps;
1309 GstH265ParserResult result;
1311 GST_DEBUG ("parse VPS");
1312 priv->parser_state = 0;
1314 memset (vps, 0, sizeof (GstH265VPS));
1316 result = gst_h265_parser_parse_vps (priv->parser, &pi->nalu, vps);
1317 if (result != GST_H265_PARSER_OK)
1318 return get_status (result);
1320 priv->parser_state |= GST_H265_VIDEO_STATE_GOT_VPS;
1321 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1324 static GstVaapiDecoderStatus
1325 parse_sps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1327 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1328 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1329 GstH265SPS *const sps = &pi->data.sps;
1330 GstH265ParserResult result;
1332 GST_DEBUG ("parse SPS");
1333 priv->parser_state = 0;
1335 memset (sps, 0, sizeof (GstH265SPS));
1337 result = gst_h265_parser_parse_sps (priv->parser, &pi->nalu, sps, TRUE);
1338 if (result != GST_H265_PARSER_OK)
1339 return get_status (result);
1341 priv->parser_state |= GST_H265_VIDEO_STATE_GOT_SPS;
1342 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1346 get_pic_width_height_in_ctbs (GstH265PPS * pps,
1347 guint * PicWidthInCtbsY, guint * PicHeightInCtbsY)
1349 gint MinCbLog2SizeY, CtbLog2SizeY, MinCbSizeY, CtbSizeY;
1350 GstH265SPS *sps = pps->sps;
1352 MinCbLog2SizeY = sps->log2_min_luma_coding_block_size_minus3 + 3;
1353 CtbLog2SizeY = MinCbLog2SizeY + sps->log2_diff_max_min_luma_coding_block_size;
1354 MinCbSizeY = 1 << MinCbLog2SizeY;
1355 CtbSizeY = 1 << CtbLog2SizeY;
1358 ceil ((double) sps->pic_width_in_luma_samples / (double) CtbSizeY);
1360 ceil ((double) sps->pic_height_in_luma_samples / (double) CtbSizeY);
1363 static GstVaapiDecoderStatus
1364 parse_pps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1366 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1367 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1368 GstH265PPS *const pps = &pi->data.pps;
1369 GstH265ParserResult result;
1370 guint col_width[19], row_height[21];
1372 GST_DEBUG ("parse PPS");
1373 priv->parser_state &= GST_H265_VIDEO_STATE_GOT_SPS;
1375 memset (col_width, 0, sizeof (col_width));
1376 memset (row_height, 0, sizeof (row_height));
1378 memset (pps, 0, sizeof (GstH265PPS));
1380 result = gst_h265_parser_parse_pps (priv->parser, &pi->nalu, pps);
1381 if (result != GST_H265_PARSER_OK)
1382 return get_status (result);
1384 if (pps->tiles_enabled_flag) {
1386 guint PicWidthInCtbsY, PicHeightInCtbsY;
1388 get_pic_width_height_in_ctbs (pps, &PicWidthInCtbsY, &PicHeightInCtbsY);
1389 GST_DEBUG ("PicWidthInCtbsY %d PicHeightInCtbsY %d", PicWidthInCtbsY,
1392 /* Tile Scanning Conversion 6-3 and 6-4 */
1393 if (pps->uniform_spacing_flag) {
1395 for (i = 0; i <= pps->num_tile_columns_minus1; i++)
1397 ((i + 1) * PicWidthInCtbsY) / (pps->num_tile_columns_minus1 + 1) -
1398 (i * PicWidthInCtbsY) / (pps->num_tile_columns_minus1 + 1);
1400 for (i = 0; i <= pps->num_tile_rows_minus1; i++)
1402 ((i + 1) * PicHeightInCtbsY) / (pps->num_tile_rows_minus1 + 1) -
1403 (i * PicHeightInCtbsY) / (pps->num_tile_rows_minus1 + 1);
1407 col_width[pps->num_tile_columns_minus1] = PicWidthInCtbsY;
1408 for (i = 0; i < pps->num_tile_columns_minus1; i++) {
1409 col_width[i] = pps->column_width_minus1[i] + 1;
1410 col_width[pps->num_tile_columns_minus1] -= col_width[i];
1413 row_height[pps->num_tile_rows_minus1] = PicHeightInCtbsY;
1414 for (i = 0; i < pps->num_tile_rows_minus1; i++) {
1415 row_height[i] = pps->row_height_minus1[i] + 1;
1416 row_height[pps->num_tile_rows_minus1] -= row_height[i];
1419 for (i = 0; i <= pps->num_tile_columns_minus1; i++)
1420 pps->column_width_minus1[i] = col_width[i] - 1;
1421 for (i = 0; i <= pps->num_tile_rows_minus1; i++)
1422 pps->row_height_minus1[i] = row_height[i] - 1;
1425 priv->parser_state |= GST_H265_VIDEO_STATE_GOT_PPS;
1426 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1429 static GstVaapiDecoderStatus
1430 parse_sei (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1432 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1433 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1434 GArray **const sei_ptr = &pi->data.sei;
1435 GstH265ParserResult result;
1437 GST_DEBUG ("parse SEI");
1439 result = gst_h265_parser_parse_sei (priv->parser, &pi->nalu, sei_ptr);
1440 if (result != GST_H265_PARSER_OK) {
1441 GST_WARNING ("failed to parse SEI messages");
1442 return get_status (result);
1444 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1447 static GstVaapiDecoderStatus
1448 parse_slice (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1450 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1451 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1452 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
1453 GstH265ParserResult result;
1455 GST_DEBUG ("parse slice");
1456 priv->parser_state &= (GST_H265_VIDEO_STATE_GOT_SPS |
1457 GST_H265_VIDEO_STATE_GOT_PPS);
1459 slice_hdr->short_term_ref_pic_set_idx = 0;
1461 memset (slice_hdr, 0, sizeof (GstH265SliceHdr));
1463 result = gst_h265_parser_parse_slice_hdr (priv->parser, &pi->nalu, slice_hdr);
1464 if (result != GST_H265_PARSER_OK)
1465 return get_status (result);
1467 priv->parser_state |= GST_H265_VIDEO_STATE_GOT_SLICE;
1468 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1471 static GstVaapiDecoderStatus
1472 decode_vps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1474 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1475 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1476 GstH265VPS *const vps = &pi->data.vps;
1478 GST_DEBUG ("decode VPS");
1480 gst_vaapi_parser_info_h265_replace (&priv->vps[vps->id], pi);
1482 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1485 static GstVaapiDecoderStatus
1486 decode_sps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1488 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1489 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1490 GstH265SPS *const sps = &pi->data.sps;
1491 guint high_precision_offsets_enabled_flag = 0, bitdepthC = 0;
1493 GST_DEBUG ("decode SPS");
1495 if (sps->max_latency_increase_plus1[sps->max_sub_layers_minus1])
1496 priv->SpsMaxLatencyPictures =
1497 sps->max_num_reorder_pics[sps->max_sub_layers_minus1] +
1498 sps->max_latency_increase_plus1[sps->max_sub_layers_minus1] - 1;
1500 /* Calculate WpOffsetHalfRangeC: (7-34)
1501 * Fixme: We don't have parser API for sps_range_extension, so assuming
1502 * high_precision_offsets_enabled_flag as zero */
1503 bitdepthC = sps->bit_depth_chroma_minus8 + 8;
1504 priv->WpOffsetHalfRangeC =
1505 1 << (high_precision_offsets_enabled_flag ? (bitdepthC - 1) : 7);
1507 gst_vaapi_parser_info_h265_replace (&priv->sps[sps->id], pi);
1509 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1512 static GstVaapiDecoderStatus
1513 decode_pps (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1515 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1516 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1517 GstH265PPS *const pps = &pi->data.pps;
1519 GST_DEBUG ("decode PPS");
1521 gst_vaapi_parser_info_h265_replace (&priv->pps[pps->id], pi);
1523 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1526 static GstVaapiDecoderStatus
1527 decode_sei (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
1530 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1531 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
1534 GST_DEBUG ("decode SEI messages");
1536 for (i = 0; i < pi->data.sei->len; i++) {
1537 const GstH265SEIMessage *const sei =
1538 &g_array_index (pi->data.sei, GstH265SEIMessage, i);
1540 switch (sei->payloadType) {
1541 case GST_H265_SEI_PIC_TIMING:{
1542 const GstH265PicTiming *const pic_timing = &sei->payload.pic_timing;
1543 priv->pic_structure = pic_timing->pic_struct;
1550 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1553 static GstVaapiDecoderStatus
1554 decode_sequence_end (GstVaapiDecoderH265 * decoder)
1556 GstVaapiDecoderStatus status;
1558 GST_DEBUG ("decode sequence-end");
1560 status = decode_current_picture (decoder);
1561 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1564 dpb_flush (decoder);
1565 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1568 /* 8.3.1 - Decoding process for picture order count */
1570 init_picture_poc (GstVaapiDecoderH265 * decoder,
1571 GstVaapiPictureH265 * picture, GstVaapiParserInfoH265 * pi)
1573 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1574 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
1575 GstH265SPS *const sps = get_sps (decoder);
1576 const gint32 MaxPicOrderCntLsb =
1577 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
1578 guint8 nal_type = pi->nalu.type;
1579 guint8 temporal_id = pi->nalu.temporal_id_plus1 - 1;
1581 GST_DEBUG ("decode PicOrderCntVal");
1583 priv->prev_poc_lsb = priv->poc_lsb;
1584 priv->prev_poc_msb = priv->poc_msb;
1586 if (!(nal_is_irap (nal_type) && picture->NoRaslOutputFlag)) {
1587 priv->prev_poc_lsb = priv->prev_tid0pic_poc_lsb;
1588 priv->prev_poc_msb = priv->prev_tid0pic_poc_msb;
1591 /* Finding PicOrderCntMsb */
1592 if (nal_is_irap (nal_type) && picture->NoRaslOutputFlag)
1596 if ((slice_hdr->pic_order_cnt_lsb < priv->prev_poc_lsb) &&
1597 ((priv->prev_poc_lsb - slice_hdr->pic_order_cnt_lsb) >=
1598 (MaxPicOrderCntLsb / 2)))
1599 priv->poc_msb = priv->prev_poc_msb + MaxPicOrderCntLsb;
1601 else if ((slice_hdr->pic_order_cnt_lsb > priv->prev_poc_lsb) &&
1602 ((slice_hdr->pic_order_cnt_lsb - priv->prev_poc_lsb) >
1603 (MaxPicOrderCntLsb / 2)))
1604 priv->poc_msb = priv->prev_poc_msb - MaxPicOrderCntLsb;
1607 priv->poc_msb = priv->prev_poc_msb;
1611 priv->poc = picture->poc = priv->poc_msb + slice_hdr->pic_order_cnt_lsb;
1612 priv->poc_lsb = picture->poc_lsb = slice_hdr->pic_order_cnt_lsb;
1614 if (nal_is_idr (nal_type)) {
1616 picture->poc_lsb = 0;
1619 priv->prev_poc_lsb = 0;
1620 priv->prev_poc_msb = 0;
1621 priv->prev_tid0pic_poc_lsb = 0;
1622 priv->prev_tid0pic_poc_msb = 0;
1625 picture->base.poc = picture->poc;
1626 GST_DEBUG ("PicOrderCntVal %d", picture->base.poc);
1628 if (!temporal_id && !nal_is_rasl (nal_type) &&
1629 !nal_is_radl (nal_type) && nal_is_ref (nal_type)) {
1630 priv->prev_tid0pic_poc_lsb = slice_hdr->pic_order_cnt_lsb;
1631 priv->prev_tid0pic_poc_msb = priv->poc_msb;
1636 init_picture_refs (GstVaapiDecoderH265 * decoder,
1637 GstVaapiPictureH265 * picture, GstH265SliceHdr * slice_hdr)
1639 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1640 guint32 NumRpsCurrTempList0 = 0, NumRpsCurrTempList1 = 0;
1641 GstVaapiPictureH265 *RefPicListTemp0[16] = { NULL, }, *RefPicListTemp1[16] = {
1644 guint num_ref_idx_l0_active_minus1 = 0;
1645 guint num_ref_idx_l1_active_minus1 = 0;
1646 GstH265RefPicListModification *ref_pic_list_modification;
1649 memset (priv->RefPicList0, 0, sizeof (GstVaapiPictureH265 *) * 16);
1650 memset (priv->RefPicList1, 0, sizeof (GstVaapiPictureH265 *) * 16);
1651 priv->RefPicList0_count = priv->RefPicList1_count = 0;
1653 if (slice_hdr->dependent_slice_segment_flag) {
1654 GstH265SliceHdr *tmp = &priv->prev_independent_slice_pi->data.slice_hdr;
1655 num_ref_idx_l0_active_minus1 = tmp->num_ref_idx_l0_active_minus1;
1656 num_ref_idx_l1_active_minus1 = tmp->num_ref_idx_l1_active_minus1;
1657 ref_pic_list_modification = &tmp->ref_pic_list_modification;
1660 num_ref_idx_l0_active_minus1 = slice_hdr->num_ref_idx_l0_active_minus1;
1661 num_ref_idx_l1_active_minus1 = slice_hdr->num_ref_idx_l1_active_minus1;
1662 ref_pic_list_modification = &slice_hdr->ref_pic_list_modification;
1663 type = slice_hdr->type;
1666 /* decoding process for reference picture list construction needs to be
1667 * invoked only for P and B slice */
1668 if (type == GST_H265_I_SLICE)
1671 NumRpsCurrTempList0 =
1672 MAX ((num_ref_idx_l0_active_minus1 + 1), priv->NumPocTotalCurr);
1673 NumRpsCurrTempList1 =
1674 MAX ((num_ref_idx_l1_active_minus1 + 1), priv->NumPocTotalCurr);
1677 while (rIdx < NumRpsCurrTempList0) {
1678 for (i = 0; i < priv->NumPocStCurrBefore && rIdx < NumRpsCurrTempList0;
1680 RefPicListTemp0[rIdx] = priv->RefPicSetStCurrBefore[i];
1681 for (i = 0; i < priv->NumPocStCurrAfter && rIdx < NumRpsCurrTempList0;
1683 RefPicListTemp0[rIdx] = priv->RefPicSetStCurrAfter[i];
1684 for (i = 0; i < priv->NumPocLtCurr && rIdx < NumRpsCurrTempList0;
1686 RefPicListTemp0[rIdx] = priv->RefPicSetLtCurr[i];
1689 /* construct RefPicList0 (8-9) */
1690 for (rIdx = 0; rIdx <= num_ref_idx_l0_active_minus1; rIdx++)
1691 priv->RefPicList0[rIdx] =
1692 ref_pic_list_modification->ref_pic_list_modification_flag_l0 ?
1693 RefPicListTemp0[ref_pic_list_modification->list_entry_l0[rIdx]] :
1694 RefPicListTemp0[rIdx];
1695 priv->RefPicList0_count = rIdx;
1697 if (type == GST_H265_B_SLICE) {
1701 while (rIdx < NumRpsCurrTempList1) {
1702 for (i = 0; i < priv->NumPocStCurrAfter && rIdx < NumRpsCurrTempList1;
1704 RefPicListTemp1[rIdx] = priv->RefPicSetStCurrAfter[i];
1705 for (i = 0; i < priv->NumPocStCurrBefore && rIdx < NumRpsCurrTempList1;
1707 RefPicListTemp1[rIdx] = priv->RefPicSetStCurrBefore[i];
1708 for (i = 0; i < priv->NumPocLtCurr && rIdx < NumRpsCurrTempList1;
1710 RefPicListTemp1[rIdx] = priv->RefPicSetLtCurr[i];
1713 /* construct RefPicList1 (8-10) */
1714 for (rIdx = 0; rIdx <= num_ref_idx_l1_active_minus1; rIdx++)
1715 priv->RefPicList1[rIdx] =
1716 ref_pic_list_modification->ref_pic_list_modification_flag_l1 ?
1717 RefPicListTemp1[ref_pic_list_modification->list_entry_l1
1718 [rIdx]] : RefPicListTemp1[rIdx];
1719 priv->RefPicList1_count = rIdx;
1724 init_picture (GstVaapiDecoderH265 * decoder,
1725 GstVaapiPictureH265 * picture, GstVaapiParserInfoH265 * pi)
1727 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1728 GstVaapiPicture *const base_picture = &picture->base;
1729 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
1731 base_picture->pts = GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts;
1732 base_picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
1734 if (nal_is_idr (pi->nalu.type)) {
1735 GST_DEBUG ("<IDR>");
1736 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_IDR);
1739 if (pi->nalu.type >= GST_H265_NAL_SLICE_BLA_W_LP &&
1740 pi->nalu.type <= GST_H265_NAL_SLICE_CRA_NUT)
1741 picture->RapPicFlag = TRUE;
1743 /*Fixme: Use SEI header values */
1744 base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1745 picture->structure = base_picture->structure;
1747 /*NoRaslOutputFlag ==1 if the current picture is
1750 3) a CRA picture that is the first access unit in the bitstream
1751 4) first picture that follows an end of sequence NAL unit in decoding order
1752 5) has HandleCraAsBlaFlag == 1 (set by external means, so not considering )
1754 if (nal_is_idr (pi->nalu.type) || nal_is_bla (pi->nalu.type) ||
1755 (nal_is_cra (pi->nalu.type) && priv->new_bitstream)
1756 || priv->prev_nal_is_eos) {
1757 picture->NoRaslOutputFlag = 1;
1760 if (nal_is_irap (pi->nalu.type)) {
1761 picture->IntraPicFlag = TRUE;
1762 priv->associated_irap_NoRaslOutputFlag = picture->NoRaslOutputFlag;
1765 if (nal_is_rasl (pi->nalu.type) && priv->associated_irap_NoRaslOutputFlag)
1766 picture->output_flag = FALSE;
1768 picture->output_flag = slice_hdr->pic_output_flag;
1770 init_picture_poc (decoder, picture, pi);
1776 vaapi_init_picture (VAPictureHEVC * pic)
1778 pic->picture_id = VA_INVALID_SURFACE;
1779 pic->pic_order_cnt = 0;
1780 pic->flags = VA_PICTURE_HEVC_INVALID;
1784 vaapi_fill_picture (VAPictureHEVC * pic, GstVaapiPictureH265 * picture,
1785 guint picture_structure)
1788 if (!picture_structure)
1789 picture_structure = picture->structure;
1791 pic->picture_id = picture->base.surface_id;
1792 pic->pic_order_cnt = picture->poc;
1795 /* Set the VAPictureHEVC flags */
1796 if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE (picture))
1797 pic->flags |= VA_PICTURE_HEVC_LONG_TERM_REFERENCE;
1799 if (GST_VAAPI_PICTURE_FLAG_IS_SET (picture,
1800 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_BEFORE))
1801 pic->flags |= VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE;
1803 else if (GST_VAAPI_PICTURE_FLAG_IS_SET (picture,
1804 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_AFTER))
1805 pic->flags |= VA_PICTURE_HEVC_RPS_ST_CURR_AFTER;
1807 else if (GST_VAAPI_PICTURE_FLAG_IS_SET (picture,
1808 GST_VAAPI_PICTURE_FLAG_RPS_LT_CURR))
1809 pic->flags |= VA_PICTURE_HEVC_RPS_LT_CURR;
1811 switch (picture_structure) {
1812 case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
1814 case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
1815 pic->flags |= VA_PICTURE_HEVC_FIELD_PIC;
1817 case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
1818 pic->flags |= VA_PICTURE_HEVC_FIELD_PIC;
1819 pic->flags |= VA_PICTURE_HEVC_BOTTOM_FIELD;
1827 get_index_for_RefPicListX (VAPictureHEVC * ReferenceFrames,
1828 GstVaapiPictureH265 * pic)
1832 for (i = 0; i < 15; i++) {
1833 if ((ReferenceFrames[i].picture_id != VA_INVALID_ID) && pic) {
1834 if ((ReferenceFrames[i].pic_order_cnt == pic->poc) &&
1835 (ReferenceFrames[i].picture_id == pic->base.surface_id)) {
1844 fill_picture (GstVaapiDecoderH265 * decoder, GstVaapiPictureH265 * picture)
1846 GstVaapiDecoderH265Private *const priv = &decoder->priv;
1847 GstVaapiPicture *const base_picture = &picture->base;
1848 GstH265PPS *const pps = get_pps (decoder);
1849 GstH265SPS *const sps = get_sps (decoder);
1850 VAPictureParameterBufferHEVC *const pic_param = base_picture->param;
1853 pic_param->pic_fields.value = 0;
1854 pic_param->slice_parsing_fields.value = 0;
1856 /* Fill in VAPictureHEVC */
1857 vaapi_fill_picture (&pic_param->CurrPic, picture, 0);
1858 /* Fill in ReferenceFrames */
1859 for (i = 0, n = 0; i < priv->dpb_count; i++) {
1860 GstVaapiFrameStore *const fs = priv->dpb[i];
1861 if ((gst_vaapi_frame_store_has_reference (fs)))
1862 vaapi_fill_picture (&pic_param->ReferenceFrames[n++], fs->buffer,
1863 fs->buffer->structure);
1864 if (n >= G_N_ELEMENTS (pic_param->ReferenceFrames))
1867 for (; n < G_N_ELEMENTS (pic_param->ReferenceFrames); n++)
1868 vaapi_init_picture (&pic_param->ReferenceFrames[n]);
1871 #define COPY_FIELD(s, f) \
1872 pic_param->f = (s)->f
1873 #define COPY_BFM(a, s, f) \
1874 pic_param->a.bits.f = (s)->f
1876 COPY_FIELD (sps, pic_width_in_luma_samples);
1877 COPY_FIELD (sps, pic_height_in_luma_samples);
1878 COPY_BFM (pic_fields, sps, chroma_format_idc);
1879 COPY_BFM (pic_fields, sps, separate_colour_plane_flag);
1880 COPY_BFM (pic_fields, sps, pcm_enabled_flag);
1881 COPY_BFM (pic_fields, sps, scaling_list_enabled_flag);
1882 COPY_BFM (pic_fields, pps, transform_skip_enabled_flag);
1883 COPY_BFM (pic_fields, sps, amp_enabled_flag);
1884 COPY_BFM (pic_fields, sps, strong_intra_smoothing_enabled_flag);
1885 COPY_BFM (pic_fields, pps, sign_data_hiding_enabled_flag);
1886 COPY_BFM (pic_fields, pps, constrained_intra_pred_flag);
1887 COPY_BFM (pic_fields, pps, cu_qp_delta_enabled_flag);
1888 COPY_BFM (pic_fields, pps, weighted_pred_flag);
1889 COPY_BFM (pic_fields, pps, weighted_bipred_flag);
1890 COPY_BFM (pic_fields, pps, transquant_bypass_enabled_flag);
1891 COPY_BFM (pic_fields, pps, tiles_enabled_flag);
1892 COPY_BFM (pic_fields, pps, entropy_coding_sync_enabled_flag);
1893 pic_param->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag =
1894 pps->loop_filter_across_slices_enabled_flag;
1895 COPY_BFM (pic_fields, pps, loop_filter_across_tiles_enabled_flag);
1896 COPY_BFM (pic_fields, sps, pcm_loop_filter_disabled_flag);
1897 /* Fix: Assign value based on sps_max_num_reorder_pics */
1898 pic_param->pic_fields.bits.NoPicReorderingFlag = 0;
1899 /* Fix: Enable if picture has no B slices */
1900 pic_param->pic_fields.bits.NoBiPredFlag = 0;
1902 pic_param->sps_max_dec_pic_buffering_minus1 =
1903 sps->max_dec_pic_buffering_minus1[0];
1904 COPY_FIELD (sps, bit_depth_luma_minus8);
1905 COPY_FIELD (sps, bit_depth_chroma_minus8);
1906 COPY_FIELD (sps, pcm_sample_bit_depth_luma_minus1);
1907 COPY_FIELD (sps, pcm_sample_bit_depth_chroma_minus1);
1908 COPY_FIELD (sps, log2_min_luma_coding_block_size_minus3);
1909 COPY_FIELD (sps, log2_diff_max_min_luma_coding_block_size);
1910 COPY_FIELD (sps, log2_min_transform_block_size_minus2);
1911 COPY_FIELD (sps, log2_diff_max_min_transform_block_size);
1912 COPY_FIELD (sps, log2_min_pcm_luma_coding_block_size_minus3);
1913 COPY_FIELD (sps, log2_diff_max_min_pcm_luma_coding_block_size);
1914 COPY_FIELD (sps, max_transform_hierarchy_depth_intra);
1915 COPY_FIELD (sps, max_transform_hierarchy_depth_inter);
1916 COPY_FIELD (pps, init_qp_minus26);
1917 COPY_FIELD (pps, diff_cu_qp_delta_depth);
1918 pic_param->pps_cb_qp_offset = pps->cb_qp_offset;
1919 pic_param->pps_cr_qp_offset = pps->cr_qp_offset;
1920 COPY_FIELD (pps, log2_parallel_merge_level_minus2);
1921 COPY_FIELD (pps, num_tile_columns_minus1);
1922 COPY_FIELD (pps, num_tile_rows_minus1);
1923 for (i = 0; i <= pps->num_tile_columns_minus1; i++)
1924 pic_param->column_width_minus1[i] = pps->column_width_minus1[i];
1926 pic_param->column_width_minus1[i] = 0;
1927 for (i = 0; i <= pps->num_tile_rows_minus1; i++)
1928 pic_param->row_height_minus1[i] = pps->row_height_minus1[i];
1930 pic_param->row_height_minus1[i] = 0;
1932 COPY_BFM (slice_parsing_fields, pps, lists_modification_present_flag);
1933 COPY_BFM (slice_parsing_fields, sps, long_term_ref_pics_present_flag);
1934 pic_param->slice_parsing_fields.bits.sps_temporal_mvp_enabled_flag =
1935 sps->temporal_mvp_enabled_flag;
1936 COPY_BFM (slice_parsing_fields, pps, cabac_init_present_flag);
1937 COPY_BFM (slice_parsing_fields, pps, output_flag_present_flag);
1938 COPY_BFM (slice_parsing_fields, pps, dependent_slice_segments_enabled_flag);
1939 pic_param->slice_parsing_fields.
1940 bits.pps_slice_chroma_qp_offsets_present_flag =
1941 pps->slice_chroma_qp_offsets_present_flag;
1942 COPY_BFM (slice_parsing_fields, sps, sample_adaptive_offset_enabled_flag);
1943 COPY_BFM (slice_parsing_fields, pps, deblocking_filter_override_enabled_flag);
1944 pic_param->slice_parsing_fields.bits.pps_disable_deblocking_filter_flag =
1945 pps->deblocking_filter_disabled_flag;
1946 COPY_BFM (slice_parsing_fields, pps,
1947 slice_segment_header_extension_present_flag);
1948 pic_param->slice_parsing_fields.bits.RapPicFlag = picture->RapPicFlag;
1949 pic_param->slice_parsing_fields.bits.IdrPicFlag =
1950 GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_IDR);
1951 pic_param->slice_parsing_fields.bits.IntraPicFlag = picture->IntraPicFlag;
1953 COPY_FIELD (sps, log2_max_pic_order_cnt_lsb_minus4);
1954 COPY_FIELD (sps, num_short_term_ref_pic_sets);
1955 pic_param->num_long_term_ref_pic_sps = sps->num_long_term_ref_pics_sps;
1956 COPY_FIELD (pps, num_ref_idx_l0_default_active_minus1);
1957 COPY_FIELD (pps, num_ref_idx_l1_default_active_minus1);
1958 pic_param->pps_beta_offset_div2 = pps->beta_offset_div2;
1959 pic_param->pps_tc_offset_div2 = pps->tc_offset_div2;
1960 COPY_FIELD (pps, num_extra_slice_header_bits);
1962 /*Fixme: Set correct value as mentioned in va_dec_hevc.h */
1963 pic_param->st_rps_bits = 0;
1967 /* Detection of the first VCL NAL unit of a coded picture (7.4.2.4.5 ) */
1969 is_new_picture (GstVaapiParserInfoH265 * pi, GstVaapiParserInfoH265 * prev_pi)
1971 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
1976 if (slice_hdr->first_slice_segment_in_pic_flag)
1982 /* Detection of a new access unit, assuming we are already in presence
1984 static inline gboolean
1985 is_new_access_unit (GstVaapiParserInfoH265 * pi,
1986 GstVaapiParserInfoH265 * prev_pi)
1995 has_entry_in_rps (GstVaapiPictureH265 * dpb_pic,
1996 GstVaapiPictureH265 ** rps_list, guint rps_list_length)
2000 if (!dpb_pic || !rps_list || !rps_list_length)
2003 for (i = 0; i < rps_list_length; i++) {
2004 if (rps_list[i] && rps_list[i]->poc == dpb_pic->poc)
2010 /* the derivation process for the RPS and the picture marking */
2012 derive_and_mark_rps (GstVaapiDecoderH265 * decoder,
2013 GstVaapiPictureH265 * picture, GstVaapiParserInfoH265 * pi,
2014 gint32 * CurrDeltaPocMsbPresentFlag, gint32 * FollDeltaPocMsbPresentFlag)
2016 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2017 GstVaapiPictureH265 *dpb_pic = NULL;
2020 memset (priv->RefPicSetLtCurr, 0, sizeof (GstVaapiPictureH265 *) * 16);
2021 memset (priv->RefPicSetLtFoll, 0, sizeof (GstVaapiPictureH265 *) * 16);
2022 memset (priv->RefPicSetStCurrBefore, 0, sizeof (GstVaapiPictureH265 *) * 16);
2023 memset (priv->RefPicSetStCurrAfter, 0, sizeof (GstVaapiPictureH265 *) * 16);
2024 memset (priv->RefPicSetStFoll, 0, sizeof (GstVaapiPictureH265 *) * 16);
2027 for (i = 0; i < priv->NumPocLtCurr; i++) {
2028 if (!CurrDeltaPocMsbPresentFlag[i]) {
2029 dpb_pic = dpb_get_picture (decoder, priv->PocLtCurr[i], TRUE);
2031 priv->RefPicSetLtCurr[i] = dpb_pic;
2033 priv->RefPicSetLtCurr[i] = NULL;
2035 dpb_pic = dpb_get_picture (decoder, priv->PocLtCurr[i], FALSE);
2037 priv->RefPicSetLtCurr[i] = dpb_pic;
2039 priv->RefPicSetLtCurr[i] = NULL;
2043 priv->RefPicSetLtCurr[i] = NULL;
2045 for (i = 0; i < priv->NumPocLtFoll; i++) {
2046 if (!FollDeltaPocMsbPresentFlag[i]) {
2047 dpb_pic = dpb_get_picture (decoder, priv->PocLtFoll[i], TRUE);
2049 priv->RefPicSetLtFoll[i] = dpb_pic;
2051 priv->RefPicSetLtFoll[i] = NULL;
2053 dpb_pic = dpb_get_picture (decoder, priv->PocLtFoll[i], FALSE);
2055 priv->RefPicSetLtFoll[i] = dpb_pic;
2057 priv->RefPicSetLtFoll[i] = NULL;
2061 priv->RefPicSetLtFoll[i] = NULL;
2063 /* Mark all ref pics in RefPicSetLtCurr and RefPicSetLtFol as long_term_refs */
2064 for (i = 0; i < priv->NumPocLtCurr; i++) {
2065 if (priv->RefPicSetLtCurr[i])
2066 gst_vaapi_picture_h265_set_reference (priv->RefPicSetLtCurr[i],
2067 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE |
2068 GST_VAAPI_PICTURE_FLAG_RPS_LT_CURR);
2070 for (i = 0; i < priv->NumPocLtFoll; i++) {
2071 if (priv->RefPicSetLtFoll[i])
2072 gst_vaapi_picture_h265_set_reference (priv->RefPicSetLtFoll[i],
2073 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE |
2074 GST_VAAPI_PICTURE_FLAG_RPS_LT_FOLL);
2078 for (i = 0; i < priv->NumPocStCurrBefore; i++) {
2079 dpb_pic = dpb_get_ref_picture (decoder, priv->PocStCurrBefore[i], TRUE);
2081 gst_vaapi_picture_h265_set_reference (dpb_pic,
2082 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
2083 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_BEFORE);
2084 priv->RefPicSetStCurrBefore[i] = dpb_pic;
2086 priv->RefPicSetStCurrBefore[i] = NULL;
2089 priv->RefPicSetStCurrBefore[i] = NULL;
2091 for (i = 0; i < priv->NumPocStCurrAfter; i++) {
2092 dpb_pic = dpb_get_ref_picture (decoder, priv->PocStCurrAfter[i], TRUE);
2094 gst_vaapi_picture_h265_set_reference (dpb_pic,
2095 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
2096 GST_VAAPI_PICTURE_FLAG_RPS_ST_CURR_AFTER);
2097 priv->RefPicSetStCurrAfter[i] = dpb_pic;
2099 priv->RefPicSetStCurrAfter[i] = NULL;
2102 priv->RefPicSetStCurrAfter[i] = NULL;
2104 for (i = 0; i < priv->NumPocStFoll; i++) {
2105 dpb_pic = dpb_get_ref_picture (decoder, priv->PocStFoll[i], TRUE);
2107 gst_vaapi_picture_h265_set_reference (dpb_pic,
2108 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
2109 GST_VAAPI_PICTURE_FLAG_RPS_ST_FOLL);
2110 priv->RefPicSetStFoll[i] = dpb_pic;
2112 priv->RefPicSetStFoll[i] = NULL;
2115 priv->RefPicSetStFoll[i] = NULL;
2117 /* Mark all dpb pics not beloging to RefPicSet*[] as unused for ref */
2118 for (i = 0; i < priv->dpb_count; i++) {
2119 dpb_pic = priv->dpb[i]->buffer;
2121 !has_entry_in_rps (dpb_pic, priv->RefPicSetLtCurr, priv->NumPocLtCurr)
2122 && !has_entry_in_rps (dpb_pic, priv->RefPicSetLtFoll,
2124 && !has_entry_in_rps (dpb_pic, priv->RefPicSetStCurrAfter,
2125 priv->NumPocStCurrAfter)
2126 && !has_entry_in_rps (dpb_pic, priv->RefPicSetStCurrBefore,
2127 priv->NumPocStCurrBefore)
2128 && !has_entry_in_rps (dpb_pic, priv->RefPicSetStFoll,
2129 priv->NumPocStFoll))
2130 gst_vaapi_picture_h265_set_reference (dpb_pic, 0);
2135 /* Decoding process for reference picture set (8.3.2) */
2137 decode_ref_pic_set (GstVaapiDecoderH265 * decoder,
2138 GstVaapiPictureH265 * picture, GstVaapiParserInfoH265 * pi)
2141 gint32 CurrDeltaPocMsbPresentFlag[16] = { 0, };
2142 gint32 FollDeltaPocMsbPresentFlag[16] = { 0, };
2143 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2144 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
2145 GstH265SPS *const sps = get_sps (decoder);
2146 const gint32 MaxPicOrderCntLsb =
2147 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
2149 /* if it is an irap pic, set all ref pics in dpb as unused for ref */
2150 if (nal_is_irap (pi->nalu.type) && picture->NoRaslOutputFlag) {
2151 for (i = 0; i < priv->dpb_count; i++) {
2152 GstVaapiFrameStore *const fs = priv->dpb[i];
2153 gst_vaapi_picture_h265_set_reference (fs->buffer, 0);
2157 /* Reset everything for IDR */
2158 if (nal_is_idr (pi->nalu.type)) {
2159 memset (priv->PocStCurrBefore, 0, sizeof (guint) * 16);
2160 memset (priv->PocStCurrAfter, 0, sizeof (guint) * 16);
2161 memset (priv->PocStFoll, 0, sizeof (guint) * 16);
2162 memset (priv->PocLtCurr, 0, sizeof (guint) * 16);
2163 memset (priv->PocLtFoll, 0, sizeof (guint) * 16);
2164 priv->NumPocStCurrBefore = priv->NumPocStCurrAfter = priv->NumPocStFoll = 0;
2165 priv->NumPocLtCurr = priv->NumPocLtFoll = 0;
2167 GstH265ShortTermRefPicSet *stRefPic = NULL;
2168 gint32 num_lt_pics, pocLt, PocLsbLt[16] = { 0, }
2169 , UsedByCurrPicLt[16] = {
2171 gint32 DeltaPocMsbCycleLt[16] = { 0, };
2172 gint numtotalcurr = 0;
2174 /* this is based on CurrRpsIdx described in spec */
2175 if (!slice_hdr->short_term_ref_pic_set_sps_flag)
2176 stRefPic = &slice_hdr->short_term_ref_pic_sets;
2177 else if (sps->num_short_term_ref_pic_sets)
2179 &sps->short_term_ref_pic_set[slice_hdr->short_term_ref_pic_set_idx];
2181 g_assert (stRefPic != NULL);
2183 for (i = 0, j = 0, k = 0; i < stRefPic->NumNegativePics; i++) {
2184 if (stRefPic->UsedByCurrPicS0[i]) {
2185 priv->PocStCurrBefore[j++] = picture->poc + stRefPic->DeltaPocS0[i];
2188 priv->PocStFoll[k++] = picture->poc + stRefPic->DeltaPocS0[i];
2190 priv->NumPocStCurrBefore = j;
2191 for (i = 0, j = 0; i < stRefPic->NumPositivePics; i++) {
2192 if (stRefPic->UsedByCurrPicS1[i]) {
2193 priv->PocStCurrAfter[j++] = picture->poc + stRefPic->DeltaPocS1[i];
2196 priv->PocStFoll[k++] = picture->poc + stRefPic->DeltaPocS1[i];
2198 priv->NumPocStCurrAfter = j;
2199 priv->NumPocStFoll = k;
2200 num_lt_pics = slice_hdr->num_long_term_sps + slice_hdr->num_long_term_pics;
2201 /* The variables PocLsbLt[i] and UsedByCurrPicLt[i] are derived as follows: */
2202 for (i = 0; i < num_lt_pics; i++) {
2203 if (i < slice_hdr->num_long_term_sps) {
2204 PocLsbLt[i] = sps->lt_ref_pic_poc_lsb_sps[slice_hdr->lt_idx_sps[i]];
2205 UsedByCurrPicLt[i] =
2206 sps->used_by_curr_pic_lt_sps_flag[slice_hdr->lt_idx_sps[i]];
2208 PocLsbLt[i] = slice_hdr->poc_lsb_lt[i];
2209 UsedByCurrPicLt[i] = slice_hdr->used_by_curr_pic_lt_flag[i];
2211 if (UsedByCurrPicLt[i])
2215 priv->NumPocTotalCurr = numtotalcurr;
2217 /* The variable DeltaPocMsbCycleLt[i] is derived as follows: (7-38) */
2218 for (i = 0; i < num_lt_pics; i++) {
2219 if (i == 0 || i == slice_hdr->num_long_term_sps)
2220 DeltaPocMsbCycleLt[i] = slice_hdr->delta_poc_msb_cycle_lt[i];
2222 DeltaPocMsbCycleLt[i] =
2223 slice_hdr->delta_poc_msb_cycle_lt[i] + DeltaPocMsbCycleLt[i - 1];
2227 for (i = 0, j = 0, k = 0; i < num_lt_pics; i++) {
2228 pocLt = PocLsbLt[i];
2229 if (slice_hdr->delta_poc_msb_present_flag[i])
2231 picture->poc - DeltaPocMsbCycleLt[i] * MaxPicOrderCntLsb -
2232 slice_hdr->pic_order_cnt_lsb;
2233 if (UsedByCurrPicLt[i]) {
2234 priv->PocLtCurr[j] = pocLt;
2235 CurrDeltaPocMsbPresentFlag[j++] =
2236 slice_hdr->delta_poc_msb_present_flag[i];
2238 priv->PocLtFoll[k] = pocLt;
2239 FollDeltaPocMsbPresentFlag[k++] =
2240 slice_hdr->delta_poc_msb_present_flag[i];
2243 priv->NumPocLtCurr = j;
2244 priv->NumPocLtFoll = k;
2248 /* the derivation process for the RPS and the picture marking */
2249 derive_and_mark_rps (decoder, picture, pi, CurrDeltaPocMsbPresentFlag,
2250 FollDeltaPocMsbPresentFlag);
2255 static GstVaapiDecoderStatus
2256 decode_picture (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
2258 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2259 GstVaapiParserInfoH265 *pi = unit->parsed_info;
2260 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
2261 GstH265PPS *const pps = ensure_pps (decoder, slice_hdr->pps);
2262 GstH265SPS *const sps = ensure_sps (decoder, slice_hdr->pps->sps);
2263 GstVaapiPictureH265 *picture;
2264 GstVaapiDecoderStatus status;
2266 g_return_val_if_fail (pps != NULL, GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN);
2267 g_return_val_if_fail (sps != NULL, GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN);
2269 status = ensure_context (decoder, sps);
2270 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2273 priv->decoder_state = 0;
2275 /* Create new picture */
2276 picture = gst_vaapi_picture_h265_new (decoder);
2278 GST_ERROR ("failed to allocate picture");
2279 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2282 gst_vaapi_picture_replace (&priv->current_picture, picture);
2283 gst_vaapi_picture_unref (picture);
2285 /* Update cropping rectangle */
2286 if (sps->conformance_window_flag) {
2287 GstVaapiRectangle crop_rect;
2288 crop_rect.x = sps->crop_rect_x;
2289 crop_rect.y = sps->crop_rect_y;
2290 crop_rect.width = sps->crop_rect_width;
2291 crop_rect.height = sps->crop_rect_height;
2292 gst_vaapi_picture_set_crop_rect (&picture->base, &crop_rect);
2295 status = ensure_quant_matrix (decoder, picture);
2296 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
2297 GST_ERROR ("failed to reset quantizer matrix");
2301 if (!init_picture (decoder, picture, pi))
2302 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2304 /* Drop all RASL pictures having NoRaslOutputFlag is TRUE for the
2305 * associated IRAP picture */
2306 if (nal_is_rasl (pi->nalu.type) && priv->associated_irap_NoRaslOutputFlag) {
2307 gst_vaapi_picture_replace (&priv->current_picture, NULL);
2308 return (GstVaapiDecoderStatus) GST_VAAPI_DECODER_STATUS_DROP_FRAME;
2311 if (!decode_ref_pic_set (decoder, picture, pi))
2312 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2314 if (!dpb_init (decoder, picture, pi))
2315 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2317 if (!fill_picture (decoder, picture))
2318 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2320 priv->decoder_state = pi->state;
2321 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2325 get_slice_data_byte_offset (GstH265SliceHdr * slice_hdr, guint nal_header_bytes)
2329 epb_count = slice_hdr->n_emulation_prevention_bytes;
2330 return nal_header_bytes + (slice_hdr->header_size + 7) / 8 - epb_count;
2334 fill_pred_weight_table (GstVaapiDecoderH265 * decoder,
2335 GstVaapiSlice * slice, GstH265SliceHdr * slice_hdr)
2337 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2338 VASliceParameterBufferHEVC *const slice_param = slice->param;
2339 GstH265PPS *const pps = get_pps (decoder);
2340 GstH265SPS *const sps = get_sps (decoder);
2341 GstH265PredWeightTable *const w = &slice_hdr->pred_weight_table;
2342 gint chroma_weight, chroma_log2_weight_denom;
2345 slice_param->luma_log2_weight_denom = 0;
2346 slice_param->delta_chroma_log2_weight_denom = 0;
2348 if ((pps->weighted_pred_flag && GST_H265_IS_P_SLICE (slice_hdr)) ||
2349 (pps->weighted_bipred_flag && GST_H265_IS_B_SLICE (slice_hdr))) {
2351 /* Fixme: This should be done in parser apis */
2352 memset (slice_param->delta_luma_weight_l0, 0,
2353 sizeof (slice_param->delta_luma_weight_l0));
2354 memset (slice_param->luma_offset_l0, 0,
2355 sizeof (slice_param->luma_offset_l0));
2356 memset (slice_param->delta_luma_weight_l1, 0,
2357 sizeof (slice_param->delta_luma_weight_l1));
2358 memset (slice_param->luma_offset_l1, 0,
2359 sizeof (slice_param->luma_offset_l1));
2360 memset (slice_param->delta_chroma_weight_l0, 0,
2361 sizeof (slice_param->delta_chroma_weight_l0));
2362 memset (slice_param->ChromaOffsetL0, 0,
2363 sizeof (slice_param->ChromaOffsetL0));
2364 memset (slice_param->delta_chroma_weight_l1, 0,
2365 sizeof (slice_param->delta_chroma_weight_l1));
2366 memset (slice_param->ChromaOffsetL1, 0,
2367 sizeof (slice_param->ChromaOffsetL1));
2369 slice_param->luma_log2_weight_denom = w->luma_log2_weight_denom;
2370 if (sps->chroma_array_type != 0)
2371 slice_param->delta_chroma_log2_weight_denom =
2372 w->delta_chroma_log2_weight_denom;
2374 chroma_log2_weight_denom =
2375 slice_param->luma_log2_weight_denom +
2376 slice_param->delta_chroma_log2_weight_denom;
2378 for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
2379 if (slice_hdr->pred_weight_table.luma_weight_l0_flag[i]) {
2380 slice_param->delta_luma_weight_l0[i] = w->delta_luma_weight_l0[i];
2381 slice_param->luma_offset_l0[i] = w->luma_offset_l0[i];
2383 if (slice_hdr->pred_weight_table.chroma_weight_l0_flag[i]) {
2384 for (j = 0; j < 2; j++) {
2385 slice_param->delta_chroma_weight_l0[i][j] =
2386 w->delta_chroma_weight_l0[i][j];
2387 /* Find ChromaWeightL0 */
2389 (1 << chroma_log2_weight_denom) + w->delta_chroma_weight_l0[i][j];
2391 slice_param->ChromaOffsetL0[i][j] = CLAMP (
2392 (priv->WpOffsetHalfRangeC + w->delta_chroma_offset_l0[i][j] -
2393 ((priv->WpOffsetHalfRangeC *
2394 chroma_weight) >> chroma_log2_weight_denom)),
2395 -priv->WpOffsetHalfRangeC, priv->WpOffsetHalfRangeC - 1);
2400 if (GST_H265_IS_B_SLICE (slice_hdr)) {
2401 for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
2402 if (slice_hdr->pred_weight_table.luma_weight_l1_flag[i]) {
2403 slice_param->delta_luma_weight_l1[i] = w->delta_luma_weight_l1[i];
2404 slice_param->luma_offset_l1[i] = w->luma_offset_l1[i];
2406 if (slice_hdr->pred_weight_table.chroma_weight_l1_flag[i]) {
2407 for (j = 0; j < 2; j++) {
2408 slice_param->delta_chroma_weight_l1[i][j] =
2409 w->delta_chroma_weight_l1[i][j];
2410 /* Find ChromaWeightL1 */
2412 (1 << chroma_log2_weight_denom) +
2413 w->delta_chroma_weight_l1[i][j];
2415 slice_param->ChromaOffsetL1[i][j] =
2416 CLAMP ((priv->WpOffsetHalfRangeC +
2417 w->delta_chroma_offset_l1[i][j] -
2418 ((priv->WpOffsetHalfRangeC *
2419 chroma_weight) >> chroma_log2_weight_denom)),
2420 -priv->WpOffsetHalfRangeC, priv->WpOffsetHalfRangeC - 1);
2430 fill_RefPicList (GstVaapiDecoderH265 * decoder,
2431 GstVaapiPictureH265 * picture, GstVaapiSlice * slice,
2432 GstH265SliceHdr * slice_hdr)
2434 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2435 VASliceParameterBufferHEVC *const slice_param = slice->param;
2436 GstVaapiPicture *const base_picture = &picture->base;
2437 VAPictureParameterBufferHEVC *const pic_param = base_picture->param;
2438 guint i, num_ref_lists = 0, j;
2440 slice_param->num_ref_idx_l0_active_minus1 = 0;
2441 slice_param->num_ref_idx_l1_active_minus1 = 0;
2442 for (j = 0; j < 2; j++)
2443 for (i = 0; i < 15; i++)
2444 slice_param->RefPicList[j][i] = 0xFF;
2446 if (GST_H265_IS_B_SLICE (slice_hdr))
2448 else if (GST_H265_IS_I_SLICE (slice_hdr))
2453 if (num_ref_lists < 1)
2456 slice_param->num_ref_idx_l0_active_minus1 =
2457 slice_hdr->num_ref_idx_l0_active_minus1;
2458 slice_param->num_ref_idx_l1_active_minus1 =
2459 slice_hdr->num_ref_idx_l1_active_minus1;
2461 for (i = 0; i < priv->RefPicList0_count; i++)
2462 slice_param->RefPicList[0][i] =
2463 get_index_for_RefPicListX (pic_param->ReferenceFrames,
2464 priv->RefPicList0[i]);
2466 slice_param->RefPicList[0][i] = 0xFF;
2468 if (num_ref_lists < 2)
2471 for (i = 0; i < priv->RefPicList1_count; i++)
2472 slice_param->RefPicList[1][i] =
2473 get_index_for_RefPicListX (pic_param->ReferenceFrames,
2474 priv->RefPicList1[i]);
2476 slice_param->RefPicList[1][i] = 0xFF;
2482 fill_slice (GstVaapiDecoderH265 * decoder,
2483 GstVaapiPictureH265 * picture, GstVaapiSlice * slice,
2484 GstVaapiParserInfoH265 * pi, GstVaapiDecoderUnit * unit)
2486 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2487 VASliceParameterBufferHEVC *const slice_param = slice->param;
2488 GstH265SliceHdr *slice_hdr = &pi->data.slice_hdr;
2490 /* Fill in VASliceParameterBufferH265 */
2491 slice_param->LongSliceFlags.value = 0;
2492 slice_param->slice_data_byte_offset =
2493 get_slice_data_byte_offset (slice_hdr, pi->nalu.header_bytes);
2495 slice_param->slice_segment_address = slice_hdr->segment_address;
2497 #define COPY_LFF(f) \
2498 slice_param->LongSliceFlags.fields.f = (slice_hdr)->f
2500 if (GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_AU_END))
2501 slice_param->LongSliceFlags.fields.LastSliceOfPic = 1;
2503 slice_param->LongSliceFlags.fields.LastSliceOfPic = 0;
2505 COPY_LFF (dependent_slice_segment_flag);
2507 /* use most recent independent slice segment header syntax elements
2508 * for filling the missing fields in dependent slice segment header */
2509 if (slice_hdr->dependent_slice_segment_flag)
2510 slice_hdr = &priv->prev_independent_slice_pi->data.slice_hdr;
2512 COPY_LFF (mvd_l1_zero_flag);
2513 COPY_LFF (cabac_init_flag);
2514 COPY_LFF (collocated_from_l0_flag);
2515 slice_param->LongSliceFlags.fields.color_plane_id =
2516 slice_hdr->colour_plane_id;
2517 slice_param->LongSliceFlags.fields.slice_type = slice_hdr->type;
2518 slice_param->LongSliceFlags.fields.slice_sao_luma_flag =
2519 slice_hdr->sao_luma_flag;
2520 slice_param->LongSliceFlags.fields.slice_sao_chroma_flag =
2521 slice_hdr->sao_chroma_flag;
2522 slice_param->LongSliceFlags.fields.slice_temporal_mvp_enabled_flag =
2523 slice_hdr->temporal_mvp_enabled_flag;
2524 slice_param->LongSliceFlags.fields.slice_deblocking_filter_disabled_flag =
2525 slice_hdr->deblocking_filter_disabled_flag;
2526 slice_param->LongSliceFlags.
2527 fields.slice_loop_filter_across_slices_enabled_flag =
2528 slice_hdr->loop_filter_across_slices_enabled_flag;
2530 if (!slice_hdr->temporal_mvp_enabled_flag)
2531 slice_param->collocated_ref_idx = 0xFF;
2533 slice_param->collocated_ref_idx = slice_hdr->collocated_ref_idx;
2535 slice_param->num_ref_idx_l0_active_minus1 =
2536 slice_hdr->num_ref_idx_l0_active_minus1;
2537 slice_param->num_ref_idx_l1_active_minus1 =
2538 slice_hdr->num_ref_idx_l1_active_minus1;
2539 slice_param->slice_qp_delta = slice_hdr->qp_delta;
2540 slice_param->slice_cb_qp_offset = slice_hdr->cb_qp_offset;
2541 slice_param->slice_cr_qp_offset = slice_hdr->cr_qp_offset;
2542 slice_param->slice_beta_offset_div2 = slice_hdr->beta_offset_div2;
2543 slice_param->slice_tc_offset_div2 = slice_hdr->tc_offset_div2;
2544 slice_param->five_minus_max_num_merge_cand =
2545 slice_hdr->five_minus_max_num_merge_cand;
2547 if (!fill_RefPicList (decoder, picture, slice, slice_hdr))
2550 if (!fill_pred_weight_table (decoder, slice, slice_hdr))
2556 static GstVaapiDecoderStatus
2557 decode_slice (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
2559 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2560 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
2561 GstVaapiPictureH265 *const picture = priv->current_picture;
2562 GstH265SliceHdr *const slice_hdr = &pi->data.slice_hdr;
2563 GstVaapiSlice *slice;
2564 GstBuffer *const buffer =
2565 GST_VAAPI_DECODER_CODEC_FRAME (decoder)->input_buffer;
2566 GstMapInfo map_info;
2568 GST_DEBUG ("slice (%u bytes)", pi->nalu.size);
2569 if (!is_valid_state (pi->state, GST_H265_VIDEO_STATE_VALID_PICTURE_HEADERS)) {
2570 GST_WARNING ("failed to receive enough headers to decode slice");
2571 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2574 if (!ensure_pps (decoder, slice_hdr->pps)) {
2575 GST_ERROR ("failed to activate PPS");
2576 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2579 if (!ensure_sps (decoder, slice_hdr->pps->sps)) {
2580 GST_ERROR ("failed to activate SPS");
2581 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2584 if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) {
2585 GST_ERROR ("failed to map buffer");
2586 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2589 /* Check wether this is the first/last slice in the current access unit */
2590 if (pi->flags & GST_VAAPI_DECODER_UNIT_FLAG_AU_START)
2591 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_AU_START);
2593 if (pi->flags & GST_VAAPI_DECODER_UNIT_FLAG_AU_END)
2594 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_AU_END);
2596 slice = GST_VAAPI_SLICE_NEW (HEVC, decoder,
2597 (map_info.data + unit->offset + pi->nalu.offset), pi->nalu.size);
2599 gst_buffer_unmap (buffer, &map_info);
2601 GST_ERROR ("failed to allocate slice");
2602 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2605 init_picture_refs (decoder, picture, slice_hdr);
2607 if (!fill_slice (decoder, picture, slice, pi, unit)) {
2608 gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (slice));
2609 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2612 gst_vaapi_picture_add_slice (GST_VAAPI_PICTURE_CAST (picture), slice);
2613 picture->last_slice_hdr = slice_hdr;
2614 priv->decoder_state |= GST_H265_VIDEO_STATE_GOT_SLICE;
2615 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2619 scan_for_start_code (GstAdapter * adapter, guint ofs, guint size, guint32 * scp)
2621 return (gint) gst_adapter_masked_scan_uint32_peek (adapter,
2622 0xffffff00, 0x00000100, ofs, size, scp);
2625 static GstVaapiDecoderStatus
2626 decode_unit (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
2628 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2629 GstVaapiParserInfoH265 *const pi = unit->parsed_info;
2630 GstVaapiDecoderStatus status;
2631 priv->decoder_state |= pi->state;
2632 switch (pi->nalu.type) {
2633 case GST_H265_NAL_VPS:
2634 status = decode_vps (decoder, unit);
2636 case GST_H265_NAL_SPS:
2637 status = decode_sps (decoder, unit);
2639 case GST_H265_NAL_PPS:
2640 status = decode_pps (decoder, unit);
2642 case GST_H265_NAL_SLICE_TRAIL_N:
2643 case GST_H265_NAL_SLICE_TRAIL_R:
2644 case GST_H265_NAL_SLICE_TSA_N:
2645 case GST_H265_NAL_SLICE_TSA_R:
2646 case GST_H265_NAL_SLICE_STSA_N:
2647 case GST_H265_NAL_SLICE_STSA_R:
2648 case GST_H265_NAL_SLICE_RADL_N:
2649 case GST_H265_NAL_SLICE_RADL_R:
2650 case GST_H265_NAL_SLICE_RASL_N:
2651 case GST_H265_NAL_SLICE_RASL_R:
2652 case GST_H265_NAL_SLICE_BLA_W_LP:
2653 case GST_H265_NAL_SLICE_BLA_W_RADL:
2654 case GST_H265_NAL_SLICE_BLA_N_LP:
2655 case GST_H265_NAL_SLICE_IDR_W_RADL:
2656 case GST_H265_NAL_SLICE_IDR_N_LP:
2657 case GST_H265_NAL_SLICE_CRA_NUT:
2658 /* slice decoding will get started only after completing all the
2659 initialization routines for each picture which is hanlding in
2660 start_frame() call back, so the new_bitstream and prev_nal_is_eos
2661 flags will have effects starting from the next frame onwards */
2662 priv->new_bitstream = FALSE;
2663 priv->prev_nal_is_eos = FALSE;
2664 status = decode_slice (decoder, unit);
2666 case GST_H265_NAL_EOB:
2667 priv->new_bitstream = TRUE;
2669 ("Next AU(if there is any) will be the begining of new bitstream");
2670 status = decode_sequence_end (decoder);
2672 case GST_H265_NAL_EOS:
2673 priv->prev_nal_is_eos = TRUE;
2674 status = decode_sequence_end (decoder);
2676 case GST_H265_NAL_SUFFIX_SEI:
2677 case GST_H265_NAL_PREFIX_SEI:
2678 status = decode_sei (decoder, unit);
2681 GST_WARNING ("unsupported NAL unit type %d", pi->nalu.type);
2682 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
2688 static GstVaapiDecoderStatus
2689 gst_vaapi_decoder_h265_decode_codec_data (GstVaapiDecoder *
2690 base_decoder, const guchar * buf, guint buf_size)
2692 GstVaapiDecoderH265 *const decoder =
2693 GST_VAAPI_DECODER_H265_CAST (base_decoder);
2694 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2695 GstVaapiDecoderStatus status;
2696 GstVaapiDecoderUnit unit;
2697 GstVaapiParserInfoH265 *pi = NULL;
2698 GstH265ParserResult result;
2699 guint num_nal_arrays, num_nals;
2702 unit.parsed_info = NULL;
2704 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2706 GST_ERROR ("failed to decode codec-data, not in hvcC format");
2707 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
2710 priv->nal_length_size = (buf[21] & 0x03) + 1;
2711 GST_DEBUG ("nal length size %u", priv->nal_length_size);
2712 num_nal_arrays = buf[22];
2714 for (i = 0; i < num_nal_arrays; i++) {
2715 num_nals = GST_READ_UINT16_BE (buf + ofs + 1);
2716 for (j = 0; j < num_nals; j++) {
2717 pi = gst_vaapi_parser_info_h265_new ();
2719 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2720 unit.parsed_info = pi;
2721 result = gst_h265_parser_identify_nalu_hevc (priv->parser,
2722 buf, ofs + 3, buf_size, 2, &pi->nalu);
2723 if (result != GST_H265_PARSER_OK) {
2724 status = get_status (result);
2728 switch (pi->nalu.type) {
2729 case GST_H265_NAL_VPS:
2730 status = parse_vps (decoder, &unit);
2731 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2733 status = decode_vps (decoder, &unit);
2734 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2737 case GST_H265_NAL_SPS:
2738 status = parse_sps (decoder, &unit);
2739 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2741 status = decode_sps (decoder, &unit);
2742 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2745 case GST_H265_NAL_PPS:
2746 status = parse_pps (decoder, &unit);
2747 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2749 status = decode_pps (decoder, &unit);
2750 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2754 gst_vaapi_parser_info_h265_replace (&pi, NULL);
2758 priv->is_hvcC = TRUE;
2759 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
2761 gst_vaapi_parser_info_h265_replace (&pi, NULL);
2765 static GstVaapiDecoderStatus
2766 ensure_decoder (GstVaapiDecoderH265 * decoder)
2768 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2769 GstVaapiDecoderStatus status;
2771 if (!priv->is_opened) {
2772 priv->is_opened = gst_vaapi_decoder_h265_open (decoder);
2773 if (!priv->is_opened)
2774 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
2776 gst_vaapi_decoder_decode_codec_data (GST_VAAPI_DECODER_CAST (decoder));
2777 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2780 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2783 static GstVaapiDecoderStatus
2784 gst_vaapi_decoder_h265_parse (GstVaapiDecoder * base_decoder,
2785 GstAdapter * adapter, gboolean at_eos, GstVaapiDecoderUnit * unit)
2787 GstVaapiDecoderH265 *const decoder =
2788 GST_VAAPI_DECODER_H265_CAST (base_decoder);
2789 GstVaapiDecoderH265Private *const priv = &decoder->priv;
2790 GstVaapiParserState *const ps = GST_VAAPI_PARSER_STATE (base_decoder);
2791 GstVaapiParserInfoH265 *pi;
2792 GstVaapiDecoderStatus status;
2793 GstH265ParserResult result;
2795 guint i, size, buf_size, nalu_size, flags;
2798 gboolean at_au_end = FALSE;
2800 status = ensure_decoder (decoder);
2801 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2804 switch (priv->stream_alignment) {
2805 case GST_VAAPI_STREAM_ALIGN_H265_NALU:
2806 case GST_VAAPI_STREAM_ALIGN_H265_AU:
2807 size = gst_adapter_available_fast (adapter);
2810 size = gst_adapter_available (adapter);
2814 if (priv->is_hvcC) {
2815 if (size < priv->nal_length_size)
2816 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2817 buf = (guchar *) & start_code;
2818 g_assert (priv->nal_length_size <= sizeof (start_code));
2819 gst_adapter_copy (adapter, buf, 0, priv->nal_length_size);
2821 for (i = 0; i < priv->nal_length_size; i++)
2822 nalu_size = (nalu_size << 8) | buf[i];
2823 buf_size = priv->nal_length_size + nalu_size;
2824 if (size < buf_size)
2825 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2826 else if (priv->stream_alignment == GST_VAAPI_STREAM_ALIGN_H265_AU)
2827 at_au_end = (buf_size == size);
2830 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2831 if (priv->stream_alignment == GST_VAAPI_STREAM_ALIGN_H265_NALU)
2834 ofs = scan_for_start_code (adapter, 0, size, NULL);
2836 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2838 gst_adapter_flush (adapter, ofs);
2842 ofs2 = ps->input_offset2 - ofs - 4;
2845 ofs = G_UNLIKELY (size < ofs2 + 4) ? -1 :
2846 scan_for_start_code (adapter, ofs2, size - ofs2, NULL);
2848 // Assume the whole NAL unit is present if end-of-stream
2849 // or stream buffers aligned on access unit boundaries
2850 if (priv->stream_alignment == GST_VAAPI_STREAM_ALIGN_H265_AU)
2853 ps->input_offset2 = size;
2854 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2861 ps->input_offset2 = 0;
2862 buf = (guchar *) gst_adapter_map (adapter, buf_size);
2864 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2865 unit->size = buf_size;
2866 pi = gst_vaapi_parser_info_h265_new ();
2868 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2869 gst_vaapi_decoder_unit_set_parsed_info (unit,
2870 pi, (GDestroyNotify) gst_vaapi_mini_object_unref);
2872 result = gst_h265_parser_identify_nalu_hevc (priv->parser,
2873 buf, 0, buf_size, priv->nal_length_size, &pi->nalu);
2875 result = gst_h265_parser_identify_nalu_unchecked (priv->parser,
2876 buf, 0, buf_size, &pi->nalu);
2877 status = get_status (result);
2878 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2880 switch (pi->nalu.type) {
2881 case GST_H265_NAL_VPS:
2882 status = parse_vps (decoder, unit);
2884 case GST_H265_NAL_SPS:
2885 status = parse_sps (decoder, unit);
2887 case GST_H265_NAL_PPS:
2888 status = parse_pps (decoder, unit);
2890 case GST_H265_NAL_PREFIX_SEI:
2891 case GST_H265_NAL_SUFFIX_SEI:
2892 status = parse_sei (decoder, unit);
2894 case GST_H265_NAL_SLICE_TRAIL_N:
2895 case GST_H265_NAL_SLICE_TRAIL_R:
2896 case GST_H265_NAL_SLICE_TSA_N:
2897 case GST_H265_NAL_SLICE_TSA_R:
2898 case GST_H265_NAL_SLICE_STSA_N:
2899 case GST_H265_NAL_SLICE_STSA_R:
2900 case GST_H265_NAL_SLICE_RADL_N:
2901 case GST_H265_NAL_SLICE_RADL_R:
2902 case GST_H265_NAL_SLICE_RASL_N:
2903 case GST_H265_NAL_SLICE_RASL_R:
2904 case GST_H265_NAL_SLICE_BLA_W_LP:
2905 case GST_H265_NAL_SLICE_BLA_W_RADL:
2906 case GST_H265_NAL_SLICE_BLA_N_LP:
2907 case GST_H265_NAL_SLICE_IDR_W_RADL:
2908 case GST_H265_NAL_SLICE_IDR_N_LP:
2909 case GST_H265_NAL_SLICE_CRA_NUT:
2910 status = parse_slice (decoder, unit);
2913 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
2916 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2920 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END |
2921 GST_VAAPI_DECODER_UNIT_FLAG_AU_END;
2924 switch (pi->nalu.type) {
2925 case GST_H265_NAL_AUD:
2926 flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START;
2927 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
2929 case GST_H265_NAL_FD:
2930 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
2932 case GST_H265_NAL_EOB:
2933 flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
2935 case GST_H265_NAL_SUFFIX_SEI:
2936 case GST_H265_NAL_EOS:
2937 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
2938 flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_END;
2940 case GST_H265_NAL_VPS:
2941 case GST_H265_NAL_SPS:
2942 case GST_H265_NAL_PPS:
2943 case GST_H265_NAL_PREFIX_SEI:
2944 flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START;
2945 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
2947 case GST_H265_NAL_SLICE_TRAIL_N:
2948 case GST_H265_NAL_SLICE_TRAIL_R:
2949 case GST_H265_NAL_SLICE_TSA_N:
2950 case GST_H265_NAL_SLICE_TSA_R:
2951 case GST_H265_NAL_SLICE_STSA_N:
2952 case GST_H265_NAL_SLICE_STSA_R:
2953 case GST_H265_NAL_SLICE_RADL_N:
2954 case GST_H265_NAL_SLICE_RADL_R:
2955 case GST_H265_NAL_SLICE_RASL_N:
2956 case GST_H265_NAL_SLICE_RASL_R:
2957 case GST_H265_NAL_SLICE_BLA_W_LP:
2958 case GST_H265_NAL_SLICE_BLA_W_RADL:
2959 case GST_H265_NAL_SLICE_BLA_N_LP:
2960 case GST_H265_NAL_SLICE_IDR_W_RADL:
2961 case GST_H265_NAL_SLICE_IDR_N_LP:
2962 case GST_H265_NAL_SLICE_CRA_NUT:
2963 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
2964 if (priv->prev_pi &&
2965 (priv->prev_pi->flags & GST_VAAPI_DECODER_UNIT_FLAG_AU_END)) {
2966 flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START |
2967 GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
2968 } else if (is_new_picture (pi, priv->prev_slice_pi)) {
2969 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
2970 if (is_new_access_unit (pi, priv->prev_slice_pi))
2971 flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_START;
2973 gst_vaapi_parser_info_h265_replace (&priv->prev_slice_pi, pi);
2974 if (!pi->data.slice_hdr.dependent_slice_segment_flag)
2975 gst_vaapi_parser_info_h265_replace (&priv->prev_independent_slice_pi,
2982 if ((flags & GST_VAAPI_DECODER_UNIT_FLAGS_AU) && priv->prev_slice_pi)
2983 priv->prev_slice_pi->flags |= GST_VAAPI_DECODER_UNIT_FLAG_AU_END;
2984 GST_VAAPI_DECODER_UNIT_FLAG_SET (unit, flags);
2985 pi->nalu.data = NULL;
2986 pi->state = priv->parser_state;
2988 gst_vaapi_parser_info_h265_replace (&priv->prev_pi, pi);
2989 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2992 static GstVaapiDecoderStatus
2993 gst_vaapi_decoder_h265_decode (GstVaapiDecoder * base_decoder,
2994 GstVaapiDecoderUnit * unit)
2996 GstVaapiDecoderH265 *const decoder =
2997 GST_VAAPI_DECODER_H265_CAST (base_decoder);
2998 GstVaapiDecoderStatus status;
3000 status = ensure_decoder (decoder);
3001 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3003 return decode_unit (decoder, unit);
3006 static GstVaapiDecoderStatus
3007 gst_vaapi_decoder_h265_start_frame (GstVaapiDecoder * base_decoder,
3008 GstVaapiDecoderUnit * unit)
3010 GstVaapiDecoderH265 *const decoder =
3011 GST_VAAPI_DECODER_H265_CAST (base_decoder);
3013 return decode_picture (decoder, unit);
3016 static GstVaapiDecoderStatus
3017 gst_vaapi_decoder_h265_end_frame (GstVaapiDecoder * base_decoder)
3019 GstVaapiDecoderH265 *const decoder =
3020 GST_VAAPI_DECODER_H265_CAST (base_decoder);
3022 return decode_current_picture (decoder);
3025 static GstVaapiDecoderStatus
3026 gst_vaapi_decoder_h265_flush (GstVaapiDecoder * base_decoder)
3028 GstVaapiDecoderH265 *const decoder =
3029 GST_VAAPI_DECODER_H265_CAST (base_decoder);
3031 dpb_flush (decoder);
3032 return GST_VAAPI_DECODER_STATUS_SUCCESS;
3036 gst_vaapi_decoder_h265_class_init (GstVaapiDecoderH265Class * klass)
3038 GstVaapiMiniObjectClass *const object_class =
3039 GST_VAAPI_MINI_OBJECT_CLASS (klass);
3040 GstVaapiDecoderClass *const decoder_class = GST_VAAPI_DECODER_CLASS (klass);
3042 object_class->size = sizeof (GstVaapiDecoderH265);
3043 object_class->finalize = (GDestroyNotify) gst_vaapi_decoder_finalize;
3044 decoder_class->create = gst_vaapi_decoder_h265_create;
3045 decoder_class->destroy = gst_vaapi_decoder_h265_destroy;
3046 decoder_class->parse = gst_vaapi_decoder_h265_parse;
3047 decoder_class->decode = gst_vaapi_decoder_h265_decode;
3048 decoder_class->start_frame = gst_vaapi_decoder_h265_start_frame;
3049 decoder_class->end_frame = gst_vaapi_decoder_h265_end_frame;
3050 decoder_class->flush = gst_vaapi_decoder_h265_flush;
3051 decoder_class->decode_codec_data = gst_vaapi_decoder_h265_decode_codec_data;
3054 static inline const GstVaapiDecoderClass *
3055 gst_vaapi_decoder_h265_class (void)
3057 static GstVaapiDecoderH265Class g_class;
3058 static gsize g_class_init = FALSE;
3060 if (g_once_init_enter (&g_class_init)) {
3061 gst_vaapi_decoder_h265_class_init (&g_class);
3062 g_once_init_leave (&g_class_init, TRUE);
3064 return GST_VAAPI_DECODER_CLASS (&g_class);
3068 * gst_vaapi_decoder_h265_set_alignment:
3069 * @decoder: a #GstVaapiDecoderH265
3070 * @alignment: the #GstVaapiStreamAlignH265
3072 * Specifies how stream buffers are aligned / fed, i.e. the boundaries
3073 * of each buffer that is supplied to the decoder. This could be no
3074 * specific alignment, NAL unit boundaries, or access unit boundaries.
3077 gst_vaapi_decoder_h265_set_alignment (GstVaapiDecoderH265 * decoder,
3078 GstVaapiStreamAlignH265 alignment)
3080 g_return_if_fail (decoder != NULL);
3081 decoder->priv.stream_alignment = alignment;
3085 * gst_vaapi_decoder_h265_new:
3086 * @display: a #GstVaapiDisplay
3087 * @caps: a #GstCaps holding codec information
3089 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
3090 * hold extra information like codec-data and pictured coded size.
3092 * Return value: the newly allocated #GstVaapiDecoder object
3095 gst_vaapi_decoder_h265_new (GstVaapiDisplay * display, GstCaps * caps)
3097 return gst_vaapi_decoder_new (gst_vaapi_decoder_h265_class (), display, caps);