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;
2036 GstVaapiPicture * const base_picture = &picture->base;
2039 init_picture_ref_lists(decoder);
2040 init_picture_refs_pic_num(decoder, picture, slice_hdr);
2042 priv->RefPicList0_count = 0;
2043 priv->RefPicList1_count = 0;
2045 switch (base_picture->type) {
2046 case GST_VAAPI_PICTURE_TYPE_P:
2047 case GST_VAAPI_PICTURE_TYPE_SP:
2048 init_picture_refs_p_slice(decoder, picture, slice_hdr);
2050 case GST_VAAPI_PICTURE_TYPE_B:
2051 init_picture_refs_b_slice(decoder, picture, slice_hdr);
2057 exec_picture_refs_modification(decoder, picture, slice_hdr);
2059 switch (base_picture->type) {
2060 case GST_VAAPI_PICTURE_TYPE_B:
2061 num_refs = 1 + slice_hdr->num_ref_idx_l1_active_minus1;
2062 for (i = priv->RefPicList1_count; i < num_refs; i++)
2063 priv->RefPicList1[i] = NULL;
2064 priv->RefPicList1_count = num_refs;
2067 case GST_VAAPI_PICTURE_TYPE_P:
2068 case GST_VAAPI_PICTURE_TYPE_SP:
2069 num_refs = 1 + slice_hdr->num_ref_idx_l0_active_minus1;
2070 for (i = priv->RefPicList0_count; i < num_refs; i++)
2071 priv->RefPicList0[i] = NULL;
2072 priv->RefPicList0_count = num_refs;
2081 GstVaapiDecoderH264 *decoder,
2082 GstVaapiPictureH264 *picture, GstVaapiParserInfoH264 *pi)
2084 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2085 GstVaapiPicture * const base_picture = &picture->base;
2086 GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
2088 priv->prev_frame_num = priv->frame_num;
2089 priv->frame_num = slice_hdr->frame_num;
2090 picture->frame_num = priv->frame_num;
2091 picture->frame_num_wrap = priv->frame_num;
2092 picture->output_flag = TRUE; /* XXX: conformant to Annex A only */
2093 base_picture->pts = GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts;
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 slice type */
2103 switch (slice_hdr->type % 5) {
2104 case GST_H264_P_SLICE:
2105 base_picture->type = GST_VAAPI_PICTURE_TYPE_P;
2107 case GST_H264_B_SLICE:
2108 base_picture->type = GST_VAAPI_PICTURE_TYPE_B;
2110 case GST_H264_I_SLICE:
2111 base_picture->type = GST_VAAPI_PICTURE_TYPE_I;
2113 case GST_H264_SP_SLICE:
2114 base_picture->type = GST_VAAPI_PICTURE_TYPE_SP;
2116 case GST_H264_SI_SLICE:
2117 base_picture->type = GST_VAAPI_PICTURE_TYPE_SI;
2121 /* Initialize picture structure */
2122 if (!slice_hdr->field_pic_flag)
2123 base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
2125 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
2126 if (!slice_hdr->bottom_field_flag)
2127 base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
2129 base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
2131 picture->structure = base_picture->structure;
2133 /* Initialize reference flags */
2134 if (pi->nalu.ref_idc) {
2135 GstH264DecRefPicMarking * const dec_ref_pic_marking =
2136 &slice_hdr->dec_ref_pic_marking;
2138 if (GST_VAAPI_PICTURE_IS_IDR(picture) &&
2139 dec_ref_pic_marking->long_term_reference_flag)
2140 GST_VAAPI_PICTURE_FLAG_SET(picture,
2141 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE);
2143 GST_VAAPI_PICTURE_FLAG_SET(picture,
2144 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE);
2147 init_picture_poc(decoder, picture, slice_hdr);
2148 init_picture_refs(decoder, picture, slice_hdr);
2152 /* 8.2.5.3 - Sliding window decoded reference picture marking process */
2154 exec_ref_pic_marking_sliding_window(GstVaapiDecoderH264 *decoder)
2156 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2157 GstH264SPS * const sps = get_sps(decoder);
2158 GstVaapiPictureH264 *ref_picture;
2159 guint i, m, max_num_ref_frames;
2161 GST_DEBUG("reference picture marking process (sliding window)");
2163 if (!GST_VAAPI_PICTURE_IS_FIRST_FIELD(priv->current_picture))
2166 max_num_ref_frames = sps->num_ref_frames;
2167 if (max_num_ref_frames == 0)
2168 max_num_ref_frames = 1;
2169 if (!GST_VAAPI_PICTURE_IS_FRAME(priv->current_picture))
2170 max_num_ref_frames <<= 1;
2172 if (priv->short_ref_count + priv->long_ref_count < max_num_ref_frames)
2174 if (priv->short_ref_count < 1)
2177 for (m = 0, i = 1; i < priv->short_ref_count; i++) {
2178 GstVaapiPictureH264 * const picture = priv->short_ref[i];
2179 if (picture->frame_num_wrap < priv->short_ref[m]->frame_num_wrap)
2183 ref_picture = priv->short_ref[m];
2184 gst_vaapi_picture_h264_set_reference(ref_picture, 0, TRUE);
2185 ARRAY_REMOVE_INDEX(priv->short_ref, m);
2187 /* Both fields need to be marked as "unused for reference", so
2188 remove the other field from the short_ref[] list as well */
2189 if (!GST_VAAPI_PICTURE_IS_FRAME(priv->current_picture) && ref_picture->other_field) {
2190 for (i = 0; i < priv->short_ref_count; i++) {
2191 if (priv->short_ref[i] == ref_picture->other_field) {
2192 ARRAY_REMOVE_INDEX(priv->short_ref, i);
2200 static inline gint32
2201 get_picNumX(GstVaapiPictureH264 *picture, GstH264RefPicMarking *ref_pic_marking)
2205 if (GST_VAAPI_PICTURE_IS_FRAME(picture))
2206 pic_num = picture->frame_num_wrap;
2208 pic_num = 2 * picture->frame_num_wrap + 1;
2209 pic_num -= ref_pic_marking->difference_of_pic_nums_minus1 + 1;
2213 /* 8.2.5.4.1. Mark short-term reference picture as "unused for reference" */
2215 exec_ref_pic_marking_adaptive_mmco_1(
2216 GstVaapiDecoderH264 *decoder,
2217 GstVaapiPictureH264 *picture,
2218 GstH264RefPicMarking *ref_pic_marking
2221 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2224 picNumX = get_picNumX(picture, ref_pic_marking);
2225 i = find_short_term_reference(decoder, picNumX);
2229 gst_vaapi_picture_h264_set_reference(priv->short_ref[i], 0,
2230 GST_VAAPI_PICTURE_IS_FRAME(picture));
2231 ARRAY_REMOVE_INDEX(priv->short_ref, i);
2234 /* 8.2.5.4.2. Mark long-term reference picture as "unused for reference" */
2236 exec_ref_pic_marking_adaptive_mmco_2(
2237 GstVaapiDecoderH264 *decoder,
2238 GstVaapiPictureH264 *picture,
2239 GstH264RefPicMarking *ref_pic_marking
2242 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2245 i = find_long_term_reference(decoder, ref_pic_marking->long_term_pic_num);
2249 gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0,
2250 GST_VAAPI_PICTURE_IS_FRAME(picture));
2251 ARRAY_REMOVE_INDEX(priv->long_ref, i);
2254 /* 8.2.5.4.3. Assign LongTermFrameIdx to a short-term reference picture */
2256 exec_ref_pic_marking_adaptive_mmco_3(
2257 GstVaapiDecoderH264 *decoder,
2258 GstVaapiPictureH264 *picture,
2259 GstH264RefPicMarking *ref_pic_marking
2262 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2263 GstVaapiPictureH264 *ref_picture;
2266 for (i = 0; i < priv->long_ref_count; i++) {
2267 if (priv->long_ref[i]->long_term_frame_idx == ref_pic_marking->long_term_frame_idx)
2270 if (i != priv->long_ref_count) {
2271 gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0, TRUE);
2272 ARRAY_REMOVE_INDEX(priv->long_ref, i);
2275 picNumX = get_picNumX(picture, ref_pic_marking);
2276 i = find_short_term_reference(decoder, picNumX);
2280 ref_picture = priv->short_ref[i];
2281 ARRAY_REMOVE_INDEX(priv->short_ref, i);
2282 priv->long_ref[priv->long_ref_count++] = ref_picture;
2284 ref_picture->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
2285 gst_vaapi_picture_h264_set_reference(ref_picture,
2286 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE,
2287 GST_VAAPI_PICTURE_IS_FRAME(picture));
2290 /* 8.2.5.4.4. Mark pictures with LongTermFramIdx > max_long_term_frame_idx
2291 * as "unused for reference" */
2293 exec_ref_pic_marking_adaptive_mmco_4(
2294 GstVaapiDecoderH264 *decoder,
2295 GstVaapiPictureH264 *picture,
2296 GstH264RefPicMarking *ref_pic_marking
2299 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2300 gint32 i, long_term_frame_idx;
2302 long_term_frame_idx = ref_pic_marking->max_long_term_frame_idx_plus1 - 1;
2304 for (i = 0; i < priv->long_ref_count; i++) {
2305 if (priv->long_ref[i]->long_term_frame_idx <= long_term_frame_idx)
2307 gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0, FALSE);
2308 ARRAY_REMOVE_INDEX(priv->long_ref, i);
2313 /* 8.2.5.4.5. Mark all reference pictures as "unused for reference" */
2315 exec_ref_pic_marking_adaptive_mmco_5(
2316 GstVaapiDecoderH264 *decoder,
2317 GstVaapiPictureH264 *picture,
2318 GstH264RefPicMarking *ref_pic_marking
2321 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2325 priv->prev_pic_has_mmco5 = TRUE;
2327 /* The picture shall be inferred to have had frame_num equal to 0 (7.4.3) */
2328 priv->frame_num = 0;
2329 priv->frame_num_offset = 0;
2330 picture->frame_num = 0;
2332 /* Update TopFieldOrderCnt and BottomFieldOrderCnt (8.2.1) */
2333 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
2334 picture->field_poc[TOP_FIELD] -= picture->base.poc;
2335 if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
2336 picture->field_poc[BOTTOM_FIELD] -= picture->base.poc;
2337 picture->base.poc = 0;
2340 /* 8.2.5.4.6. Assign a long-term frame index to the current picture */
2342 exec_ref_pic_marking_adaptive_mmco_6(
2343 GstVaapiDecoderH264 *decoder,
2344 GstVaapiPictureH264 *picture,
2345 GstH264RefPicMarking *ref_pic_marking
2348 picture->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
2349 gst_vaapi_picture_h264_set_reference(picture,
2350 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE, FALSE);
2353 /* 8.2.5.4. Adaptive memory control decoded reference picture marking process */
2355 exec_ref_pic_marking_adaptive(
2356 GstVaapiDecoderH264 *decoder,
2357 GstVaapiPictureH264 *picture,
2358 GstH264DecRefPicMarking *dec_ref_pic_marking
2363 GST_DEBUG("reference picture marking process (adaptive memory control)");
2365 typedef void (*exec_ref_pic_marking_adaptive_mmco_func)(
2366 GstVaapiDecoderH264 *decoder,
2367 GstVaapiPictureH264 *picture,
2368 GstH264RefPicMarking *ref_pic_marking
2371 static const exec_ref_pic_marking_adaptive_mmco_func mmco_funcs[] = {
2373 exec_ref_pic_marking_adaptive_mmco_1,
2374 exec_ref_pic_marking_adaptive_mmco_2,
2375 exec_ref_pic_marking_adaptive_mmco_3,
2376 exec_ref_pic_marking_adaptive_mmco_4,
2377 exec_ref_pic_marking_adaptive_mmco_5,
2378 exec_ref_pic_marking_adaptive_mmco_6,
2381 for (i = 0; i < dec_ref_pic_marking->n_ref_pic_marking; i++) {
2382 GstH264RefPicMarking * const ref_pic_marking =
2383 &dec_ref_pic_marking->ref_pic_marking[i];
2385 const guint mmco = ref_pic_marking->memory_management_control_operation;
2386 if (mmco < G_N_ELEMENTS(mmco_funcs) && mmco_funcs[mmco])
2387 mmco_funcs[mmco](decoder, picture, ref_pic_marking);
2389 GST_ERROR("unhandled MMCO %u", mmco);
2396 /* 8.2.5 - Execute reference picture marking process */
2398 exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
2400 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2402 priv->prev_pic_has_mmco5 = FALSE;
2403 priv->prev_pic_structure = picture->structure;
2405 if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
2408 if (!GST_VAAPI_PICTURE_IS_IDR(picture)) {
2409 GstH264DecRefPicMarking * const dec_ref_pic_marking =
2410 &picture->last_slice_hdr->dec_ref_pic_marking;
2411 if (dec_ref_pic_marking->adaptive_ref_pic_marking_mode_flag) {
2412 if (!exec_ref_pic_marking_adaptive(decoder, picture, dec_ref_pic_marking))
2416 if (!exec_ref_pic_marking_sliding_window(decoder))
2424 vaapi_init_picture(VAPictureH264 *pic)
2426 pic->picture_id = VA_INVALID_ID;
2428 pic->flags = VA_PICTURE_H264_INVALID;
2429 pic->TopFieldOrderCnt = 0;
2430 pic->BottomFieldOrderCnt = 0;
2434 vaapi_fill_picture(VAPictureH264 *pic, GstVaapiPictureH264 *picture,
2435 guint picture_structure)
2437 if (!picture_structure)
2438 picture_structure = picture->structure;
2440 pic->picture_id = picture->base.surface_id;
2443 if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture)) {
2444 pic->flags |= VA_PICTURE_H264_LONG_TERM_REFERENCE;
2445 pic->frame_idx = picture->long_term_frame_idx;
2448 if (GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
2449 pic->flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2450 pic->frame_idx = picture->frame_num;
2453 switch (picture_structure) {
2454 case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
2455 pic->TopFieldOrderCnt = picture->field_poc[TOP_FIELD];
2456 pic->BottomFieldOrderCnt = picture->field_poc[BOTTOM_FIELD];
2458 case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
2459 pic->flags |= VA_PICTURE_H264_TOP_FIELD;
2460 pic->TopFieldOrderCnt = picture->field_poc[TOP_FIELD];
2461 pic->BottomFieldOrderCnt = 0;
2463 case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
2464 pic->flags |= VA_PICTURE_H264_BOTTOM_FIELD;
2465 pic->BottomFieldOrderCnt = picture->field_poc[BOTTOM_FIELD];
2466 pic->TopFieldOrderCnt = 0;
2472 fill_picture(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
2474 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2475 GstVaapiPicture * const base_picture = &picture->base;
2476 GstH264PPS * const pps = get_pps(decoder);
2477 GstH264SPS * const sps = get_sps(decoder);
2478 VAPictureParameterBufferH264 * const pic_param = base_picture->param;
2481 /* Fill in VAPictureParameterBufferH264 */
2482 vaapi_fill_picture(&pic_param->CurrPic, picture, 0);
2484 for (i = 0, n = 0; i < priv->dpb_count; i++) {
2485 GstVaapiFrameStore * const fs = priv->dpb[i];
2486 if (gst_vaapi_frame_store_has_reference(fs))
2487 vaapi_fill_picture(&pic_param->ReferenceFrames[n++],
2488 fs->buffers[0], fs->structure);
2490 for (; n < G_N_ELEMENTS(pic_param->ReferenceFrames); n++)
2491 vaapi_init_picture(&pic_param->ReferenceFrames[n]);
2493 #define COPY_FIELD(s, f) \
2494 pic_param->f = (s)->f
2496 #define COPY_BFM(a, s, f) \
2497 pic_param->a.bits.f = (s)->f
2499 pic_param->picture_width_in_mbs_minus1 = priv->mb_width - 1;
2500 pic_param->picture_height_in_mbs_minus1 = priv->mb_height - 1;
2501 pic_param->frame_num = priv->frame_num;
2503 COPY_FIELD(sps, bit_depth_luma_minus8);
2504 COPY_FIELD(sps, bit_depth_chroma_minus8);
2505 COPY_FIELD(sps, num_ref_frames);
2506 COPY_FIELD(pps, num_slice_groups_minus1);
2507 COPY_FIELD(pps, slice_group_map_type);
2508 COPY_FIELD(pps, slice_group_change_rate_minus1);
2509 COPY_FIELD(pps, pic_init_qp_minus26);
2510 COPY_FIELD(pps, pic_init_qs_minus26);
2511 COPY_FIELD(pps, chroma_qp_index_offset);
2512 COPY_FIELD(pps, second_chroma_qp_index_offset);
2514 pic_param->seq_fields.value = 0; /* reset all bits */
2515 pic_param->seq_fields.bits.residual_colour_transform_flag = sps->separate_colour_plane_flag;
2516 pic_param->seq_fields.bits.MinLumaBiPredSize8x8 = sps->level_idc >= 31; /* A.3.3.2 */
2518 COPY_BFM(seq_fields, sps, chroma_format_idc);
2519 COPY_BFM(seq_fields, sps, gaps_in_frame_num_value_allowed_flag);
2520 COPY_BFM(seq_fields, sps, frame_mbs_only_flag);
2521 COPY_BFM(seq_fields, sps, mb_adaptive_frame_field_flag);
2522 COPY_BFM(seq_fields, sps, direct_8x8_inference_flag);
2523 COPY_BFM(seq_fields, sps, log2_max_frame_num_minus4);
2524 COPY_BFM(seq_fields, sps, pic_order_cnt_type);
2525 COPY_BFM(seq_fields, sps, log2_max_pic_order_cnt_lsb_minus4);
2526 COPY_BFM(seq_fields, sps, delta_pic_order_always_zero_flag);
2528 pic_param->pic_fields.value = 0; /* reset all bits */
2529 pic_param->pic_fields.bits.field_pic_flag = GST_VAAPI_PICTURE_IS_INTERLACED(picture);
2530 pic_param->pic_fields.bits.reference_pic_flag = GST_VAAPI_PICTURE_IS_REFERENCE(picture);
2532 COPY_BFM(pic_fields, pps, entropy_coding_mode_flag);
2533 COPY_BFM(pic_fields, pps, weighted_pred_flag);
2534 COPY_BFM(pic_fields, pps, weighted_bipred_idc);
2535 COPY_BFM(pic_fields, pps, transform_8x8_mode_flag);
2536 COPY_BFM(pic_fields, pps, constrained_intra_pred_flag);
2537 COPY_BFM(pic_fields, pps, pic_order_present_flag);
2538 COPY_BFM(pic_fields, pps, deblocking_filter_control_present_flag);
2539 COPY_BFM(pic_fields, pps, redundant_pic_cnt_present_flag);
2543 /* Detection of the first VCL NAL unit of a primary coded picture (7.4.1.2.4) */
2545 is_new_picture(GstVaapiParserInfoH264 *pi, GstVaapiParserInfoH264 *prev_pi)
2547 GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
2548 GstH264PPS * const pps = slice_hdr->pps;
2549 GstH264SPS * const sps = pps->sequence;
2550 GstH264SliceHdr *prev_slice_hdr;
2554 prev_slice_hdr = &prev_pi->data.slice_hdr;
2556 #define CHECK_EXPR(expr, field_name) do { \
2558 GST_DEBUG(field_name " differs in value"); \
2563 #define CHECK_VALUE(new_slice_hdr, old_slice_hdr, field) \
2564 CHECK_EXPR(((new_slice_hdr)->field == (old_slice_hdr)->field), #field)
2566 /* frame_num differs in value, regardless of inferred values to 0 */
2567 CHECK_VALUE(slice_hdr, prev_slice_hdr, frame_num);
2569 /* pic_parameter_set_id differs in value */
2570 CHECK_VALUE(slice_hdr, prev_slice_hdr, pps);
2572 /* field_pic_flag differs in value */
2573 CHECK_VALUE(slice_hdr, prev_slice_hdr, field_pic_flag);
2575 /* bottom_field_flag is present in both and differs in value */
2576 if (slice_hdr->field_pic_flag && prev_slice_hdr->field_pic_flag)
2577 CHECK_VALUE(slice_hdr, prev_slice_hdr, bottom_field_flag);
2579 /* nal_ref_idc differs in value with one of the nal_ref_idc values is 0 */
2580 CHECK_EXPR((pi->nalu.ref_idc != 0) ==
2581 (prev_pi->nalu.ref_idc != 0), "nal_ref_idc");
2583 /* POC type is 0 for both and either pic_order_cnt_lsb differs in
2584 value or delta_pic_order_cnt_bottom differs in value */
2585 if (sps->pic_order_cnt_type == 0) {
2586 CHECK_VALUE(slice_hdr, prev_slice_hdr, pic_order_cnt_lsb);
2587 if (pps->pic_order_present_flag && !slice_hdr->field_pic_flag)
2588 CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt_bottom);
2591 /* POC type is 1 for both and either delta_pic_order_cnt[0]
2592 differs in value or delta_pic_order_cnt[1] differs in value */
2593 else if (sps->pic_order_cnt_type == 1) {
2594 CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt[0]);
2595 CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt[1]);
2598 /* IdrPicFlag differs in value */
2599 CHECK_VALUE(&pi->nalu, &prev_pi->nalu, idr_pic_flag);
2601 /* IdrPicFlag is equal to 1 for both and idr_pic_id differs in value */
2602 if (pi->nalu.idr_pic_flag)
2603 CHECK_VALUE(slice_hdr, prev_slice_hdr, idr_pic_id);
2610 static GstVaapiDecoderStatus
2611 decode_picture(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
2613 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2614 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
2615 GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
2616 GstH264PPS * const pps = ensure_pps(decoder, slice_hdr->pps);
2617 GstH264SPS * const sps = ensure_sps(decoder, slice_hdr->pps->sequence);
2618 GstVaapiPictureH264 *picture;
2619 GstVaapiDecoderStatus status;
2621 g_return_val_if_fail(pps != NULL, GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN);
2622 g_return_val_if_fail(sps != NULL, GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN);
2624 status = ensure_context(decoder, sps);
2625 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2628 priv->decoder_state = 0;
2630 if (priv->current_picture) {
2631 /* Re-use current picture where the first field was decoded */
2632 picture = gst_vaapi_picture_h264_new_field(priv->current_picture);
2634 GST_ERROR("failed to allocate field picture");
2635 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2639 /* Create new picture */
2640 picture = gst_vaapi_picture_h264_new(decoder);
2642 GST_ERROR("failed to allocate picture");
2643 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2646 gst_vaapi_picture_replace(&priv->current_picture, picture);
2647 gst_vaapi_picture_unref(picture);
2649 /* Update cropping rectangle */
2650 if (sps->frame_cropping_flag) {
2651 GstVaapiRectangle crop_rect;
2652 crop_rect.x = sps->crop_rect_x;
2653 crop_rect.y = sps->crop_rect_y;
2654 crop_rect.width = sps->crop_rect_width;
2655 crop_rect.height = sps->crop_rect_height;
2656 gst_vaapi_picture_set_crop_rect(&picture->base, &crop_rect);
2659 status = ensure_quant_matrix(decoder, picture);
2660 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
2661 GST_ERROR("failed to reset quantizer matrix");
2665 if (!init_picture(decoder, picture, pi))
2666 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2667 if (!fill_picture(decoder, picture))
2668 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2670 priv->decoder_state = pi->state;
2671 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2675 get_slice_data_bit_offset(GstH264SliceHdr *slice_hdr)
2679 epb_count = slice_hdr->n_emulation_prevention_bytes;
2680 return 8 /* nal_unit_type */ + slice_hdr->header_size - epb_count * 8;
2684 fill_pred_weight_table(GstVaapiDecoderH264 *decoder,
2685 GstVaapiSlice *slice, GstH264SliceHdr *slice_hdr)
2687 VASliceParameterBufferH264 * const slice_param = slice->param;
2688 GstH264PPS * const pps = get_pps(decoder);
2689 GstH264SPS * const sps = get_sps(decoder);
2690 GstH264PredWeightTable * const w = &slice_hdr->pred_weight_table;
2691 guint num_weight_tables = 0;
2694 if (pps->weighted_pred_flag &&
2695 (GST_H264_IS_P_SLICE(slice_hdr) || GST_H264_IS_SP_SLICE(slice_hdr)))
2696 num_weight_tables = 1;
2697 else if (pps->weighted_bipred_idc == 1 && GST_H264_IS_B_SLICE(slice_hdr))
2698 num_weight_tables = 2;
2700 num_weight_tables = 0;
2702 slice_param->luma_log2_weight_denom = 0;
2703 slice_param->chroma_log2_weight_denom = 0;
2704 slice_param->luma_weight_l0_flag = 0;
2705 slice_param->chroma_weight_l0_flag = 0;
2706 slice_param->luma_weight_l1_flag = 0;
2707 slice_param->chroma_weight_l1_flag = 0;
2709 if (num_weight_tables < 1)
2712 slice_param->luma_log2_weight_denom = w->luma_log2_weight_denom;
2713 slice_param->chroma_log2_weight_denom = w->chroma_log2_weight_denom;
2715 slice_param->luma_weight_l0_flag = 1;
2716 for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
2717 slice_param->luma_weight_l0[i] = w->luma_weight_l0[i];
2718 slice_param->luma_offset_l0[i] = w->luma_offset_l0[i];
2721 slice_param->chroma_weight_l0_flag = sps->chroma_array_type != 0;
2722 if (slice_param->chroma_weight_l0_flag) {
2723 for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
2724 for (j = 0; j < 2; j++) {
2725 slice_param->chroma_weight_l0[i][j] = w->chroma_weight_l0[i][j];
2726 slice_param->chroma_offset_l0[i][j] = w->chroma_offset_l0[i][j];
2731 if (num_weight_tables < 2)
2734 slice_param->luma_weight_l1_flag = 1;
2735 for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
2736 slice_param->luma_weight_l1[i] = w->luma_weight_l1[i];
2737 slice_param->luma_offset_l1[i] = w->luma_offset_l1[i];
2740 slice_param->chroma_weight_l1_flag = sps->chroma_array_type != 0;
2741 if (slice_param->chroma_weight_l1_flag) {
2742 for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
2743 for (j = 0; j < 2; j++) {
2744 slice_param->chroma_weight_l1[i][j] = w->chroma_weight_l1[i][j];
2745 slice_param->chroma_offset_l1[i][j] = w->chroma_offset_l1[i][j];
2753 fill_RefPicList(GstVaapiDecoderH264 *decoder,
2754 GstVaapiSlice *slice, GstH264SliceHdr *slice_hdr)
2756 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2757 VASliceParameterBufferH264 * const slice_param = slice->param;
2758 guint i, num_ref_lists = 0;
2760 slice_param->num_ref_idx_l0_active_minus1 = 0;
2761 slice_param->num_ref_idx_l1_active_minus1 = 0;
2763 if (GST_H264_IS_B_SLICE(slice_hdr))
2765 else if (GST_H264_IS_I_SLICE(slice_hdr))
2770 if (num_ref_lists < 1)
2773 slice_param->num_ref_idx_l0_active_minus1 =
2774 slice_hdr->num_ref_idx_l0_active_minus1;
2776 for (i = 0; i < priv->RefPicList0_count && priv->RefPicList0[i]; i++)
2777 vaapi_fill_picture(&slice_param->RefPicList0[i], priv->RefPicList0[i], 0);
2778 for (; i <= slice_param->num_ref_idx_l0_active_minus1; i++)
2779 vaapi_init_picture(&slice_param->RefPicList0[i]);
2781 if (num_ref_lists < 2)
2784 slice_param->num_ref_idx_l1_active_minus1 =
2785 slice_hdr->num_ref_idx_l1_active_minus1;
2787 for (i = 0; i < priv->RefPicList1_count && priv->RefPicList1[i]; i++)
2788 vaapi_fill_picture(&slice_param->RefPicList1[i], priv->RefPicList1[i], 0);
2789 for (; i <= slice_param->num_ref_idx_l1_active_minus1; i++)
2790 vaapi_init_picture(&slice_param->RefPicList1[i]);
2795 fill_slice(GstVaapiDecoderH264 *decoder,
2796 GstVaapiSlice *slice, GstH264SliceHdr *slice_hdr)
2798 VASliceParameterBufferH264 * const slice_param = slice->param;
2800 /* Fill in VASliceParameterBufferH264 */
2801 slice_param->slice_data_bit_offset = get_slice_data_bit_offset(slice_hdr);
2802 slice_param->first_mb_in_slice = slice_hdr->first_mb_in_slice;
2803 slice_param->slice_type = slice_hdr->type % 5;
2804 slice_param->direct_spatial_mv_pred_flag = slice_hdr->direct_spatial_mv_pred_flag;
2805 slice_param->cabac_init_idc = slice_hdr->cabac_init_idc;
2806 slice_param->slice_qp_delta = slice_hdr->slice_qp_delta;
2807 slice_param->disable_deblocking_filter_idc = slice_hdr->disable_deblocking_filter_idc;
2808 slice_param->slice_alpha_c0_offset_div2 = slice_hdr->slice_alpha_c0_offset_div2;
2809 slice_param->slice_beta_offset_div2 = slice_hdr->slice_beta_offset_div2;
2811 if (!fill_RefPicList(decoder, slice, slice_hdr))
2813 if (!fill_pred_weight_table(decoder, slice, slice_hdr))
2818 static GstVaapiDecoderStatus
2819 decode_slice(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
2821 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2822 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
2823 GstVaapiPictureH264 * const picture = priv->current_picture;
2824 GstH264SliceHdr * const slice_hdr = &pi->data.slice_hdr;
2825 GstVaapiSlice *slice;
2826 GstBuffer * const buffer =
2827 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer;
2828 GstMapInfo map_info;
2830 GST_DEBUG("slice (%u bytes)", pi->nalu.size);
2832 if (!is_valid_state(pi->state,
2833 GST_H264_VIDEO_STATE_VALID_PICTURE_HEADERS)) {
2834 GST_WARNING("failed to receive enough headers to decode slice");
2835 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2838 if (!ensure_pps(decoder, slice_hdr->pps)) {
2839 GST_ERROR("failed to activate PPS");
2840 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2843 if (!ensure_sps(decoder, slice_hdr->pps->sequence)) {
2844 GST_ERROR("failed to activate SPS");
2845 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2848 if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) {
2849 GST_ERROR("failed to map buffer");
2850 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2853 slice = GST_VAAPI_SLICE_NEW(H264, decoder,
2854 (map_info.data + unit->offset + pi->nalu.offset), pi->nalu.size);
2855 gst_buffer_unmap(buffer, &map_info);
2857 GST_ERROR("failed to allocate slice");
2858 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2861 if (!fill_slice(decoder, slice, slice_hdr)) {
2862 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(slice));
2863 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2866 gst_vaapi_picture_add_slice(GST_VAAPI_PICTURE_CAST(picture), slice);
2867 picture->last_slice_hdr = slice_hdr;
2868 priv->decoder_state |= GST_H264_VIDEO_STATE_GOT_SLICE;
2869 return GST_VAAPI_DECODER_STATUS_SUCCESS;
2873 scan_for_start_code(GstAdapter *adapter, guint ofs, guint size, guint32 *scp)
2875 return (gint)gst_adapter_masked_scan_uint32_peek(adapter,
2876 0xffffff00, 0x00000100,
2881 static GstVaapiDecoderStatus
2882 decode_unit(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit)
2884 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2885 GstVaapiParserInfoH264 * const pi = unit->parsed_info;
2886 GstVaapiDecoderStatus status;
2888 priv->decoder_state |= pi->state;
2889 switch (pi->nalu.type) {
2890 case GST_H264_NAL_SPS:
2891 status = decode_sps(decoder, unit);
2893 case GST_H264_NAL_PPS:
2894 status = decode_pps(decoder, unit);
2896 case GST_H264_NAL_SLICE_IDR:
2897 /* fall-through. IDR specifics are handled in init_picture() */
2898 case GST_H264_NAL_SLICE:
2899 status = decode_slice(decoder, unit);
2901 case GST_H264_NAL_SEQ_END:
2902 case GST_H264_NAL_STREAM_END:
2903 status = decode_sequence_end(decoder);
2905 case GST_H264_NAL_SEI:
2906 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
2909 GST_WARNING("unsupported NAL unit type %d", pi->nalu.type);
2910 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
2916 static GstVaapiDecoderStatus
2917 gst_vaapi_decoder_h264_decode_codec_data(GstVaapiDecoder *base_decoder,
2918 const guchar *buf, guint buf_size)
2920 GstVaapiDecoderH264 * const decoder =
2921 GST_VAAPI_DECODER_H264_CAST(base_decoder);
2922 GstVaapiDecoderH264Private * const priv = &decoder->priv;
2923 GstVaapiDecoderStatus status;
2924 GstVaapiDecoderUnit unit;
2925 GstVaapiParserInfoH264 *pi = NULL;
2926 GstH264ParserResult result;
2927 guint i, ofs, num_sps, num_pps;
2929 unit.parsed_info = NULL;
2932 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
2935 GST_ERROR("failed to decode codec-data, not in avcC format");
2936 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
2939 priv->nal_length_size = (buf[4] & 0x03) + 1;
2941 num_sps = buf[5] & 0x1f;
2944 for (i = 0; i < num_sps; i++) {
2945 pi = gst_vaapi_parser_info_h264_new();
2947 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2948 unit.parsed_info = pi;
2950 result = gst_h264_parser_identify_nalu_avc(
2952 buf, ofs, buf_size, 2,
2955 if (result != GST_H264_PARSER_OK) {
2956 status = get_status(result);
2960 status = parse_sps(decoder, &unit);
2961 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2963 ofs = pi->nalu.offset + pi->nalu.size;
2965 status = decode_sps(decoder, &unit);
2966 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2968 gst_vaapi_parser_info_h264_replace(&pi, NULL);
2974 for (i = 0; i < num_pps; i++) {
2975 pi = gst_vaapi_parser_info_h264_new();
2977 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2978 unit.parsed_info = pi;
2980 result = gst_h264_parser_identify_nalu_avc(
2982 buf, ofs, buf_size, 2,
2985 if (result != GST_H264_PARSER_OK) {
2986 status = get_status(result);
2990 status = parse_pps(decoder, &unit);
2991 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2993 ofs = pi->nalu.offset + pi->nalu.size;
2995 status = decode_pps(decoder, &unit);
2996 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2998 gst_vaapi_parser_info_h264_replace(&pi, NULL);
3001 priv->is_avcC = TRUE;
3002 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
3005 gst_vaapi_parser_info_h264_replace(&pi, NULL);
3009 static GstVaapiDecoderStatus
3010 ensure_decoder(GstVaapiDecoderH264 *decoder)
3012 GstVaapiDecoderH264Private * const priv = &decoder->priv;
3013 GstVaapiDecoderStatus status;
3015 if (!priv->is_opened) {
3016 priv->is_opened = gst_vaapi_decoder_h264_open(decoder);
3017 if (!priv->is_opened)
3018 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
3020 status = gst_vaapi_decoder_decode_codec_data(
3021 GST_VAAPI_DECODER_CAST(decoder));
3022 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3025 return GST_VAAPI_DECODER_STATUS_SUCCESS;
3028 static GstVaapiDecoderStatus
3029 gst_vaapi_decoder_h264_parse(GstVaapiDecoder *base_decoder,
3030 GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit *unit)
3032 GstVaapiDecoderH264 * const decoder =
3033 GST_VAAPI_DECODER_H264_CAST(base_decoder);
3034 GstVaapiDecoderH264Private * const priv = &decoder->priv;
3035 GstVaapiParserState * const ps = GST_VAAPI_PARSER_STATE(base_decoder);
3036 GstVaapiParserInfoH264 *pi;
3037 GstVaapiDecoderStatus status;
3038 GstH264ParserResult result;
3040 guint i, size, buf_size, nalu_size, flags;
3044 status = ensure_decoder(decoder);
3045 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3048 size = gst_adapter_available(adapter);
3050 if (priv->is_avcC) {
3051 if (size < priv->nal_length_size)
3052 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3054 buf = (guchar *)&start_code;
3055 g_assert(priv->nal_length_size <= sizeof(start_code));
3056 gst_adapter_copy(adapter, buf, 0, priv->nal_length_size);
3059 for (i = 0; i < priv->nal_length_size; i++)
3060 nalu_size = (nalu_size << 8) | buf[i];
3062 buf_size = priv->nal_length_size + nalu_size;
3063 if (size < buf_size)
3064 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3068 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3070 ofs = scan_for_start_code(adapter, 0, size, NULL);
3072 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3075 gst_adapter_flush(adapter, ofs);
3079 ofs2 = ps->input_offset2 - ofs - 4;
3083 ofs = G_UNLIKELY(size < ofs2 + 4) ? -1 :
3084 scan_for_start_code(adapter, ofs2, size - ofs2, NULL);
3086 // Assume the whole NAL unit is present if end-of-stream
3088 ps->input_offset2 = size;
3089 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3095 ps->input_offset2 = 0;
3097 buf = (guchar *)gst_adapter_map(adapter, buf_size);
3099 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3101 unit->size = buf_size;
3103 pi = gst_vaapi_parser_info_h264_new();
3105 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
3107 gst_vaapi_decoder_unit_set_parsed_info(unit,
3108 pi, (GDestroyNotify)gst_vaapi_mini_object_unref);
3111 result = gst_h264_parser_identify_nalu_avc(priv->parser,
3112 buf, 0, buf_size, priv->nal_length_size, &pi->nalu);
3114 result = gst_h264_parser_identify_nalu_unchecked(priv->parser,
3115 buf, 0, buf_size, &pi->nalu);
3116 status = get_status(result);
3117 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3120 switch (pi->nalu.type) {
3121 case GST_H264_NAL_SPS:
3122 status = parse_sps(decoder, unit);
3124 case GST_H264_NAL_PPS:
3125 status = parse_pps(decoder, unit);
3127 case GST_H264_NAL_SEI:
3128 status = parse_sei(decoder, unit);
3130 case GST_H264_NAL_SLICE_IDR:
3131 case GST_H264_NAL_SLICE:
3132 status = parse_slice(decoder, unit);
3135 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
3138 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3142 switch (pi->nalu.type) {
3143 case GST_H264_NAL_AU_DELIMITER:
3144 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
3146 case GST_H264_NAL_FILLER_DATA:
3147 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
3149 case GST_H264_NAL_STREAM_END:
3150 flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
3152 case GST_H264_NAL_SEQ_END:
3153 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
3155 case GST_H264_NAL_SPS:
3156 case GST_H264_NAL_PPS:
3157 case GST_H264_NAL_SEI:
3158 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
3160 case GST_H264_NAL_SLICE_IDR:
3161 case GST_H264_NAL_SLICE:
3162 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
3163 if (is_new_picture(pi, priv->prev_slice_pi))
3164 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
3165 gst_vaapi_parser_info_h264_replace(&priv->prev_slice_pi, pi);
3168 if (pi->nalu.type >= 14 && pi->nalu.type <= 18)
3169 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
3172 GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
3174 pi->nalu.data = NULL;
3175 pi->state = priv->parser_state;
3176 return GST_VAAPI_DECODER_STATUS_SUCCESS;
3179 static GstVaapiDecoderStatus
3180 gst_vaapi_decoder_h264_decode(GstVaapiDecoder *base_decoder,
3181 GstVaapiDecoderUnit *unit)
3183 GstVaapiDecoderH264 * const decoder =
3184 GST_VAAPI_DECODER_H264_CAST(base_decoder);
3185 GstVaapiDecoderStatus status;
3187 status = ensure_decoder(decoder);
3188 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3190 return decode_unit(decoder, unit);
3193 static GstVaapiDecoderStatus
3194 gst_vaapi_decoder_h264_start_frame(GstVaapiDecoder *base_decoder,
3195 GstVaapiDecoderUnit *unit)
3197 GstVaapiDecoderH264 * const decoder =
3198 GST_VAAPI_DECODER_H264_CAST(base_decoder);
3200 return decode_picture(decoder, unit);
3203 static GstVaapiDecoderStatus
3204 gst_vaapi_decoder_h264_end_frame(GstVaapiDecoder *base_decoder)
3206 GstVaapiDecoderH264 * const decoder =
3207 GST_VAAPI_DECODER_H264_CAST(base_decoder);
3209 return decode_current_picture(decoder);
3212 static GstVaapiDecoderStatus
3213 gst_vaapi_decoder_h264_flush(GstVaapiDecoder *base_decoder)
3215 GstVaapiDecoderH264 * const decoder =
3216 GST_VAAPI_DECODER_H264_CAST(base_decoder);
3219 return GST_VAAPI_DECODER_STATUS_SUCCESS;
3223 gst_vaapi_decoder_h264_class_init(GstVaapiDecoderH264Class *klass)
3225 GstVaapiMiniObjectClass * const object_class =
3226 GST_VAAPI_MINI_OBJECT_CLASS(klass);
3227 GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
3229 object_class->size = sizeof(GstVaapiDecoderH264);
3230 object_class->finalize = (GDestroyNotify)gst_vaapi_decoder_finalize;
3232 decoder_class->create = gst_vaapi_decoder_h264_create;
3233 decoder_class->destroy = gst_vaapi_decoder_h264_destroy;
3234 decoder_class->parse = gst_vaapi_decoder_h264_parse;
3235 decoder_class->decode = gst_vaapi_decoder_h264_decode;
3236 decoder_class->start_frame = gst_vaapi_decoder_h264_start_frame;
3237 decoder_class->end_frame = gst_vaapi_decoder_h264_end_frame;
3238 decoder_class->flush = gst_vaapi_decoder_h264_flush;
3240 decoder_class->decode_codec_data =
3241 gst_vaapi_decoder_h264_decode_codec_data;
3244 static inline const GstVaapiDecoderClass *
3245 gst_vaapi_decoder_h264_class(void)
3247 static GstVaapiDecoderH264Class g_class;
3248 static gsize g_class_init = FALSE;
3250 if (g_once_init_enter(&g_class_init)) {
3251 gst_vaapi_decoder_h264_class_init(&g_class);
3252 g_once_init_leave(&g_class_init, TRUE);
3254 return GST_VAAPI_DECODER_CLASS(&g_class);
3258 * gst_vaapi_decoder_h264_new:
3259 * @display: a #GstVaapiDisplay
3260 * @caps: a #GstCaps holding codec information
3262 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
3263 * hold extra information like codec-data and pictured coded size.
3265 * Return value: the newly allocated #GstVaapiDecoder object
3268 gst_vaapi_decoder_h264_new(GstVaapiDisplay *display, GstCaps *caps)
3270 return gst_vaapi_decoder_new(gst_vaapi_decoder_h264_class(), display, caps);