2 * gstvaapidecoder_h264.c - H.264 decoder
4 * Copyright (C) 2011-2012 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1
9 * of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
23 * SECTION:gstvaapidecoder_h264
24 * @short_description: H.264 decoder
30 #include <gst/base/gstadapter.h>
31 #include <gst/codecparsers/gsth264parser.h>
32 #include "gstvaapidecoder_h264.h"
33 #include "gstvaapidecoder_objects.h"
34 #include "gstvaapidecoder_priv.h"
35 #include "gstvaapidisplay_priv.h"
36 #include "gstvaapiobject_priv.h"
39 #include "gstvaapidebug.h"
41 /* Defined to 1 if strict ordering of DPB is needed. Only useful for debug */
42 #define USE_STRICT_DPB_ORDERING 0
44 typedef struct _GstVaapiFrameStore GstVaapiFrameStore;
45 typedef struct _GstVaapiFrameStoreClass GstVaapiFrameStoreClass;
46 typedef struct _GstVaapiPictureH264 GstVaapiPictureH264;
47 typedef struct _GstVaapiPictureH264Class GstVaapiPictureH264Class;
48 typedef struct _GstVaapiSliceH264 GstVaapiSliceH264;
49 typedef struct _GstVaapiSliceH264Class GstVaapiSliceH264Class;
51 // Used for field_poc[]
53 #define BOTTOM_FIELD 1
55 /* ------------------------------------------------------------------------- */
56 /* --- H.264 Pictures --- */
57 /* ------------------------------------------------------------------------- */
59 #define GST_VAAPI_TYPE_PICTURE_H264 \
60 (gst_vaapi_picture_h264_get_type())
62 #define GST_VAAPI_PICTURE_H264_CAST(obj) \
63 ((GstVaapiPictureH264 *)(obj))
65 #define GST_VAAPI_PICTURE_H264(obj) \
66 (G_TYPE_CHECK_INSTANCE_CAST((obj), \
67 GST_VAAPI_TYPE_PICTURE_H264, \
70 #define GST_VAAPI_PICTURE_H264_CLASS(klass) \
71 (G_TYPE_CHECK_CLASS_CAST((klass), \
72 GST_VAAPI_TYPE_PICTURE_H264, \
73 GstVaapiPictureH264Class))
75 #define GST_VAAPI_IS_PICTURE_H264(obj) \
76 (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_PICTURE_H264))
78 #define GST_VAAPI_IS_PICTURE_H264_CLASS(klass) \
79 (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_PICTURE_H264))
81 #define GST_VAAPI_PICTURE_H264_GET_CLASS(obj) \
82 (G_TYPE_INSTANCE_GET_CLASS((obj), \
83 GST_VAAPI_TYPE_PICTURE_H264, \
84 GstVaapiPictureH264Class))
87 * Extended picture flags:
89 * @GST_VAAPI_PICTURE_FLAG_IDR: flag that specifies an IDR picture
90 * @GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE: flag that specifies
91 * "used for short-term reference"
92 * @GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE: flag that specifies
93 * "used for long-term reference"
94 * @GST_VAAPI_PICTURE_FLAGS_REFERENCE: mask covering any kind of
95 * reference picture (short-term reference or long-term reference)
98 GST_VAAPI_PICTURE_FLAG_IDR = (GST_VAAPI_PICTURE_FLAG_LAST << 0),
100 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE = (
101 GST_VAAPI_PICTURE_FLAG_REFERENCE),
102 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE = (
103 GST_VAAPI_PICTURE_FLAG_REFERENCE | (GST_VAAPI_PICTURE_FLAG_LAST << 1)),
104 GST_VAAPI_PICTURE_FLAGS_REFERENCE = (
105 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
106 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE),
109 #define GST_VAAPI_PICTURE_IS_IDR(picture) \
110 (GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_IDR))
112 #define GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture) \
113 ((GST_VAAPI_PICTURE_FLAGS(picture) & \
114 GST_VAAPI_PICTURE_FLAGS_REFERENCE) == \
115 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE)
117 #define GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture) \
118 ((GST_VAAPI_PICTURE_FLAGS(picture) & \
119 GST_VAAPI_PICTURE_FLAGS_REFERENCE) == \
120 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE)
122 struct _GstVaapiPictureH264 {
123 GstVaapiPicture base;
127 gint32 frame_num; // Original frame_num from slice_header()
128 gint32 frame_num_wrap; // Temporary for ref pic marking: FrameNumWrap
129 gint32 long_term_frame_idx; // Temporary for ref pic marking: LongTermFrameIdx
130 gint32 pic_num; // Temporary for ref pic marking: PicNum
131 gint32 long_term_pic_num; // Temporary for ref pic marking: LongTermPicNum
132 GstVaapiPictureH264 *other_field; // Temporary for ref pic marking: other field in the same frame store
133 guint output_flag : 1;
134 guint output_needed : 1;
137 struct _GstVaapiPictureH264Class {
139 GstVaapiPictureClass parent_class;
142 GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiPictureH264,
143 gst_vaapi_picture_h264,
144 GST_VAAPI_TYPE_PICTURE)
147 gst_vaapi_picture_h264_destroy(GstVaapiPictureH264 *decoder)
152 gst_vaapi_picture_h264_create(
153 GstVaapiPictureH264 *picture,
154 const GstVaapiCodecObjectConstructorArgs *args
161 gst_vaapi_picture_h264_init(GstVaapiPictureH264 *picture)
163 picture->field_poc[0] = G_MAXINT32;
164 picture->field_poc[1] = G_MAXINT32;
165 picture->output_needed = FALSE;
168 static inline GstVaapiPictureH264 *
169 gst_vaapi_picture_h264_new(GstVaapiDecoderH264 *decoder)
171 GstVaapiCodecObject *object;
173 g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
175 object = gst_vaapi_codec_object_new(
176 GST_VAAPI_TYPE_PICTURE_H264,
177 GST_VAAPI_CODEC_BASE(decoder),
178 NULL, sizeof(VAPictureParameterBufferH264),
183 return GST_VAAPI_PICTURE_H264_CAST(object);
187 gst_vaapi_picture_h264_set_reference(
188 GstVaapiPictureH264 *picture,
189 guint reference_flags,
193 g_return_if_fail(GST_VAAPI_IS_PICTURE_H264(picture));
195 GST_VAAPI_PICTURE_FLAG_UNSET(picture, GST_VAAPI_PICTURE_FLAGS_REFERENCE);
196 GST_VAAPI_PICTURE_FLAG_SET(picture, reference_flags);
198 if (!other_field || !(picture = picture->other_field))
200 GST_VAAPI_PICTURE_FLAG_UNSET(picture, GST_VAAPI_PICTURE_FLAGS_REFERENCE);
201 GST_VAAPI_PICTURE_FLAG_SET(picture, reference_flags);
204 static inline GstVaapiPictureH264 *
205 gst_vaapi_picture_h264_new_field(GstVaapiPictureH264 *picture)
207 GstVaapiPicture *base_picture;
209 g_return_val_if_fail(GST_VAAPI_IS_PICTURE_H264(picture), NULL);
211 base_picture = gst_vaapi_picture_new_field(&picture->base);
214 return GST_VAAPI_PICTURE_H264_CAST(base_picture);
217 static inline GstVaapiSliceH264 *
218 gst_vaapi_picture_h264_get_last_slice(GstVaapiPictureH264 *picture)
220 g_return_val_if_fail(GST_VAAPI_IS_PICTURE_H264(picture), NULL);
222 if (G_UNLIKELY(picture->base.slices->len < 1))
224 return g_ptr_array_index(picture->base.slices,
225 picture->base.slices->len - 1);
228 /* ------------------------------------------------------------------------- */
230 /* ------------------------------------------------------------------------- */
232 #define GST_VAAPI_TYPE_SLICE_H264 \
233 (gst_vaapi_slice_h264_get_type())
235 #define GST_VAAPI_SLICE_H264_CAST(obj) \
236 ((GstVaapiSliceH264 *)(obj))
238 #define GST_VAAPI_SLICE_H264(obj) \
239 (G_TYPE_CHECK_INSTANCE_CAST((obj), \
240 GST_VAAPI_TYPE_SLICE_H264, \
243 #define GST_VAAPI_SLICE_H264_CLASS(klass) \
244 (G_TYPE_CHECK_CLASS_CAST((klass), \
245 GST_VAAPI_TYPE_SLICE_H264, \
246 GstVaapiSliceH264Class))
248 #define GST_VAAPI_IS_SLICE_H264(obj) \
249 (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SLICE_H264))
251 #define GST_VAAPI_IS_SLICE_H264_CLASS(klass) \
252 (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SLICE_H264))
254 #define GST_VAAPI_SLICE_H264_GET_CLASS(obj) \
255 (G_TYPE_INSTANCE_GET_CLASS((obj), \
256 GST_VAAPI_TYPE_SLICE_H264, \
257 GstVaapiSliceH264Class))
259 struct _GstVaapiSliceH264 {
261 GstH264SliceHdr slice_hdr; // parsed slice_header()
264 struct _GstVaapiSliceH264Class {
266 GstVaapiSliceClass parent_class;
269 GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiSliceH264,
270 gst_vaapi_slice_h264,
271 GST_VAAPI_TYPE_SLICE)
274 gst_vaapi_slice_h264_destroy(GstVaapiSliceH264 *slice)
279 gst_vaapi_slice_h264_create(
280 GstVaapiSliceH264 *slice,
281 const GstVaapiCodecObjectConstructorArgs *args
288 gst_vaapi_slice_h264_init(GstVaapiSliceH264 *slice)
292 static inline GstVaapiSliceH264 *
293 gst_vaapi_slice_h264_new(
294 GstVaapiDecoderH264 *decoder,
299 GstVaapiCodecObject *object;
301 g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
303 object = gst_vaapi_codec_object_new(
304 GST_VAAPI_TYPE_SLICE_H264,
305 GST_VAAPI_CODEC_BASE(decoder),
306 NULL, sizeof(VASliceParameterBufferH264),
311 return GST_VAAPI_SLICE_H264_CAST(object);
314 /* ------------------------------------------------------------------------- */
315 /* --- Frame Buffers (DPB) --- */
316 /* ------------------------------------------------------------------------- */
318 #define GST_VAAPI_TYPE_FRAME_STORE \
319 (gst_vaapi_frame_store_get_type())
321 #define GST_VAAPI_FRAME_STORE_CAST(obj) \
322 ((GstVaapiFrameStore *)(obj))
324 #define GST_VAAPI_FRAME_STORE(obj) \
325 (G_TYPE_CHECK_INSTANCE_CAST((obj), \
326 GST_VAAPI_TYPE_FRAME_STORE, \
329 #define GST_VAAPI_FRAME_STORE_CLASS(klass) \
330 (G_TYPE_CHECK_CLASS_CAST((klass), \
331 GST_VAAPI_TYPE_FRAME_STORE, \
332 GstVaapiFrameStoreClass))
334 #define GST_VAAPI_IS_FRAME_STORE(obj) \
335 (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_FRAME_STORE))
337 #define GST_VAAPI_IS_FRAME_STORE_CLASS(klass) \
338 (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_FRAME_STORE))
340 #define GST_VAAPI_FRAME_STORE_GET_CLASS(obj) \
341 (G_TYPE_INSTANCE_GET_CLASS((obj), \
342 GST_VAAPI_TYPE_FRAME_STORE, \
343 GstVaapiFrameStoreClass))
345 struct _GstVaapiFrameStore {
347 GstMiniObject parent_instance;
350 GstVaapiPictureH264 *buffers[2];
355 struct _GstVaapiFrameStoreClass {
357 GstMiniObjectClass parent_class;
360 G_DEFINE_TYPE(GstVaapiFrameStore, gst_vaapi_frame_store, GST_TYPE_MINI_OBJECT)
363 gst_vaapi_frame_store_finalize(GstMiniObject *object)
365 GstVaapiFrameStore * const fs = GST_VAAPI_FRAME_STORE_CAST(object);
366 GstMiniObjectClass *parent_class;
369 for (i = 0; i < fs->num_buffers; i++)
370 gst_vaapi_picture_replace(&fs->buffers[i], NULL);
372 parent_class = GST_MINI_OBJECT_CLASS(gst_vaapi_frame_store_parent_class);
373 if (parent_class->finalize)
374 parent_class->finalize(object);
378 gst_vaapi_frame_store_init(GstVaapiFrameStore *fs)
383 gst_vaapi_frame_store_class_init(GstVaapiFrameStoreClass *klass)
385 GstMiniObjectClass * const object_class = GST_MINI_OBJECT_CLASS(klass);
387 object_class->finalize = gst_vaapi_frame_store_finalize;
390 static inline gpointer
391 _gst_vaapi_frame_store_new(void)
393 return gst_mini_object_new(GST_VAAPI_TYPE_FRAME_STORE);
396 static GstVaapiFrameStore *
397 gst_vaapi_frame_store_new(GstVaapiPictureH264 *picture)
399 GstVaapiFrameStore *fs;
401 g_return_val_if_fail(GST_VAAPI_IS_PICTURE_H264(picture), NULL);
403 fs = _gst_vaapi_frame_store_new();
407 fs->structure = picture->structure;
408 fs->buffers[0] = gst_vaapi_picture_ref(picture);
410 fs->output_needed = picture->output_needed;
415 gst_vaapi_frame_store_add(GstVaapiFrameStore *fs, GstVaapiPictureH264 *picture)
419 g_return_val_if_fail(GST_VAAPI_IS_FRAME_STORE(fs), FALSE);
420 g_return_val_if_fail(fs->num_buffers == 1, FALSE);
421 g_return_val_if_fail(GST_VAAPI_IS_PICTURE_H264(picture), FALSE);
422 g_return_val_if_fail(!GST_VAAPI_PICTURE_IS_FRAME(picture), FALSE);
424 gst_vaapi_picture_replace(&fs->buffers[fs->num_buffers++], picture);
425 if (picture->output_flag) {
426 picture->output_needed = TRUE;
430 fs->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
432 field = picture->structure == GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD ?
433 TOP_FIELD : BOTTOM_FIELD;
434 g_return_val_if_fail(fs->buffers[0]->field_poc[field] == G_MAXINT32, FALSE);
435 fs->buffers[0]->field_poc[field] = picture->field_poc[field];
436 g_return_val_if_fail(picture->field_poc[!field] == G_MAXINT32, FALSE);
437 picture->field_poc[!field] = fs->buffers[0]->field_poc[!field];
442 gst_vaapi_frame_store_split_fields(GstVaapiFrameStore *fs)
444 GstVaapiPictureH264 * const first_field = fs->buffers[0];
445 GstVaapiPictureH264 *second_field;
447 g_return_val_if_fail(fs->num_buffers == 1, FALSE);
449 first_field->base.structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
450 GST_VAAPI_PICTURE_FLAG_SET(first_field, GST_VAAPI_PICTURE_FLAG_INTERLACED);
452 second_field = gst_vaapi_picture_h264_new_field(first_field);
455 gst_vaapi_picture_replace(&fs->buffers[fs->num_buffers++], second_field);
456 gst_vaapi_picture_unref(second_field);
458 second_field->frame_num = first_field->frame_num;
459 second_field->field_poc[0] = first_field->field_poc[0];
460 second_field->field_poc[1] = first_field->field_poc[1];
461 second_field->output_flag = first_field->output_flag;
462 if (second_field->output_flag) {
463 second_field->output_needed = TRUE;
469 static inline gboolean
470 gst_vaapi_frame_store_has_frame(GstVaapiFrameStore *fs)
472 return fs->structure == GST_VAAPI_PICTURE_STRUCTURE_FRAME;
475 static inline gboolean
476 gst_vaapi_frame_store_has_reference(GstVaapiFrameStore *fs)
480 for (i = 0; i < fs->num_buffers; i++) {
481 if (GST_VAAPI_PICTURE_IS_REFERENCE(fs->buffers[i]))
487 #define gst_vaapi_frame_store_ref(fs) \
488 gst_mini_object_ref(GST_MINI_OBJECT(fs))
490 #define gst_vaapi_frame_store_unref(fs) \
491 gst_mini_object_unref(GST_MINI_OBJECT(fs))
493 #define gst_vaapi_frame_store_replace(old_fs_p, new_fs) \
494 gst_mini_object_replace((GstMiniObject **)(old_fs_p), \
495 (GstMiniObject *)(new_fs))
497 /* ------------------------------------------------------------------------- */
498 /* --- H.264 Decoder --- */
499 /* ------------------------------------------------------------------------- */
501 G_DEFINE_TYPE(GstVaapiDecoderH264,
502 gst_vaapi_decoder_h264,
503 GST_VAAPI_TYPE_DECODER)
505 #define GST_VAAPI_DECODER_H264_GET_PRIVATE(obj) \
506 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
507 GST_VAAPI_TYPE_DECODER_H264, \
508 GstVaapiDecoderH264Private))
510 struct _GstVaapiDecoderH264Private {
512 GstH264NalParser *parser;
513 /* Last decoded SPS. May not be the last activated one. Just here because
514 it may not fit stack memory allocation in decode_sps() */
516 /* Last decoded PPS. May not be the last activated one. Just here because
517 it may not fit stack memory allocation in decode_pps() */
519 /* Temporary slice header. Just here because it may not fit stack
520 memory allocation in decode_slice() */
521 GstH264SliceHdr temp_slice_hdr;
522 GstVaapiPictureH264 *current_picture;
523 GstVaapiFrameStore *prev_frame;
524 GstVaapiFrameStore *dpb[16];
527 GstVaapiProfile profile;
528 GstVaapiEntrypoint entrypoint;
529 GstVaapiChromaType chroma_type;
530 GstVaapiPictureH264 *short_ref[32];
531 guint short_ref_count;
532 GstVaapiPictureH264 *long_ref[32];
533 guint long_ref_count;
534 GstVaapiPictureH264 *RefPicList0[32];
535 guint RefPicList0_count;
536 GstVaapiPictureH264 *RefPicList1[32];
537 guint RefPicList1_count;
538 guint nal_length_size;
541 gint32 field_poc[2]; // 0:TopFieldOrderCnt / 1:BottomFieldOrderCnt
542 gint32 poc_msb; // PicOrderCntMsb
543 gint32 poc_lsb; // pic_order_cnt_lsb (from slice_header())
544 gint32 prev_poc_msb; // prevPicOrderCntMsb
545 gint32 prev_poc_lsb; // prevPicOrderCntLsb
546 gint32 frame_num_offset; // FrameNumOffset
547 gint32 frame_num; // frame_num (from slice_header())
548 gint32 prev_frame_num; // prevFrameNum
549 gboolean prev_pic_has_mmco5; // prevMmco5Pic
550 gboolean prev_pic_structure; // previous picture structure
551 guint is_constructed : 1;
556 guint has_context : 1;
557 guint progressive_sequence : 1;
561 exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture);
563 /* Get number of reference frames to use */
565 get_max_dec_frame_buffering(GstH264SPS *sps)
567 guint max_dec_frame_buffering, MaxDpbMbs, PicSizeMbs;
569 /* Table A-1 - Level limits */
570 switch (sps->level_idc) {
571 case 10: MaxDpbMbs = 396; break;
572 case 11: MaxDpbMbs = 900; break;
573 case 12: MaxDpbMbs = 2376; break;
574 case 13: MaxDpbMbs = 2376; break;
575 case 20: MaxDpbMbs = 2376; break;
576 case 21: MaxDpbMbs = 4752; break;
577 case 22: MaxDpbMbs = 8100; break;
578 case 30: MaxDpbMbs = 8100; break;
579 case 31: MaxDpbMbs = 18000; break;
580 case 32: MaxDpbMbs = 20480; break;
581 case 40: MaxDpbMbs = 32768; break;
582 case 41: MaxDpbMbs = 32768; break;
583 case 42: MaxDpbMbs = 34816; break;
584 case 50: MaxDpbMbs = 110400; break;
585 case 51: MaxDpbMbs = 184320; break;
587 g_assert(0 && "unhandled level");
591 PicSizeMbs = ((sps->pic_width_in_mbs_minus1 + 1) *
592 (sps->pic_height_in_map_units_minus1 + 1) *
593 (sps->frame_mbs_only_flag ? 1 : 2));
594 max_dec_frame_buffering = MaxDpbMbs / PicSizeMbs;
597 if (sps->vui_parameters_present_flag) {
598 GstH264VUIParams * const vui_params = &sps->vui_parameters;
599 if (vui_params->bitstream_restriction_flag)
600 max_dec_frame_buffering = vui_params->max_dec_frame_buffering;
602 switch (sps->profile_idc) {
603 case 44: // CAVLC 4:4:4 Intra profile
604 case 86: // Scalable High profile
605 case 100: // High profile
606 case 110: // High 10 profile
607 case 122: // High 4:2:2 profile
608 case 244: // High 4:4:4 Predictive profile
609 if (sps->constraint_set3_flag)
610 max_dec_frame_buffering = 0;
616 if (max_dec_frame_buffering > 16)
617 max_dec_frame_buffering = 16;
618 else if (max_dec_frame_buffering < sps->num_ref_frames)
619 max_dec_frame_buffering = sps->num_ref_frames;
620 return MAX(1, max_dec_frame_buffering);
624 array_remove_index_fast(void *array, guint *array_length_ptr, guint index)
626 gpointer * const entries = array;
627 guint num_entries = *array_length_ptr;
629 g_return_if_fail(index < num_entries);
631 if (index != --num_entries)
632 entries[index] = entries[num_entries];
633 entries[num_entries] = NULL;
634 *array_length_ptr = num_entries;
639 array_remove_index(void *array, guint *array_length_ptr, guint index)
641 array_remove_index_fast(array, array_length_ptr, index);
645 array_remove_index(void *array, guint *array_length_ptr, guint index)
647 gpointer * const entries = array;
648 const guint num_entries = *array_length_ptr - 1;
651 g_return_if_fail(index <= num_entries);
653 for (i = index; i < num_entries; i++)
654 entries[i] = entries[i + 1];
655 entries[num_entries] = NULL;
656 *array_length_ptr = num_entries;
660 #define ARRAY_REMOVE_INDEX(array, index) \
661 array_remove_index(array, &array##_count, index)
664 dpb_remove_index(GstVaapiDecoderH264 *decoder, guint index)
666 GstVaapiDecoderH264Private * const priv = decoder->priv;
667 guint i, num_frames = --priv->dpb_count;
669 if (USE_STRICT_DPB_ORDERING) {
670 for (i = index; i < num_frames; i++)
671 gst_vaapi_frame_store_replace(&priv->dpb[i], priv->dpb[i + 1]);
673 else if (index != num_frames)
674 gst_vaapi_frame_store_replace(&priv->dpb[index], priv->dpb[num_frames]);
675 gst_vaapi_frame_store_replace(&priv->dpb[num_frames], NULL);
680 GstVaapiDecoderH264 *decoder,
681 GstVaapiFrameStore *fs,
682 GstVaapiPictureH264 *picture
685 picture->output_needed = FALSE;
688 if (--fs->output_needed > 0)
690 picture = fs->buffers[0];
693 /* XXX: update cropping rectangle */
694 return gst_vaapi_picture_output(GST_VAAPI_PICTURE_CAST(picture));
698 dpb_evict(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture, guint i)
700 GstVaapiFrameStore * const fs = decoder->priv->dpb[i];
702 if (!fs->output_needed && !gst_vaapi_frame_store_has_reference(fs))
703 dpb_remove_index(decoder, i);
707 dpb_bump(GstVaapiDecoderH264 *decoder)
709 GstVaapiDecoderH264Private * const priv = decoder->priv;
710 GstVaapiPictureH264 *found_picture = NULL;
711 guint i, j, found_index;
714 for (i = 0; i < priv->dpb_count; i++) {
715 GstVaapiFrameStore * const fs = priv->dpb[i];
716 if (!fs->output_needed)
718 for (j = 0; j < fs->num_buffers; j++) {
719 GstVaapiPictureH264 * const picture = fs->buffers[j];
720 if (!picture->output_needed)
722 if (!found_picture || found_picture->base.poc > picture->base.poc)
723 found_picture = picture, found_index = i;
729 success = dpb_output(decoder, priv->dpb[found_index], found_picture);
730 dpb_evict(decoder, found_picture, found_index);
735 dpb_clear(GstVaapiDecoderH264 *decoder)
737 GstVaapiDecoderH264Private * const priv = decoder->priv;
740 for (i = 0; i < priv->dpb_count; i++)
741 gst_vaapi_frame_store_replace(&priv->dpb[i], NULL);
744 gst_vaapi_frame_store_replace(&priv->prev_frame, NULL);
748 dpb_flush(GstVaapiDecoderH264 *decoder)
750 while (dpb_bump(decoder))
756 dpb_add(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
758 GstVaapiDecoderH264Private * const priv = decoder->priv;
759 GstVaapiFrameStore *fs;
762 // Remove all unused pictures
763 if (!GST_VAAPI_PICTURE_IS_IDR(picture)) {
765 while (i < priv->dpb_count) {
766 GstVaapiFrameStore * const fs = priv->dpb[i];
767 if (!fs->output_needed && !gst_vaapi_frame_store_has_reference(fs))
768 dpb_remove_index(decoder, i);
774 // Check if picture is the second field and the first field is still in DPB
775 fs = priv->prev_frame;
776 if (fs && !gst_vaapi_frame_store_has_frame(fs)) {
777 g_return_val_if_fail(fs->num_buffers == 1, FALSE);
778 g_return_val_if_fail(!GST_VAAPI_PICTURE_IS_FRAME(picture), FALSE);
779 g_return_val_if_fail(!GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture), FALSE);
780 return gst_vaapi_frame_store_add(fs, picture);
783 // Create new frame store, and split fields if necessary
784 fs = gst_vaapi_frame_store_new(picture);
787 gst_vaapi_frame_store_replace(&priv->prev_frame, fs);
788 gst_vaapi_frame_store_unref(fs);
790 if (!priv->progressive_sequence && gst_vaapi_frame_store_has_frame(fs)) {
791 if (!gst_vaapi_frame_store_split_fields(fs))
795 // C.4.5.1 - Storage and marking of a reference decoded picture into the DPB
796 if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
797 while (priv->dpb_count == priv->dpb_size) {
798 if (!dpb_bump(decoder))
801 gst_vaapi_frame_store_replace(&priv->dpb[priv->dpb_count++], fs);
802 if (picture->output_flag) {
803 picture->output_needed = TRUE;
808 // C.4.5.2 - Storage and marking of a non-reference decoded picture into the DPB
810 if (!picture->output_flag)
812 while (priv->dpb_count == priv->dpb_size) {
813 gboolean found_picture = FALSE;
814 for (i = 0; !found_picture && i < priv->dpb_count; i++) {
815 GstVaapiFrameStore * const fs = priv->dpb[i];
816 if (!fs->output_needed)
818 for (j = 0; !found_picture && j < fs->num_buffers; j++)
819 found_picture = fs->buffers[j]->output_needed &&
820 fs->buffers[j]->base.poc < picture->base.poc;
823 return dpb_output(decoder, NULL, picture);
824 if (!dpb_bump(decoder))
827 gst_vaapi_frame_store_replace(&priv->dpb[priv->dpb_count++], fs);
828 picture->output_needed = TRUE;
835 dpb_reset(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
837 GstVaapiDecoderH264Private * const priv = decoder->priv;
839 priv->dpb_size = get_max_dec_frame_buffering(sps);
840 GST_DEBUG("DPB size %u", priv->dpb_size);
843 static GstVaapiDecoderStatus
844 get_status(GstH264ParserResult result)
846 GstVaapiDecoderStatus status;
849 case GST_H264_PARSER_OK:
850 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
852 case GST_H264_PARSER_NO_NAL_END:
853 status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
855 case GST_H264_PARSER_ERROR:
856 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
859 status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
866 gst_vaapi_decoder_h264_clear_buffer(GstVaapiDecoder *base)
868 GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(base);
869 GstVaapiDecoderH264Private * const priv = decoder->priv;
871 gst_vaapi_picture_replace(&priv->current_picture, NULL);
876 gst_adapter_clear(priv->adapter);
881 gst_vaapi_decoder_h264_close(GstVaapiDecoderH264 *decoder)
883 GstVaapiDecoderH264Private * const priv = decoder->priv;
885 gst_vaapi_decoder_h264_clear_buffer(GST_VAAPI_DECODER_CAST(decoder));
888 gst_h264_nal_parser_free(priv->parser);
893 g_object_unref(priv->adapter);
894 priv->adapter = NULL;
899 gst_vaapi_decoder_h264_open(GstVaapiDecoderH264 *decoder, GstBuffer *buffer)
901 GstVaapiDecoderH264Private * const priv = decoder->priv;
903 gst_vaapi_decoder_h264_close(decoder);
905 priv->adapter = gst_adapter_new();
909 priv->parser = gst_h264_nal_parser_new();
916 gst_vaapi_decoder_h264_destroy(GstVaapiDecoderH264 *decoder)
918 gst_vaapi_decoder_h264_close(decoder);
922 gst_vaapi_decoder_h264_create(GstVaapiDecoderH264 *decoder)
924 if (!GST_VAAPI_DECODER_CODEC(decoder))
930 h264_get_profile(GstH264SPS *sps)
934 switch (sps->profile_idc) {
936 profile = GST_VAAPI_PROFILE_H264_BASELINE;
939 profile = GST_VAAPI_PROFILE_H264_MAIN;
942 profile = GST_VAAPI_PROFILE_H264_HIGH;
949 h264_get_chroma_type(GstH264SPS *sps)
951 guint chroma_type = 0;
953 switch (sps->chroma_format_idc) {
955 chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
958 chroma_type = GST_VAAPI_CHROMA_TYPE_YUV422;
961 if (!sps->separate_colour_plane_flag)
962 chroma_type = GST_VAAPI_CHROMA_TYPE_YUV444;
968 static GstVaapiProfile
969 get_profile(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
971 GstVaapiDecoderH264Private * const priv = decoder->priv;
972 GstVaapiDisplay * const display = GST_VAAPI_DECODER_DISPLAY(decoder);
973 GstVaapiProfile profile, profiles[2];
974 guint i, n_profiles = 0;
976 profile = h264_get_profile(sps);
978 return GST_VAAPI_PROFILE_UNKNOWN;
980 profiles[n_profiles++] = profile;
982 case GST_VAAPI_PROFILE_H264_MAIN:
983 profiles[n_profiles++] = GST_VAAPI_PROFILE_H264_HIGH;
989 /* If the preferred profile (profiles[0]) matches one that we already
990 found, then just return it now instead of searching for it again */
991 if (profiles[0] == priv->profile)
992 return priv->profile;
994 for (i = 0; i < n_profiles; i++) {
995 if (gst_vaapi_display_has_decoder(display, profiles[i], priv->entrypoint))
998 return GST_VAAPI_PROFILE_UNKNOWN;
1001 static GstVaapiDecoderStatus
1002 ensure_context(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
1004 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
1005 GstVaapiDecoderH264Private * const priv = decoder->priv;
1006 GstVaapiContextInfo info;
1007 GstVaapiProfile profile;
1008 GstVaapiChromaType chroma_type;
1009 gboolean reset_context = FALSE;
1010 guint mb_width, mb_height;
1012 profile = get_profile(decoder, sps);
1014 GST_ERROR("unsupported profile_idc %u", sps->profile_idc);
1015 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
1018 if (priv->profile != profile) {
1019 GST_DEBUG("profile changed");
1020 reset_context = TRUE;
1021 priv->profile = profile;
1024 chroma_type = h264_get_chroma_type(sps);
1025 if (!chroma_type || chroma_type != GST_VAAPI_CHROMA_TYPE_YUV420) {
1026 GST_ERROR("unsupported chroma_format_idc %u", sps->chroma_format_idc);
1027 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
1030 if (priv->chroma_type != chroma_type) {
1031 GST_DEBUG("chroma format changed");
1032 reset_context = TRUE;
1033 priv->chroma_type = chroma_type;
1036 mb_width = sps->pic_width_in_mbs_minus1 + 1;
1037 mb_height = (sps->pic_height_in_map_units_minus1 + 1) <<
1038 !sps->frame_mbs_only_flag;
1039 if (priv->mb_width != mb_width || priv->mb_height != mb_height) {
1040 GST_DEBUG("size changed");
1041 reset_context = TRUE;
1042 priv->mb_width = mb_width;
1043 priv->mb_height = mb_height;
1046 priv->progressive_sequence = sps->frame_mbs_only_flag;
1048 /* XXX: we only output complete frames for now */
1049 gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
1052 gst_vaapi_decoder_set_pixel_aspect_ratio(
1054 sps->vui_parameters.par_n,
1055 sps->vui_parameters.par_d
1058 if (!reset_context && priv->has_context)
1059 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1061 /* XXX: fix surface size when cropping is implemented */
1062 info.profile = priv->profile;
1063 info.entrypoint = priv->entrypoint;
1064 info.width = sps->width;
1065 info.height = sps->height;
1066 info.ref_frames = get_max_dec_frame_buffering(sps);
1068 if (!gst_vaapi_decoder_ensure_context(GST_VAAPI_DECODER(decoder), &info))
1069 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1070 priv->has_context = TRUE;
1073 dpb_reset(decoder, sps);
1074 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1078 fill_iq_matrix_4x4(VAIQMatrixBufferH264 *iq_matrix, const GstH264PPS *pps)
1080 const guint8 (* const ScalingList4x4)[6][16] = &pps->scaling_lists_4x4;
1083 /* There are always 6 4x4 scaling lists */
1084 g_assert(G_N_ELEMENTS(iq_matrix->ScalingList4x4) == 6);
1085 g_assert(G_N_ELEMENTS(iq_matrix->ScalingList4x4[0]) == 16);
1087 if (sizeof(iq_matrix->ScalingList4x4[0][0]) == 1)
1088 memcpy(iq_matrix->ScalingList4x4, *ScalingList4x4,
1089 sizeof(iq_matrix->ScalingList4x4));
1091 for (i = 0; i < G_N_ELEMENTS(iq_matrix->ScalingList4x4); i++) {
1092 for (j = 0; j < G_N_ELEMENTS(iq_matrix->ScalingList4x4[i]); j++)
1093 iq_matrix->ScalingList4x4[i][j] = (*ScalingList4x4)[i][j];
1099 fill_iq_matrix_8x8(VAIQMatrixBufferH264 *iq_matrix, const GstH264PPS *pps)
1101 const guint8 (* const ScalingList8x8)[6][64] = &pps->scaling_lists_8x8;
1102 const GstH264SPS * const sps = pps->sequence;
1105 /* If chroma_format_idc != 3, there are up to 2 8x8 scaling lists */
1106 if (!pps->transform_8x8_mode_flag)
1109 g_assert(G_N_ELEMENTS(iq_matrix->ScalingList8x8) >= 2);
1110 g_assert(G_N_ELEMENTS(iq_matrix->ScalingList8x8[0]) == 64);
1112 if (sizeof(iq_matrix->ScalingList8x8[0][0]) == 1)
1113 memcpy(iq_matrix->ScalingList8x8, *ScalingList8x8,
1114 sizeof(iq_matrix->ScalingList8x8));
1116 n = (sps->chroma_format_idc != 3) ? 2 : 6;
1117 for (i = 0; i < n; i++) {
1118 for (j = 0; j < G_N_ELEMENTS(iq_matrix->ScalingList8x8[i]); j++)
1119 iq_matrix->ScalingList8x8[i][j] = (*ScalingList8x8)[i][j];
1124 static GstVaapiDecoderStatus
1125 ensure_quant_matrix(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
1127 GstVaapiPicture * const base_picture = &picture->base;
1128 GstH264PPS * const pps = picture->pps;
1129 GstH264SPS * const sps = pps->sequence;
1130 VAIQMatrixBufferH264 *iq_matrix;
1132 base_picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(H264, decoder);
1133 if (!base_picture->iq_matrix) {
1134 GST_ERROR("failed to allocate IQ matrix");
1135 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1137 iq_matrix = base_picture->iq_matrix->param;
1139 /* XXX: we can only support 4:2:0 or 4:2:2 since ScalingLists8x8[]
1140 is not large enough to hold lists for 4:4:4 */
1141 if (sps->chroma_format_idc == 3)
1142 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
1144 fill_iq_matrix_4x4(iq_matrix, pps);
1145 fill_iq_matrix_8x8(iq_matrix, pps);
1147 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1150 static GstVaapiDecoderStatus
1151 decode_current_picture(GstVaapiDecoderH264 *decoder)
1153 GstVaapiDecoderH264Private * const priv = decoder->priv;
1154 GstVaapiPictureH264 * const picture = priv->current_picture;
1155 GstVaapiDecoderStatus status;
1158 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1160 status = ensure_context(decoder, picture->pps->sequence);
1161 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1164 if (!exec_ref_pic_marking(decoder, picture))
1166 if (!dpb_add(decoder, picture))
1168 if (!gst_vaapi_picture_decode(GST_VAAPI_PICTURE_CAST(picture)))
1170 if (priv->prev_frame && gst_vaapi_frame_store_has_frame(priv->prev_frame))
1171 gst_vaapi_picture_replace(&priv->current_picture, NULL);
1172 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1175 /* XXX: fix for cases where first field failed to be decoded */
1176 gst_vaapi_picture_replace(&priv->current_picture, NULL);
1177 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1180 static GstVaapiDecoderStatus
1181 decode_sps(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
1183 GstVaapiDecoderH264Private * const priv = decoder->priv;
1184 GstH264SPS * const sps = &priv->last_sps;
1185 GstH264ParserResult result;
1187 GST_DEBUG("decode SPS");
1189 memset(sps, 0, sizeof(*sps));
1190 result = gst_h264_parser_parse_sps(priv->parser, nalu, sps, TRUE);
1191 if (result != GST_H264_PARSER_OK) {
1192 priv->got_sps = FALSE;
1193 return get_status(result);
1196 priv->got_sps = TRUE;
1197 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1200 static GstVaapiDecoderStatus
1201 decode_pps(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
1203 GstVaapiDecoderH264Private * const priv = decoder->priv;
1204 GstH264PPS * const pps = &priv->last_pps;
1205 GstH264ParserResult result;
1207 GST_DEBUG("decode PPS");
1209 memset(pps, 0, sizeof(*pps));
1210 result = gst_h264_parser_parse_pps(priv->parser, nalu, pps);
1211 if (result != GST_H264_PARSER_OK) {
1212 priv->got_pps = FALSE;
1213 return get_status(result);
1216 priv->got_pps = TRUE;
1217 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1220 static GstVaapiDecoderStatus
1221 decode_sei(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
1223 GstVaapiDecoderH264Private * const priv = decoder->priv;
1224 GstH264SEIMessage sei;
1225 GstH264ParserResult result;
1227 GST_DEBUG("decode SEI");
1229 memset(&sei, 0, sizeof(sei));
1230 result = gst_h264_parser_parse_sei(priv->parser, nalu, &sei);
1231 if (result != GST_H264_PARSER_OK) {
1232 GST_WARNING("failed to decode SEI, payload type:%d", sei.payloadType);
1233 return get_status(result);
1236 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1239 static GstVaapiDecoderStatus
1240 decode_sequence_end(GstVaapiDecoderH264 *decoder)
1242 GstVaapiDecoderStatus status;
1244 GST_DEBUG("decode sequence-end");
1246 status = decode_current_picture(decoder);
1247 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1251 return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
1254 /* 8.2.1.1 - Decoding process for picture order count type 0 */
1257 GstVaapiDecoderH264 *decoder,
1258 GstVaapiPictureH264 *picture,
1259 GstH264SliceHdr *slice_hdr
1262 GstVaapiDecoderH264Private * const priv = decoder->priv;
1263 GstH264PPS * const pps = slice_hdr->pps;
1264 GstH264SPS * const sps = pps->sequence;
1265 const gint32 MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
1268 GST_DEBUG("decode picture order count type 0");
1270 if (GST_VAAPI_PICTURE_IS_IDR(picture)) {
1271 priv->prev_poc_msb = 0;
1272 priv->prev_poc_lsb = 0;
1274 else if (priv->prev_pic_has_mmco5) {
1275 priv->prev_poc_msb = 0;
1276 priv->prev_poc_lsb =
1277 (priv->prev_pic_structure == GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD ?
1278 0 : priv->field_poc[TOP_FIELD]);
1281 priv->prev_poc_msb = priv->poc_msb;
1282 priv->prev_poc_lsb = priv->poc_lsb;
1286 priv->poc_lsb = slice_hdr->pic_order_cnt_lsb;
1287 if (priv->poc_lsb < priv->prev_poc_lsb &&
1288 (priv->prev_poc_lsb - priv->poc_lsb) >= (MaxPicOrderCntLsb / 2))
1289 priv->poc_msb = priv->prev_poc_msb + MaxPicOrderCntLsb;
1290 else if (priv->poc_lsb > priv->prev_poc_lsb &&
1291 (priv->poc_lsb - priv->prev_poc_lsb) > (MaxPicOrderCntLsb / 2))
1292 priv->poc_msb = priv->prev_poc_msb - MaxPicOrderCntLsb;
1294 priv->poc_msb = priv->prev_poc_msb;
1296 temp_poc = priv->poc_msb + priv->poc_lsb;
1297 switch (picture->structure) {
1298 case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
1300 priv->field_poc[TOP_FIELD] = temp_poc;
1301 priv->field_poc[BOTTOM_FIELD] = temp_poc +
1302 slice_hdr->delta_pic_order_cnt_bottom;
1304 case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
1306 priv->field_poc[TOP_FIELD] = temp_poc;
1308 case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
1310 priv->field_poc[BOTTOM_FIELD] = temp_poc;
1315 /* 8.2.1.2 - Decoding process for picture order count type 1 */
1318 GstVaapiDecoderH264 *decoder,
1319 GstVaapiPictureH264 *picture,
1320 GstH264SliceHdr *slice_hdr
1323 GstVaapiDecoderH264Private * const priv = decoder->priv;
1324 GstH264PPS * const pps = slice_hdr->pps;
1325 GstH264SPS * const sps = pps->sequence;
1326 const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
1327 gint32 prev_frame_num_offset, abs_frame_num, expected_poc;
1330 GST_DEBUG("decode picture order count type 1");
1332 if (priv->prev_pic_has_mmco5)
1333 prev_frame_num_offset = 0;
1335 prev_frame_num_offset = priv->frame_num_offset;
1338 if (GST_VAAPI_PICTURE_IS_IDR(picture))
1339 priv->frame_num_offset = 0;
1340 else if (priv->prev_frame_num > priv->frame_num)
1341 priv->frame_num_offset = prev_frame_num_offset + MaxFrameNum;
1343 priv->frame_num_offset = prev_frame_num_offset;
1346 if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
1347 abs_frame_num = priv->frame_num_offset + priv->frame_num;
1350 if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture) && abs_frame_num > 0)
1351 abs_frame_num = abs_frame_num - 1;
1353 if (abs_frame_num > 0) {
1354 gint32 expected_delta_per_poc_cycle;
1355 gint32 poc_cycle_cnt, frame_num_in_poc_cycle;
1357 expected_delta_per_poc_cycle = 0;
1358 for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++)
1359 expected_delta_per_poc_cycle += sps->offset_for_ref_frame[i];
1362 poc_cycle_cnt = (abs_frame_num - 1) /
1363 sps->num_ref_frames_in_pic_order_cnt_cycle;
1364 frame_num_in_poc_cycle = (abs_frame_num - 1) %
1365 sps->num_ref_frames_in_pic_order_cnt_cycle;
1368 expected_poc = poc_cycle_cnt * expected_delta_per_poc_cycle;
1369 for (i = 0; i <= frame_num_in_poc_cycle; i++)
1370 expected_poc += sps->offset_for_ref_frame[i];
1374 if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
1375 expected_poc += sps->offset_for_non_ref_pic;
1378 switch (picture->structure) {
1379 case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
1380 priv->field_poc[TOP_FIELD] = expected_poc +
1381 slice_hdr->delta_pic_order_cnt[0];
1382 priv->field_poc[BOTTOM_FIELD] = priv->field_poc[TOP_FIELD] +
1383 sps->offset_for_top_to_bottom_field +
1384 slice_hdr->delta_pic_order_cnt[1];
1386 case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
1387 priv->field_poc[TOP_FIELD] = expected_poc +
1388 slice_hdr->delta_pic_order_cnt[0];
1390 case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
1391 priv->field_poc[BOTTOM_FIELD] = expected_poc +
1392 sps->offset_for_top_to_bottom_field +
1393 slice_hdr->delta_pic_order_cnt[0];
1398 /* 8.2.1.3 - Decoding process for picture order count type 2 */
1401 GstVaapiDecoderH264 *decoder,
1402 GstVaapiPictureH264 *picture,
1403 GstH264SliceHdr *slice_hdr
1406 GstVaapiDecoderH264Private * const priv = decoder->priv;
1407 GstH264PPS * const pps = slice_hdr->pps;
1408 GstH264SPS * const sps = pps->sequence;
1409 const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
1410 gint32 prev_frame_num_offset, temp_poc;
1412 GST_DEBUG("decode picture order count type 2");
1414 if (priv->prev_pic_has_mmco5)
1415 prev_frame_num_offset = 0;
1417 prev_frame_num_offset = priv->frame_num_offset;
1420 if (GST_VAAPI_PICTURE_IS_IDR(picture))
1421 priv->frame_num_offset = 0;
1422 else if (priv->prev_frame_num > priv->frame_num)
1423 priv->frame_num_offset = prev_frame_num_offset + MaxFrameNum;
1425 priv->frame_num_offset = prev_frame_num_offset;
1428 if (GST_VAAPI_PICTURE_IS_IDR(picture))
1430 else if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
1431 temp_poc = 2 * (priv->frame_num_offset + priv->frame_num) - 1;
1433 temp_poc = 2 * (priv->frame_num_offset + priv->frame_num);
1436 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
1437 priv->field_poc[TOP_FIELD] = temp_poc;
1438 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
1439 priv->field_poc[BOTTOM_FIELD] = temp_poc;
1442 /* 8.2.1 - Decoding process for picture order count */
1445 GstVaapiDecoderH264 *decoder,
1446 GstVaapiPictureH264 *picture,
1447 GstH264SliceHdr *slice_hdr
1450 GstVaapiDecoderH264Private * const priv = decoder->priv;
1451 GstH264PPS * const pps = slice_hdr->pps;
1452 GstH264SPS * const sps = pps->sequence;
1454 switch (sps->pic_order_cnt_type) {
1456 init_picture_poc_0(decoder, picture, slice_hdr);
1459 init_picture_poc_1(decoder, picture, slice_hdr);
1462 init_picture_poc_2(decoder, picture, slice_hdr);
1466 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
1467 picture->field_poc[TOP_FIELD] = priv->field_poc[TOP_FIELD];
1468 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
1469 picture->field_poc[BOTTOM_FIELD] = priv->field_poc[BOTTOM_FIELD];
1470 picture->base.poc = MIN(picture->field_poc[0], picture->field_poc[1]);
1474 compare_picture_pic_num_dec(const void *a, const void *b)
1476 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1477 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1479 return picB->pic_num - picA->pic_num;
1483 compare_picture_long_term_pic_num_inc(const void *a, const void *b)
1485 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1486 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1488 return picA->long_term_pic_num - picB->long_term_pic_num;
1492 compare_picture_poc_dec(const void *a, const void *b)
1494 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1495 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1497 return picB->base.poc - picA->base.poc;
1501 compare_picture_poc_inc(const void *a, const void *b)
1503 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1504 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1506 return picA->base.poc - picB->base.poc;
1510 compare_picture_frame_num_wrap_dec(const void *a, const void *b)
1512 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1513 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1515 return picB->frame_num_wrap - picA->frame_num_wrap;
1519 compare_picture_long_term_frame_idx_inc(const void *a, const void *b)
1521 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1522 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1524 return picA->long_term_frame_idx - picB->long_term_frame_idx;
1527 /* 8.2.4.1 - Decoding process for picture numbers */
1529 init_picture_refs_pic_num(
1530 GstVaapiDecoderH264 *decoder,
1531 GstVaapiPictureH264 *picture,
1532 GstH264SliceHdr *slice_hdr
1535 GstVaapiDecoderH264Private * const priv = decoder->priv;
1536 GstH264PPS * const pps = slice_hdr->pps;
1537 GstH264SPS * const sps = pps->sequence;
1538 const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
1541 GST_DEBUG("decode picture numbers");
1543 for (i = 0; i < priv->short_ref_count; i++) {
1544 GstVaapiPictureH264 * const pic = priv->short_ref[i];
1547 if (pic->frame_num > priv->frame_num)
1548 pic->frame_num_wrap = pic->frame_num - MaxFrameNum;
1550 pic->frame_num_wrap = pic->frame_num;
1552 // (8-28, 8-30, 8-31)
1553 if (GST_VAAPI_PICTURE_IS_FRAME(picture))
1554 pic->pic_num = pic->frame_num_wrap;
1556 if (pic->structure == picture->structure)
1557 pic->pic_num = 2 * pic->frame_num_wrap + 1;
1559 pic->pic_num = 2 * pic->frame_num_wrap;
1563 for (i = 0; i < priv->long_ref_count; i++) {
1564 GstVaapiPictureH264 * const pic = priv->long_ref[i];
1566 // (8-29, 8-32, 8-33)
1567 if (GST_VAAPI_PICTURE_IS_FRAME(picture))
1568 pic->long_term_pic_num = pic->long_term_frame_idx;
1570 if (pic->structure == picture->structure)
1571 pic->long_term_pic_num = 2 * pic->long_term_frame_idx + 1;
1573 pic->long_term_pic_num = 2 * pic->long_term_frame_idx;
1578 #define SORT_REF_LIST(list, n, compare_func) \
1579 qsort(list, n, sizeof(*(list)), compare_picture_##compare_func)
1582 init_picture_refs_fields_1(
1583 guint picture_structure,
1584 GstVaapiPictureH264 *RefPicList[32],
1585 guint *RefPicList_count,
1586 GstVaapiPictureH264 *ref_list[32],
1587 guint ref_list_count
1594 n = *RefPicList_count;
1597 for (; i < ref_list_count; i++) {
1598 if (ref_list[i]->structure == picture_structure) {
1599 RefPicList[n++] = ref_list[i++];
1603 for (; j < ref_list_count; j++) {
1604 if (ref_list[j]->structure != picture_structure) {
1605 RefPicList[n++] = ref_list[j++];
1609 } while (i < ref_list_count || j < ref_list_count);
1610 *RefPicList_count = n;
1614 init_picture_refs_fields(
1615 GstVaapiPictureH264 *picture,
1616 GstVaapiPictureH264 *RefPicList[32],
1617 guint *RefPicList_count,
1618 GstVaapiPictureH264 *short_ref[32],
1619 guint short_ref_count,
1620 GstVaapiPictureH264 *long_ref[32],
1621 guint long_ref_count
1626 /* 8.2.4.2.5 - reference picture lists in fields */
1627 init_picture_refs_fields_1(picture->structure, RefPicList, &n,
1628 short_ref, short_ref_count);
1629 init_picture_refs_fields_1(picture->structure, RefPicList, &n,
1630 long_ref, long_ref_count);
1631 *RefPicList_count = n;
1635 init_picture_refs_p_slice(
1636 GstVaapiDecoderH264 *decoder,
1637 GstVaapiPictureH264 *picture,
1638 GstH264SliceHdr *slice_hdr
1641 GstVaapiDecoderH264Private * const priv = decoder->priv;
1642 GstVaapiPictureH264 **ref_list;
1645 GST_DEBUG("decode reference picture list for P and SP slices");
1647 if (GST_VAAPI_PICTURE_IS_FRAME(picture)) {
1648 /* 8.2.4.2.1 - P and SP slices in frames */
1649 if (priv->short_ref_count > 0) {
1650 ref_list = priv->RefPicList0;
1651 for (i = 0; i < priv->short_ref_count; i++)
1652 ref_list[i] = priv->short_ref[i];
1653 SORT_REF_LIST(ref_list, i, pic_num_dec);
1654 priv->RefPicList0_count += i;
1657 if (priv->long_ref_count > 0) {
1658 ref_list = &priv->RefPicList0[priv->RefPicList0_count];
1659 for (i = 0; i < priv->long_ref_count; i++)
1660 ref_list[i] = priv->long_ref[i];
1661 SORT_REF_LIST(ref_list, i, long_term_pic_num_inc);
1662 priv->RefPicList0_count += i;
1666 /* 8.2.4.2.2 - P and SP slices in fields */
1667 GstVaapiPictureH264 *short_ref[32];
1668 guint short_ref_count = 0;
1669 GstVaapiPictureH264 *long_ref[32];
1670 guint long_ref_count = 0;
1672 if (priv->short_ref_count > 0) {
1673 for (i = 0; i < priv->short_ref_count; i++)
1674 short_ref[i] = priv->short_ref[i];
1675 SORT_REF_LIST(short_ref, i, frame_num_wrap_dec);
1676 short_ref_count = i;
1679 if (priv->long_ref_count > 0) {
1680 for (i = 0; i < priv->long_ref_count; i++)
1681 long_ref[i] = priv->long_ref[i];
1682 SORT_REF_LIST(long_ref, i, long_term_frame_idx_inc);
1686 init_picture_refs_fields(
1688 priv->RefPicList0, &priv->RefPicList0_count,
1689 short_ref, short_ref_count,
1690 long_ref, long_ref_count
1696 init_picture_refs_b_slice(
1697 GstVaapiDecoderH264 *decoder,
1698 GstVaapiPictureH264 *picture,
1699 GstH264SliceHdr *slice_hdr
1702 GstVaapiDecoderH264Private * const priv = decoder->priv;
1703 GstVaapiPictureH264 **ref_list;
1706 GST_DEBUG("decode reference picture list for B slices");
1708 if (GST_VAAPI_PICTURE_IS_FRAME(picture)) {
1709 /* 8.2.4.2.3 - B slices in frames */
1712 if (priv->short_ref_count > 0) {
1713 // 1. Short-term references
1714 ref_list = priv->RefPicList0;
1715 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1716 if (priv->short_ref[i]->base.poc < picture->base.poc)
1717 ref_list[n++] = priv->short_ref[i];
1719 SORT_REF_LIST(ref_list, n, poc_dec);
1720 priv->RefPicList0_count += n;
1722 ref_list = &priv->RefPicList0[priv->RefPicList0_count];
1723 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1724 if (priv->short_ref[i]->base.poc >= picture->base.poc)
1725 ref_list[n++] = priv->short_ref[i];
1727 SORT_REF_LIST(ref_list, n, poc_inc);
1728 priv->RefPicList0_count += n;
1731 if (priv->long_ref_count > 0) {
1732 // 2. Long-term references
1733 ref_list = &priv->RefPicList0[priv->RefPicList0_count];
1734 for (n = 0, i = 0; i < priv->long_ref_count; i++)
1735 ref_list[n++] = priv->long_ref[i];
1736 SORT_REF_LIST(ref_list, n, long_term_pic_num_inc);
1737 priv->RefPicList0_count += n;
1741 if (priv->short_ref_count > 0) {
1742 // 1. Short-term references
1743 ref_list = priv->RefPicList1;
1744 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1745 if (priv->short_ref[i]->base.poc > picture->base.poc)
1746 ref_list[n++] = priv->short_ref[i];
1748 SORT_REF_LIST(ref_list, n, poc_inc);
1749 priv->RefPicList1_count += n;
1751 ref_list = &priv->RefPicList1[priv->RefPicList1_count];
1752 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1753 if (priv->short_ref[i]->base.poc <= picture->base.poc)
1754 ref_list[n++] = priv->short_ref[i];
1756 SORT_REF_LIST(ref_list, n, poc_dec);
1757 priv->RefPicList1_count += n;
1760 if (priv->long_ref_count > 0) {
1761 // 2. Long-term references
1762 ref_list = &priv->RefPicList1[priv->RefPicList1_count];
1763 for (n = 0, i = 0; i < priv->long_ref_count; i++)
1764 ref_list[n++] = priv->long_ref[i];
1765 SORT_REF_LIST(ref_list, n, long_term_pic_num_inc);
1766 priv->RefPicList1_count += n;
1770 /* 8.2.4.2.4 - B slices in fields */
1771 GstVaapiPictureH264 *short_ref0[32];
1772 guint short_ref0_count = 0;
1773 GstVaapiPictureH264 *short_ref1[32];
1774 guint short_ref1_count = 0;
1775 GstVaapiPictureH264 *long_ref[32];
1776 guint long_ref_count = 0;
1778 /* refFrameList0ShortTerm */
1779 if (priv->short_ref_count > 0) {
1780 ref_list = short_ref0;
1781 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1782 if (priv->short_ref[i]->base.poc <= picture->base.poc)
1783 ref_list[n++] = priv->short_ref[i];
1785 SORT_REF_LIST(ref_list, n, poc_dec);
1786 short_ref0_count += n;
1788 ref_list = &short_ref0[short_ref0_count];
1789 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1790 if (priv->short_ref[i]->base.poc > picture->base.poc)
1791 ref_list[n++] = priv->short_ref[i];
1793 SORT_REF_LIST(ref_list, n, poc_inc);
1794 short_ref0_count += n;
1797 /* refFrameList1ShortTerm */
1798 if (priv->short_ref_count > 0) {
1799 ref_list = short_ref1;
1800 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1801 if (priv->short_ref[i]->base.poc > picture->base.poc)
1802 ref_list[n++] = priv->short_ref[i];
1804 SORT_REF_LIST(ref_list, n, poc_inc);
1805 short_ref1_count += n;
1807 ref_list = &short_ref1[short_ref1_count];
1808 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1809 if (priv->short_ref[i]->base.poc <= picture->base.poc)
1810 ref_list[n++] = priv->short_ref[i];
1812 SORT_REF_LIST(ref_list, n, poc_dec);
1813 short_ref1_count += n;
1816 /* refFrameListLongTerm */
1817 if (priv->long_ref_count > 0) {
1818 for (i = 0; i < priv->long_ref_count; i++)
1819 long_ref[i] = priv->long_ref[i];
1820 SORT_REF_LIST(long_ref, i, long_term_frame_idx_inc);
1824 init_picture_refs_fields(
1826 priv->RefPicList0, &priv->RefPicList0_count,
1827 short_ref0, short_ref0_count,
1828 long_ref, long_ref_count
1831 init_picture_refs_fields(
1833 priv->RefPicList1, &priv->RefPicList1_count,
1834 short_ref1, short_ref1_count,
1835 long_ref, long_ref_count
1839 /* Check whether RefPicList1 is identical to RefPicList0, then
1840 swap if necessary */
1841 if (priv->RefPicList1_count > 1 &&
1842 priv->RefPicList1_count == priv->RefPicList0_count &&
1843 memcmp(priv->RefPicList0, priv->RefPicList1,
1844 priv->RefPicList0_count * sizeof(priv->RefPicList0[0])) == 0) {
1845 GstVaapiPictureH264 * const tmp = priv->RefPicList1[0];
1846 priv->RefPicList1[0] = priv->RefPicList1[1];
1847 priv->RefPicList1[1] = tmp;
1851 #undef SORT_REF_LIST
1854 find_short_term_reference(GstVaapiDecoderH264 *decoder, gint32 pic_num)
1856 GstVaapiDecoderH264Private * const priv = decoder->priv;
1859 for (i = 0; i < priv->short_ref_count; i++) {
1860 if (priv->short_ref[i]->pic_num == pic_num)
1863 GST_ERROR("found no short-term reference picture with PicNum = %d",
1869 find_long_term_reference(GstVaapiDecoderH264 *decoder, gint32 long_term_pic_num)
1871 GstVaapiDecoderH264Private * const priv = decoder->priv;
1874 for (i = 0; i < priv->long_ref_count; i++) {
1875 if (priv->long_ref[i]->long_term_pic_num == long_term_pic_num)
1878 GST_ERROR("found no long-term reference picture with LongTermPicNum = %d",
1884 exec_picture_refs_modification_1(
1885 GstVaapiDecoderH264 *decoder,
1886 GstVaapiPictureH264 *picture,
1887 GstH264SliceHdr *slice_hdr,
1891 GstVaapiDecoderH264Private * const priv = decoder->priv;
1892 GstH264PPS * const pps = slice_hdr->pps;
1893 GstH264SPS * const sps = pps->sequence;
1894 GstH264RefPicListModification *ref_pic_list_modification;
1895 guint num_ref_pic_list_modifications;
1896 GstVaapiPictureH264 **ref_list;
1897 guint *ref_list_count_ptr, ref_list_count, ref_list_idx = 0;
1898 guint i, j, n, num_refs;
1900 gint32 MaxPicNum, CurrPicNum, picNumPred;
1902 GST_DEBUG("modification process of reference picture list %u", list);
1905 ref_pic_list_modification = slice_hdr->ref_pic_list_modification_l0;
1906 num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_l0;
1907 ref_list = priv->RefPicList0;
1908 ref_list_count_ptr = &priv->RefPicList0_count;
1909 num_refs = slice_hdr->num_ref_idx_l0_active_minus1 + 1;
1912 ref_pic_list_modification = slice_hdr->ref_pic_list_modification_l1;
1913 num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_l1;
1914 ref_list = priv->RefPicList1;
1915 ref_list_count_ptr = &priv->RefPicList1_count;
1916 num_refs = slice_hdr->num_ref_idx_l1_active_minus1 + 1;
1918 ref_list_count = *ref_list_count_ptr;
1919 if (num_refs > ref_list_count)
1920 num_refs = ref_list_count;
1922 if (!GST_VAAPI_PICTURE_IS_FRAME(picture)) {
1923 MaxPicNum = 1 << (sps->log2_max_frame_num_minus4 + 5); // 2 * MaxFrameNum
1924 CurrPicNum = 2 * slice_hdr->frame_num + 1; // 2 * frame_num + 1
1927 MaxPicNum = 1 << (sps->log2_max_frame_num_minus4 + 4); // MaxFrameNum
1928 CurrPicNum = slice_hdr->frame_num; // frame_num
1931 picNumPred = CurrPicNum;
1933 for (i = 0; i < num_ref_pic_list_modifications; i++) {
1934 GstH264RefPicListModification * const l = &ref_pic_list_modification[i];
1935 if (l->modification_of_pic_nums_idc == 3)
1938 /* 8.2.4.3.1 - Short-term reference pictures */
1939 if (l->modification_of_pic_nums_idc == 0 || l->modification_of_pic_nums_idc == 1) {
1940 gint32 abs_diff_pic_num = l->value.abs_diff_pic_num_minus1 + 1;
1941 gint32 picNum, picNumNoWrap;
1944 if (l->modification_of_pic_nums_idc == 0) {
1945 picNumNoWrap = picNumPred - abs_diff_pic_num;
1946 if (picNumNoWrap < 0)
1947 picNumNoWrap += MaxPicNum;
1952 picNumNoWrap = picNumPred + abs_diff_pic_num;
1953 if (picNumNoWrap >= MaxPicNum)
1954 picNumNoWrap -= MaxPicNum;
1956 picNumPred = picNumNoWrap;
1959 picNum = picNumNoWrap;
1960 if (picNum > CurrPicNum)
1961 picNum -= MaxPicNum;
1964 for (j = num_refs; j > ref_list_idx; j--)
1965 ref_list[j] = ref_list[j - 1];
1966 found_ref_idx = find_short_term_reference(decoder, picNum);
1967 ref_list[ref_list_idx++] =
1968 found_ref_idx >= 0 ? priv->short_ref[found_ref_idx] : NULL;
1970 for (j = ref_list_idx; j <= num_refs; j++) {
1975 GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(ref_list[j]) ?
1976 ref_list[j]->pic_num : MaxPicNum;
1977 if (PicNumF != picNum)
1978 ref_list[n++] = ref_list[j];
1982 /* 8.2.4.3.2 - Long-term reference pictures */
1985 for (j = num_refs; j > ref_list_idx; j--)
1986 ref_list[j] = ref_list[j - 1];
1988 find_long_term_reference(decoder, l->value.long_term_pic_num);
1989 ref_list[ref_list_idx++] =
1990 found_ref_idx >= 0 ? priv->long_ref[found_ref_idx] : NULL;
1992 for (j = ref_list_idx; j <= num_refs; j++) {
1993 gint32 LongTermPicNumF;
1997 GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(ref_list[j]) ?
1998 ref_list[j]->long_term_pic_num : INT_MAX;
1999 if (LongTermPicNumF != l->value.long_term_pic_num)
2000 ref_list[n++] = ref_list[j];
2006 for (i = 0; i < num_refs; i++)
2008 GST_ERROR("list %u entry %u is empty", list, i);
2010 *ref_list_count_ptr = num_refs;
2013 /* 8.2.4.3 - Modification process for reference picture lists */
2015 exec_picture_refs_modification(
2016 GstVaapiDecoderH264 *decoder,
2017 GstVaapiPictureH264 *picture,
2018 GstH264SliceHdr *slice_hdr
2021 GST_DEBUG("execute ref_pic_list_modification()");
2024 if (!GST_H264_IS_I_SLICE(slice_hdr) && !GST_H264_IS_SI_SLICE(slice_hdr) &&
2025 slice_hdr->ref_pic_list_modification_flag_l0)
2026 exec_picture_refs_modification_1(decoder, picture, slice_hdr, 0);
2029 if (GST_H264_IS_B_SLICE(slice_hdr) &&
2030 slice_hdr->ref_pic_list_modification_flag_l1)
2031 exec_picture_refs_modification_1(decoder, picture, slice_hdr, 1);
2035 init_picture_ref_lists(GstVaapiDecoderH264 *decoder)
2037 GstVaapiDecoderH264Private * const priv = decoder->priv;
2038 guint i, j, short_ref_count, long_ref_count;
2040 short_ref_count = 0;
2042 if (GST_VAAPI_PICTURE_IS_FRAME(priv->current_picture)) {
2043 for (i = 0; i < priv->dpb_count; i++) {
2044 GstVaapiFrameStore * const fs = priv->dpb[i];
2045 GstVaapiPictureH264 *picture;
2046 if (!gst_vaapi_frame_store_has_frame(fs))
2048 picture = fs->buffers[0];
2049 if (GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
2050 priv->short_ref[short_ref_count++] = picture;
2051 else if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture))
2052 priv->long_ref[long_ref_count++] = picture;
2053 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
2054 picture->other_field = fs->buffers[1];
2058 for (i = 0; i < priv->dpb_count; i++) {
2059 GstVaapiFrameStore * const fs = priv->dpb[i];
2060 for (j = 0; j < fs->num_buffers; j++) {
2061 GstVaapiPictureH264 * const picture = fs->buffers[j];
2062 if (GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
2063 priv->short_ref[short_ref_count++] = picture;
2064 else if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture))
2065 priv->long_ref[long_ref_count++] = picture;
2066 picture->structure = picture->base.structure;
2067 picture->other_field = fs->buffers[j ^ 1];
2072 for (i = short_ref_count; i < priv->short_ref_count; i++)
2073 priv->short_ref[i] = NULL;
2074 priv->short_ref_count = short_ref_count;
2076 for (i = long_ref_count; i < priv->long_ref_count; i++)
2077 priv->long_ref[i] = NULL;
2078 priv->long_ref_count = long_ref_count;
2082 remove_short_reference(GstVaapiDecoderH264* decoder, gint32 frame_num)
2084 GstVaapiDecoderH264Private * const priv = decoder->priv;
2085 GstVaapiPictureH264 *ref_picture;
2088 for (i = 0; i < priv->short_ref_count; ++i) {
2089 if (priv->short_ref[i]->frame_num == frame_num) {
2090 ref_picture = priv->short_ref[i];
2091 gst_vaapi_picture_h264_set_reference(ref_picture, 0, FALSE);
2092 ARRAY_REMOVE_INDEX(priv->short_ref, i);
2100 GstVaapiDecoderH264 *decoder,
2101 GstVaapiPictureH264 *picture,
2102 GstH264SliceHdr *slice_hdr
2105 GstVaapiDecoderH264Private * const priv = decoder->priv;
2106 GstVaapiPicture * const base_picture = &picture->base;
2109 init_picture_ref_lists(decoder);
2110 init_picture_refs_pic_num(decoder, picture, slice_hdr);
2112 priv->RefPicList0_count = 0;
2113 priv->RefPicList1_count = 0;
2115 switch (base_picture->type) {
2116 case GST_VAAPI_PICTURE_TYPE_P:
2117 case GST_VAAPI_PICTURE_TYPE_SP:
2118 init_picture_refs_p_slice(decoder, picture, slice_hdr);
2120 case GST_VAAPI_PICTURE_TYPE_B:
2121 init_picture_refs_b_slice(decoder, picture, slice_hdr);
2127 exec_picture_refs_modification(decoder, picture, slice_hdr);
2129 switch (base_picture->type) {
2130 case GST_VAAPI_PICTURE_TYPE_B:
2131 num_refs = 1 + slice_hdr->num_ref_idx_l1_active_minus1;
2132 for (i = priv->RefPicList1_count; i < num_refs; i++)
2133 priv->RefPicList1[i] = NULL;
2134 //priv->RefPicList1_count = num_refs;
2137 case GST_VAAPI_PICTURE_TYPE_P:
2138 case GST_VAAPI_PICTURE_TYPE_SP:
2139 num_refs = 1 + slice_hdr->num_ref_idx_l0_active_minus1;
2140 for (i = priv->RefPicList0_count; i < num_refs; i++)
2141 priv->RefPicList0[i] = NULL;
2142 //priv->RefPicList0_count = num_refs;
2151 GstVaapiDecoderH264 *decoder,
2152 GstVaapiPictureH264 *picture,
2153 GstH264SliceHdr *slice_hdr,
2154 GstH264NalUnit *nalu
2157 GstVaapiDecoderH264Private * const priv = decoder->priv;
2158 GstVaapiPicture * const base_picture = &picture->base;
2160 priv->prev_frame_num = priv->frame_num;
2161 priv->frame_num = slice_hdr->frame_num;
2162 picture->frame_num = priv->frame_num;
2163 picture->frame_num_wrap = priv->frame_num;
2164 picture->output_flag = TRUE; /* XXX: conformant to Annex A only */
2165 base_picture->pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
2167 /* Reset decoder state for IDR pictures */
2168 if (nalu->type == GST_H264_NAL_SLICE_IDR) {
2170 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_IDR);
2174 /* Initialize slice type */
2175 switch (slice_hdr->type % 5) {
2176 case GST_H264_P_SLICE:
2177 base_picture->type = GST_VAAPI_PICTURE_TYPE_P;
2179 case GST_H264_B_SLICE:
2180 base_picture->type = GST_VAAPI_PICTURE_TYPE_B;
2182 case GST_H264_I_SLICE:
2183 base_picture->type = GST_VAAPI_PICTURE_TYPE_I;
2185 case GST_H264_SP_SLICE:
2186 base_picture->type = GST_VAAPI_PICTURE_TYPE_SP;
2188 case GST_H264_SI_SLICE:
2189 base_picture->type = GST_VAAPI_PICTURE_TYPE_SI;
2193 /* Initialize picture structure */
2194 if (!slice_hdr->field_pic_flag)
2195 base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
2197 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
2198 if (!slice_hdr->bottom_field_flag)
2199 base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
2201 base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
2203 picture->structure = base_picture->structure;
2205 /* Initialize reference flags */
2206 if (nalu->ref_idc) {
2207 GstH264DecRefPicMarking * const dec_ref_pic_marking =
2208 &slice_hdr->dec_ref_pic_marking;
2210 if (GST_VAAPI_PICTURE_IS_IDR(picture) &&
2211 dec_ref_pic_marking->long_term_reference_flag)
2212 GST_VAAPI_PICTURE_FLAG_SET(picture,
2213 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE);
2215 GST_VAAPI_PICTURE_FLAG_SET(picture,
2216 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE);
2219 init_picture_poc(decoder, picture, slice_hdr);
2220 init_picture_refs(decoder, picture, slice_hdr);
2224 /* 8.2.5.3 - Sliding window decoded reference picture marking process */
2226 exec_ref_pic_marking_sliding_window(GstVaapiDecoderH264 *decoder)
2228 GstVaapiDecoderH264Private * const priv = decoder->priv;
2229 GstH264PPS * const pps = priv->current_picture->pps;
2230 GstH264SPS * const sps = pps->sequence;
2231 GstVaapiPictureH264 *ref_picture;
2232 guint i, m, max_num_ref_frames;
2234 GST_DEBUG("reference picture marking process (sliding window)");
2236 if (!GST_VAAPI_PICTURE_IS_FIRST_FIELD(priv->current_picture))
2239 max_num_ref_frames = sps->num_ref_frames;
2240 if (max_num_ref_frames == 0)
2241 max_num_ref_frames = 1;
2242 if (!GST_VAAPI_PICTURE_IS_FRAME(priv->current_picture))
2243 max_num_ref_frames <<= 1;
2245 if (priv->short_ref_count + priv->long_ref_count < max_num_ref_frames)
2247 if (priv->short_ref_count < 1)
2250 for (m = 0, i = 1; i < priv->short_ref_count; i++) {
2251 GstVaapiPictureH264 * const picture = priv->short_ref[i];
2252 if (picture->frame_num_wrap < priv->short_ref[m]->frame_num_wrap)
2256 ref_picture = priv->short_ref[m];
2257 gst_vaapi_picture_h264_set_reference(ref_picture, 0, TRUE);
2258 ARRAY_REMOVE_INDEX(priv->short_ref, m);
2260 /* Both fields need to be marked as "unused for reference", so
2261 remove the other field from the short_ref[] list as well */
2262 if (!GST_VAAPI_PICTURE_IS_FRAME(priv->current_picture) && ref_picture->other_field) {
2263 for (i = 0; i < priv->short_ref_count; i++) {
2264 if (priv->short_ref[i] == ref_picture->other_field) {
2265 ARRAY_REMOVE_INDEX(priv->short_ref, i);
2273 static inline gint32
2274 get_picNumX(GstVaapiPictureH264 *picture, GstH264RefPicMarking *ref_pic_marking)
2278 if (GST_VAAPI_PICTURE_IS_FRAME(picture))
2279 pic_num = picture->frame_num_wrap;
2281 pic_num = 2 * picture->frame_num_wrap + 1;
2282 pic_num -= ref_pic_marking->difference_of_pic_nums_minus1 + 1;
2286 /* 8.2.5.4.1. Mark short-term reference picture as "unused for reference" */
2288 exec_ref_pic_marking_adaptive_mmco_1(
2289 GstVaapiDecoderH264 *decoder,
2290 GstVaapiPictureH264 *picture,
2291 GstH264RefPicMarking *ref_pic_marking
2294 GstVaapiDecoderH264Private * const priv = decoder->priv;
2297 picNumX = get_picNumX(picture, ref_pic_marking);
2298 i = find_short_term_reference(decoder, picNumX);
2302 gst_vaapi_picture_h264_set_reference(priv->short_ref[i], 0,
2303 GST_VAAPI_PICTURE_IS_FRAME(picture));
2304 ARRAY_REMOVE_INDEX(priv->short_ref, i);
2307 /* 8.2.5.4.2. Mark long-term reference picture as "unused for reference" */
2309 exec_ref_pic_marking_adaptive_mmco_2(
2310 GstVaapiDecoderH264 *decoder,
2311 GstVaapiPictureH264 *picture,
2312 GstH264RefPicMarking *ref_pic_marking
2315 GstVaapiDecoderH264Private * const priv = decoder->priv;
2318 i = find_long_term_reference(decoder, ref_pic_marking->long_term_pic_num);
2322 gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0,
2323 GST_VAAPI_PICTURE_IS_FRAME(picture));
2324 ARRAY_REMOVE_INDEX(priv->long_ref, i);
2327 /* 8.2.5.4.3. Assign LongTermFrameIdx to a short-term reference picture */
2329 exec_ref_pic_marking_adaptive_mmco_3(
2330 GstVaapiDecoderH264 *decoder,
2331 GstVaapiPictureH264 *picture,
2332 GstH264RefPicMarking *ref_pic_marking
2335 GstVaapiDecoderH264Private * const priv = decoder->priv;
2336 GstVaapiPictureH264 *ref_picture;
2339 for (i = 0; i < priv->long_ref_count; i++) {
2340 if (priv->long_ref[i]->long_term_frame_idx == ref_pic_marking->long_term_frame_idx)
2343 if (i != priv->long_ref_count) {
2344 gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0, TRUE);
2345 ARRAY_REMOVE_INDEX(priv->long_ref, i);
2348 picNumX = get_picNumX(picture, ref_pic_marking);
2349 i = find_short_term_reference(decoder, picNumX);
2353 ref_picture = priv->short_ref[i];
2354 ARRAY_REMOVE_INDEX(priv->short_ref, i);
2355 priv->long_ref[priv->long_ref_count++] = ref_picture;
2357 ref_picture->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
2358 gst_vaapi_picture_h264_set_reference(ref_picture,
2359 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE,
2360 GST_VAAPI_PICTURE_IS_FRAME(picture));
2363 /* 8.2.5.4.4. Mark pictures with LongTermFramIdx > max_long_term_frame_idx
2364 * as "unused for reference" */
2366 exec_ref_pic_marking_adaptive_mmco_4(
2367 GstVaapiDecoderH264 *decoder,
2368 GstVaapiPictureH264 *picture,
2369 GstH264RefPicMarking *ref_pic_marking
2372 GstVaapiDecoderH264Private * const priv = decoder->priv;
2373 gint32 i, long_term_frame_idx;
2375 long_term_frame_idx = ref_pic_marking->max_long_term_frame_idx_plus1 - 1;
2377 for (i = 0; i < priv->long_ref_count; i++) {
2378 if (priv->long_ref[i]->long_term_frame_idx <= long_term_frame_idx)
2380 gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0, FALSE);
2381 ARRAY_REMOVE_INDEX(priv->long_ref, i);
2386 /* 8.2.5.4.5. Mark all reference pictures as "unused for reference" */
2388 exec_ref_pic_marking_adaptive_mmco_5(
2389 GstVaapiDecoderH264 *decoder,
2390 GstVaapiPictureH264 *picture,
2391 GstH264RefPicMarking *ref_pic_marking
2394 GstVaapiDecoderH264Private * const priv = decoder->priv;
2398 priv->prev_pic_has_mmco5 = TRUE;
2400 /* The picture shall be inferred to have had frame_num equal to 0 (7.4.3) */
2401 priv->frame_num = 0;
2402 priv->frame_num_offset = 0;
2403 picture->frame_num = 0;
2405 /* Update TopFieldOrderCnt and BottomFieldOrderCnt (8.2.1) */
2406 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
2407 picture->field_poc[TOP_FIELD] -= picture->base.poc;
2408 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
2409 picture->field_poc[BOTTOM_FIELD] -= picture->base.poc;
2410 picture->base.poc = 0;
2413 /* 8.2.5.4.6. Assign a long-term frame index to the current picture */
2415 exec_ref_pic_marking_adaptive_mmco_6(
2416 GstVaapiDecoderH264 *decoder,
2417 GstVaapiPictureH264 *picture,
2418 GstH264RefPicMarking *ref_pic_marking
2421 picture->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
2422 gst_vaapi_picture_h264_set_reference(picture,
2423 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE, FALSE);
2426 /* 8.2.5.4. Adaptive memory control decoded reference picture marking process */
2428 exec_ref_pic_marking_adaptive(
2429 GstVaapiDecoderH264 *decoder,
2430 GstVaapiPictureH264 *picture,
2431 GstH264DecRefPicMarking *dec_ref_pic_marking
2436 GST_DEBUG("reference picture marking process (adaptive memory control)");
2438 typedef void (*exec_ref_pic_marking_adaptive_mmco_func)(
2439 GstVaapiDecoderH264 *decoder,
2440 GstVaapiPictureH264 *picture,
2441 GstH264RefPicMarking *ref_pic_marking
2444 static const exec_ref_pic_marking_adaptive_mmco_func mmco_funcs[] = {
2446 exec_ref_pic_marking_adaptive_mmco_1,
2447 exec_ref_pic_marking_adaptive_mmco_2,
2448 exec_ref_pic_marking_adaptive_mmco_3,
2449 exec_ref_pic_marking_adaptive_mmco_4,
2450 exec_ref_pic_marking_adaptive_mmco_5,
2451 exec_ref_pic_marking_adaptive_mmco_6,
2454 for (i = 0; i < dec_ref_pic_marking->n_ref_pic_marking; i++) {
2455 GstH264RefPicMarking * const ref_pic_marking =
2456 &dec_ref_pic_marking->ref_pic_marking[i];
2458 const guint mmco = ref_pic_marking->memory_management_control_operation;
2459 if (mmco < G_N_ELEMENTS(mmco_funcs) && mmco_funcs[mmco])
2460 mmco_funcs[mmco](decoder, picture, ref_pic_marking);
2462 GST_ERROR("unhandled MMCO %u", mmco);
2469 /* 8.2.5 - Execute reference picture marking process */
2471 exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
2473 GstVaapiDecoderH264Private * const priv = decoder->priv;
2475 priv->prev_pic_has_mmco5 = FALSE;
2476 priv->prev_pic_structure = picture->structure;
2478 if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
2481 if (!GST_VAAPI_PICTURE_IS_IDR(picture)) {
2482 GstVaapiSliceH264 * const slice =
2483 gst_vaapi_picture_h264_get_last_slice(picture);
2484 GstH264DecRefPicMarking * const dec_ref_pic_marking =
2485 &slice->slice_hdr.dec_ref_pic_marking;
2486 if (dec_ref_pic_marking->adaptive_ref_pic_marking_mode_flag) {
2487 if (!exec_ref_pic_marking_adaptive(decoder, picture, dec_ref_pic_marking))
2491 if (!exec_ref_pic_marking_sliding_window(decoder))
2494 if (!priv->prev_pic_has_mmco5)
2495 remove_short_reference(decoder, picture->frame_num);
2501 vaapi_init_picture(VAPictureH264 *pic)
2503 pic->picture_id = VA_INVALID_ID;
2505 pic->flags = VA_PICTURE_H264_INVALID;
2506 pic->TopFieldOrderCnt = 0;
2507 pic->BottomFieldOrderCnt = 0;
2511 vaapi_fill_picture(VAPictureH264 *pic, GstVaapiPictureH264 *picture,
2512 guint picture_structure)
2514 if (!picture_structure)
2515 picture_structure = picture->structure;
2517 pic->picture_id = picture->base.surface_id;
2520 if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture)) {
2521 pic->flags |= VA_PICTURE_H264_LONG_TERM_REFERENCE;
2522 pic->frame_idx = picture->long_term_frame_idx;
2525 if (GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
2526 pic->flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2527 pic->frame_idx = picture->frame_num;
2530 switch (picture_structure) {
2531 case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
2532 pic->TopFieldOrderCnt = picture->field_poc[TOP_FIELD];
2533 pic->BottomFieldOrderCnt = picture->field_poc[BOTTOM_FIELD];
2535 case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
2536 pic->flags |= VA_PICTURE_H264_TOP_FIELD;
2537 pic->TopFieldOrderCnt = picture->field_poc[TOP_FIELD];
2538 pic->BottomFieldOrderCnt = 0;
2540 case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
2541 pic->flags |= VA_PICTURE_H264_BOTTOM_FIELD;
2542 pic->BottomFieldOrderCnt = picture->field_poc[BOTTOM_FIELD];
2543 pic->TopFieldOrderCnt = 0;
2550 GstVaapiDecoderH264 *decoder,
2551 GstVaapiPictureH264 *picture,
2552 GstH264SliceHdr *slice_hdr,
2553 GstH264NalUnit *nalu
2556 GstVaapiDecoderH264Private * const priv = decoder->priv;
2557 GstVaapiPicture * const base_picture = &picture->base;
2558 GstH264PPS * const pps = picture->pps;
2559 GstH264SPS * const sps = pps->sequence;
2560 VAPictureParameterBufferH264 * const pic_param = base_picture->param;
2563 /* Fill in VAPictureParameterBufferH264 */
2564 vaapi_fill_picture(&pic_param->CurrPic, picture, 0);
2566 for (i = 0, n = 0; i < priv->dpb_count; i++) {
2567 GstVaapiFrameStore * const fs = priv->dpb[i];
2568 if (gst_vaapi_frame_store_has_reference(fs))
2569 vaapi_fill_picture(&pic_param->ReferenceFrames[n++],
2570 fs->buffers[0], fs->structure);
2572 for (; n < G_N_ELEMENTS(pic_param->ReferenceFrames); n++)
2573 vaapi_init_picture(&pic_param->ReferenceFrames[n]);
2575 #define COPY_FIELD(s, f) \
2576 pic_param->f = (s)->f
2578 #define COPY_BFM(a, s, f) \
2579 pic_param->a.bits.f = (s)->f
2581 pic_param->picture_width_in_mbs_minus1 = priv->mb_width - 1;
2582 pic_param->picture_height_in_mbs_minus1 = priv->mb_height - 1;
2583 pic_param->frame_num = priv->frame_num;
2585 COPY_FIELD(sps, bit_depth_luma_minus8);
2586 COPY_FIELD(sps, bit_depth_chroma_minus8);
2587 COPY_FIELD(sps, num_ref_frames);
2588 COPY_FIELD(pps, num_slice_groups_minus1);
2589 COPY_FIELD(pps, slice_group_map_type);
2590 COPY_FIELD(pps, slice_group_change_rate_minus1);
2591 COPY_FIELD(pps, pic_init_qp_minus26);
2592 COPY_FIELD(pps, pic_init_qs_minus26);
2593 COPY_FIELD(pps, chroma_qp_index_offset);
2594 COPY_FIELD(pps, second_chroma_qp_index_offset);
2596 pic_param->seq_fields.value = 0; /* reset all bits */
2597 pic_param->seq_fields.bits.residual_colour_transform_flag = sps->separate_colour_plane_flag;
2598 pic_param->seq_fields.bits.MinLumaBiPredSize8x8 = sps->level_idc >= 31; /* A.3.3.2 */
2600 COPY_BFM(seq_fields, sps, chroma_format_idc);
2601 COPY_BFM(seq_fields, sps, gaps_in_frame_num_value_allowed_flag);
2602 COPY_BFM(seq_fields, sps, frame_mbs_only_flag);
2603 COPY_BFM(seq_fields, sps, mb_adaptive_frame_field_flag);
2604 COPY_BFM(seq_fields, sps, direct_8x8_inference_flag);
2605 COPY_BFM(seq_fields, sps, log2_max_frame_num_minus4);
2606 COPY_BFM(seq_fields, sps, pic_order_cnt_type);
2607 COPY_BFM(seq_fields, sps, log2_max_pic_order_cnt_lsb_minus4);
2608 COPY_BFM(seq_fields, sps, delta_pic_order_always_zero_flag);
2610 pic_param->pic_fields.value = 0; /* reset all bits */
2611 pic_param->pic_fields.bits.field_pic_flag = slice_hdr->field_pic_flag;
2612 pic_param->pic_fields.bits.reference_pic_flag = GST_VAAPI_PICTURE_IS_REFERENCE(picture);
2614 COPY_BFM(pic_fields, pps, entropy_coding_mode_flag);
2615 COPY_BFM(pic_fields, pps, weighted_pred_flag);
2616 COPY_BFM(pic_fields, pps, weighted_bipred_idc);
2617 COPY_BFM(pic_fields, pps, transform_8x8_mode_flag);
2618 COPY_BFM(pic_fields, pps, constrained_intra_pred_flag);
2619 COPY_BFM(pic_fields, pps, pic_order_present_flag);
2620 COPY_BFM(pic_fields, pps, deblocking_filter_control_present_flag);
2621 COPY_BFM(pic_fields, pps, redundant_pic_cnt_present_flag);
2625 /* Detection of the first VCL NAL unit of a primary coded picture (7.4.1.2.4) */
2628 GstVaapiDecoderH264 *decoder,
2629 GstH264NalUnit *nalu,
2630 GstH264SliceHdr *slice_hdr
2633 GstVaapiDecoderH264Private * const priv = decoder->priv;
2634 GstH264PPS * const pps = slice_hdr->pps;
2635 GstH264SPS * const sps = pps->sequence;
2636 GstVaapiSliceH264 *slice;
2637 GstH264SliceHdr *prev_slice_hdr;
2639 if (!priv->current_picture)
2642 slice = gst_vaapi_picture_h264_get_last_slice(priv->current_picture);
2645 prev_slice_hdr = &slice->slice_hdr;
2647 #define CHECK_EXPR(expr, field_name) do { \
2649 GST_DEBUG(field_name " differs in value"); \
2654 #define CHECK_VALUE(new_slice_hdr, old_slice_hdr, field) \
2655 CHECK_EXPR(((new_slice_hdr)->field == (old_slice_hdr)->field), #field)
2657 /* frame_num differs in value, regardless of inferred values to 0 */
2658 CHECK_VALUE(slice_hdr, prev_slice_hdr, frame_num);
2660 /* pic_parameter_set_id differs in value */
2661 CHECK_VALUE(slice_hdr, prev_slice_hdr, pps);
2663 /* field_pic_flag differs in value */
2664 CHECK_VALUE(slice_hdr, prev_slice_hdr, field_pic_flag);
2666 /* bottom_field_flag is present in both and differs in value */
2667 if (slice_hdr->field_pic_flag && prev_slice_hdr->field_pic_flag)
2668 CHECK_VALUE(slice_hdr, prev_slice_hdr, bottom_field_flag);
2670 /* nal_ref_idc differs in value with one of the nal_ref_idc values is 0 */
2671 CHECK_EXPR(((GST_VAAPI_PICTURE_IS_REFERENCE(priv->current_picture) ^
2672 (nalu->ref_idc != 0)) == 0), "nal_ref_idc");
2674 /* POC type is 0 for both and either pic_order_cnt_lsb differs in
2675 value or delta_pic_order_cnt_bottom differs in value */
2676 if (sps->pic_order_cnt_type == 0) {
2677 CHECK_VALUE(slice_hdr, prev_slice_hdr, pic_order_cnt_lsb);
2678 if (pps->pic_order_present_flag && !slice_hdr->field_pic_flag)
2679 CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt_bottom);
2682 /* POC type is 1 for both and either delta_pic_order_cnt[0]
2683 differs in value or delta_pic_order_cnt[1] differs in value */
2684 else if (sps->pic_order_cnt_type == 1) {
2685 CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt[0]);
2686 CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt[1]);
2689 /* IdrPicFlag differs in value */
2690 CHECK_EXPR(((GST_VAAPI_PICTURE_IS_IDR(priv->current_picture) ^
2691 (nalu->type == GST_H264_NAL_SLICE_IDR)) == 0), "IdrPicFlag");
2693 /* IdrPicFlag is equal to 1 for both and idr_pic_id differs in value */
2694 if (GST_VAAPI_PICTURE_IS_IDR(priv->current_picture))
2695 CHECK_VALUE(slice_hdr, prev_slice_hdr, idr_pic_id);
2702 static GstVaapiDecoderStatus
2703 decode_picture(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu, GstH264SliceHdr *slice_hdr)
2705 GstVaapiDecoderH264Private * const priv = decoder->priv;
2706 GstVaapiPictureH264 *picture;
2707 GstVaapiDecoderStatus status;
2708 GstH264PPS * const pps = slice_hdr->pps;
2709 GstH264SPS * const sps = pps->sequence;
2711 status = decode_current_picture(decoder);
2712 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2715 status = ensure_context(decoder, sps);
2716 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2719 if (priv->current_picture) {
2720 /* Re-use current picture where the first field was decoded */
2721 picture = gst_vaapi_picture_h264_new_field(priv->current_picture);
2723 GST_ERROR("failed to allocate field picture");
2724 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2728 /* Create new picture */
2729 picture = gst_vaapi_picture_h264_new(decoder);
2731 GST_ERROR("failed to allocate picture");
2732 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2735 gst_vaapi_picture_replace(&priv->current_picture, picture);
2736 gst_vaapi_picture_unref(picture);
2740 status = ensure_quant_matrix(decoder, picture);
2741 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
2742 GST_ERROR("failed to reset quantizer matrix");
2746 if (!init_picture(decoder, picture, slice_hdr, nalu))
2747 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2748 if (!fill_picture(decoder, picture, slice_hdr, nalu))
2749 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2750 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2754 get_slice_data_bit_offset(GstH264SliceHdr *slice_hdr, GstH264NalUnit *nalu)
2758 epb_count = slice_hdr->n_emulation_prevention_bytes;
2759 return 8 /* nal_unit_type */ + slice_hdr->header_size - epb_count * 8;
2763 fill_pred_weight_table(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
2765 GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
2766 GstH264PPS * const pps = slice_hdr->pps;
2767 GstH264SPS * const sps = pps->sequence;
2768 GstH264PredWeightTable * const w = &slice_hdr->pred_weight_table;
2769 VASliceParameterBufferH264 * const slice_param = slice->base.param;
2770 guint num_weight_tables = 0;
2773 if (pps->weighted_pred_flag &&
2774 (GST_H264_IS_P_SLICE(slice_hdr) || GST_H264_IS_SP_SLICE(slice_hdr)))
2775 num_weight_tables = 1;
2776 else if (pps->weighted_bipred_idc == 1 && GST_H264_IS_B_SLICE(slice_hdr))
2777 num_weight_tables = 2;
2779 num_weight_tables = 0;
2781 slice_param->luma_log2_weight_denom = w->luma_log2_weight_denom;
2782 slice_param->chroma_log2_weight_denom = w->chroma_log2_weight_denom;
2783 slice_param->luma_weight_l0_flag = 0;
2784 slice_param->chroma_weight_l0_flag = 0;
2785 slice_param->luma_weight_l1_flag = 0;
2786 slice_param->chroma_weight_l1_flag = 0;
2788 if (num_weight_tables < 1)
2791 slice_param->luma_weight_l0_flag = 1;
2792 for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
2793 slice_param->luma_weight_l0[i] = w->luma_weight_l0[i];
2794 slice_param->luma_offset_l0[i] = w->luma_offset_l0[i];
2797 slice_param->chroma_weight_l0_flag = sps->chroma_array_type != 0;
2798 if (slice_param->chroma_weight_l0_flag) {
2799 for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
2800 for (j = 0; j < 2; j++) {
2801 slice_param->chroma_weight_l0[i][j] = w->chroma_weight_l0[i][j];
2802 slice_param->chroma_offset_l0[i][j] = w->chroma_offset_l0[i][j];
2807 if (num_weight_tables < 2)
2810 slice_param->luma_weight_l1_flag = 1;
2811 for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
2812 slice_param->luma_weight_l1[i] = w->luma_weight_l1[i];
2813 slice_param->luma_offset_l1[i] = w->luma_offset_l1[i];
2816 slice_param->chroma_weight_l1_flag = sps->chroma_array_type != 0;
2817 if (slice_param->chroma_weight_l1_flag) {
2818 for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
2819 for (j = 0; j < 2; j++) {
2820 slice_param->chroma_weight_l1[i][j] = w->chroma_weight_l1[i][j];
2821 slice_param->chroma_offset_l1[i][j] = w->chroma_offset_l1[i][j];
2829 fill_RefPicList(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
2831 GstVaapiDecoderH264Private * const priv = decoder->priv;
2832 GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
2833 VASliceParameterBufferH264 * const slice_param = slice->base.param;
2834 guint i, num_ref_lists = 0;
2836 slice_param->num_ref_idx_l0_active_minus1 = 0;
2837 slice_param->num_ref_idx_l1_active_minus1 = 0;
2839 if (GST_H264_IS_B_SLICE(slice_hdr))
2841 else if (GST_H264_IS_I_SLICE(slice_hdr))
2846 if (num_ref_lists < 1)
2849 slice_param->num_ref_idx_l0_active_minus1 =
2850 slice_hdr->num_ref_idx_l0_active_minus1;
2852 for (i = 0; i < priv->RefPicList0_count && priv->RefPicList0[i]; i++)
2853 vaapi_fill_picture(&slice_param->RefPicList0[i], priv->RefPicList0[i], 0);
2854 for (; i <= slice_param->num_ref_idx_l0_active_minus1; i++)
2855 vaapi_init_picture(&slice_param->RefPicList0[i]);
2857 if (num_ref_lists < 2)
2860 slice_param->num_ref_idx_l1_active_minus1 =
2861 slice_hdr->num_ref_idx_l1_active_minus1;
2863 for (i = 0; i < priv->RefPicList1_count && priv->RefPicList1[i]; i++)
2864 vaapi_fill_picture(&slice_param->RefPicList1[i], priv->RefPicList1[i], 0);
2865 for (; i <= slice_param->num_ref_idx_l1_active_minus1; i++)
2866 vaapi_init_picture(&slice_param->RefPicList1[i]);
2872 GstVaapiDecoderH264 *decoder,
2873 GstVaapiSliceH264 *slice,
2874 GstH264NalUnit *nalu
2877 GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
2878 VASliceParameterBufferH264 * const slice_param = slice->base.param;
2880 /* Fill in VASliceParameterBufferH264 */
2881 slice_param->slice_data_bit_offset = get_slice_data_bit_offset(slice_hdr, nalu);
2882 slice_param->first_mb_in_slice = slice_hdr->first_mb_in_slice;
2883 slice_param->slice_type = slice_hdr->type % 5;
2884 slice_param->direct_spatial_mv_pred_flag = slice_hdr->direct_spatial_mv_pred_flag;
2885 slice_param->cabac_init_idc = slice_hdr->cabac_init_idc;
2886 slice_param->slice_qp_delta = slice_hdr->slice_qp_delta;
2887 slice_param->disable_deblocking_filter_idc = slice_hdr->disable_deblocking_filter_idc;
2888 slice_param->slice_alpha_c0_offset_div2 = slice_hdr->slice_alpha_c0_offset_div2;
2889 slice_param->slice_beta_offset_div2 = slice_hdr->slice_beta_offset_div2;
2891 if (!fill_RefPicList(decoder, slice))
2893 if (!fill_pred_weight_table(decoder, slice))
2898 static GstVaapiDecoderStatus
2899 decode_slice(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
2901 GstVaapiDecoderH264Private * const priv = decoder->priv;
2902 GstVaapiDecoderStatus status;
2903 GstVaapiPictureH264 *picture;
2904 GstVaapiSliceH264 *slice = NULL;
2905 GstH264SliceHdr *slice_hdr;
2906 GstH264ParserResult result;
2907 gboolean is_first_slice = !priv->has_context;
2909 GST_DEBUG("slice (%u bytes)", nalu->size);
2911 if (is_first_slice) {
2912 slice_hdr = &priv->temp_slice_hdr;
2913 memset(slice_hdr, 0, sizeof(*slice_hdr));
2914 result = gst_h264_parser_parse_slice_hdr(priv->parser, nalu,
2915 slice_hdr, TRUE, TRUE);
2916 if (result != GST_H264_PARSER_OK) {
2917 status = get_status(result);
2921 status = ensure_context(decoder, slice_hdr->pps->sequence);
2922 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2926 slice = gst_vaapi_slice_h264_new(
2928 nalu->data + nalu->offset,
2932 GST_ERROR("failed to allocate slice");
2933 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2936 slice_hdr = &slice->slice_hdr;
2938 memcpy(slice_hdr, &priv->temp_slice_hdr, sizeof(*slice_hdr));
2940 memset(slice_hdr, 0, sizeof(*slice_hdr));
2941 result = gst_h264_parser_parse_slice_hdr(priv->parser, nalu,
2942 slice_hdr, TRUE, TRUE);
2943 if (result != GST_H264_PARSER_OK) {
2944 status = get_status(result);
2949 if (is_new_picture(decoder, nalu, slice_hdr)) {
2950 status = decode_picture(decoder, nalu, slice_hdr);
2951 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2954 picture = priv->current_picture;
2956 if (!fill_slice(decoder, slice, nalu)) {
2957 status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2960 gst_vaapi_picture_add_slice(
2961 GST_VAAPI_PICTURE_CAST(picture),
2962 GST_VAAPI_SLICE_CAST(slice)
2964 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2968 gst_mini_object_unref(GST_MINI_OBJECT(slice));
2973 scan_for_start_code(GstAdapter *adapter, guint ofs, guint size, guint32 *scp)
2975 return (gint)gst_adapter_masked_scan_uint32_peek(adapter,
2976 0xffffff00, 0x00000100,
2981 static GstVaapiDecoderStatus
2982 decode_nalu(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
2984 GstVaapiDecoderH264Private * const priv = decoder->priv;
2985 GstVaapiDecoderStatus status;
2987 switch (nalu->type) {
2988 case GST_H264_NAL_SLICE_IDR:
2989 /* fall-through. IDR specifics are handled in init_picture() */
2990 case GST_H264_NAL_SLICE:
2991 if (!priv->got_sps || !priv->got_pps)
2992 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2993 status = decode_slice(decoder, nalu);
2995 case GST_H264_NAL_SPS:
2996 status = decode_sps(decoder, nalu);
2998 case GST_H264_NAL_PPS:
2999 status = decode_pps(decoder, nalu);
3001 case GST_H264_NAL_SEI:
3002 status = decode_sei(decoder, nalu);
3004 case GST_H264_NAL_SEQ_END:
3005 status = decode_sequence_end(decoder);
3007 case GST_H264_NAL_AU_DELIMITER:
3008 /* skip all Access Unit NALs */
3009 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
3011 case GST_H264_NAL_FILLER_DATA:
3012 /* skip all Filler Data NALs */
3013 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
3016 GST_WARNING("unsupported NAL unit type %d", nalu->type);
3017 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
3023 static GstVaapiDecoderStatus
3024 decode_buffer(GstVaapiDecoderH264 *decoder, GstBuffer *buffer)
3026 GstVaapiDecoderH264Private * const priv = decoder->priv;
3027 GstVaapiDecoderStatus status;
3028 GstH264ParserResult result;
3029 GstH264NalUnit nalu;
3032 guint i, buf_size, nalu_size, size;
3036 buf = GST_BUFFER_DATA(buffer);
3037 buf_size = GST_BUFFER_SIZE(buffer);
3038 is_eos = GST_BUFFER_IS_EOS(buffer);
3039 if (buf && buf_size > 0)
3040 gst_adapter_push(priv->adapter, gst_buffer_ref(buffer));
3042 size = gst_adapter_available(priv->adapter);
3045 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
3049 status = gst_vaapi_decoder_check_status(GST_VAAPI_DECODER(decoder));
3050 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3053 status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3055 if (size < priv->nal_length_size)
3057 buf = gst_adapter_peek(priv->adapter, priv->nal_length_size);
3060 for (i = 0; i < priv->nal_length_size; i++)
3061 nalu_size = (nalu_size << 8) | buf[i];
3063 buf_size = priv->nal_length_size + nalu_size;
3064 if (size < buf_size)
3066 buffer = gst_adapter_take_buffer(priv->adapter, buf_size);
3069 buf = GST_BUFFER_DATA(buffer);
3070 buf_size = GST_BUFFER_SIZE(buffer);
3072 result = gst_h264_parser_identify_nalu_avc(
3074 buf, 0, buf_size, priv->nal_length_size,
3081 ofs = scan_for_start_code(priv->adapter, 0, size, &start_code);
3084 gst_adapter_flush(priv->adapter, ofs);
3087 ofs = G_UNLIKELY(size < 8) ? -1 :
3088 scan_for_start_code(priv->adapter, 4, size - 4, NULL);
3090 // Assume the whole NAL unit is present if end-of-stream
3095 buffer = gst_adapter_take_buffer(priv->adapter, ofs);
3098 buf = GST_BUFFER_DATA(buffer);
3099 buf_size = GST_BUFFER_SIZE(buffer);
3101 result = gst_h264_parser_identify_nalu_unchecked(
3107 status = get_status(result);
3108 if (status == GST_VAAPI_DECODER_STATUS_SUCCESS)
3109 status = decode_nalu(decoder, &nalu);
3110 gst_buffer_unref(buffer);
3111 } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
3113 if (is_eos && (status == GST_VAAPI_DECODER_STATUS_SUCCESS ||
3114 status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA))
3115 status = decode_sequence_end(decoder);
3119 static GstVaapiDecoderStatus
3120 decode_codec_data(GstVaapiDecoderH264 *decoder, GstBuffer *buffer)
3122 GstVaapiDecoderH264Private * const priv = decoder->priv;
3123 GstVaapiDecoderStatus status;
3124 GstH264NalUnit nalu;
3125 GstH264ParserResult result;
3128 guint i, ofs, num_sps, num_pps;
3130 buf = GST_BUFFER_DATA(buffer);
3131 buf_size = GST_BUFFER_SIZE(buffer);
3132 if (!buf || buf_size == 0)
3133 return GST_VAAPI_DECODER_STATUS_SUCCESS;
3136 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3139 GST_ERROR("failed to decode codec-data, not in avcC format");
3140 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
3143 priv->nal_length_size = (buf[4] & 0x03) + 1;
3145 num_sps = buf[5] & 0x1f;
3148 for (i = 0; i < num_sps; i++) {
3149 result = gst_h264_parser_identify_nalu_avc(
3151 buf, ofs, buf_size, 2,
3154 if (result != GST_H264_PARSER_OK)
3155 return get_status(result);
3157 status = decode_sps(decoder, &nalu);
3158 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3160 ofs = nalu.offset + nalu.size;
3166 for (i = 0; i < num_pps; i++) {
3167 result = gst_h264_parser_identify_nalu_avc(
3169 buf, ofs, buf_size, 2,
3172 if (result != GST_H264_PARSER_OK)
3173 return get_status(result);
3175 status = decode_pps(decoder, &nalu);
3176 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3178 ofs = nalu.offset + nalu.size;
3181 priv->is_avc = TRUE;
3185 GstVaapiDecoderStatus
3186 gst_vaapi_decoder_h264_decode(GstVaapiDecoder *base, GstBuffer *buffer)
3188 GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(base);
3189 GstVaapiDecoderH264Private * const priv = decoder->priv;
3190 GstVaapiDecoderStatus status;
3191 GstBuffer *codec_data;
3193 g_return_val_if_fail(priv->is_constructed,
3194 GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
3196 if (!priv->is_opened) {
3197 priv->is_opened = gst_vaapi_decoder_h264_open(decoder, buffer);
3198 if (!priv->is_opened)
3199 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
3201 codec_data = GST_VAAPI_DECODER_CODEC_DATA(decoder);
3203 status = decode_codec_data(decoder, codec_data);
3204 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3208 return decode_buffer(decoder, buffer);
3212 gst_vaapi_decoder_h264_finalize(GObject *object)
3214 GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(object);
3216 gst_vaapi_decoder_h264_destroy(decoder);
3218 G_OBJECT_CLASS(gst_vaapi_decoder_h264_parent_class)->finalize(object);
3222 gst_vaapi_decoder_h264_constructed(GObject *object)
3224 GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(object);
3225 GstVaapiDecoderH264Private * const priv = decoder->priv;
3226 GObjectClass *parent_class;
3228 parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_h264_parent_class);
3229 if (parent_class->constructed)
3230 parent_class->constructed(object);
3232 priv->is_constructed = gst_vaapi_decoder_h264_create(decoder);
3236 gst_vaapi_decoder_h264_class_init(GstVaapiDecoderH264Class *klass)
3238 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
3239 GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
3241 g_type_class_add_private(klass, sizeof(GstVaapiDecoderH264Private));
3243 object_class->finalize = gst_vaapi_decoder_h264_finalize;
3244 object_class->constructed = gst_vaapi_decoder_h264_constructed;
3246 decoder_class->decode = gst_vaapi_decoder_h264_decode;
3247 decoder_class->clear_buffer = gst_vaapi_decoder_h264_clear_buffer;
3251 gst_vaapi_decoder_h264_init(GstVaapiDecoderH264 *decoder)
3253 GstVaapiDecoderH264Private *priv;
3255 priv = GST_VAAPI_DECODER_H264_GET_PRIVATE(decoder);
3256 decoder->priv = priv;
3257 priv->parser = NULL;
3258 priv->current_picture = NULL;
3259 priv->dpb_count = 0;
3261 priv->profile = GST_VAAPI_PROFILE_UNKNOWN;
3262 priv->entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
3263 priv->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
3264 priv->short_ref_count = 0;
3265 priv->long_ref_count = 0;
3266 priv->RefPicList0_count = 0;
3267 priv->RefPicList1_count = 0;
3268 priv->nal_length_size = 0;
3269 priv->adapter = NULL;
3270 priv->field_poc[0] = 0;
3271 priv->field_poc[1] = 0;
3274 priv->prev_poc_msb = 0;
3275 priv->prev_poc_lsb = 0;
3276 priv->frame_num_offset = 0;
3277 priv->frame_num = 0;
3278 priv->prev_frame_num = 0;
3279 priv->prev_pic_has_mmco5 = FALSE;
3280 priv->prev_pic_structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
3281 priv->is_constructed = FALSE;
3282 priv->is_opened = FALSE;
3283 priv->is_avc = FALSE;
3284 priv->has_context = FALSE;
3285 priv->progressive_sequence = TRUE;
3287 memset(priv->dpb, 0, sizeof(priv->dpb));
3288 memset(priv->short_ref, 0, sizeof(priv->short_ref));
3289 memset(priv->long_ref, 0, sizeof(priv->long_ref));
3290 memset(priv->RefPicList0, 0, sizeof(priv->RefPicList0));
3291 memset(priv->RefPicList1, 0, sizeof(priv->RefPicList1));
3295 * gst_vaapi_decoder_h264_new:
3296 * @display: a #GstVaapiDisplay
3297 * @caps: a #GstCaps holding codec information
3299 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
3300 * hold extra information like codec-data and pictured coded size.
3302 * Return value: the newly allocated #GstVaapiDecoder object
3305 gst_vaapi_decoder_h264_new(GstVaapiDisplay *display, GstCaps *caps)
3307 GstVaapiDecoderH264 *decoder;
3309 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
3310 g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
3312 decoder = g_object_new(
3313 GST_VAAPI_TYPE_DECODER_H264,
3318 if (!decoder->priv->is_constructed) {
3319 g_object_unref(decoder);
3322 return GST_VAAPI_DECODER_CAST(decoder);