2 * gstvaapidecoder_h264.c - H.264 decoder
4 * Copyright (C) 2011-2014 Intel Corporation
5 * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1
10 * of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA
24 * SECTION:gstvaapidecoder_h264
25 * @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"
37 #include "gstvaapiutils_h264_priv.h"
40 #include "gstvaapidebug.h"
42 /* Defined to 1 if strict ordering of DPB is needed. Only useful for debug */
43 #define USE_STRICT_DPB_ORDERING 0
45 typedef struct _GstVaapiDecoderH264Private GstVaapiDecoderH264Private;
46 typedef struct _GstVaapiDecoderH264Class GstVaapiDecoderH264Class;
47 typedef struct _GstVaapiFrameStore GstVaapiFrameStore;
48 typedef struct _GstVaapiFrameStoreClass GstVaapiFrameStoreClass;
49 typedef struct _GstVaapiParserInfoH264 GstVaapiParserInfoH264;
50 typedef struct _GstVaapiPictureH264 GstVaapiPictureH264;
52 // Used for field_poc[]
54 #define BOTTOM_FIELD 1
56 /* ------------------------------------------------------------------------- */
57 /* --- H.264 Parser Info --- */
58 /* ------------------------------------------------------------------------- */
60 #define GST_VAAPI_PARSER_INFO_H264(obj) \
61 ((GstVaapiParserInfoH264 *)(obj))
63 struct _GstVaapiParserInfoH264 {
64 GstVaapiMiniObject parent_instance;
70 GstH264SliceHdr slice_hdr;
76 gst_vaapi_parser_info_h264_finalize(GstVaapiParserInfoH264 *pi)
78 switch (pi->nalu.type) {
79 case GST_H264_NAL_SEI:
81 g_array_unref(pi->data.sei);
88 static inline const GstVaapiMiniObjectClass *
89 gst_vaapi_parser_info_h264_class(void)
91 static const GstVaapiMiniObjectClass GstVaapiParserInfoH264Class = {
92 .size = sizeof(GstVaapiParserInfoH264),
93 .finalize = (GDestroyNotify)gst_vaapi_parser_info_h264_finalize
95 return &GstVaapiParserInfoH264Class;
98 static inline GstVaapiParserInfoH264 *
99 gst_vaapi_parser_info_h264_new(void)
101 return (GstVaapiParserInfoH264 *)
102 gst_vaapi_mini_object_new(gst_vaapi_parser_info_h264_class());
105 #define gst_vaapi_parser_info_h264_ref(pi) \
106 gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(pi))
108 #define gst_vaapi_parser_info_h264_unref(pi) \
109 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(pi))
111 #define gst_vaapi_parser_info_h264_replace(old_pi_ptr, new_pi) \
112 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_pi_ptr), \
113 (GstVaapiMiniObject *)(new_pi))
115 /* ------------------------------------------------------------------------- */
116 /* --- H.264 Pictures --- */
117 /* ------------------------------------------------------------------------- */
120 * Extended picture flags:
122 * @GST_VAAPI_PICTURE_FLAG_IDR: flag that specifies an IDR picture
123 * @GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE: flag that specifies
124 * "used for short-term reference"
125 * @GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE: flag that specifies
126 * "used for long-term reference"
127 * @GST_VAAPI_PICTURE_FLAGS_REFERENCE: mask covering any kind of
128 * reference picture (short-term reference or long-term reference)
131 GST_VAAPI_PICTURE_FLAG_IDR = (GST_VAAPI_PICTURE_FLAG_LAST << 0),
133 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE = (
134 GST_VAAPI_PICTURE_FLAG_REFERENCE),
135 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE = (
136 GST_VAAPI_PICTURE_FLAG_REFERENCE | (GST_VAAPI_PICTURE_FLAG_LAST << 1)),
137 GST_VAAPI_PICTURE_FLAGS_REFERENCE = (
138 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
139 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE),
142 #define GST_VAAPI_PICTURE_IS_IDR(picture) \
143 (GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_IDR))
145 #define GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture) \
146 ((GST_VAAPI_PICTURE_FLAGS(picture) & \
147 GST_VAAPI_PICTURE_FLAGS_REFERENCE) == \
148 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE)
150 #define GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture) \
151 ((GST_VAAPI_PICTURE_FLAGS(picture) & \
152 GST_VAAPI_PICTURE_FLAGS_REFERENCE) == \
153 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE)
155 struct _GstVaapiPictureH264 {
156 GstVaapiPicture base;
157 GstH264SliceHdr *last_slice_hdr;
160 gint32 frame_num; // Original frame_num from slice_header()
161 gint32 frame_num_wrap; // Temporary for ref pic marking: FrameNumWrap
162 gint32 long_term_frame_idx; // Temporary for ref pic marking: LongTermFrameIdx
163 gint32 pic_num; // Temporary for ref pic marking: PicNum
164 gint32 long_term_pic_num; // Temporary for ref pic marking: LongTermPicNum
165 GstVaapiPictureH264 *other_field; // Temporary for ref pic marking: other field in the same frame store
166 guint output_flag : 1;
167 guint output_needed : 1;
170 GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiPictureH264, gst_vaapi_picture_h264);
173 gst_vaapi_picture_h264_destroy(GstVaapiPictureH264 *picture)
175 gst_vaapi_picture_destroy(GST_VAAPI_PICTURE(picture));
179 gst_vaapi_picture_h264_create(
180 GstVaapiPictureH264 *picture,
181 const GstVaapiCodecObjectConstructorArgs *args
184 if (!gst_vaapi_picture_create(GST_VAAPI_PICTURE(picture), args))
187 picture->field_poc[0] = G_MAXINT32;
188 picture->field_poc[1] = G_MAXINT32;
189 picture->output_needed = FALSE;
193 static inline GstVaapiPictureH264 *
194 gst_vaapi_picture_h264_new(GstVaapiDecoderH264 *decoder)
196 return (GstVaapiPictureH264 *)gst_vaapi_codec_object_new(
197 &GstVaapiPictureH264Class,
198 GST_VAAPI_CODEC_BASE(decoder),
199 NULL, sizeof(VAPictureParameterBufferH264),
205 gst_vaapi_picture_h264_set_reference(
206 GstVaapiPictureH264 *picture,
207 guint reference_flags,
213 GST_VAAPI_PICTURE_FLAG_UNSET(picture, GST_VAAPI_PICTURE_FLAGS_REFERENCE);
214 GST_VAAPI_PICTURE_FLAG_SET(picture, reference_flags);
216 if (!other_field || !(picture = picture->other_field))
218 GST_VAAPI_PICTURE_FLAG_UNSET(picture, GST_VAAPI_PICTURE_FLAGS_REFERENCE);
219 GST_VAAPI_PICTURE_FLAG_SET(picture, reference_flags);
222 static inline GstVaapiPictureH264 *
223 gst_vaapi_picture_h264_new_field(GstVaapiPictureH264 *picture)
225 g_return_val_if_fail(picture, NULL);
227 return (GstVaapiPictureH264 *)gst_vaapi_picture_new_field(&picture->base);
230 /* ------------------------------------------------------------------------- */
231 /* --- Frame Buffers (DPB) --- */
232 /* ------------------------------------------------------------------------- */
234 struct _GstVaapiFrameStore {
236 GstVaapiMiniObject parent_instance;
239 GstVaapiPictureH264 *buffers[2];
245 gst_vaapi_frame_store_finalize(gpointer object)
247 GstVaapiFrameStore * const fs = object;
250 for (i = 0; i < fs->num_buffers; i++)
251 gst_vaapi_picture_replace(&fs->buffers[i], NULL);
254 static GstVaapiFrameStore *
255 gst_vaapi_frame_store_new(GstVaapiPictureH264 *picture)
257 GstVaapiFrameStore *fs;
259 static const GstVaapiMiniObjectClass GstVaapiFrameStoreClass = {
260 sizeof(GstVaapiFrameStore),
261 gst_vaapi_frame_store_finalize
264 fs = (GstVaapiFrameStore *)
265 gst_vaapi_mini_object_new(&GstVaapiFrameStoreClass);
269 fs->structure = picture->structure;
270 fs->buffers[0] = gst_vaapi_picture_ref(picture);
271 fs->buffers[1] = NULL;
273 fs->output_needed = picture->output_needed;
278 gst_vaapi_frame_store_add(GstVaapiFrameStore *fs, GstVaapiPictureH264 *picture)
282 g_return_val_if_fail(fs->num_buffers == 1, FALSE);
283 g_return_val_if_fail(!GST_VAAPI_PICTURE_IS_FRAME(picture), FALSE);
284 g_return_val_if_fail(!GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture), FALSE);
286 gst_vaapi_picture_replace(&fs->buffers[fs->num_buffers++], picture);
287 if (picture->output_flag) {
288 picture->output_needed = TRUE;
292 fs->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
294 field = picture->structure == GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD ?
295 TOP_FIELD : BOTTOM_FIELD;
296 g_return_val_if_fail(fs->buffers[0]->field_poc[field] == G_MAXINT32, FALSE);
297 fs->buffers[0]->field_poc[field] = picture->field_poc[field];
298 g_return_val_if_fail(picture->field_poc[!field] == G_MAXINT32, FALSE);
299 picture->field_poc[!field] = fs->buffers[0]->field_poc[!field];
304 gst_vaapi_frame_store_split_fields(GstVaapiFrameStore *fs)
306 GstVaapiPictureH264 * const first_field = fs->buffers[0];
307 GstVaapiPictureH264 *second_field;
309 g_return_val_if_fail(fs->num_buffers == 1, FALSE);
311 first_field->base.structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
312 GST_VAAPI_PICTURE_FLAG_SET(first_field, GST_VAAPI_PICTURE_FLAG_INTERLACED);
314 second_field = gst_vaapi_picture_h264_new_field(first_field);
317 gst_vaapi_picture_replace(&fs->buffers[fs->num_buffers++], second_field);
318 gst_vaapi_picture_unref(second_field);
320 second_field->frame_num = first_field->frame_num;
321 second_field->field_poc[0] = first_field->field_poc[0];
322 second_field->field_poc[1] = first_field->field_poc[1];
323 second_field->output_flag = first_field->output_flag;
324 if (second_field->output_flag) {
325 second_field->output_needed = TRUE;
331 static inline gboolean
332 gst_vaapi_frame_store_has_frame(GstVaapiFrameStore *fs)
334 return fs->structure == GST_VAAPI_PICTURE_STRUCTURE_FRAME;
337 static inline gboolean
338 gst_vaapi_frame_store_has_reference(GstVaapiFrameStore *fs)
342 for (i = 0; i < fs->num_buffers; i++) {
343 if (GST_VAAPI_PICTURE_IS_REFERENCE(fs->buffers[i]))
349 #define gst_vaapi_frame_store_ref(fs) \
350 gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(fs))
352 #define gst_vaapi_frame_store_unref(fs) \
353 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(fs))
355 #define gst_vaapi_frame_store_replace(old_fs_p, new_fs) \
356 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_fs_p), \
357 (GstVaapiMiniObject *)(new_fs))
359 /* ------------------------------------------------------------------------- */
360 /* --- H.264 Decoder --- */
361 /* ------------------------------------------------------------------------- */
363 #define GST_VAAPI_DECODER_H264_CAST(decoder) \
364 ((GstVaapiDecoderH264 *)(decoder))
367 GST_H264_VIDEO_STATE_GOT_SPS = 1 << 0,
368 GST_H264_VIDEO_STATE_GOT_PPS = 1 << 1,
369 GST_H264_VIDEO_STATE_GOT_SLICE = 1 << 2,
371 GST_H264_VIDEO_STATE_VALID_PICTURE_HEADERS = (
372 GST_H264_VIDEO_STATE_GOT_SPS |
373 GST_H264_VIDEO_STATE_GOT_PPS),
374 GST_H264_VIDEO_STATE_VALID_PICTURE = (
375 GST_H264_VIDEO_STATE_VALID_PICTURE_HEADERS |
376 GST_H264_VIDEO_STATE_GOT_SLICE)
379 struct _GstVaapiDecoderH264Private {
380 GstH264NalParser *parser;
383 GstVaapiPictureH264 *current_picture;
384 GstVaapiParserInfoH264 *sps[GST_H264_MAX_SPS_COUNT];
385 GstVaapiParserInfoH264 *active_sps;
386 GstVaapiParserInfoH264 *pps[GST_H264_MAX_PPS_COUNT];
387 GstVaapiParserInfoH264 *active_pps;
388 GstVaapiParserInfoH264 *prev_slice_pi;
389 GstVaapiFrameStore *prev_frame;
390 GstVaapiFrameStore *dpb[16];
393 GstVaapiProfile profile;
394 GstVaapiEntrypoint entrypoint;
395 GstVaapiChromaType chroma_type;
396 GstVaapiPictureH264 *short_ref[32];
397 guint short_ref_count;
398 GstVaapiPictureH264 *long_ref[32];
399 guint long_ref_count;
400 GstVaapiPictureH264 *RefPicList0[32];
401 guint RefPicList0_count;
402 GstVaapiPictureH264 *RefPicList1[32];
403 guint RefPicList1_count;
404 guint nal_length_size;
407 gint32 field_poc[2]; // 0:TopFieldOrderCnt / 1:BottomFieldOrderCnt
408 gint32 poc_msb; // PicOrderCntMsb
409 gint32 poc_lsb; // pic_order_cnt_lsb (from slice_header())
410 gint32 prev_poc_msb; // prevPicOrderCntMsb
411 gint32 prev_poc_lsb; // prevPicOrderCntLsb
412 gint32 frame_num_offset; // FrameNumOffset
413 gint32 frame_num; // frame_num (from slice_header())
414 gint32 prev_frame_num; // prevFrameNum
415 gboolean prev_pic_has_mmco5; // prevMmco5Pic
416 gboolean prev_pic_structure; // previous picture structure
419 guint has_context : 1;
420 guint progressive_sequence : 1;
424 * GstVaapiDecoderH264:
426 * A decoder based on H264.
428 struct _GstVaapiDecoderH264 {
430 GstVaapiDecoder parent_instance;
431 GstVaapiDecoderH264Private priv;
435 * GstVaapiDecoderH264Class:
437 * A decoder class based on H264.
439 struct _GstVaapiDecoderH264Class {
441 GstVaapiDecoderClass parent_class;
445 exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture);
447 /* Get number of reference frames to use */
449 get_max_dec_frame_buffering(GstH264SPS *sps)
451 guint max_dec_frame_buffering, PicSizeMbs;
452 GstVaapiLevelH264 level;
453 const GstVaapiH264LevelLimits *level_limits;
455 /* Table A-1 - Level limits */
456 if (G_UNLIKELY(sps->level_idc == 11 && sps->constraint_set3_flag))
457 level = GST_VAAPI_LEVEL_H264_L1b;
459 level = gst_vaapi_utils_h264_get_level(sps->level_idc);
460 level_limits = gst_vaapi_utils_h264_get_level_limits(level);
464 PicSizeMbs = ((sps->pic_width_in_mbs_minus1 + 1) *
465 (sps->pic_height_in_map_units_minus1 + 1) *
466 (sps->frame_mbs_only_flag ? 1 : 2));
467 max_dec_frame_buffering = level_limits->MaxDpbMbs / PicSizeMbs;
470 if (sps->vui_parameters_present_flag) {
471 GstH264VUIParams * const vui_params = &sps->vui_parameters;
472 if (vui_params->bitstream_restriction_flag)
473 max_dec_frame_buffering = vui_params->max_dec_frame_buffering;
475 switch (sps->profile_idc) {
476 case 44: // CAVLC 4:4:4 Intra profile
477 case GST_H264_PROFILE_SCALABLE_HIGH:
478 case GST_H264_PROFILE_HIGH:
479 case GST_H264_PROFILE_HIGH10:
480 case GST_H264_PROFILE_HIGH_422:
481 case GST_H264_PROFILE_HIGH_444:
482 if (sps->constraint_set3_flag)
483 max_dec_frame_buffering = 0;
489 if (max_dec_frame_buffering > 16)
490 max_dec_frame_buffering = 16;
491 else if (max_dec_frame_buffering < sps->num_ref_frames)
492 max_dec_frame_buffering = sps->num_ref_frames;
493 return MAX(1, max_dec_frame_buffering);
497 array_remove_index_fast(void *array, guint *array_length_ptr, guint index)
499 gpointer * const entries = array;
500 guint num_entries = *array_length_ptr;
502 g_return_if_fail(index < num_entries);
504 if (index != --num_entries)
505 entries[index] = entries[num_entries];
506 entries[num_entries] = NULL;
507 *array_length_ptr = num_entries;
512 array_remove_index(void *array, guint *array_length_ptr, guint index)
514 array_remove_index_fast(array, array_length_ptr, index);
518 array_remove_index(void *array, guint *array_length_ptr, guint index)
520 gpointer * const entries = array;
521 const guint num_entries = *array_length_ptr - 1;
524 g_return_if_fail(index <= num_entries);
526 for (i = index; i < num_entries; i++)
527 entries[i] = entries[i + 1];
528 entries[num_entries] = NULL;
529 *array_length_ptr = num_entries;
533 #define ARRAY_REMOVE_INDEX(array, index) \
534 array_remove_index(array, &array##_count, index)
537 dpb_remove_index(GstVaapiDecoderH264 *decoder, guint index)
539 GstVaapiDecoderH264Private * const priv = &decoder->priv;
540 guint i, num_frames = --priv->dpb_count;
542 if (USE_STRICT_DPB_ORDERING) {
543 for (i = index; i < num_frames; i++)
544 gst_vaapi_frame_store_replace(&priv->dpb[i], priv->dpb[i + 1]);
546 else if (index != num_frames)
547 gst_vaapi_frame_store_replace(&priv->dpb[index], priv->dpb[num_frames]);
548 gst_vaapi_frame_store_replace(&priv->dpb[num_frames], NULL);
553 GstVaapiDecoderH264 *decoder,
554 GstVaapiFrameStore *fs,
555 GstVaapiPictureH264 *picture
558 picture->output_needed = FALSE;
561 if (--fs->output_needed > 0)
563 picture = fs->buffers[0];
565 return gst_vaapi_picture_output(GST_VAAPI_PICTURE_CAST(picture));
569 dpb_evict(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture, guint i)
571 GstVaapiDecoderH264Private * const priv = &decoder->priv;
572 GstVaapiFrameStore * const fs = priv->dpb[i];
574 if (!fs->output_needed && !gst_vaapi_frame_store_has_reference(fs))
575 dpb_remove_index(decoder, i);
579 dpb_bump(GstVaapiDecoderH264 *decoder)
581 GstVaapiDecoderH264Private * const priv = &decoder->priv;
582 GstVaapiPictureH264 *found_picture = NULL;
583 guint i, j, found_index;
586 for (i = 0; i < priv->dpb_count; i++) {
587 GstVaapiFrameStore * const fs = priv->dpb[i];
588 if (!fs->output_needed)
590 for (j = 0; j < fs->num_buffers; j++) {
591 GstVaapiPictureH264 * const picture = fs->buffers[j];
592 if (!picture->output_needed)
594 if (!found_picture || found_picture->base.poc > picture->base.poc)
595 found_picture = picture, found_index = i;
601 success = dpb_output(decoder, priv->dpb[found_index], found_picture);
602 dpb_evict(decoder, found_picture, found_index);
607 dpb_clear(GstVaapiDecoderH264 *decoder)
609 GstVaapiDecoderH264Private * const priv = &decoder->priv;
612 for (i = 0; i < priv->dpb_count; i++)
613 gst_vaapi_frame_store_replace(&priv->dpb[i], NULL);
616 gst_vaapi_frame_store_replace(&priv->prev_frame, NULL);
620 dpb_flush(GstVaapiDecoderH264 *decoder)
622 while (dpb_bump(decoder))
628 dpb_add(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
630 GstVaapiDecoderH264Private * const priv = &decoder->priv;
631 GstVaapiFrameStore *fs;
634 // Remove all unused pictures
635 if (!GST_VAAPI_PICTURE_IS_IDR(picture)) {
637 while (i < priv->dpb_count) {
638 GstVaapiFrameStore * const fs = priv->dpb[i];
639 if (!fs->output_needed && !gst_vaapi_frame_store_has_reference(fs))
640 dpb_remove_index(decoder, i);
646 // Check if picture is the second field and the first field is still in DPB
647 fs = priv->prev_frame;
648 if (fs && !gst_vaapi_frame_store_has_frame(fs))
649 return gst_vaapi_frame_store_add(fs, picture);
651 // Create new frame store, and split fields if necessary
652 fs = gst_vaapi_frame_store_new(picture);
655 gst_vaapi_frame_store_replace(&priv->prev_frame, fs);
656 gst_vaapi_frame_store_unref(fs);
658 if (!priv->progressive_sequence && gst_vaapi_frame_store_has_frame(fs)) {
659 if (!gst_vaapi_frame_store_split_fields(fs))
663 // C.4.5.1 - Storage and marking of a reference decoded picture into the DPB
664 if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
665 while (priv->dpb_count == priv->dpb_size) {
666 if (!dpb_bump(decoder))
669 gst_vaapi_frame_store_replace(&priv->dpb[priv->dpb_count++], fs);
670 if (picture->output_flag) {
671 picture->output_needed = TRUE;
676 // C.4.5.2 - Storage and marking of a non-reference decoded picture into the DPB
678 if (!picture->output_flag)
680 while (priv->dpb_count == priv->dpb_size) {
681 gboolean found_picture = FALSE;
682 for (i = 0; !found_picture && i < priv->dpb_count; i++) {
683 GstVaapiFrameStore * const fs = priv->dpb[i];
684 if (!fs->output_needed)
686 for (j = 0; !found_picture && j < fs->num_buffers; j++)
687 found_picture = fs->buffers[j]->output_needed &&
688 fs->buffers[j]->base.poc < picture->base.poc;
691 return dpb_output(decoder, NULL, picture);
692 if (!dpb_bump(decoder))
695 gst_vaapi_frame_store_replace(&priv->dpb[priv->dpb_count++], fs);
696 picture->output_needed = TRUE;
703 dpb_reset(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
705 GstVaapiDecoderH264Private * const priv = &decoder->priv;
707 priv->dpb_size = get_max_dec_frame_buffering(sps);
708 GST_DEBUG("DPB size %u", priv->dpb_size);
711 static GstVaapiDecoderStatus
712 get_status(GstH264ParserResult result)
714 GstVaapiDecoderStatus status;
717 case GST_H264_PARSER_OK:
718 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
720 case GST_H264_PARSER_NO_NAL_END:
721 status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
723 case GST_H264_PARSER_ERROR:
724 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
727 status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
734 gst_vaapi_decoder_h264_close(GstVaapiDecoderH264 *decoder)
736 GstVaapiDecoderH264Private * const priv = &decoder->priv;
738 gst_vaapi_picture_replace(&priv->current_picture, NULL);
739 gst_vaapi_parser_info_h264_replace(&priv->prev_slice_pi, NULL);
744 gst_h264_nal_parser_free(priv->parser);
750 gst_vaapi_decoder_h264_open(GstVaapiDecoderH264 *decoder)
752 GstVaapiDecoderH264Private * const priv = &decoder->priv;
754 gst_vaapi_decoder_h264_close(decoder);
756 priv->parser = gst_h264_nal_parser_new();
763 gst_vaapi_decoder_h264_destroy(GstVaapiDecoder *base_decoder)
765 GstVaapiDecoderH264 * const decoder =
766 GST_VAAPI_DECODER_H264_CAST(base_decoder);
767 GstVaapiDecoderH264Private * const priv = &decoder->priv;
770 gst_vaapi_decoder_h264_close(decoder);
772 for (i = 0; i < G_N_ELEMENTS(priv->pps); i++)
773 gst_vaapi_parser_info_h264_replace(&priv->pps[i], NULL);
774 gst_vaapi_parser_info_h264_replace(&priv->active_pps, NULL);
776 for (i = 0; i < G_N_ELEMENTS(priv->sps); i++)
777 gst_vaapi_parser_info_h264_replace(&priv->sps[i], NULL);
778 gst_vaapi_parser_info_h264_replace(&priv->active_sps, NULL);
782 gst_vaapi_decoder_h264_create(GstVaapiDecoder *base_decoder)
784 GstVaapiDecoderH264 * const decoder =
785 GST_VAAPI_DECODER_H264_CAST(base_decoder);
786 GstVaapiDecoderH264Private * const priv = &decoder->priv;
788 priv->profile = GST_VAAPI_PROFILE_UNKNOWN;
789 priv->entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
790 priv->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
791 priv->prev_pic_structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
792 priv->progressive_sequence = TRUE;
796 /* Activates the supplied PPS */
798 ensure_pps(GstVaapiDecoderH264 *decoder, GstH264PPS *pps)
800 GstVaapiDecoderH264Private * const priv = &decoder->priv;
801 GstVaapiParserInfoH264 * const pi = priv->pps[pps->id];
803 gst_vaapi_parser_info_h264_replace(&priv->active_pps, pi);
804 return pi ? &pi->data.pps : NULL;
807 /* Returns the active PPS */
808 static inline GstH264PPS *
809 get_pps(GstVaapiDecoderH264 *decoder)
811 GstVaapiParserInfoH264 * const pi = decoder->priv.active_pps;
813 return pi ? &pi->data.pps : NULL;
816 /* Activate the supplied SPS */
818 ensure_sps(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
820 GstVaapiDecoderH264Private * const priv = &decoder->priv;
821 GstVaapiParserInfoH264 * const pi = priv->sps[sps->id];
823 gst_vaapi_parser_info_h264_replace(&priv->active_sps, pi);
824 return pi ? &pi->data.sps : NULL;
827 /* Returns the active SPS */
828 static inline GstH264SPS *
829 get_sps(GstVaapiDecoderH264 *decoder)
831 GstVaapiParserInfoH264 * const pi = decoder->priv.active_sps;
833 return pi ? &pi->data.sps : NULL;
837 fill_profiles(GstVaapiProfile profiles[16], guint *n_profiles_ptr,
838 GstVaapiProfile profile)
840 guint n_profiles = *n_profiles_ptr;
842 profiles[n_profiles++] = profile;
844 case GST_VAAPI_PROFILE_H264_MAIN:
845 profiles[n_profiles++] = GST_VAAPI_PROFILE_H264_HIGH;
850 *n_profiles_ptr = n_profiles;
853 static GstVaapiProfile
854 get_profile(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
856 GstVaapiDecoderH264Private * const priv = &decoder->priv;
857 GstVaapiDisplay * const display = GST_VAAPI_DECODER_DISPLAY(decoder);
858 GstVaapiProfile profile, profiles[4];
859 guint i, n_profiles = 0;
861 profile = gst_vaapi_utils_h264_get_profile(sps->profile_idc);
863 return GST_VAAPI_PROFILE_UNKNOWN;
865 fill_profiles(profiles, &n_profiles, profile);
867 case GST_VAAPI_PROFILE_H264_BASELINE:
868 if (sps->constraint_set1_flag) { // A.2.2 (main profile)
869 fill_profiles(profiles, &n_profiles,
870 GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE);
871 fill_profiles(profiles, &n_profiles,
872 GST_VAAPI_PROFILE_H264_MAIN);
875 case GST_VAAPI_PROFILE_H264_EXTENDED:
876 if (sps->constraint_set1_flag) { // A.2.2 (main profile)
877 fill_profiles(profiles, &n_profiles,
878 GST_VAAPI_PROFILE_H264_MAIN);
885 /* If the preferred profile (profiles[0]) matches one that we already
886 found, then just return it now instead of searching for it again */
887 if (profiles[0] == priv->profile)
888 return priv->profile;
890 for (i = 0; i < n_profiles; i++) {
891 if (gst_vaapi_display_has_decoder(display, profiles[i], priv->entrypoint))
894 return GST_VAAPI_PROFILE_UNKNOWN;
897 static GstVaapiDecoderStatus
898 ensure_context(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
900 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
901 GstVaapiDecoderH264Private * const priv = &decoder->priv;
902 GstVaapiContextInfo info;
903 GstVaapiProfile profile;
904 GstVaapiChromaType chroma_type;
905 gboolean reset_context = FALSE;
906 guint mb_width, mb_height;
908 profile = get_profile(decoder, sps);
910 GST_ERROR("unsupported profile_idc %u", sps->profile_idc);
911 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
914 if (priv->profile != profile) {
915 GST_DEBUG("profile changed");
916 reset_context = TRUE;
917 priv->profile = profile;
920 chroma_type = gst_vaapi_utils_h264_get_chroma_type(sps->chroma_format_idc);
922 GST_ERROR("unsupported chroma_format_idc %u", sps->chroma_format_idc);
923 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
926 if (priv->chroma_type != chroma_type) {
927 GST_DEBUG("chroma format changed");
928 reset_context = TRUE;
929 priv->chroma_type = chroma_type;
932 mb_width = sps->pic_width_in_mbs_minus1 + 1;
933 mb_height = (sps->pic_height_in_map_units_minus1 + 1) <<
934 !sps->frame_mbs_only_flag;
935 if (priv->mb_width != mb_width || priv->mb_height != mb_height) {
936 GST_DEBUG("size changed");
937 reset_context = TRUE;
938 priv->mb_width = mb_width;
939 priv->mb_height = mb_height;
942 priv->progressive_sequence = sps->frame_mbs_only_flag;
944 /* XXX: we only output complete frames for now */
945 gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
948 gst_vaapi_decoder_set_pixel_aspect_ratio(
950 sps->vui_parameters.par_n,
951 sps->vui_parameters.par_d
954 if (!reset_context && priv->has_context)
955 return GST_VAAPI_DECODER_STATUS_SUCCESS;
957 /* XXX: fix surface size when cropping is implemented */
958 info.profile = priv->profile;
959 info.entrypoint = priv->entrypoint;
960 info.chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
961 info.width = sps->width;
962 info.height = sps->height;
963 info.ref_frames = get_max_dec_frame_buffering(sps);
965 if (!gst_vaapi_decoder_ensure_context(GST_VAAPI_DECODER(decoder), &info))
966 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
967 priv->has_context = TRUE;
970 dpb_reset(decoder, sps);
971 return GST_VAAPI_DECODER_STATUS_SUCCESS;
975 fill_iq_matrix_4x4(VAIQMatrixBufferH264 *iq_matrix, const GstH264PPS *pps,
976 const GstH264SPS *sps)
980 /* There are always 6 4x4 scaling lists */
981 g_assert(G_N_ELEMENTS(iq_matrix->ScalingList4x4) == 6);
982 g_assert(G_N_ELEMENTS(iq_matrix->ScalingList4x4[0]) == 16);
984 for (i = 0; i < G_N_ELEMENTS(iq_matrix->ScalingList4x4); i++)
985 gst_h264_video_quant_matrix_4x4_get_raster_from_zigzag(
986 iq_matrix->ScalingList4x4[i], pps->scaling_lists_4x4[i]);
990 fill_iq_matrix_8x8(VAIQMatrixBufferH264 *iq_matrix, const GstH264PPS *pps,
991 const GstH264SPS *sps)
995 /* If chroma_format_idc != 3, there are up to 2 8x8 scaling lists */
996 if (!pps->transform_8x8_mode_flag)
999 g_assert(G_N_ELEMENTS(iq_matrix->ScalingList8x8) >= 2);
1000 g_assert(G_N_ELEMENTS(iq_matrix->ScalingList8x8[0]) == 64);
1002 n = (sps->chroma_format_idc != 3) ? 2 : 6;
1003 for (i = 0; i < n; i++) {
1004 gst_h264_video_quant_matrix_8x8_get_raster_from_zigzag(
1005 iq_matrix->ScalingList8x8[i], pps->scaling_lists_8x8[i]);
1009 static GstVaapiDecoderStatus
1010 ensure_quant_matrix(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
1012 GstVaapiPicture * const base_picture = &picture->base;
1013 GstH264PPS * const pps = get_pps(decoder);
1014 GstH264SPS * const sps = get_sps(decoder);
1015 VAIQMatrixBufferH264 *iq_matrix;
1017 base_picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(H264, decoder);
1018 if (!base_picture->iq_matrix) {
1019 GST_ERROR("failed to allocate IQ matrix");
1020 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1022 iq_matrix = base_picture->iq_matrix->param;
1024 /* XXX: we can only support 4:2:0 or 4:2:2 since ScalingLists8x8[]
1025 is not large enough to hold lists for 4:4:4 */
1026 if (sps->chroma_format_idc == 3)
1027 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
1029 fill_iq_matrix_4x4(iq_matrix, pps, sps);
1030 fill_iq_matrix_8x8(iq_matrix, pps, sps);
1032 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1035 static inline gboolean
1036 is_valid_state(guint state, guint ref_state)
1038 return (state & ref_state) == ref_state;
1041 static GstVaapiDecoderStatus
1042 decode_current_picture(GstVaapiDecoderH264 *decoder)
1044 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1045 GstVaapiPictureH264 * const picture = priv->current_picture;
1047 if (!is_valid_state(priv->decoder_state, GST_H264_VIDEO_STATE_VALID_PICTURE))
1049 priv->decoder_state = 0;
1052 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1054 if (!exec_ref_pic_marking(decoder, picture))
1056 if (!dpb_add(decoder, picture))
1058 if (!gst_vaapi_picture_decode(GST_VAAPI_PICTURE_CAST(picture)))
1060 if (priv->prev_frame && gst_vaapi_frame_store_has_frame(priv->prev_frame))
1061 gst_vaapi_picture_replace(&priv->current_picture, NULL);
1062 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1065 /* XXX: fix for cases where first field failed to be decoded */
1066 gst_vaapi_picture_replace(&priv->current_picture, NULL);
1067 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1070 priv->decoder_state = 0;
1071 return GST_VAAPI_DECODER_STATUS_DROP_FRAME;
1074 static GstVaapiDecoderStatus
1075 parse_sps(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
1077 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1078 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
1079 GstH264SPS * const sps = &pi->data.sps;
1080 GstH264ParserResult result;
1082 GST_DEBUG("parse SPS");
1084 priv->parser_state = 0;
1086 /* Variables that don't have inferred values per the H.264
1087 standard but that should get a default value anyway */
1088 sps->log2_max_pic_order_cnt_lsb_minus4 = 0;
1090 result = gst_h264_parser_parse_sps(priv->parser, &pi->nalu, sps, TRUE);
1091 if (result != GST_H264_PARSER_OK)
1092 return get_status(result);
1094 priv->parser_state |= GST_H264_VIDEO_STATE_GOT_SPS;
1095 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1098 static GstVaapiDecoderStatus
1099 parse_pps(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
1101 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1102 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
1103 GstH264PPS * const pps = &pi->data.pps;
1104 GstH264ParserResult result;
1106 GST_DEBUG("parse PPS");
1108 priv->parser_state &= GST_H264_VIDEO_STATE_GOT_SPS;
1110 /* Variables that don't have inferred values per the H.264
1111 standard but that should get a default value anyway */
1112 pps->slice_group_map_type = 0;
1113 pps->slice_group_change_rate_minus1 = 0;
1115 result = gst_h264_parser_parse_pps(priv->parser, &pi->nalu, pps);
1116 if (result != GST_H264_PARSER_OK)
1117 return get_status(result);
1119 priv->parser_state |= GST_H264_VIDEO_STATE_GOT_PPS;
1120 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1123 static GstVaapiDecoderStatus
1124 parse_sei(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
1126 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1127 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
1128 GArray ** const sei_ptr = &pi->data.sei;
1129 GstH264ParserResult result;
1131 GST_DEBUG("parse SEI");
1133 result = gst_h264_parser_parse_sei(priv->parser, &pi->nalu, sei_ptr);
1134 if (result != GST_H264_PARSER_OK) {
1135 GST_WARNING("failed to parse SEI messages");
1136 return get_status(result);
1138 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1141 static GstVaapiDecoderStatus
1142 parse_slice(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
1144 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1145 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
1146 GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
1147 GstH264ParserResult result;
1149 GST_DEBUG("parse slice");
1151 priv->parser_state &= (GST_H264_VIDEO_STATE_GOT_SPS|
1152 GST_H264_VIDEO_STATE_GOT_PPS);
1154 /* Variables that don't have inferred values per the H.264
1155 standard but that should get a default value anyway */
1156 slice_hdr->cabac_init_idc = 0;
1157 slice_hdr->direct_spatial_mv_pred_flag = 0;
1159 result = gst_h264_parser_parse_slice_hdr(priv->parser, &pi->nalu,
1160 slice_hdr, TRUE, TRUE);
1161 if (result != GST_H264_PARSER_OK)
1162 return get_status(result);
1164 priv->parser_state |= GST_H264_VIDEO_STATE_GOT_SLICE;
1165 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1168 static GstVaapiDecoderStatus
1169 decode_sps(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
1171 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1172 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
1173 GstH264SPS * const sps = &pi->data.sps;
1175 GST_DEBUG("decode SPS");
1177 gst_vaapi_parser_info_h264_replace(&priv->sps[sps->id], pi);
1178 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1181 static GstVaapiDecoderStatus
1182 decode_pps(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
1184 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1185 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
1186 GstH264PPS * const pps = &pi->data.pps;
1188 GST_DEBUG("decode PPS");
1190 gst_vaapi_parser_info_h264_replace(&priv->pps[pps->id], pi);
1191 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1194 static GstVaapiDecoderStatus
1195 decode_sequence_end(GstVaapiDecoderH264 *decoder)
1197 GstVaapiDecoderStatus status;
1199 GST_DEBUG("decode sequence-end");
1201 status = decode_current_picture(decoder);
1202 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1206 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1209 /* 8.2.1.1 - Decoding process for picture order count type 0 */
1212 GstVaapiDecoderH264 *decoder,
1213 GstVaapiPictureH264 *picture,
1214 GstH264SliceHdr *slice_hdr
1217 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1218 GstH264SPS * const sps = get_sps(decoder);
1219 const gint32 MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
1222 GST_DEBUG("decode picture order count type 0");
1224 if (GST_VAAPI_PICTURE_IS_IDR(picture)) {
1225 priv->prev_poc_msb = 0;
1226 priv->prev_poc_lsb = 0;
1228 else if (priv->prev_pic_has_mmco5) {
1229 priv->prev_poc_msb = 0;
1230 priv->prev_poc_lsb =
1231 (priv->prev_pic_structure == GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD ?
1232 0 : priv->field_poc[TOP_FIELD]);
1235 priv->prev_poc_msb = priv->poc_msb;
1236 priv->prev_poc_lsb = priv->poc_lsb;
1240 priv->poc_lsb = slice_hdr->pic_order_cnt_lsb;
1241 if (priv->poc_lsb < priv->prev_poc_lsb &&
1242 (priv->prev_poc_lsb - priv->poc_lsb) >= (MaxPicOrderCntLsb / 2))
1243 priv->poc_msb = priv->prev_poc_msb + MaxPicOrderCntLsb;
1244 else if (priv->poc_lsb > priv->prev_poc_lsb &&
1245 (priv->poc_lsb - priv->prev_poc_lsb) > (MaxPicOrderCntLsb / 2))
1246 priv->poc_msb = priv->prev_poc_msb - MaxPicOrderCntLsb;
1248 priv->poc_msb = priv->prev_poc_msb;
1250 temp_poc = priv->poc_msb + priv->poc_lsb;
1251 switch (picture->structure) {
1252 case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
1254 priv->field_poc[TOP_FIELD] = temp_poc;
1255 priv->field_poc[BOTTOM_FIELD] = temp_poc +
1256 slice_hdr->delta_pic_order_cnt_bottom;
1258 case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
1260 priv->field_poc[TOP_FIELD] = temp_poc;
1262 case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
1264 priv->field_poc[BOTTOM_FIELD] = temp_poc;
1269 /* 8.2.1.2 - Decoding process for picture order count type 1 */
1272 GstVaapiDecoderH264 *decoder,
1273 GstVaapiPictureH264 *picture,
1274 GstH264SliceHdr *slice_hdr
1277 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1278 GstH264SPS * const sps = get_sps(decoder);
1279 const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
1280 gint32 prev_frame_num_offset, abs_frame_num, expected_poc;
1283 GST_DEBUG("decode picture order count type 1");
1285 if (priv->prev_pic_has_mmco5)
1286 prev_frame_num_offset = 0;
1288 prev_frame_num_offset = priv->frame_num_offset;
1291 if (GST_VAAPI_PICTURE_IS_IDR(picture))
1292 priv->frame_num_offset = 0;
1293 else if (priv->prev_frame_num > priv->frame_num)
1294 priv->frame_num_offset = prev_frame_num_offset + MaxFrameNum;
1296 priv->frame_num_offset = prev_frame_num_offset;
1299 if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
1300 abs_frame_num = priv->frame_num_offset + priv->frame_num;
1303 if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture) && abs_frame_num > 0)
1304 abs_frame_num = abs_frame_num - 1;
1306 if (abs_frame_num > 0) {
1307 gint32 expected_delta_per_poc_cycle;
1308 gint32 poc_cycle_cnt, frame_num_in_poc_cycle;
1310 expected_delta_per_poc_cycle = 0;
1311 for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++)
1312 expected_delta_per_poc_cycle += sps->offset_for_ref_frame[i];
1315 poc_cycle_cnt = (abs_frame_num - 1) /
1316 sps->num_ref_frames_in_pic_order_cnt_cycle;
1317 frame_num_in_poc_cycle = (abs_frame_num - 1) %
1318 sps->num_ref_frames_in_pic_order_cnt_cycle;
1321 expected_poc = poc_cycle_cnt * expected_delta_per_poc_cycle;
1322 for (i = 0; i <= frame_num_in_poc_cycle; i++)
1323 expected_poc += sps->offset_for_ref_frame[i];
1327 if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
1328 expected_poc += sps->offset_for_non_ref_pic;
1331 switch (picture->structure) {
1332 case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
1333 priv->field_poc[TOP_FIELD] = expected_poc +
1334 slice_hdr->delta_pic_order_cnt[0];
1335 priv->field_poc[BOTTOM_FIELD] = priv->field_poc[TOP_FIELD] +
1336 sps->offset_for_top_to_bottom_field +
1337 slice_hdr->delta_pic_order_cnt[1];
1339 case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
1340 priv->field_poc[TOP_FIELD] = expected_poc +
1341 slice_hdr->delta_pic_order_cnt[0];
1343 case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
1344 priv->field_poc[BOTTOM_FIELD] = expected_poc +
1345 sps->offset_for_top_to_bottom_field +
1346 slice_hdr->delta_pic_order_cnt[0];
1351 /* 8.2.1.3 - Decoding process for picture order count type 2 */
1354 GstVaapiDecoderH264 *decoder,
1355 GstVaapiPictureH264 *picture,
1356 GstH264SliceHdr *slice_hdr
1359 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1360 GstH264SPS * const sps = get_sps(decoder);
1361 const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
1362 gint32 prev_frame_num_offset, temp_poc;
1364 GST_DEBUG("decode picture order count type 2");
1366 if (priv->prev_pic_has_mmco5)
1367 prev_frame_num_offset = 0;
1369 prev_frame_num_offset = priv->frame_num_offset;
1372 if (GST_VAAPI_PICTURE_IS_IDR(picture))
1373 priv->frame_num_offset = 0;
1374 else if (priv->prev_frame_num > priv->frame_num)
1375 priv->frame_num_offset = prev_frame_num_offset + MaxFrameNum;
1377 priv->frame_num_offset = prev_frame_num_offset;
1380 if (GST_VAAPI_PICTURE_IS_IDR(picture))
1382 else if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
1383 temp_poc = 2 * (priv->frame_num_offset + priv->frame_num) - 1;
1385 temp_poc = 2 * (priv->frame_num_offset + priv->frame_num);
1388 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
1389 priv->field_poc[TOP_FIELD] = temp_poc;
1390 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
1391 priv->field_poc[BOTTOM_FIELD] = temp_poc;
1394 /* 8.2.1 - Decoding process for picture order count */
1397 GstVaapiDecoderH264 *decoder,
1398 GstVaapiPictureH264 *picture,
1399 GstH264SliceHdr *slice_hdr
1402 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1403 GstH264SPS * const sps = get_sps(decoder);
1405 switch (sps->pic_order_cnt_type) {
1407 init_picture_poc_0(decoder, picture, slice_hdr);
1410 init_picture_poc_1(decoder, picture, slice_hdr);
1413 init_picture_poc_2(decoder, picture, slice_hdr);
1417 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
1418 picture->field_poc[TOP_FIELD] = priv->field_poc[TOP_FIELD];
1419 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
1420 picture->field_poc[BOTTOM_FIELD] = priv->field_poc[BOTTOM_FIELD];
1421 picture->base.poc = MIN(picture->field_poc[0], picture->field_poc[1]);
1425 compare_picture_pic_num_dec(const void *a, const void *b)
1427 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1428 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1430 return picB->pic_num - picA->pic_num;
1434 compare_picture_long_term_pic_num_inc(const void *a, const void *b)
1436 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1437 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1439 return picA->long_term_pic_num - picB->long_term_pic_num;
1443 compare_picture_poc_dec(const void *a, const void *b)
1445 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1446 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1448 return picB->base.poc - picA->base.poc;
1452 compare_picture_poc_inc(const void *a, const void *b)
1454 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1455 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1457 return picA->base.poc - picB->base.poc;
1461 compare_picture_frame_num_wrap_dec(const void *a, const void *b)
1463 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1464 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1466 return picB->frame_num_wrap - picA->frame_num_wrap;
1470 compare_picture_long_term_frame_idx_inc(const void *a, const void *b)
1472 const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1473 const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1475 return picA->long_term_frame_idx - picB->long_term_frame_idx;
1478 /* 8.2.4.1 - Decoding process for picture numbers */
1480 init_picture_refs_pic_num(
1481 GstVaapiDecoderH264 *decoder,
1482 GstVaapiPictureH264 *picture,
1483 GstH264SliceHdr *slice_hdr
1486 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1487 GstH264SPS * const sps = get_sps(decoder);
1488 const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
1491 GST_DEBUG("decode picture numbers");
1493 for (i = 0; i < priv->short_ref_count; i++) {
1494 GstVaapiPictureH264 * const pic = priv->short_ref[i];
1497 if (pic->frame_num > priv->frame_num)
1498 pic->frame_num_wrap = pic->frame_num - MaxFrameNum;
1500 pic->frame_num_wrap = pic->frame_num;
1502 // (8-28, 8-30, 8-31)
1503 if (GST_VAAPI_PICTURE_IS_FRAME(picture))
1504 pic->pic_num = pic->frame_num_wrap;
1506 if (pic->structure == picture->structure)
1507 pic->pic_num = 2 * pic->frame_num_wrap + 1;
1509 pic->pic_num = 2 * pic->frame_num_wrap;
1513 for (i = 0; i < priv->long_ref_count; i++) {
1514 GstVaapiPictureH264 * const pic = priv->long_ref[i];
1516 // (8-29, 8-32, 8-33)
1517 if (GST_VAAPI_PICTURE_IS_FRAME(picture))
1518 pic->long_term_pic_num = pic->long_term_frame_idx;
1520 if (pic->structure == picture->structure)
1521 pic->long_term_pic_num = 2 * pic->long_term_frame_idx + 1;
1523 pic->long_term_pic_num = 2 * pic->long_term_frame_idx;
1528 #define SORT_REF_LIST(list, n, compare_func) \
1529 qsort(list, n, sizeof(*(list)), compare_picture_##compare_func)
1532 init_picture_refs_fields_1(
1533 guint picture_structure,
1534 GstVaapiPictureH264 *RefPicList[32],
1535 guint *RefPicList_count,
1536 GstVaapiPictureH264 *ref_list[32],
1537 guint ref_list_count
1544 n = *RefPicList_count;
1547 for (; i < ref_list_count; i++) {
1548 if (ref_list[i]->structure == picture_structure) {
1549 RefPicList[n++] = ref_list[i++];
1553 for (; j < ref_list_count; j++) {
1554 if (ref_list[j]->structure != picture_structure) {
1555 RefPicList[n++] = ref_list[j++];
1559 } while (i < ref_list_count || j < ref_list_count);
1560 *RefPicList_count = n;
1564 init_picture_refs_fields(
1565 GstVaapiPictureH264 *picture,
1566 GstVaapiPictureH264 *RefPicList[32],
1567 guint *RefPicList_count,
1568 GstVaapiPictureH264 *short_ref[32],
1569 guint short_ref_count,
1570 GstVaapiPictureH264 *long_ref[32],
1571 guint long_ref_count
1576 /* 8.2.4.2.5 - reference picture lists in fields */
1577 init_picture_refs_fields_1(picture->structure, RefPicList, &n,
1578 short_ref, short_ref_count);
1579 init_picture_refs_fields_1(picture->structure, RefPicList, &n,
1580 long_ref, long_ref_count);
1581 *RefPicList_count = n;
1585 init_picture_refs_p_slice(
1586 GstVaapiDecoderH264 *decoder,
1587 GstVaapiPictureH264 *picture,
1588 GstH264SliceHdr *slice_hdr
1591 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1592 GstVaapiPictureH264 **ref_list;
1595 GST_DEBUG("decode reference picture list for P and SP slices");
1597 if (GST_VAAPI_PICTURE_IS_FRAME(picture)) {
1598 /* 8.2.4.2.1 - P and SP slices in frames */
1599 if (priv->short_ref_count > 0) {
1600 ref_list = priv->RefPicList0;
1601 for (i = 0; i < priv->short_ref_count; i++)
1602 ref_list[i] = priv->short_ref[i];
1603 SORT_REF_LIST(ref_list, i, pic_num_dec);
1604 priv->RefPicList0_count += i;
1607 if (priv->long_ref_count > 0) {
1608 ref_list = &priv->RefPicList0[priv->RefPicList0_count];
1609 for (i = 0; i < priv->long_ref_count; i++)
1610 ref_list[i] = priv->long_ref[i];
1611 SORT_REF_LIST(ref_list, i, long_term_pic_num_inc);
1612 priv->RefPicList0_count += i;
1616 /* 8.2.4.2.2 - P and SP slices in fields */
1617 GstVaapiPictureH264 *short_ref[32];
1618 guint short_ref_count = 0;
1619 GstVaapiPictureH264 *long_ref[32];
1620 guint long_ref_count = 0;
1622 if (priv->short_ref_count > 0) {
1623 for (i = 0; i < priv->short_ref_count; i++)
1624 short_ref[i] = priv->short_ref[i];
1625 SORT_REF_LIST(short_ref, i, frame_num_wrap_dec);
1626 short_ref_count = i;
1629 if (priv->long_ref_count > 0) {
1630 for (i = 0; i < priv->long_ref_count; i++)
1631 long_ref[i] = priv->long_ref[i];
1632 SORT_REF_LIST(long_ref, i, long_term_frame_idx_inc);
1636 init_picture_refs_fields(
1638 priv->RefPicList0, &priv->RefPicList0_count,
1639 short_ref, short_ref_count,
1640 long_ref, long_ref_count
1646 init_picture_refs_b_slice(
1647 GstVaapiDecoderH264 *decoder,
1648 GstVaapiPictureH264 *picture,
1649 GstH264SliceHdr *slice_hdr
1652 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1653 GstVaapiPictureH264 **ref_list;
1656 GST_DEBUG("decode reference picture list for B slices");
1658 if (GST_VAAPI_PICTURE_IS_FRAME(picture)) {
1659 /* 8.2.4.2.3 - B slices in frames */
1662 if (priv->short_ref_count > 0) {
1663 // 1. Short-term references
1664 ref_list = priv->RefPicList0;
1665 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1666 if (priv->short_ref[i]->base.poc < picture->base.poc)
1667 ref_list[n++] = priv->short_ref[i];
1669 SORT_REF_LIST(ref_list, n, poc_dec);
1670 priv->RefPicList0_count += n;
1672 ref_list = &priv->RefPicList0[priv->RefPicList0_count];
1673 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1674 if (priv->short_ref[i]->base.poc >= picture->base.poc)
1675 ref_list[n++] = priv->short_ref[i];
1677 SORT_REF_LIST(ref_list, n, poc_inc);
1678 priv->RefPicList0_count += n;
1681 if (priv->long_ref_count > 0) {
1682 // 2. Long-term references
1683 ref_list = &priv->RefPicList0[priv->RefPicList0_count];
1684 for (n = 0, i = 0; i < priv->long_ref_count; i++)
1685 ref_list[n++] = priv->long_ref[i];
1686 SORT_REF_LIST(ref_list, n, long_term_pic_num_inc);
1687 priv->RefPicList0_count += n;
1691 if (priv->short_ref_count > 0) {
1692 // 1. Short-term references
1693 ref_list = priv->RefPicList1;
1694 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1695 if (priv->short_ref[i]->base.poc > picture->base.poc)
1696 ref_list[n++] = priv->short_ref[i];
1698 SORT_REF_LIST(ref_list, n, poc_inc);
1699 priv->RefPicList1_count += n;
1701 ref_list = &priv->RefPicList1[priv->RefPicList1_count];
1702 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1703 if (priv->short_ref[i]->base.poc <= picture->base.poc)
1704 ref_list[n++] = priv->short_ref[i];
1706 SORT_REF_LIST(ref_list, n, poc_dec);
1707 priv->RefPicList1_count += n;
1710 if (priv->long_ref_count > 0) {
1711 // 2. Long-term references
1712 ref_list = &priv->RefPicList1[priv->RefPicList1_count];
1713 for (n = 0, i = 0; i < priv->long_ref_count; i++)
1714 ref_list[n++] = priv->long_ref[i];
1715 SORT_REF_LIST(ref_list, n, long_term_pic_num_inc);
1716 priv->RefPicList1_count += n;
1720 /* 8.2.4.2.4 - B slices in fields */
1721 GstVaapiPictureH264 *short_ref0[32];
1722 guint short_ref0_count = 0;
1723 GstVaapiPictureH264 *short_ref1[32];
1724 guint short_ref1_count = 0;
1725 GstVaapiPictureH264 *long_ref[32];
1726 guint long_ref_count = 0;
1728 /* refFrameList0ShortTerm */
1729 if (priv->short_ref_count > 0) {
1730 ref_list = short_ref0;
1731 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1732 if (priv->short_ref[i]->base.poc <= picture->base.poc)
1733 ref_list[n++] = priv->short_ref[i];
1735 SORT_REF_LIST(ref_list, n, poc_dec);
1736 short_ref0_count += n;
1738 ref_list = &short_ref0[short_ref0_count];
1739 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1740 if (priv->short_ref[i]->base.poc > picture->base.poc)
1741 ref_list[n++] = priv->short_ref[i];
1743 SORT_REF_LIST(ref_list, n, poc_inc);
1744 short_ref0_count += n;
1747 /* refFrameList1ShortTerm */
1748 if (priv->short_ref_count > 0) {
1749 ref_list = short_ref1;
1750 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1751 if (priv->short_ref[i]->base.poc > picture->base.poc)
1752 ref_list[n++] = priv->short_ref[i];
1754 SORT_REF_LIST(ref_list, n, poc_inc);
1755 short_ref1_count += n;
1757 ref_list = &short_ref1[short_ref1_count];
1758 for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1759 if (priv->short_ref[i]->base.poc <= picture->base.poc)
1760 ref_list[n++] = priv->short_ref[i];
1762 SORT_REF_LIST(ref_list, n, poc_dec);
1763 short_ref1_count += n;
1766 /* refFrameListLongTerm */
1767 if (priv->long_ref_count > 0) {
1768 for (i = 0; i < priv->long_ref_count; i++)
1769 long_ref[i] = priv->long_ref[i];
1770 SORT_REF_LIST(long_ref, i, long_term_frame_idx_inc);
1774 init_picture_refs_fields(
1776 priv->RefPicList0, &priv->RefPicList0_count,
1777 short_ref0, short_ref0_count,
1778 long_ref, long_ref_count
1781 init_picture_refs_fields(
1783 priv->RefPicList1, &priv->RefPicList1_count,
1784 short_ref1, short_ref1_count,
1785 long_ref, long_ref_count
1789 /* Check whether RefPicList1 is identical to RefPicList0, then
1790 swap if necessary */
1791 if (priv->RefPicList1_count > 1 &&
1792 priv->RefPicList1_count == priv->RefPicList0_count &&
1793 memcmp(priv->RefPicList0, priv->RefPicList1,
1794 priv->RefPicList0_count * sizeof(priv->RefPicList0[0])) == 0) {
1795 GstVaapiPictureH264 * const tmp = priv->RefPicList1[0];
1796 priv->RefPicList1[0] = priv->RefPicList1[1];
1797 priv->RefPicList1[1] = tmp;
1801 #undef SORT_REF_LIST
1804 find_short_term_reference(GstVaapiDecoderH264 *decoder, gint32 pic_num)
1806 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1809 for (i = 0; i < priv->short_ref_count; i++) {
1810 if (priv->short_ref[i]->pic_num == pic_num)
1813 GST_ERROR("found no short-term reference picture with PicNum = %d",
1819 find_long_term_reference(GstVaapiDecoderH264 *decoder, gint32 long_term_pic_num)
1821 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1824 for (i = 0; i < priv->long_ref_count; i++) {
1825 if (priv->long_ref[i]->long_term_pic_num == long_term_pic_num)
1828 GST_ERROR("found no long-term reference picture with LongTermPicNum = %d",
1834 exec_picture_refs_modification_1(
1835 GstVaapiDecoderH264 *decoder,
1836 GstVaapiPictureH264 *picture,
1837 GstH264SliceHdr *slice_hdr,
1841 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1842 GstH264SPS * const sps = get_sps(decoder);
1843 GstH264RefPicListModification *ref_pic_list_modification;
1844 guint num_ref_pic_list_modifications;
1845 GstVaapiPictureH264 **ref_list;
1846 guint *ref_list_count_ptr, ref_list_count, ref_list_idx = 0;
1847 guint i, j, n, num_refs;
1849 gint32 MaxPicNum, CurrPicNum, picNumPred;
1851 GST_DEBUG("modification process of reference picture list %u", list);
1854 ref_pic_list_modification = slice_hdr->ref_pic_list_modification_l0;
1855 num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_l0;
1856 ref_list = priv->RefPicList0;
1857 ref_list_count_ptr = &priv->RefPicList0_count;
1858 num_refs = slice_hdr->num_ref_idx_l0_active_minus1 + 1;
1861 ref_pic_list_modification = slice_hdr->ref_pic_list_modification_l1;
1862 num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_l1;
1863 ref_list = priv->RefPicList1;
1864 ref_list_count_ptr = &priv->RefPicList1_count;
1865 num_refs = slice_hdr->num_ref_idx_l1_active_minus1 + 1;
1867 ref_list_count = *ref_list_count_ptr;
1869 if (!GST_VAAPI_PICTURE_IS_FRAME(picture)) {
1870 MaxPicNum = 1 << (sps->log2_max_frame_num_minus4 + 5); // 2 * MaxFrameNum
1871 CurrPicNum = 2 * slice_hdr->frame_num + 1; // 2 * frame_num + 1
1874 MaxPicNum = 1 << (sps->log2_max_frame_num_minus4 + 4); // MaxFrameNum
1875 CurrPicNum = slice_hdr->frame_num; // frame_num
1878 picNumPred = CurrPicNum;
1880 for (i = 0; i < num_ref_pic_list_modifications; i++) {
1881 GstH264RefPicListModification * const l = &ref_pic_list_modification[i];
1882 if (l->modification_of_pic_nums_idc == 3)
1885 /* 8.2.4.3.1 - Short-term reference pictures */
1886 if (l->modification_of_pic_nums_idc == 0 || l->modification_of_pic_nums_idc == 1) {
1887 gint32 abs_diff_pic_num = l->value.abs_diff_pic_num_minus1 + 1;
1888 gint32 picNum, picNumNoWrap;
1891 if (l->modification_of_pic_nums_idc == 0) {
1892 picNumNoWrap = picNumPred - abs_diff_pic_num;
1893 if (picNumNoWrap < 0)
1894 picNumNoWrap += MaxPicNum;
1899 picNumNoWrap = picNumPred + abs_diff_pic_num;
1900 if (picNumNoWrap >= MaxPicNum)
1901 picNumNoWrap -= MaxPicNum;
1903 picNumPred = picNumNoWrap;
1906 picNum = picNumNoWrap;
1907 if (picNum > CurrPicNum)
1908 picNum -= MaxPicNum;
1911 for (j = num_refs; j > ref_list_idx; j--)
1912 ref_list[j] = ref_list[j - 1];
1913 found_ref_idx = find_short_term_reference(decoder, picNum);
1914 ref_list[ref_list_idx++] =
1915 found_ref_idx >= 0 ? priv->short_ref[found_ref_idx] : NULL;
1917 for (j = ref_list_idx; j <= num_refs; j++) {
1922 GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(ref_list[j]) ?
1923 ref_list[j]->pic_num : MaxPicNum;
1924 if (PicNumF != picNum)
1925 ref_list[n++] = ref_list[j];
1929 /* 8.2.4.3.2 - Long-term reference pictures */
1932 for (j = num_refs; j > ref_list_idx; j--)
1933 ref_list[j] = ref_list[j - 1];
1935 find_long_term_reference(decoder, l->value.long_term_pic_num);
1936 ref_list[ref_list_idx++] =
1937 found_ref_idx >= 0 ? priv->long_ref[found_ref_idx] : NULL;
1939 for (j = ref_list_idx; j <= num_refs; j++) {
1940 gint32 LongTermPicNumF;
1944 GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(ref_list[j]) ?
1945 ref_list[j]->long_term_pic_num : INT_MAX;
1946 if (LongTermPicNumF != l->value.long_term_pic_num)
1947 ref_list[n++] = ref_list[j];
1953 for (i = 0; i < num_refs; i++)
1955 GST_ERROR("list %u entry %u is empty", list, i);
1957 *ref_list_count_ptr = num_refs;
1960 /* 8.2.4.3 - Modification process for reference picture lists */
1962 exec_picture_refs_modification(
1963 GstVaapiDecoderH264 *decoder,
1964 GstVaapiPictureH264 *picture,
1965 GstH264SliceHdr *slice_hdr
1968 GST_DEBUG("execute ref_pic_list_modification()");
1971 if (!GST_H264_IS_I_SLICE(slice_hdr) && !GST_H264_IS_SI_SLICE(slice_hdr) &&
1972 slice_hdr->ref_pic_list_modification_flag_l0)
1973 exec_picture_refs_modification_1(decoder, picture, slice_hdr, 0);
1976 if (GST_H264_IS_B_SLICE(slice_hdr) &&
1977 slice_hdr->ref_pic_list_modification_flag_l1)
1978 exec_picture_refs_modification_1(decoder, picture, slice_hdr, 1);
1982 init_picture_ref_lists(GstVaapiDecoderH264 *decoder)
1984 GstVaapiDecoderH264Private * const priv = &decoder->priv;
1985 guint i, j, short_ref_count, long_ref_count;
1987 short_ref_count = 0;
1989 if (GST_VAAPI_PICTURE_IS_FRAME(priv->current_picture)) {
1990 for (i = 0; i < priv->dpb_count; i++) {
1991 GstVaapiFrameStore * const fs = priv->dpb[i];
1992 GstVaapiPictureH264 *picture;
1993 if (!gst_vaapi_frame_store_has_frame(fs))
1995 picture = fs->buffers[0];
1996 if (GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
1997 priv->short_ref[short_ref_count++] = picture;
1998 else if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture))
1999 priv->long_ref[long_ref_count++] = picture;
2000 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
2001 picture->other_field = fs->buffers[1];
2005 for (i = 0; i < priv->dpb_count; i++) {
2006 GstVaapiFrameStore * const fs = priv->dpb[i];
2007 for (j = 0; j < fs->num_buffers; j++) {
2008 GstVaapiPictureH264 * const picture = fs->buffers[j];
2009 if (GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
2010 priv->short_ref[short_ref_count++] = picture;
2011 else if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture))
2012 priv->long_ref[long_ref_count++] = picture;
2013 picture->structure = picture->base.structure;
2014 picture->other_field = fs->buffers[j ^ 1];
2019 for (i = short_ref_count; i < priv->short_ref_count; i++)
2020 priv->short_ref[i] = NULL;
2021 priv->short_ref_count = short_ref_count;
2023 for (i = long_ref_count; i < priv->long_ref_count; i++)
2024 priv->long_ref[i] = NULL;
2025 priv->long_ref_count = long_ref_count;
2030 GstVaapiDecoderH264 *decoder,
2031 GstVaapiPictureH264 *picture,
2032 GstH264SliceHdr *slice_hdr
2035 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2038 init_picture_ref_lists(decoder);
2039 init_picture_refs_pic_num(decoder, picture, slice_hdr);
2041 priv->RefPicList0_count = 0;
2042 priv->RefPicList1_count = 0;
2044 switch (slice_hdr->type % 5) {
2045 case GST_H264_P_SLICE:
2046 case GST_H264_SP_SLICE:
2047 init_picture_refs_p_slice(decoder, picture, slice_hdr);
2049 case GST_H264_B_SLICE:
2050 init_picture_refs_b_slice(decoder, picture, slice_hdr);
2056 exec_picture_refs_modification(decoder, picture, slice_hdr);
2058 switch (slice_hdr->type % 5) {
2059 case GST_H264_B_SLICE:
2060 num_refs = 1 + slice_hdr->num_ref_idx_l1_active_minus1;
2061 for (i = priv->RefPicList1_count; i < num_refs; i++)
2062 priv->RefPicList1[i] = NULL;
2063 priv->RefPicList1_count = num_refs;
2066 case GST_H264_P_SLICE:
2067 case GST_H264_SP_SLICE:
2068 num_refs = 1 + slice_hdr->num_ref_idx_l0_active_minus1;
2069 for (i = priv->RefPicList0_count; i < num_refs; i++)
2070 priv->RefPicList0[i] = NULL;
2071 priv->RefPicList0_count = num_refs;
2080 GstVaapiDecoderH264 *decoder,
2081 GstVaapiPictureH264 *picture, GstVaapiParserInfoH264 *pi)
2083 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2084 GstVaapiPicture * const base_picture = &picture->base;
2085 GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
2087 priv->prev_frame_num = priv->frame_num;
2088 priv->frame_num = slice_hdr->frame_num;
2089 picture->frame_num = priv->frame_num;
2090 picture->frame_num_wrap = priv->frame_num;
2091 picture->output_flag = TRUE; /* XXX: conformant to Annex A only */
2092 base_picture->pts = GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts;
2093 base_picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
2095 /* Reset decoder state for IDR pictures */
2096 if (pi->nalu.type == GST_H264_NAL_SLICE_IDR) {
2098 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_IDR);
2102 /* Initialize picture structure */
2103 if (!slice_hdr->field_pic_flag)
2104 base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
2106 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
2107 if (!slice_hdr->bottom_field_flag)
2108 base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
2110 base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
2112 picture->structure = base_picture->structure;
2114 /* Initialize reference flags */
2115 if (pi->nalu.ref_idc) {
2116 GstH264DecRefPicMarking * const dec_ref_pic_marking =
2117 &slice_hdr->dec_ref_pic_marking;
2119 if (GST_VAAPI_PICTURE_IS_IDR(picture) &&
2120 dec_ref_pic_marking->long_term_reference_flag)
2121 GST_VAAPI_PICTURE_FLAG_SET(picture,
2122 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE);
2124 GST_VAAPI_PICTURE_FLAG_SET(picture,
2125 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE);
2128 init_picture_poc(decoder, picture, slice_hdr);
2132 /* 8.2.5.3 - Sliding window decoded reference picture marking process */
2134 exec_ref_pic_marking_sliding_window(GstVaapiDecoderH264 *decoder)
2136 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2137 GstH264SPS * const sps = get_sps(decoder);
2138 GstVaapiPictureH264 *ref_picture;
2139 guint i, m, max_num_ref_frames;
2141 GST_DEBUG("reference picture marking process (sliding window)");
2143 if (!GST_VAAPI_PICTURE_IS_FIRST_FIELD(priv->current_picture))
2146 max_num_ref_frames = sps->num_ref_frames;
2147 if (max_num_ref_frames == 0)
2148 max_num_ref_frames = 1;
2149 if (!GST_VAAPI_PICTURE_IS_FRAME(priv->current_picture))
2150 max_num_ref_frames <<= 1;
2152 if (priv->short_ref_count + priv->long_ref_count < max_num_ref_frames)
2154 if (priv->short_ref_count < 1)
2157 for (m = 0, i = 1; i < priv->short_ref_count; i++) {
2158 GstVaapiPictureH264 * const picture = priv->short_ref[i];
2159 if (picture->frame_num_wrap < priv->short_ref[m]->frame_num_wrap)
2163 ref_picture = priv->short_ref[m];
2164 gst_vaapi_picture_h264_set_reference(ref_picture, 0, TRUE);
2165 ARRAY_REMOVE_INDEX(priv->short_ref, m);
2167 /* Both fields need to be marked as "unused for reference", so
2168 remove the other field from the short_ref[] list as well */
2169 if (!GST_VAAPI_PICTURE_IS_FRAME(priv->current_picture) && ref_picture->other_field) {
2170 for (i = 0; i < priv->short_ref_count; i++) {
2171 if (priv->short_ref[i] == ref_picture->other_field) {
2172 ARRAY_REMOVE_INDEX(priv->short_ref, i);
2180 static inline gint32
2181 get_picNumX(GstVaapiPictureH264 *picture, GstH264RefPicMarking *ref_pic_marking)
2185 if (GST_VAAPI_PICTURE_IS_FRAME(picture))
2186 pic_num = picture->frame_num_wrap;
2188 pic_num = 2 * picture->frame_num_wrap + 1;
2189 pic_num -= ref_pic_marking->difference_of_pic_nums_minus1 + 1;
2193 /* 8.2.5.4.1. Mark short-term reference picture as "unused for reference" */
2195 exec_ref_pic_marking_adaptive_mmco_1(
2196 GstVaapiDecoderH264 *decoder,
2197 GstVaapiPictureH264 *picture,
2198 GstH264RefPicMarking *ref_pic_marking
2201 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2204 picNumX = get_picNumX(picture, ref_pic_marking);
2205 i = find_short_term_reference(decoder, picNumX);
2209 gst_vaapi_picture_h264_set_reference(priv->short_ref[i], 0,
2210 GST_VAAPI_PICTURE_IS_FRAME(picture));
2211 ARRAY_REMOVE_INDEX(priv->short_ref, i);
2214 /* 8.2.5.4.2. Mark long-term reference picture as "unused for reference" */
2216 exec_ref_pic_marking_adaptive_mmco_2(
2217 GstVaapiDecoderH264 *decoder,
2218 GstVaapiPictureH264 *picture,
2219 GstH264RefPicMarking *ref_pic_marking
2222 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2225 i = find_long_term_reference(decoder, ref_pic_marking->long_term_pic_num);
2229 gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0,
2230 GST_VAAPI_PICTURE_IS_FRAME(picture));
2231 ARRAY_REMOVE_INDEX(priv->long_ref, i);
2234 /* 8.2.5.4.3. Assign LongTermFrameIdx to a short-term reference picture */
2236 exec_ref_pic_marking_adaptive_mmco_3(
2237 GstVaapiDecoderH264 *decoder,
2238 GstVaapiPictureH264 *picture,
2239 GstH264RefPicMarking *ref_pic_marking
2242 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2243 GstVaapiPictureH264 *ref_picture;
2246 for (i = 0; i < priv->long_ref_count; i++) {
2247 if (priv->long_ref[i]->long_term_frame_idx == ref_pic_marking->long_term_frame_idx)
2250 if (i != priv->long_ref_count) {
2251 gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0, TRUE);
2252 ARRAY_REMOVE_INDEX(priv->long_ref, i);
2255 picNumX = get_picNumX(picture, ref_pic_marking);
2256 i = find_short_term_reference(decoder, picNumX);
2260 ref_picture = priv->short_ref[i];
2261 ARRAY_REMOVE_INDEX(priv->short_ref, i);
2262 priv->long_ref[priv->long_ref_count++] = ref_picture;
2264 ref_picture->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
2265 gst_vaapi_picture_h264_set_reference(ref_picture,
2266 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE,
2267 GST_VAAPI_PICTURE_IS_COMPLETE(picture));
2270 /* 8.2.5.4.4. Mark pictures with LongTermFramIdx > max_long_term_frame_idx
2271 * as "unused for reference" */
2273 exec_ref_pic_marking_adaptive_mmco_4(
2274 GstVaapiDecoderH264 *decoder,
2275 GstVaapiPictureH264 *picture,
2276 GstH264RefPicMarking *ref_pic_marking
2279 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2280 gint32 i, long_term_frame_idx;
2282 long_term_frame_idx = ref_pic_marking->max_long_term_frame_idx_plus1 - 1;
2284 for (i = 0; i < priv->long_ref_count; i++) {
2285 if (priv->long_ref[i]->long_term_frame_idx <= long_term_frame_idx)
2287 gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0, FALSE);
2288 ARRAY_REMOVE_INDEX(priv->long_ref, i);
2293 /* 8.2.5.4.5. Mark all reference pictures as "unused for reference" */
2295 exec_ref_pic_marking_adaptive_mmco_5(
2296 GstVaapiDecoderH264 *decoder,
2297 GstVaapiPictureH264 *picture,
2298 GstH264RefPicMarking *ref_pic_marking
2301 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2305 priv->prev_pic_has_mmco5 = TRUE;
2307 /* The picture shall be inferred to have had frame_num equal to 0 (7.4.3) */
2308 priv->frame_num = 0;
2309 priv->frame_num_offset = 0;
2310 picture->frame_num = 0;
2312 /* Update TopFieldOrderCnt and BottomFieldOrderCnt (8.2.1) */
2313 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
2314 picture->field_poc[TOP_FIELD] -= picture->base.poc;
2315 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
2316 picture->field_poc[BOTTOM_FIELD] -= picture->base.poc;
2317 picture->base.poc = 0;
2320 /* 8.2.5.4.6. Assign a long-term frame index to the current picture */
2322 exec_ref_pic_marking_adaptive_mmco_6(
2323 GstVaapiDecoderH264 *decoder,
2324 GstVaapiPictureH264 *picture,
2325 GstH264RefPicMarking *ref_pic_marking
2328 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2331 for (i = 0; i < priv->long_ref_count; i++) {
2332 if (priv->long_ref[i]->long_term_frame_idx == ref_pic_marking->long_term_frame_idx)
2335 if (i != priv->long_ref_count) {
2336 gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0, TRUE);
2337 ARRAY_REMOVE_INDEX(priv->long_ref, i);
2340 picture->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
2341 gst_vaapi_picture_h264_set_reference(picture,
2342 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE,
2343 GST_VAAPI_PICTURE_IS_COMPLETE(picture));
2346 /* 8.2.5.4. Adaptive memory control decoded reference picture marking process */
2348 exec_ref_pic_marking_adaptive(
2349 GstVaapiDecoderH264 *decoder,
2350 GstVaapiPictureH264 *picture,
2351 GstH264DecRefPicMarking *dec_ref_pic_marking
2356 GST_DEBUG("reference picture marking process (adaptive memory control)");
2358 typedef void (*exec_ref_pic_marking_adaptive_mmco_func)(
2359 GstVaapiDecoderH264 *decoder,
2360 GstVaapiPictureH264 *picture,
2361 GstH264RefPicMarking *ref_pic_marking
2364 static const exec_ref_pic_marking_adaptive_mmco_func mmco_funcs[] = {
2366 exec_ref_pic_marking_adaptive_mmco_1,
2367 exec_ref_pic_marking_adaptive_mmco_2,
2368 exec_ref_pic_marking_adaptive_mmco_3,
2369 exec_ref_pic_marking_adaptive_mmco_4,
2370 exec_ref_pic_marking_adaptive_mmco_5,
2371 exec_ref_pic_marking_adaptive_mmco_6,
2374 for (i = 0; i < dec_ref_pic_marking->n_ref_pic_marking; i++) {
2375 GstH264RefPicMarking * const ref_pic_marking =
2376 &dec_ref_pic_marking->ref_pic_marking[i];
2378 const guint mmco = ref_pic_marking->memory_management_control_operation;
2379 if (mmco < G_N_ELEMENTS(mmco_funcs) && mmco_funcs[mmco])
2380 mmco_funcs[mmco](decoder, picture, ref_pic_marking);
2382 GST_ERROR("unhandled MMCO %u", mmco);
2389 /* 8.2.5 - Execute reference picture marking process */
2391 exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
2393 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2395 priv->prev_pic_has_mmco5 = FALSE;
2396 priv->prev_pic_structure = picture->structure;
2398 if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
2401 if (!GST_VAAPI_PICTURE_IS_IDR(picture)) {
2402 GstH264DecRefPicMarking * const dec_ref_pic_marking =
2403 &picture->last_slice_hdr->dec_ref_pic_marking;
2404 if (dec_ref_pic_marking->adaptive_ref_pic_marking_mode_flag) {
2405 if (!exec_ref_pic_marking_adaptive(decoder, picture, dec_ref_pic_marking))
2409 if (!exec_ref_pic_marking_sliding_window(decoder))
2417 vaapi_init_picture(VAPictureH264 *pic)
2419 pic->picture_id = VA_INVALID_ID;
2421 pic->flags = VA_PICTURE_H264_INVALID;
2422 pic->TopFieldOrderCnt = 0;
2423 pic->BottomFieldOrderCnt = 0;
2427 vaapi_fill_picture(VAPictureH264 *pic, GstVaapiPictureH264 *picture,
2428 guint picture_structure)
2430 if (!picture_structure)
2431 picture_structure = picture->structure;
2433 pic->picture_id = picture->base.surface_id;
2436 if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture)) {
2437 pic->flags |= VA_PICTURE_H264_LONG_TERM_REFERENCE;
2438 pic->frame_idx = picture->long_term_frame_idx;
2441 if (GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
2442 pic->flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2443 pic->frame_idx = picture->frame_num;
2446 switch (picture_structure) {
2447 case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
2448 pic->TopFieldOrderCnt = picture->field_poc[TOP_FIELD];
2449 pic->BottomFieldOrderCnt = picture->field_poc[BOTTOM_FIELD];
2451 case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
2452 pic->flags |= VA_PICTURE_H264_TOP_FIELD;
2453 pic->TopFieldOrderCnt = picture->field_poc[TOP_FIELD];
2454 pic->BottomFieldOrderCnt = 0;
2456 case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
2457 pic->flags |= VA_PICTURE_H264_BOTTOM_FIELD;
2458 pic->BottomFieldOrderCnt = picture->field_poc[BOTTOM_FIELD];
2459 pic->TopFieldOrderCnt = 0;
2465 fill_picture(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
2467 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2468 GstVaapiPicture * const base_picture = &picture->base;
2469 GstH264PPS * const pps = get_pps(decoder);
2470 GstH264SPS * const sps = get_sps(decoder);
2471 VAPictureParameterBufferH264 * const pic_param = base_picture->param;
2474 /* Fill in VAPictureParameterBufferH264 */
2475 vaapi_fill_picture(&pic_param->CurrPic, picture, 0);
2477 for (i = 0, n = 0; i < priv->dpb_count; i++) {
2478 GstVaapiFrameStore * const fs = priv->dpb[i];
2479 if (gst_vaapi_frame_store_has_reference(fs))
2480 vaapi_fill_picture(&pic_param->ReferenceFrames[n++],
2481 fs->buffers[0], fs->structure);
2483 for (; n < G_N_ELEMENTS(pic_param->ReferenceFrames); n++)
2484 vaapi_init_picture(&pic_param->ReferenceFrames[n]);
2486 #define COPY_FIELD(s, f) \
2487 pic_param->f = (s)->f
2489 #define COPY_BFM(a, s, f) \
2490 pic_param->a.bits.f = (s)->f
2492 pic_param->picture_width_in_mbs_minus1 = priv->mb_width - 1;
2493 pic_param->picture_height_in_mbs_minus1 = priv->mb_height - 1;
2494 pic_param->frame_num = priv->frame_num;
2496 COPY_FIELD(sps, bit_depth_luma_minus8);
2497 COPY_FIELD(sps, bit_depth_chroma_minus8);
2498 COPY_FIELD(sps, num_ref_frames);
2499 COPY_FIELD(pps, num_slice_groups_minus1);
2500 COPY_FIELD(pps, slice_group_map_type);
2501 COPY_FIELD(pps, slice_group_change_rate_minus1);
2502 COPY_FIELD(pps, pic_init_qp_minus26);
2503 COPY_FIELD(pps, pic_init_qs_minus26);
2504 COPY_FIELD(pps, chroma_qp_index_offset);
2505 COPY_FIELD(pps, second_chroma_qp_index_offset);
2507 pic_param->seq_fields.value = 0; /* reset all bits */
2508 pic_param->seq_fields.bits.residual_colour_transform_flag = sps->separate_colour_plane_flag;
2509 pic_param->seq_fields.bits.MinLumaBiPredSize8x8 = sps->level_idc >= 31; /* A.3.3.2 */
2511 COPY_BFM(seq_fields, sps, chroma_format_idc);
2512 COPY_BFM(seq_fields, sps, gaps_in_frame_num_value_allowed_flag);
2513 COPY_BFM(seq_fields, sps, frame_mbs_only_flag);
2514 COPY_BFM(seq_fields, sps, mb_adaptive_frame_field_flag);
2515 COPY_BFM(seq_fields, sps, direct_8x8_inference_flag);
2516 COPY_BFM(seq_fields, sps, log2_max_frame_num_minus4);
2517 COPY_BFM(seq_fields, sps, pic_order_cnt_type);
2518 COPY_BFM(seq_fields, sps, log2_max_pic_order_cnt_lsb_minus4);
2519 COPY_BFM(seq_fields, sps, delta_pic_order_always_zero_flag);
2521 pic_param->pic_fields.value = 0; /* reset all bits */
2522 pic_param->pic_fields.bits.field_pic_flag = GST_VAAPI_PICTURE_IS_INTERLACED(picture);
2523 pic_param->pic_fields.bits.reference_pic_flag = GST_VAAPI_PICTURE_IS_REFERENCE(picture);
2525 COPY_BFM(pic_fields, pps, entropy_coding_mode_flag);
2526 COPY_BFM(pic_fields, pps, weighted_pred_flag);
2527 COPY_BFM(pic_fields, pps, weighted_bipred_idc);
2528 COPY_BFM(pic_fields, pps, transform_8x8_mode_flag);
2529 COPY_BFM(pic_fields, pps, constrained_intra_pred_flag);
2530 COPY_BFM(pic_fields, pps, pic_order_present_flag);
2531 COPY_BFM(pic_fields, pps, deblocking_filter_control_present_flag);
2532 COPY_BFM(pic_fields, pps, redundant_pic_cnt_present_flag);
2536 /* Detection of the first VCL NAL unit of a primary coded picture (7.4.1.2.4) */
2538 is_new_picture(GstVaapiParserInfoH264 *pi, GstVaapiParserInfoH264 *prev_pi)
2540 GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
2541 GstH264PPS * const pps = slice_hdr->pps;
2542 GstH264SPS * const sps = pps->sequence;
2543 GstH264SliceHdr *prev_slice_hdr;
2547 prev_slice_hdr = &prev_pi->data.slice_hdr;
2549 #define CHECK_EXPR(expr, field_name) do { \
2551 GST_DEBUG(field_name " differs in value"); \
2556 #define CHECK_VALUE(new_slice_hdr, old_slice_hdr, field) \
2557 CHECK_EXPR(((new_slice_hdr)->field == (old_slice_hdr)->field), #field)
2559 /* frame_num differs in value, regardless of inferred values to 0 */
2560 CHECK_VALUE(slice_hdr, prev_slice_hdr, frame_num);
2562 /* pic_parameter_set_id differs in value */
2563 CHECK_VALUE(slice_hdr, prev_slice_hdr, pps);
2565 /* field_pic_flag differs in value */
2566 CHECK_VALUE(slice_hdr, prev_slice_hdr, field_pic_flag);
2568 /* bottom_field_flag is present in both and differs in value */
2569 if (slice_hdr->field_pic_flag && prev_slice_hdr->field_pic_flag)
2570 CHECK_VALUE(slice_hdr, prev_slice_hdr, bottom_field_flag);
2572 /* nal_ref_idc differs in value with one of the nal_ref_idc values is 0 */
2573 CHECK_EXPR((pi->nalu.ref_idc != 0) ==
2574 (prev_pi->nalu.ref_idc != 0), "nal_ref_idc");
2576 /* POC type is 0 for both and either pic_order_cnt_lsb differs in
2577 value or delta_pic_order_cnt_bottom differs in value */
2578 if (sps->pic_order_cnt_type == 0) {
2579 CHECK_VALUE(slice_hdr, prev_slice_hdr, pic_order_cnt_lsb);
2580 if (pps->pic_order_present_flag && !slice_hdr->field_pic_flag)
2581 CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt_bottom);
2584 /* POC type is 1 for both and either delta_pic_order_cnt[0]
2585 differs in value or delta_pic_order_cnt[1] differs in value */
2586 else if (sps->pic_order_cnt_type == 1) {
2587 CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt[0]);
2588 CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt[1]);
2591 /* IdrPicFlag differs in value */
2592 CHECK_VALUE(&pi->nalu, &prev_pi->nalu, idr_pic_flag);
2594 /* IdrPicFlag is equal to 1 for both and idr_pic_id differs in value */
2595 if (pi->nalu.idr_pic_flag)
2596 CHECK_VALUE(slice_hdr, prev_slice_hdr, idr_pic_id);
2603 static GstVaapiDecoderStatus
2604 decode_picture(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
2606 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2607 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
2608 GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
2609 GstH264PPS * const pps = ensure_pps(decoder, slice_hdr->pps);
2610 GstH264SPS * const sps = ensure_sps(decoder, slice_hdr->pps->sequence);
2611 GstVaapiPictureH264 *picture;
2612 GstVaapiDecoderStatus status;
2614 g_return_val_if_fail(pps != NULL, GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN);
2615 g_return_val_if_fail(sps != NULL, GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN);
2617 status = ensure_context(decoder, sps);
2618 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2621 priv->decoder_state = 0;
2623 if (priv->current_picture) {
2624 /* Re-use current picture where the first field was decoded */
2625 picture = gst_vaapi_picture_h264_new_field(priv->current_picture);
2627 GST_ERROR("failed to allocate field picture");
2628 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2632 /* Create new picture */
2633 picture = gst_vaapi_picture_h264_new(decoder);
2635 GST_ERROR("failed to allocate picture");
2636 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2639 gst_vaapi_picture_replace(&priv->current_picture, picture);
2640 gst_vaapi_picture_unref(picture);
2642 /* Update cropping rectangle */
2643 if (sps->frame_cropping_flag) {
2644 GstVaapiRectangle crop_rect;
2645 crop_rect.x = sps->crop_rect_x;
2646 crop_rect.y = sps->crop_rect_y;
2647 crop_rect.width = sps->crop_rect_width;
2648 crop_rect.height = sps->crop_rect_height;
2649 gst_vaapi_picture_set_crop_rect(&picture->base, &crop_rect);
2652 status = ensure_quant_matrix(decoder, picture);
2653 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
2654 GST_ERROR("failed to reset quantizer matrix");
2658 if (!init_picture(decoder, picture, pi))
2659 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2660 if (!fill_picture(decoder, picture))
2661 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2663 priv->decoder_state = pi->state;
2664 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2668 get_slice_data_bit_offset(GstH264SliceHdr *slice_hdr, guint nal_header_bytes)
2672 epb_count = slice_hdr->n_emulation_prevention_bytes;
2673 return 8 * nal_header_bytes + slice_hdr->header_size - epb_count * 8;
2677 fill_pred_weight_table(GstVaapiDecoderH264 *decoder,
2678 GstVaapiSlice *slice, GstH264SliceHdr *slice_hdr)
2680 VASliceParameterBufferH264 * const slice_param = slice->param;
2681 GstH264PPS * const pps = get_pps(decoder);
2682 GstH264SPS * const sps = get_sps(decoder);
2683 GstH264PredWeightTable * const w = &slice_hdr->pred_weight_table;
2684 guint num_weight_tables = 0;
2687 if (pps->weighted_pred_flag &&
2688 (GST_H264_IS_P_SLICE(slice_hdr) || GST_H264_IS_SP_SLICE(slice_hdr)))
2689 num_weight_tables = 1;
2690 else if (pps->weighted_bipred_idc == 1 && GST_H264_IS_B_SLICE(slice_hdr))
2691 num_weight_tables = 2;
2693 num_weight_tables = 0;
2695 slice_param->luma_log2_weight_denom = 0;
2696 slice_param->chroma_log2_weight_denom = 0;
2697 slice_param->luma_weight_l0_flag = 0;
2698 slice_param->chroma_weight_l0_flag = 0;
2699 slice_param->luma_weight_l1_flag = 0;
2700 slice_param->chroma_weight_l1_flag = 0;
2702 if (num_weight_tables < 1)
2705 slice_param->luma_log2_weight_denom = w->luma_log2_weight_denom;
2706 slice_param->chroma_log2_weight_denom = w->chroma_log2_weight_denom;
2708 slice_param->luma_weight_l0_flag = 1;
2709 for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
2710 slice_param->luma_weight_l0[i] = w->luma_weight_l0[i];
2711 slice_param->luma_offset_l0[i] = w->luma_offset_l0[i];
2714 slice_param->chroma_weight_l0_flag = sps->chroma_array_type != 0;
2715 if (slice_param->chroma_weight_l0_flag) {
2716 for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
2717 for (j = 0; j < 2; j++) {
2718 slice_param->chroma_weight_l0[i][j] = w->chroma_weight_l0[i][j];
2719 slice_param->chroma_offset_l0[i][j] = w->chroma_offset_l0[i][j];
2724 if (num_weight_tables < 2)
2727 slice_param->luma_weight_l1_flag = 1;
2728 for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
2729 slice_param->luma_weight_l1[i] = w->luma_weight_l1[i];
2730 slice_param->luma_offset_l1[i] = w->luma_offset_l1[i];
2733 slice_param->chroma_weight_l1_flag = sps->chroma_array_type != 0;
2734 if (slice_param->chroma_weight_l1_flag) {
2735 for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
2736 for (j = 0; j < 2; j++) {
2737 slice_param->chroma_weight_l1[i][j] = w->chroma_weight_l1[i][j];
2738 slice_param->chroma_offset_l1[i][j] = w->chroma_offset_l1[i][j];
2746 fill_RefPicList(GstVaapiDecoderH264 *decoder,
2747 GstVaapiSlice *slice, GstH264SliceHdr *slice_hdr)
2749 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2750 VASliceParameterBufferH264 * const slice_param = slice->param;
2751 guint i, num_ref_lists = 0;
2753 slice_param->num_ref_idx_l0_active_minus1 = 0;
2754 slice_param->num_ref_idx_l1_active_minus1 = 0;
2756 if (GST_H264_IS_B_SLICE(slice_hdr))
2758 else if (GST_H264_IS_I_SLICE(slice_hdr))
2763 if (num_ref_lists < 1)
2766 slice_param->num_ref_idx_l0_active_minus1 =
2767 slice_hdr->num_ref_idx_l0_active_minus1;
2769 for (i = 0; i < priv->RefPicList0_count && priv->RefPicList0[i]; i++)
2770 vaapi_fill_picture(&slice_param->RefPicList0[i], priv->RefPicList0[i], 0);
2771 for (; i <= slice_param->num_ref_idx_l0_active_minus1; i++)
2772 vaapi_init_picture(&slice_param->RefPicList0[i]);
2774 if (num_ref_lists < 2)
2777 slice_param->num_ref_idx_l1_active_minus1 =
2778 slice_hdr->num_ref_idx_l1_active_minus1;
2780 for (i = 0; i < priv->RefPicList1_count && priv->RefPicList1[i]; i++)
2781 vaapi_fill_picture(&slice_param->RefPicList1[i], priv->RefPicList1[i], 0);
2782 for (; i <= slice_param->num_ref_idx_l1_active_minus1; i++)
2783 vaapi_init_picture(&slice_param->RefPicList1[i]);
2788 fill_slice(GstVaapiDecoderH264 *decoder,
2789 GstVaapiSlice *slice, GstVaapiParserInfoH264 *pi)
2791 VASliceParameterBufferH264 * const slice_param = slice->param;
2792 GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
2794 /* Fill in VASliceParameterBufferH264 */
2795 slice_param->slice_data_bit_offset =
2796 get_slice_data_bit_offset(slice_hdr, pi->nalu.header_bytes);
2797 slice_param->first_mb_in_slice = slice_hdr->first_mb_in_slice;
2798 slice_param->slice_type = slice_hdr->type % 5;
2799 slice_param->direct_spatial_mv_pred_flag = slice_hdr->direct_spatial_mv_pred_flag;
2800 slice_param->cabac_init_idc = slice_hdr->cabac_init_idc;
2801 slice_param->slice_qp_delta = slice_hdr->slice_qp_delta;
2802 slice_param->disable_deblocking_filter_idc = slice_hdr->disable_deblocking_filter_idc;
2803 slice_param->slice_alpha_c0_offset_div2 = slice_hdr->slice_alpha_c0_offset_div2;
2804 slice_param->slice_beta_offset_div2 = slice_hdr->slice_beta_offset_div2;
2806 if (!fill_RefPicList(decoder, slice, slice_hdr))
2808 if (!fill_pred_weight_table(decoder, slice, slice_hdr))
2813 static GstVaapiDecoderStatus
2814 decode_slice(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
2816 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2817 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
2818 GstVaapiPictureH264 * const picture = priv->current_picture;
2819 GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
2820 GstVaapiSlice *slice;
2821 GstBuffer * const buffer =
2822 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer;
2823 GstMapInfo map_info;
2825 GST_DEBUG("slice (%u bytes)", pi->nalu.size);
2827 if (!is_valid_state(pi->state,
2828 GST_H264_VIDEO_STATE_VALID_PICTURE_HEADERS)) {
2829 GST_WARNING("failed to receive enough headers to decode slice");
2830 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2833 if (!ensure_pps(decoder, slice_hdr->pps)) {
2834 GST_ERROR("failed to activate PPS");
2835 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2838 if (!ensure_sps(decoder, slice_hdr->pps->sequence)) {
2839 GST_ERROR("failed to activate SPS");
2840 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2843 if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) {
2844 GST_ERROR("failed to map buffer");
2845 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2848 slice = GST_VAAPI_SLICE_NEW(H264, decoder,
2849 (map_info.data + unit->offset + pi->nalu.offset), pi->nalu.size);
2850 gst_buffer_unmap(buffer, &map_info);
2852 GST_ERROR("failed to allocate slice");
2853 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2856 init_picture_refs(decoder, picture, slice_hdr);
2857 if (!fill_slice(decoder, slice, pi)) {
2858 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(slice));
2859 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2862 gst_vaapi_picture_add_slice(GST_VAAPI_PICTURE_CAST(picture), slice);
2863 picture->last_slice_hdr = slice_hdr;
2864 priv->decoder_state |= GST_H264_VIDEO_STATE_GOT_SLICE;
2865 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2869 scan_for_start_code(GstAdapter *adapter, guint ofs, guint size, guint32 *scp)
2871 return (gint)gst_adapter_masked_scan_uint32_peek(adapter,
2872 0xffffff00, 0x00000100,
2877 static GstVaapiDecoderStatus
2878 decode_unit(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
2880 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2881 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
2882 GstVaapiDecoderStatus status;
2884 priv->decoder_state |= pi->state;
2885 switch (pi->nalu.type) {
2886 case GST_H264_NAL_SPS:
2887 status = decode_sps(decoder, unit);
2889 case GST_H264_NAL_PPS:
2890 status = decode_pps(decoder, unit);
2892 case GST_H264_NAL_SLICE_IDR:
2893 /* fall-through. IDR specifics are handled in init_picture() */
2894 case GST_H264_NAL_SLICE:
2895 status = decode_slice(decoder, unit);
2897 case GST_H264_NAL_SEQ_END:
2898 case GST_H264_NAL_STREAM_END:
2899 status = decode_sequence_end(decoder);
2901 case GST_H264_NAL_SEI:
2902 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
2905 GST_WARNING("unsupported NAL unit type %d", pi->nalu.type);
2906 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
2912 static GstVaapiDecoderStatus
2913 gst_vaapi_decoder_h264_decode_codec_data(GstVaapiDecoder *base_decoder,
2914 const guchar *buf, guint buf_size)
2916 GstVaapiDecoderH264 * const decoder =
2917 GST_VAAPI_DECODER_H264_CAST(base_decoder);
2918 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2919 GstVaapiDecoderStatus status;
2920 GstVaapiDecoderUnit unit;
2921 GstVaapiParserInfoH264 *pi = NULL;
2922 GstH264ParserResult result;
2923 guint i, ofs, num_sps, num_pps;
2925 unit.parsed_info = NULL;
2928 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2931 GST_ERROR("failed to decode codec-data, not in avcC format");
2932 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
2935 priv->nal_length_size = (buf[4] & 0x03) + 1;
2937 num_sps = buf[5] & 0x1f;
2940 for (i = 0; i < num_sps; i++) {
2941 pi = gst_vaapi_parser_info_h264_new();
2943 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2944 unit.parsed_info = pi;
2946 result = gst_h264_parser_identify_nalu_avc(
2948 buf, ofs, buf_size, 2,
2951 if (result != GST_H264_PARSER_OK) {
2952 status = get_status(result);
2956 status = parse_sps(decoder, &unit);
2957 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2959 ofs = pi->nalu.offset + pi->nalu.size;
2961 status = decode_sps(decoder, &unit);
2962 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2964 gst_vaapi_parser_info_h264_replace(&pi, NULL);
2970 for (i = 0; i < num_pps; i++) {
2971 pi = gst_vaapi_parser_info_h264_new();
2973 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2974 unit.parsed_info = pi;
2976 result = gst_h264_parser_identify_nalu_avc(
2978 buf, ofs, buf_size, 2,
2981 if (result != GST_H264_PARSER_OK) {
2982 status = get_status(result);
2986 status = parse_pps(decoder, &unit);
2987 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2989 ofs = pi->nalu.offset + pi->nalu.size;
2991 status = decode_pps(decoder, &unit);
2992 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2994 gst_vaapi_parser_info_h264_replace(&pi, NULL);
2997 priv->is_avcC = TRUE;
2998 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
3001 gst_vaapi_parser_info_h264_replace(&pi, NULL);
3005 static GstVaapiDecoderStatus
3006 ensure_decoder(GstVaapiDecoderH264 *decoder)
3008 GstVaapiDecoderH264Private * const priv = &decoder->priv;
3009 GstVaapiDecoderStatus status;
3011 if (!priv->is_opened) {
3012 priv->is_opened = gst_vaapi_decoder_h264_open(decoder);
3013 if (!priv->is_opened)
3014 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
3016 status = gst_vaapi_decoder_decode_codec_data(
3017 GST_VAAPI_DECODER_CAST(decoder));
3018 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3021 return GST_VAAPI_DECODER_STATUS_SUCCESS;
3024 static GstVaapiDecoderStatus
3025 gst_vaapi_decoder_h264_parse(GstVaapiDecoder *base_decoder,
3026 GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit *unit)
3028 GstVaapiDecoderH264 * const decoder =
3029 GST_VAAPI_DECODER_H264_CAST(base_decoder);
3030 GstVaapiDecoderH264Private * const priv = &decoder->priv;
3031 GstVaapiParserState * const ps = GST_VAAPI_PARSER_STATE(base_decoder);
3032 GstVaapiParserInfoH264 *pi;
3033 GstVaapiDecoderStatus status;
3034 GstH264ParserResult result;
3036 guint i, size, buf_size, nalu_size, flags;
3040 status = ensure_decoder(decoder);
3041 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3044 size = gst_adapter_available(adapter);
3046 if (priv->is_avcC) {
3047 if (size < priv->nal_length_size)
3048 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3050 buf = (guchar *)&start_code;
3051 g_assert(priv->nal_length_size <= sizeof(start_code));
3052 gst_adapter_copy(adapter, buf, 0, priv->nal_length_size);
3055 for (i = 0; i < priv->nal_length_size; i++)
3056 nalu_size = (nalu_size << 8) | buf[i];
3058 buf_size = priv->nal_length_size + nalu_size;
3059 if (size < buf_size)
3060 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3064 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3066 ofs = scan_for_start_code(adapter, 0, size, NULL);
3068 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3071 gst_adapter_flush(adapter, ofs);
3075 ofs2 = ps->input_offset2 - ofs - 4;
3079 ofs = G_UNLIKELY(size < ofs2 + 4) ? -1 :
3080 scan_for_start_code(adapter, ofs2, size - ofs2, NULL);
3082 // Assume the whole NAL unit is present if end-of-stream
3084 ps->input_offset2 = size;
3085 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3091 ps->input_offset2 = 0;
3093 buf = (guchar *)gst_adapter_map(adapter, buf_size);
3095 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3097 unit->size = buf_size;
3099 pi = gst_vaapi_parser_info_h264_new();
3101 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
3103 gst_vaapi_decoder_unit_set_parsed_info(unit,
3104 pi, (GDestroyNotify)gst_vaapi_mini_object_unref);
3107 result = gst_h264_parser_identify_nalu_avc(priv->parser,
3108 buf, 0, buf_size, priv->nal_length_size, &pi->nalu);
3110 result = gst_h264_parser_identify_nalu_unchecked(priv->parser,
3111 buf, 0, buf_size, &pi->nalu);
3112 status = get_status(result);
3113 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3116 switch (pi->nalu.type) {
3117 case GST_H264_NAL_SPS:
3118 status = parse_sps(decoder, unit);
3120 case GST_H264_NAL_PPS:
3121 status = parse_pps(decoder, unit);
3123 case GST_H264_NAL_SEI:
3124 status = parse_sei(decoder, unit);
3126 case GST_H264_NAL_SLICE_IDR:
3127 case GST_H264_NAL_SLICE:
3128 status = parse_slice(decoder, unit);
3131 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
3134 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3138 switch (pi->nalu.type) {
3139 case GST_H264_NAL_AU_DELIMITER:
3140 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
3142 case GST_H264_NAL_FILLER_DATA:
3143 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
3145 case GST_H264_NAL_STREAM_END:
3146 flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
3148 case GST_H264_NAL_SEQ_END:
3149 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
3151 case GST_H264_NAL_SPS:
3152 case GST_H264_NAL_PPS:
3153 case GST_H264_NAL_SEI:
3154 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
3156 case GST_H264_NAL_SLICE_IDR:
3157 case GST_H264_NAL_SLICE:
3158 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
3159 if (is_new_picture(pi, priv->prev_slice_pi))
3160 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
3161 gst_vaapi_parser_info_h264_replace(&priv->prev_slice_pi, pi);
3163 case GST_H264_NAL_SPS_EXT:
3164 case GST_H264_NAL_SLICE_AUX:
3165 /* skip SPS extension and auxiliary slice for now */
3166 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
3169 if (pi->nalu.type >= 14 && pi->nalu.type <= 18)
3170 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
3173 GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
3175 pi->nalu.data = NULL;
3176 pi->state = priv->parser_state;
3177 return GST_VAAPI_DECODER_STATUS_SUCCESS;
3180 static GstVaapiDecoderStatus
3181 gst_vaapi_decoder_h264_decode(GstVaapiDecoder *base_decoder,
3182 GstVaapiDecoderUnit *unit)
3184 GstVaapiDecoderH264 * const decoder =
3185 GST_VAAPI_DECODER_H264_CAST(base_decoder);
3186 GstVaapiDecoderStatus status;
3188 status = ensure_decoder(decoder);
3189 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3191 return decode_unit(decoder, unit);
3194 static GstVaapiDecoderStatus
3195 gst_vaapi_decoder_h264_start_frame(GstVaapiDecoder *base_decoder,
3196 GstVaapiDecoderUnit *unit)
3198 GstVaapiDecoderH264 * const decoder =
3199 GST_VAAPI_DECODER_H264_CAST(base_decoder);
3201 return decode_picture(decoder, unit);
3204 static GstVaapiDecoderStatus
3205 gst_vaapi_decoder_h264_end_frame(GstVaapiDecoder *base_decoder)
3207 GstVaapiDecoderH264 * const decoder =
3208 GST_VAAPI_DECODER_H264_CAST(base_decoder);
3210 return decode_current_picture(decoder);
3213 static GstVaapiDecoderStatus
3214 gst_vaapi_decoder_h264_flush(GstVaapiDecoder *base_decoder)
3216 GstVaapiDecoderH264 * const decoder =
3217 GST_VAAPI_DECODER_H264_CAST(base_decoder);
3220 return GST_VAAPI_DECODER_STATUS_SUCCESS;
3224 gst_vaapi_decoder_h264_class_init(GstVaapiDecoderH264Class *klass)
3226 GstVaapiMiniObjectClass * const object_class =
3227 GST_VAAPI_MINI_OBJECT_CLASS(klass);
3228 GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
3230 object_class->size = sizeof(GstVaapiDecoderH264);
3231 object_class->finalize = (GDestroyNotify)gst_vaapi_decoder_finalize;
3233 decoder_class->create = gst_vaapi_decoder_h264_create;
3234 decoder_class->destroy = gst_vaapi_decoder_h264_destroy;
3235 decoder_class->parse = gst_vaapi_decoder_h264_parse;
3236 decoder_class->decode = gst_vaapi_decoder_h264_decode;
3237 decoder_class->start_frame = gst_vaapi_decoder_h264_start_frame;
3238 decoder_class->end_frame = gst_vaapi_decoder_h264_end_frame;
3239 decoder_class->flush = gst_vaapi_decoder_h264_flush;
3241 decoder_class->decode_codec_data =
3242 gst_vaapi_decoder_h264_decode_codec_data;
3245 static inline const GstVaapiDecoderClass *
3246 gst_vaapi_decoder_h264_class(void)
3248 static GstVaapiDecoderH264Class g_class;
3249 static gsize g_class_init = FALSE;
3251 if (g_once_init_enter(&g_class_init)) {
3252 gst_vaapi_decoder_h264_class_init(&g_class);
3253 g_once_init_leave(&g_class_init, TRUE);
3255 return GST_VAAPI_DECODER_CLASS(&g_class);
3259 * gst_vaapi_decoder_h264_new:
3260 * @display: a #GstVaapiDisplay
3261 * @caps: a #GstCaps holding codec information
3263 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
3264 * hold extra information like codec-data and pictured coded size.
3266 * Return value: the newly allocated #GstVaapiDecoder object
3269 gst_vaapi_decoder_h264_new(GstVaapiDisplay *display, GstCaps *caps)
3271 return gst_vaapi_decoder_new(gst_vaapi_decoder_h264_class(), display, caps);