2 * gstvaapiencoder_h264_fei.c - H.264 FEI encoder
4 * Copyright (C) 2016-2017 Intel Corporation
5 * Author: Yi A Wang <yi.a.wang@intel.com>
6 * Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1
11 * of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301 USA
24 /* GValueArray has deprecated without providing an alternative in glib >= 2.32
25 * See https://bugzilla.gnome.org/show_bug.cgi?id=667228
27 #define GLIB_DISABLE_DEPRECATION_WARNINGS
31 #include <va/va_enc_h264.h>
32 #include <gst/base/gstbitwriter.h>
33 #include <gst/codecparsers/gsth264parser.h>
34 #include "gstvaapicompat.h"
35 #include "gstvaapiencoder_priv.h"
36 #include "gstvaapiutils_h264_priv.h"
37 #include "gstvaapicodedbufferproxy_priv.h"
38 #include "gstvaapisurfaceproxy_priv.h"
39 #include "gstvaapisurface.h"
40 #include "gstvaapifeiutils_h264.h"
41 #include "gstvaapiencoder_h264_fei.h"
42 #include "gstvaapifeienc_h264.h"
43 #include "gstvaapifeipak_h264.h"
44 #include "gstvaapiutils.h"
45 #include "gstvaapiutils_core.h"
46 #include "gstvaapifei_objects_priv.h"
48 #include "gstvaapidebug.h"
51 gst_vaapi_encoder_h264_fei_ensure_secondary_context (GstVaapiEncoder *
54 /* Define the maximum number of views supported */
55 #define MAX_NUM_VIEWS 10
57 /* Define the maximum value for view-id */
58 #define MAX_VIEW_ID 1023
60 /* Default CPB length (in milliseconds) */
61 #define DEFAULT_CPB_LENGTH 1500
63 /* Scale factor for CPB size (HRD cpb_size_scale: min = 4) */
66 /* Scale factor for bitrate (HRD bit_rate_scale: min = 6) */
69 /* Define default rate control mode ("constant-qp") */
70 #define DEFAULT_RATECONTROL GST_VAAPI_RATECONTROL_CQP
72 /* Supported set of VA rate controls, within this implementation */
73 #define SUPPORTED_RATECONTROLS \
74 (GST_VAAPI_RATECONTROL_MASK (CQP) | \
75 GST_VAAPI_RATECONTROL_MASK (CBR) | \
76 GST_VAAPI_RATECONTROL_MASK (VBR) | \
77 GST_VAAPI_RATECONTROL_MASK (VBR_CONSTRAINED))
79 /* Supported set of tuning options, within this implementation */
80 #define SUPPORTED_TUNE_OPTIONS \
81 (GST_VAAPI_ENCODER_TUNE_MASK (NONE) | \
82 GST_VAAPI_ENCODER_TUNE_MASK (HIGH_COMPRESSION) | \
83 GST_VAAPI_ENCODER_TUNE_MASK (LOW_POWER))
85 /* Supported set of VA packed headers, within this implementation */
86 #define SUPPORTED_PACKED_HEADERS \
87 (VA_ENC_PACKED_HEADER_SEQUENCE | \
88 VA_ENC_PACKED_HEADER_PICTURE | \
89 VA_ENC_PACKED_HEADER_SLICE | \
90 VA_ENC_PACKED_HEADER_RAW_DATA | \
91 VA_ENC_PACKED_HEADER_MISC)
93 #define GST_H264_NAL_REF_IDC_NONE 0
94 #define GST_H264_NAL_REF_IDC_LOW 1
95 #define GST_H264_NAL_REF_IDC_MEDIUM 2
96 #define GST_H264_NAL_REF_IDC_HIGH 3
98 /* only for internal usage, values won't be equal to actual payload type */
101 GST_VAAPI_H264_SEI_UNKNOWN = 0,
102 GST_VAAPI_H264_SEI_BUF_PERIOD = (1 << 0),
103 GST_VAAPI_H264_SEI_PIC_TIMING = (1 << 1)
104 } GstVaapiH264SeiPayloadType;
108 GstVaapiSurfaceProxy *pic;
111 } GstVaapiEncoderH264FeiRef;
115 GST_VAAPI_ENC_H264_REORD_NONE = 0,
116 GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES = 1,
117 GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES = 2
118 } GstVaapiEncH264ReorderState;
120 typedef struct _GstVaapiH264ViewRefPool
123 guint max_ref_frames;
124 guint max_reflist0_count;
125 guint max_reflist1_count;
126 } GstVaapiH264ViewRefPool;
128 typedef struct _GstVaapiH264ViewReorderPool
130 GQueue reorder_frame_list;
133 guint frame_count; /* monotonically increasing with in every idr period */
135 guint cur_present_index;
136 } GstVaapiH264ViewReorderPool;
138 static inline gboolean
139 _poc_greater_than (guint poc1, guint poc2, guint max_poc)
141 return (((poc1 - poc2) & (max_poc - 1)) < max_poc / 2);
144 /* Get slice_type value for H.264 specification */
146 h264_get_slice_type (GstVaapiPictureType type)
149 case GST_VAAPI_PICTURE_TYPE_I:
150 return GST_H264_I_SLICE;
151 case GST_VAAPI_PICTURE_TYPE_P:
152 return GST_H264_P_SLICE;
153 case GST_VAAPI_PICTURE_TYPE_B:
154 return GST_H264_B_SLICE;
161 /* Get log2_max_frame_num value for H.264 specification */
163 h264_get_log2_max_frame_num (guint num)
175 /* must be greater than 4 */
179 /* Determines the cpbBrNalFactor based on the supplied profile */
181 h264_get_cpb_nal_factor (GstVaapiProfile profile)
187 case GST_VAAPI_PROFILE_H264_HIGH:
190 case GST_VAAPI_PROFILE_H264_HIGH10:
193 case GST_VAAPI_PROFILE_H264_HIGH_422:
194 case GST_VAAPI_PROFILE_H264_HIGH_444:
197 case GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH:
198 case GST_VAAPI_PROFILE_H264_STEREO_HIGH:
199 f = 1500; /* H.10.2.1 (r) */
208 /* ------------------------------------------------------------------------- */
209 /* --- H.264 Bitstream Writer --- */
210 /* ------------------------------------------------------------------------- */
212 #define WRITE_UINT32(bs, val, nbits) do { \
213 if (!gst_bit_writer_put_bits_uint32 (bs, val, nbits)) { \
214 GST_WARNING ("failed to write uint32, nbits: %d", nbits); \
219 #define WRITE_UE(bs, val) do { \
220 if (!bs_write_ue (bs, val)) { \
221 GST_WARNING ("failed to write ue(v)"); \
226 #define WRITE_SE(bs, val) do { \
227 if (!bs_write_se (bs, val)) { \
228 GST_WARNING ("failed to write se(v)"); \
233 /* Write an unsigned integer Exp-Golomb-coded syntax element. i.e. ue(v) */
235 bs_write_ue (GstBitWriter * bs, guint32 value)
237 guint32 size_in_bits = 0;
238 guint32 tmp_value = ++value;
245 && !gst_bit_writer_put_bits_uint32 (bs, 0, size_in_bits - 1))
247 if (!gst_bit_writer_put_bits_uint32 (bs, value, size_in_bits))
252 /* Write a signed integer Exp-Golomb-coded syntax element. i.e. se(v) */
254 bs_write_se (GstBitWriter * bs, gint32 value)
259 new_val = -(value << 1);
261 new_val = (value << 1) - 1;
263 if (!bs_write_ue (bs, new_val))
268 /* Write the NAL unit header */
270 bs_write_nal_header (GstBitWriter * bs, guint32 nal_ref_idc,
271 guint32 nal_unit_type)
273 WRITE_UINT32 (bs, 0, 1);
274 WRITE_UINT32 (bs, nal_ref_idc, 2);
275 WRITE_UINT32 (bs, nal_unit_type, 5);
281 GST_WARNING ("failed to write NAL unit header");
286 /* Write the MVC NAL unit header extension */
288 bs_write_nal_header_mvc_extension (GstBitWriter * bs,
289 GstVaapiEncPicture * picture, guint32 view_id)
291 guint32 svc_extension_flag = 0;
292 guint32 non_idr_flag = 1;
293 guint32 priority_id = 0;
294 guint32 temporal_id = 0;
295 guint32 anchor_pic_flag = 0;
296 guint32 inter_view_flag = 0;
298 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
301 if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
303 /* svc_extension_flag == 0 for mvc stream */
304 WRITE_UINT32 (bs, svc_extension_flag, 1);
306 WRITE_UINT32 (bs, non_idr_flag, 1);
307 WRITE_UINT32 (bs, priority_id, 6);
308 WRITE_UINT32 (bs, view_id, 10);
309 WRITE_UINT32 (bs, temporal_id, 3);
310 WRITE_UINT32 (bs, anchor_pic_flag, 1);
311 WRITE_UINT32 (bs, inter_view_flag, 1);
312 WRITE_UINT32 (bs, 1, 1);
319 GST_WARNING ("failed to write NAL unit header");
324 /* Write the NAL unit trailing bits */
326 bs_write_trailing_bits (GstBitWriter * bs)
328 if (!gst_bit_writer_put_bits_uint32 (bs, 1, 1))
330 gst_bit_writer_align_bytes_unchecked (bs, 0);
336 GST_WARNING ("failed to write NAL unit trailing bits");
341 /* Write an SPS NAL unit */
343 bs_write_sps_data (GstBitWriter * bs,
344 const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
345 const VAEncMiscParameterHRD * hrd_params)
348 guint32 constraint_set0_flag, constraint_set1_flag;
349 guint32 constraint_set2_flag, constraint_set3_flag;
350 guint32 gaps_in_frame_num_value_allowed_flag = 0; // ??
351 gboolean nal_hrd_parameters_present_flag;
353 guint32 b_qpprime_y_zero_transform_bypass = 0;
354 guint32 residual_color_transform_flag = 0;
355 guint32 pic_height_in_map_units =
356 (seq_param->seq_fields.bits.frame_mbs_only_flag ?
357 seq_param->picture_height_in_mbs : seq_param->picture_height_in_mbs / 2);
358 guint32 mb_adaptive_frame_field =
359 !seq_param->seq_fields.bits.frame_mbs_only_flag;
362 profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
363 constraint_set0_flag = /* A.2.1 (baseline profile constraints) */
364 profile == GST_VAAPI_PROFILE_H264_BASELINE ||
365 profile == GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
366 constraint_set1_flag = /* A.2.2 (main profile constraints) */
367 profile == GST_VAAPI_PROFILE_H264_MAIN ||
368 profile == GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
369 constraint_set2_flag = 0;
370 constraint_set3_flag = 0;
373 WRITE_UINT32 (bs, profile_idc, 8);
374 /* constraint_set0_flag */
375 WRITE_UINT32 (bs, constraint_set0_flag, 1);
376 /* constraint_set1_flag */
377 WRITE_UINT32 (bs, constraint_set1_flag, 1);
378 /* constraint_set2_flag */
379 WRITE_UINT32 (bs, constraint_set2_flag, 1);
380 /* constraint_set3_flag */
381 WRITE_UINT32 (bs, constraint_set3_flag, 1);
382 /* reserved_zero_4bits */
383 WRITE_UINT32 (bs, 0, 4);
385 WRITE_UINT32 (bs, seq_param->level_idc, 8);
386 /* seq_parameter_set_id */
387 WRITE_UE (bs, seq_param->seq_parameter_set_id);
389 if (profile == GST_VAAPI_PROFILE_H264_HIGH ||
390 profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH ||
391 profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH) {
392 /* for high profile */
393 /* chroma_format_idc = 1, 4:2:0 */
394 WRITE_UE (bs, seq_param->seq_fields.bits.chroma_format_idc);
395 if (3 == seq_param->seq_fields.bits.chroma_format_idc) {
396 WRITE_UINT32 (bs, residual_color_transform_flag, 1);
398 /* bit_depth_luma_minus8 */
399 WRITE_UE (bs, seq_param->bit_depth_luma_minus8);
400 /* bit_depth_chroma_minus8 */
401 WRITE_UE (bs, seq_param->bit_depth_chroma_minus8);
402 /* b_qpprime_y_zero_transform_bypass */
403 WRITE_UINT32 (bs, b_qpprime_y_zero_transform_bypass, 1);
405 /* seq_scaling_matrix_present_flag */
406 g_assert (seq_param->seq_fields.bits.seq_scaling_matrix_present_flag == 0);
408 seq_param->seq_fields.bits.seq_scaling_matrix_present_flag, 1);
411 if (seq_param->seq_fields.bits.seq_scaling_matrix_present_flag) {
413 i < (seq_param->seq_fields.bits.chroma_format_idc != 3 ? 8 : 12);
415 gst_bit_writer_put_bits_uint8 (bs,
416 seq_param->seq_fields.bits.seq_scaling_list_present_flag, 1);
417 if (seq_param->seq_fields.bits.seq_scaling_list_present_flag) {
419 /* FIXME, need write scaling list if seq_scaling_matrix_present_flag ==1 */
426 /* log2_max_frame_num_minus4 */
427 WRITE_UE (bs, seq_param->seq_fields.bits.log2_max_frame_num_minus4);
428 /* pic_order_cnt_type */
429 WRITE_UE (bs, seq_param->seq_fields.bits.pic_order_cnt_type);
431 if (seq_param->seq_fields.bits.pic_order_cnt_type == 0) {
432 /* log2_max_pic_order_cnt_lsb_minus4 */
433 WRITE_UE (bs, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4);
434 } else if (seq_param->seq_fields.bits.pic_order_cnt_type == 1) {
435 g_assert (0 && "only POC type 0 is supported");
437 seq_param->seq_fields.bits.delta_pic_order_always_zero_flag, 1);
438 WRITE_SE (bs, seq_param->offset_for_non_ref_pic);
439 WRITE_SE (bs, seq_param->offset_for_top_to_bottom_field);
440 WRITE_UE (bs, seq_param->num_ref_frames_in_pic_order_cnt_cycle);
441 for (i = 0; i < seq_param->num_ref_frames_in_pic_order_cnt_cycle; i++) {
442 WRITE_SE (bs, seq_param->offset_for_ref_frame[i]);
447 WRITE_UE (bs, seq_param->max_num_ref_frames);
448 /* gaps_in_frame_num_value_allowed_flag */
449 WRITE_UINT32 (bs, gaps_in_frame_num_value_allowed_flag, 1);
451 /* pic_width_in_mbs_minus1 */
452 WRITE_UE (bs, seq_param->picture_width_in_mbs - 1);
453 /* pic_height_in_map_units_minus1 */
454 WRITE_UE (bs, pic_height_in_map_units - 1);
455 /* frame_mbs_only_flag */
456 WRITE_UINT32 (bs, seq_param->seq_fields.bits.frame_mbs_only_flag, 1);
458 if (!seq_param->seq_fields.bits.frame_mbs_only_flag) { //ONLY mbs
459 g_assert (0 && "only progressive frames encoding is supported");
460 WRITE_UINT32 (bs, mb_adaptive_frame_field, 1);
463 /* direct_8x8_inference_flag */
464 WRITE_UINT32 (bs, 0, 1);
465 /* frame_cropping_flag */
466 WRITE_UINT32 (bs, seq_param->frame_cropping_flag, 1);
468 if (seq_param->frame_cropping_flag) {
469 /* frame_crop_left_offset */
470 WRITE_UE (bs, seq_param->frame_crop_left_offset);
471 /* frame_crop_right_offset */
472 WRITE_UE (bs, seq_param->frame_crop_right_offset);
473 /* frame_crop_top_offset */
474 WRITE_UE (bs, seq_param->frame_crop_top_offset);
475 /* frame_crop_bottom_offset */
476 WRITE_UE (bs, seq_param->frame_crop_bottom_offset);
479 /* vui_parameters_present_flag */
480 WRITE_UINT32 (bs, seq_param->vui_parameters_present_flag, 1);
481 if (seq_param->vui_parameters_present_flag) {
482 /* aspect_ratio_info_present_flag */
484 seq_param->vui_fields.bits.aspect_ratio_info_present_flag, 1);
485 if (seq_param->vui_fields.bits.aspect_ratio_info_present_flag) {
486 WRITE_UINT32 (bs, seq_param->aspect_ratio_idc, 8);
487 if (seq_param->aspect_ratio_idc == 0xFF) {
488 WRITE_UINT32 (bs, seq_param->sar_width, 16);
489 WRITE_UINT32 (bs, seq_param->sar_height, 16);
493 /* overscan_info_present_flag */
494 WRITE_UINT32 (bs, 0, 1);
495 /* video_signal_type_present_flag */
496 WRITE_UINT32 (bs, 0, 1);
497 /* chroma_loc_info_present_flag */
498 WRITE_UINT32 (bs, 0, 1);
500 /* timing_info_present_flag */
501 WRITE_UINT32 (bs, seq_param->vui_fields.bits.timing_info_present_flag, 1);
502 if (seq_param->vui_fields.bits.timing_info_present_flag) {
503 WRITE_UINT32 (bs, seq_param->num_units_in_tick, 32);
504 WRITE_UINT32 (bs, seq_param->time_scale, 32);
505 WRITE_UINT32 (bs, 1, 1); /* fixed_frame_rate_flag */
508 /* nal_hrd_parameters_present_flag */
509 nal_hrd_parameters_present_flag = seq_param->bits_per_second > 0;
510 WRITE_UINT32 (bs, nal_hrd_parameters_present_flag, 1);
511 if (nal_hrd_parameters_present_flag) {
515 WRITE_UINT32 (bs, SX_BITRATE - 6, 4); /* bit_rate_scale */
516 WRITE_UINT32 (bs, SX_CPB_SIZE - 4, 4); /* cpb_size_scale */
518 for (i = 0; i < 1; ++i) {
519 /* bit_rate_value_minus1[0] */
520 WRITE_UE (bs, (seq_param->bits_per_second >> SX_BITRATE) - 1);
521 /* cpb_size_value_minus1[0] */
522 WRITE_UE (bs, (hrd_params->buffer_size >> SX_CPB_SIZE) - 1);
524 WRITE_UINT32 (bs, 1, 1);
526 /* initial_cpb_removal_delay_length_minus1 */
527 WRITE_UINT32 (bs, 23, 5);
528 /* cpb_removal_delay_length_minus1 */
529 WRITE_UINT32 (bs, 23, 5);
530 /* dpb_output_delay_length_minus1 */
531 WRITE_UINT32 (bs, 23, 5);
532 /* time_offset_length */
533 WRITE_UINT32 (bs, 23, 5);
536 /* vcl_hrd_parameters_present_flag */
537 WRITE_UINT32 (bs, 0, 1);
539 if (nal_hrd_parameters_present_flag
540 || 0 /*vcl_hrd_parameters_present_flag */ ) {
541 /* low_delay_hrd_flag */
542 WRITE_UINT32 (bs, 0, 1);
544 /* pic_struct_present_flag */
545 WRITE_UINT32 (bs, 1, 1);
546 /* bs_restriction_flag */
547 WRITE_UINT32 (bs, 0, 1);
554 GST_WARNING ("failed to write SPS NAL unit");
560 bs_write_sps (GstBitWriter * bs,
561 const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
562 const VAEncMiscParameterHRD * hrd_params)
564 if (!bs_write_sps_data (bs, seq_param, profile, hrd_params))
567 /* rbsp_trailing_bits */
568 bs_write_trailing_bits (bs);
574 bs_write_subset_sps (GstBitWriter * bs,
575 const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
576 guint num_views, guint16 * view_ids,
577 const VAEncMiscParameterHRD * hrd_params)
581 if (!bs_write_sps_data (bs, seq_param, profile, hrd_params))
584 if (profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH ||
585 profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH) {
586 guint32 num_views_minus1, num_level_values_signalled_minus1;
588 num_views_minus1 = num_views - 1;
589 g_assert (num_views_minus1 < 1024);
591 /* bit equal to one */
592 WRITE_UINT32 (bs, 1, 1);
594 WRITE_UE (bs, num_views_minus1);
596 for (i = 0; i <= num_views_minus1; i++)
597 WRITE_UE (bs, view_ids[i]);
599 for (i = 1; i <= num_views_minus1; i++) {
600 guint32 num_anchor_refs_l0 = 0;
601 guint32 num_anchor_refs_l1 = 0;
603 WRITE_UE (bs, num_anchor_refs_l0);
604 for (j = 0; j < num_anchor_refs_l0; j++)
607 WRITE_UE (bs, num_anchor_refs_l1);
608 for (j = 0; j < num_anchor_refs_l1; j++)
612 for (i = 1; i <= num_views_minus1; i++) {
613 guint32 num_non_anchor_refs_l0 = 0;
614 guint32 num_non_anchor_refs_l1 = 0;
616 WRITE_UE (bs, num_non_anchor_refs_l0);
617 for (j = 0; j < num_non_anchor_refs_l0; j++)
620 WRITE_UE (bs, num_non_anchor_refs_l1);
621 for (j = 0; j < num_non_anchor_refs_l1; j++)
625 /* num level values signalled minus1 */
626 num_level_values_signalled_minus1 = 0;
627 g_assert (num_level_values_signalled_minus1 < 64);
628 WRITE_UE (bs, num_level_values_signalled_minus1);
630 for (i = 0; i <= num_level_values_signalled_minus1; i++) {
631 guint16 num_applicable_ops_minus1 = 0;
632 g_assert (num_applicable_ops_minus1 < 1024);
634 WRITE_UINT32 (bs, seq_param->level_idc, 8);
635 WRITE_UE (bs, num_applicable_ops_minus1);
637 for (j = 0; j <= num_applicable_ops_minus1; j++) {
638 guint8 temporal_id = 0;
639 guint16 num_target_views_minus1 = 1;
641 WRITE_UINT32 (bs, temporal_id, 3);
642 WRITE_UE (bs, num_target_views_minus1);
644 for (k = 0; k <= num_target_views_minus1; k++)
647 WRITE_UE (bs, num_views_minus1);
651 /* mvc_vui_parameters_present_flag */
652 WRITE_UINT32 (bs, 0, 1);
655 /* additional_extension2_flag */
656 WRITE_UINT32 (bs, 0, 1);
658 /* rbsp_trailing_bits */
659 bs_write_trailing_bits (bs);
665 GST_WARNING ("failed to write subset SPS NAL unit");
671 /* Write a PPS NAL unit */
673 bs_write_pps (GstBitWriter * bs,
674 const VAEncPictureParameterBufferH264 * pic_param, GstVaapiProfile profile)
676 guint32 num_slice_groups_minus1 = 0;
677 guint32 pic_init_qs_minus26 = 0;
678 guint32 redundant_pic_cnt_present_flag = 0;
680 /* pic_parameter_set_id */
681 WRITE_UE (bs, pic_param->pic_parameter_set_id);
682 /* seq_parameter_set_id */
683 WRITE_UE (bs, pic_param->seq_parameter_set_id);
684 /* entropy_coding_mode_flag */
685 WRITE_UINT32 (bs, pic_param->pic_fields.bits.entropy_coding_mode_flag, 1);
686 /* pic_order_present_flag */
687 WRITE_UINT32 (bs, pic_param->pic_fields.bits.pic_order_present_flag, 1);
689 WRITE_UE (bs, num_slice_groups_minus1);
691 if (num_slice_groups_minus1 > 0) {
692 /*FIXME*/ g_assert (0 && "unsupported arbitrary slice ordering (ASO)");
694 WRITE_UE (bs, pic_param->num_ref_idx_l0_active_minus1);
695 WRITE_UE (bs, pic_param->num_ref_idx_l1_active_minus1);
696 WRITE_UINT32 (bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);
697 WRITE_UINT32 (bs, pic_param->pic_fields.bits.weighted_bipred_idc, 2);
698 /* pic_init_qp_minus26 */
699 WRITE_SE (bs, pic_param->pic_init_qp - 26);
700 /* pic_init_qs_minus26 */
701 WRITE_SE (bs, pic_init_qs_minus26);
702 /* chroma_qp_index_offset */
703 WRITE_SE (bs, pic_param->chroma_qp_index_offset);
706 pic_param->pic_fields.bits.deblocking_filter_control_present_flag, 1);
707 WRITE_UINT32 (bs, pic_param->pic_fields.bits.constrained_intra_pred_flag, 1);
708 WRITE_UINT32 (bs, redundant_pic_cnt_present_flag, 1);
711 if (profile == GST_VAAPI_PROFILE_H264_HIGH
712 || profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH
713 || profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH) {
714 WRITE_UINT32 (bs, pic_param->pic_fields.bits.transform_8x8_mode_flag, 1);
716 pic_param->pic_fields.bits.pic_scaling_matrix_present_flag, 1);
717 if (pic_param->pic_fields.bits.pic_scaling_matrix_present_flag) {
718 g_assert (0 && "unsupported scaling lists");
722 (6+(-( (chroma_format_idc ! = 3) ? 2 : 6) * -pic_param->pic_fields.bits.transform_8x8_mode_flag));
724 gst_bit_writer_put_bits_uint8(bs, pic_param->pic_fields.bits.pic_scaling_list_present_flag, 1);
728 WRITE_SE (bs, pic_param->second_chroma_qp_index_offset);
731 /* rbsp_trailing_bits */
732 bs_write_trailing_bits (bs);
738 GST_WARNING ("failed to write PPS NAL unit");
743 /* ------------------------------------------------------------------------- */
744 /* --- H.264 Encoder --- */
745 /* ------------------------------------------------------------------------- */
747 #define GST_VAAPI_ENCODER_H264_FEI_CAST(encoder) \
748 ((GstVaapiEncoderH264Fei *)(encoder))
750 struct _GstVaapiEncoderH264Fei
752 GstVaapiEncoder parent_instance;
753 GstVaapiFeiEncH264 *feienc;
754 GstVaapiFEIPakH264 *feipak;
756 GstVaapiProfile profile;
757 GstVaapiLevelH264 level;
758 GstVaapiEntrypoint entrypoint;
759 VAConfigID va_config;
761 VABufferID coded_buf;
762 guint8 max_profile_idc;
763 guint8 hw_max_profile_idc;
775 GstClockTime cts_offset;
776 gboolean config_changed;
779 guint32 max_frame_num;
780 guint32 log2_max_frame_num;
781 guint32 max_pic_order_cnt;
782 guint32 log2_max_pic_order_cnt;
784 guint8 pic_order_cnt_type;
785 guint8 delta_pic_order_always_zero_flag;
788 GstBuffer *subset_sps_data;
791 guint bitrate_bits; // bitrate (bits)
792 guint cpb_length; // length of CPB buffer (ms)
793 guint cpb_length_bits; // length of CPB buffer (bits)
794 guint num_ref_frames;
798 guint32 view_idx; /* View Order Index (VOIdx) */
800 guint16 view_ids[MAX_NUM_VIEWS];
801 GstVaapiH264ViewRefPool ref_pools[MAX_NUM_VIEWS];
802 GstVaapiH264ViewReorderPool reorder_pools[MAX_NUM_VIEWS];
803 gpointer ref_pool_ptr;
804 /*Fei frame level control */
805 gboolean is_fei_disabled;
806 gboolean is_stats_out_enabled;
812 guint submb_part_mask;
814 guint intra_part_mask;
817 guint num_mv_predictors_l0;
818 guint num_mv_predictors_l1;
819 guint adaptive_search;
826 /* Write a SEI buffering period payload */
828 bs_write_sei_buf_period (GstBitWriter * bs,
829 GstVaapiEncoderH264Fei * encoder, GstVaapiEncPicture * picture)
831 guint initial_cpb_removal_delay = 0;
832 guint initial_cpb_removal_delay_offset = 0;
833 guint8 initial_cpb_removal_delay_length = 24;
835 /* sequence_parameter_set_id */
836 WRITE_UE (bs, encoder->view_idx);
837 /* NalHrdBpPresentFlag == TRUE */
838 /* cpb_cnt_minus1 == 0 */
840 /* decoding should start when the CPB fullness reaches half of cpb size
841 * initial_cpb_remvoal_delay = (((cpb_length / 2) * 90000) / 1000) */
842 initial_cpb_removal_delay = encoder->cpb_length * 45;
844 /* initial_cpb_remvoal_dealy */
845 WRITE_UINT32 (bs, initial_cpb_removal_delay,
846 initial_cpb_removal_delay_length);
848 /* initial_cpb_removal_delay_offset */
849 WRITE_UINT32 (bs, initial_cpb_removal_delay_offset,
850 initial_cpb_removal_delay_length);
852 /* VclHrdBpPresentFlag == FALSE */
858 GST_WARNING ("failed to write Buffering Period SEI message");
863 /* Write a SEI picture timing payload */
865 bs_write_sei_pic_timing (GstBitWriter * bs,
866 GstVaapiEncoderH264Fei * encoder, GstVaapiEncPicture * picture)
868 GstVaapiH264ViewReorderPool *reorder_pool = NULL;
869 guint cpb_removal_delay;
870 guint dpb_output_delay;
871 guint8 cpb_removal_delay_length = 24;
872 guint8 dpb_output_delay_length = 24;
873 guint pic_struct = 0;
874 guint clock_timestamp_flag = 0;
876 reorder_pool = &encoder->reorder_pools[encoder->view_idx];
877 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
878 reorder_pool->frame_count = 0;
880 reorder_pool->frame_count++;
882 /* clock-tick = no_units_in_tick/time_scale (C-1)
883 * time_scale = FPS_N * 2 (E.2.1)
884 * num_units_in_tick = FPS_D (E.2.1)
885 * frame_duration = clock-tick * 2
886 * so removal time for one frame is 2 clock-ticks.
887 * but adding a tolerance of one frame duration,
888 * which is 2 more clock-ticks */
889 cpb_removal_delay = (reorder_pool->frame_count * 2 + 2);
891 if (picture->type == GST_VAAPI_PICTURE_TYPE_B)
892 dpb_output_delay = 0;
894 dpb_output_delay = picture->poc - reorder_pool->frame_count * 2;
896 /* CpbDpbDelaysPresentFlag == 1 */
897 WRITE_UINT32 (bs, cpb_removal_delay, cpb_removal_delay_length);
898 WRITE_UINT32 (bs, dpb_output_delay, dpb_output_delay_length);
900 /* pic_struct_present_flag == 1 */
902 WRITE_UINT32 (bs, pic_struct, 4);
903 /* clock_timestamp_flag */
904 WRITE_UINT32 (bs, clock_timestamp_flag, 1);
911 GST_WARNING ("failed to write Picture Timing SEI message");
916 /* Write a Slice NAL unit */
918 bs_write_slice (GstBitWriter * bs,
919 const VAEncSliceParameterBufferH264 * slice_param,
920 GstVaapiEncoderH264Fei * encoder, GstVaapiEncPicture * picture)
922 const VAEncPictureParameterBufferH264 *const pic_param = picture->param;
923 guint32 field_pic_flag = 0;
924 guint32 ref_pic_list_modification_flag_l0 = 0;
925 guint32 ref_pic_list_modification_flag_l1 = 0;
926 guint32 no_output_of_prior_pics_flag = 0;
927 guint32 long_term_reference_flag = 0;
928 guint32 adaptive_ref_pic_marking_mode_flag = 0;
930 /* first_mb_in_slice */
931 WRITE_UE (bs, slice_param->macroblock_address);
933 WRITE_UE (bs, slice_param->slice_type);
934 /* pic_parameter_set_id */
935 WRITE_UE (bs, slice_param->pic_parameter_set_id);
937 WRITE_UINT32 (bs, picture->frame_num, encoder->log2_max_frame_num);
939 /* XXX: only frames (i.e. non-interlaced) are supported for now */
940 /* frame_mbs_only_flag == 0 */
943 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
944 WRITE_UE (bs, slice_param->idr_pic_id);
946 /* XXX: only POC type 0 is supported */
947 if (!encoder->pic_order_cnt_type) {
948 WRITE_UINT32 (bs, slice_param->pic_order_cnt_lsb,
949 encoder->log2_max_pic_order_cnt);
950 /* bottom_field_pic_order_in_frame_present_flag is FALSE */
951 if (pic_param->pic_fields.bits.pic_order_present_flag && !field_pic_flag)
952 WRITE_SE (bs, slice_param->delta_pic_order_cnt_bottom);
953 } else if (encoder->pic_order_cnt_type == 1 &&
954 !encoder->delta_pic_order_always_zero_flag) {
955 WRITE_SE (bs, slice_param->delta_pic_order_cnt[0]);
956 if (pic_param->pic_fields.bits.pic_order_present_flag && !field_pic_flag)
957 WRITE_SE (bs, slice_param->delta_pic_order_cnt[1]);
959 /* redundant_pic_cnt_present_flag is FALSE, no redundant coded pictures */
961 /* only works for B-frames */
962 if (slice_param->slice_type == GST_H264_B_SLICE)
963 WRITE_UINT32 (bs, slice_param->direct_spatial_mv_pred_flag, 1);
965 /* not supporting SP slices */
966 if (slice_param->slice_type == 0 || slice_param->slice_type == 1) {
967 WRITE_UINT32 (bs, slice_param->num_ref_idx_active_override_flag, 1);
968 if (slice_param->num_ref_idx_active_override_flag) {
969 WRITE_UE (bs, slice_param->num_ref_idx_l0_active_minus1);
970 if (slice_param->slice_type == 1)
971 WRITE_UE (bs, slice_param->num_ref_idx_l1_active_minus1);
974 /* XXX: not supporting custom reference picture list modifications */
975 if ((slice_param->slice_type != 2) && (slice_param->slice_type != 4))
976 WRITE_UINT32 (bs, ref_pic_list_modification_flag_l0, 1);
977 if (slice_param->slice_type == 1)
978 WRITE_UINT32 (bs, ref_pic_list_modification_flag_l1, 1);
980 /* we have: weighted_pred_flag == FALSE and */
981 /* : weighted_bipred_idc == FALSE */
982 if ((pic_param->pic_fields.bits.weighted_pred_flag &&
983 (slice_param->slice_type == 0)) ||
984 ((pic_param->pic_fields.bits.weighted_bipred_idc == 1) &&
985 (slice_param->slice_type == 1))) {
986 /* XXXX: add pred_weight_table() */
989 /* dec_ref_pic_marking() */
990 if (slice_param->slice_type == 0 || slice_param->slice_type == 2) {
991 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture)) {
992 /* no_output_of_prior_pics_flag = 0 */
993 WRITE_UINT32 (bs, no_output_of_prior_pics_flag, 1);
994 /* long_term_reference_flag = 0 */
995 WRITE_UINT32 (bs, long_term_reference_flag, 1);
997 /* only sliding_window reference picture marking mode is supported */
998 /* adpative_ref_pic_marking_mode_flag = 0 */
999 WRITE_UINT32 (bs, adaptive_ref_pic_marking_mode_flag, 1);
1003 /* cabac_init_idc */
1004 if (pic_param->pic_fields.bits.entropy_coding_mode_flag &&
1005 slice_param->slice_type != 2)
1006 WRITE_UE (bs, slice_param->cabac_init_idc);
1008 WRITE_SE (bs, slice_param->slice_qp_delta);
1010 /* XXX: only supporting I, P and B type slices */
1011 /* no sp_for_switch_flag and no slice_qs_delta */
1013 if (pic_param->pic_fields.bits.deblocking_filter_control_present_flag) {
1014 /* disable_deblocking_filter_idc */
1015 WRITE_UE (bs, slice_param->disable_deblocking_filter_idc);
1016 if (slice_param->disable_deblocking_filter_idc != 1) {
1017 WRITE_SE (bs, slice_param->slice_alpha_c0_offset_div2);
1018 WRITE_SE (bs, slice_param->slice_beta_offset_div2);
1022 /* XXX: unsupported arbitrary slice ordering (ASO) */
1023 /* num_slic_groups_minus1 should be zero */
1029 GST_WARNING ("failed to write Slice NAL unit");
1035 _check_sps_pps_status (GstVaapiEncoderH264Fei * encoder,
1036 const guint8 * nal, guint32 size)
1039 G_GNUC_UNUSED gsize ret; /* FIXME */
1040 gboolean has_subset_sps;
1044 has_subset_sps = !encoder->is_mvc || (encoder->subset_sps_data != NULL);
1045 if (encoder->sps_data && encoder->pps_data && has_subset_sps)
1048 nal_type = nal[0] & 0x1F;
1050 case GST_H264_NAL_SPS:
1051 encoder->sps_data = gst_buffer_new_allocate (NULL, size, NULL);
1052 ret = gst_buffer_fill (encoder->sps_data, 0, nal, size);
1053 g_assert (ret == size);
1055 case GST_H264_NAL_SUBSET_SPS:
1056 encoder->subset_sps_data = gst_buffer_new_allocate (NULL, size, NULL);
1057 ret = gst_buffer_fill (encoder->subset_sps_data, 0, nal, size);
1058 g_assert (ret == size);
1060 case GST_H264_NAL_PPS:
1061 encoder->pps_data = gst_buffer_new_allocate (NULL, size, NULL);
1062 ret = gst_buffer_fill (encoder->pps_data, 0, nal, size);
1063 g_assert (ret == size);
1070 /* Determines the largest supported profile by the underlying hardware */
1072 ensure_hw_profile_limits (GstVaapiEncoderH264Fei * encoder)
1074 GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
1076 guint i, profile_idc, max_profile_idc;
1078 if (encoder->hw_max_profile_idc)
1081 profiles = gst_vaapi_display_get_encode_profiles (display);
1085 max_profile_idc = 0;
1086 for (i = 0; i < profiles->len; i++) {
1087 const GstVaapiProfile profile =
1088 g_array_index (profiles, GstVaapiProfile, i);
1089 profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
1092 if (max_profile_idc < profile_idc)
1093 max_profile_idc = profile_idc;
1095 g_array_unref (profiles);
1097 encoder->hw_max_profile_idc = max_profile_idc;
1101 /* Derives the profile supported by the underlying hardware */
1103 ensure_hw_profile (GstVaapiEncoderH264Fei * encoder)
1105 GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
1106 GstVaapiEntrypoint entrypoint = encoder->entrypoint;
1107 GstVaapiProfile profile, profiles[4];
1108 guint i, num_profiles = 0;
1110 profiles[num_profiles++] = encoder->profile;
1111 switch (encoder->profile) {
1112 case GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE:
1113 profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_BASELINE;
1114 profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_MAIN;
1116 case GST_VAAPI_PROFILE_H264_MAIN:
1117 profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_HIGH;
1123 profile = GST_VAAPI_PROFILE_UNKNOWN;
1124 for (i = 0; i < num_profiles; i++) {
1125 if (gst_vaapi_display_has_encoder (display, profiles[i], entrypoint)) {
1126 profile = profiles[i];
1130 if (profile == GST_VAAPI_PROFILE_UNKNOWN)
1131 goto error_unsupported_profile;
1133 GST_VAAPI_ENCODER_CAST (encoder)->profile = profile;
1137 error_unsupported_profile:
1139 GST_ERROR ("unsupported HW profile (0x%08x)", encoder->profile);
1144 /* Check target decoder constraints */
1146 ensure_profile_limits (GstVaapiEncoderH264Fei * encoder)
1148 GstVaapiProfile profile;
1150 if (!encoder->max_profile_idc
1151 || encoder->profile_idc <= encoder->max_profile_idc)
1154 GST_WARNING ("lowering coding tools to meet target decoder constraints");
1156 profile = GST_VAAPI_PROFILE_UNKNOWN;
1158 /* Try Main profile coding tools */
1159 if (encoder->max_profile_idc < 100) {
1160 encoder->use_dct8x8 = FALSE;
1161 profile = GST_VAAPI_PROFILE_H264_MAIN;
1164 /* Try Constrained Baseline profile coding tools */
1165 if (encoder->max_profile_idc < 77) {
1166 encoder->num_bframes = 0;
1167 encoder->use_cabac = FALSE;
1168 profile = GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
1172 encoder->profile = profile;
1173 encoder->profile_idc = encoder->max_profile_idc;
1178 /* Derives the minimum profile from the active coding tools */
1180 ensure_profile (GstVaapiEncoderH264Fei * encoder)
1182 GstVaapiProfile profile;
1184 /* Always start from "constrained-baseline" profile for maximum
1186 profile = GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
1188 /* Main profile coding tools */
1189 if (encoder->num_bframes > 0 || encoder->use_cabac)
1190 profile = GST_VAAPI_PROFILE_H264_MAIN;
1192 /* High profile coding tools */
1193 if (encoder->use_dct8x8)
1194 profile = GST_VAAPI_PROFILE_H264_HIGH;
1196 /* MVC profiles coding tools */
1197 if (encoder->num_views == 2)
1198 profile = GST_VAAPI_PROFILE_H264_STEREO_HIGH;
1199 else if (encoder->num_views > 2)
1200 profile = GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH;
1202 encoder->profile = profile;
1203 encoder->profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
1207 /* Derives the level from the currently set limits */
1209 ensure_level (GstVaapiEncoderH264Fei * encoder)
1211 const guint cpb_factor = h264_get_cpb_nal_factor (encoder->profile);
1212 const GstVaapiH264LevelLimits *limits_table;
1213 guint i, num_limits, PicSizeMbs, MaxDpbMbs, MaxMBPS;
1215 PicSizeMbs = encoder->mb_width * encoder->mb_height;
1216 MaxDpbMbs = PicSizeMbs * ((encoder->num_bframes) ? 2 : 1);
1217 MaxMBPS = gst_util_uint64_scale_int_ceil (PicSizeMbs,
1218 GST_VAAPI_ENCODER_FPS_N (encoder), GST_VAAPI_ENCODER_FPS_D (encoder));
1220 limits_table = gst_vaapi_utils_h264_get_level_limits_table (&num_limits);
1221 for (i = 0; i < num_limits; i++) {
1222 const GstVaapiH264LevelLimits *const limits = &limits_table[i];
1223 if (PicSizeMbs <= limits->MaxFS &&
1224 MaxDpbMbs <= limits->MaxDpbMbs &&
1225 MaxMBPS <= limits->MaxMBPS && (!encoder->bitrate_bits
1226 || encoder->bitrate_bits <= (limits->MaxBR * cpb_factor)) &&
1227 (!encoder->cpb_length_bits ||
1228 encoder->cpb_length_bits <= (limits->MaxCPB * cpb_factor)))
1231 if (i == num_limits)
1232 goto error_unsupported_level;
1234 encoder->level = limits_table[i].level;
1235 encoder->level_idc = limits_table[i].level_idc;
1239 error_unsupported_level:
1241 GST_ERROR ("failed to find a suitable level matching codec config");
1246 /* Enable "high-compression" tuning options */
1248 ensure_tuning_high_compression (GstVaapiEncoderH264Fei * encoder)
1252 if (!ensure_hw_profile_limits (encoder))
1255 profile_idc = encoder->hw_max_profile_idc;
1256 if (encoder->max_profile_idc && encoder->max_profile_idc < profile_idc)
1257 profile_idc = encoder->max_profile_idc;
1259 /* Tuning options to enable Main profile */
1260 if (profile_idc >= 77 && profile_idc != 88) {
1261 encoder->use_cabac = TRUE;
1262 if (!encoder->num_bframes)
1263 encoder->num_bframes = 1;
1266 /* Tuning options to enable High profile */
1267 if (profile_idc >= 100) {
1268 encoder->use_dct8x8 = TRUE;
1273 /* Ensure tuning options */
1275 ensure_tuning (GstVaapiEncoderH264Fei * encoder)
1279 switch (GST_VAAPI_ENCODER_TUNE (encoder)) {
1280 case GST_VAAPI_ENCODER_TUNE_HIGH_COMPRESSION:
1281 success = ensure_tuning_high_compression (encoder);
1283 case GST_VAAPI_ENCODER_TUNE_LOW_POWER:
1284 /* Set low-power encode entry point. If hardware doesn't have
1285 * support, it will fail in ensure_hw_profile() in later stage.
1286 * So not duplicating the profile/entrypont query mechanism
1287 * here as a part of optimization */
1288 encoder->entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_LP;
1298 /* Handle new GOP starts */
1300 reset_gop_start (GstVaapiEncoderH264Fei * encoder)
1302 GstVaapiH264ViewReorderPool *const reorder_pool =
1303 &encoder->reorder_pools[encoder->view_idx];
1305 reorder_pool->frame_index = 1;
1306 reorder_pool->cur_frame_num = 0;
1307 reorder_pool->cur_present_index = 0;
1311 /* Marks the supplied picture as a B-frame */
1313 set_b_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264Fei * encoder)
1315 GstVaapiH264ViewReorderPool *const reorder_pool =
1316 &encoder->reorder_pools[encoder->view_idx];
1318 g_assert (pic && encoder);
1319 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1320 pic->type = GST_VAAPI_PICTURE_TYPE_B;
1321 pic->frame_num = (reorder_pool->cur_frame_num % encoder->max_frame_num);
1324 /* Marks the supplied picture as a P-frame */
1326 set_p_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264Fei * encoder)
1328 GstVaapiH264ViewReorderPool *const reorder_pool =
1329 &encoder->reorder_pools[encoder->view_idx];
1331 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1332 pic->type = GST_VAAPI_PICTURE_TYPE_P;
1333 pic->frame_num = (reorder_pool->cur_frame_num % encoder->max_frame_num);
1336 /* Marks the supplied picture as an I-frame */
1338 set_i_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264Fei * encoder)
1340 GstVaapiH264ViewReorderPool *const reorder_pool =
1341 &encoder->reorder_pools[encoder->view_idx];
1343 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1344 pic->type = GST_VAAPI_PICTURE_TYPE_I;
1345 pic->frame_num = (reorder_pool->cur_frame_num % encoder->max_frame_num);
1347 g_assert (pic->frame);
1348 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1351 /* Marks the supplied picture as an IDR frame */
1353 set_idr_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264Fei * encoder)
1355 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1356 pic->type = GST_VAAPI_PICTURE_TYPE_I;
1359 GST_VAAPI_ENC_PICTURE_FLAG_SET (pic, GST_VAAPI_ENC_PICTURE_FLAG_IDR);
1361 g_assert (pic->frame);
1362 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1365 /* Marks the supplied picture a a key-frame */
1367 set_key_frame (GstVaapiEncPicture * picture,
1368 GstVaapiEncoderH264Fei * encoder, gboolean is_idr)
1371 reset_gop_start (encoder);
1372 set_idr_frame (picture, encoder);
1374 set_i_frame (picture, encoder);
1377 /* Fills in VA HRD parameters */
1379 fill_hrd_params (GstVaapiEncoderH264Fei * encoder, VAEncMiscParameterHRD * hrd)
1381 if (encoder->bitrate_bits > 0) {
1382 hrd->buffer_size = encoder->cpb_length_bits;
1383 hrd->initial_buffer_fullness = hrd->buffer_size / 2;
1385 hrd->buffer_size = 0;
1386 hrd->initial_buffer_fullness = 0;
1390 /* Adds the supplied sequence header (SPS) to the list of packed
1391 headers to pass down as-is to the encoder */
1393 add_packed_sequence_header (GstVaapiEncoderH264Fei * encoder,
1394 GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1396 GstVaapiEncPackedHeader *packed_seq;
1398 VAEncPackedHeaderParameterBuffer packed_seq_param = { 0 };
1399 const VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1400 GstVaapiProfile profile = encoder->profile;
1402 VAEncMiscParameterHRD hrd_params;
1403 guint32 data_bit_size;
1406 fill_hrd_params (encoder, &hrd_params);
1408 gst_bit_writer_init_with_size (&bs, 128, FALSE);
1409 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1410 bs_write_nal_header (&bs, GST_H264_NAL_REF_IDC_HIGH, GST_H264_NAL_SPS);
1412 /* Set High profile for encoding the MVC base view. Otherwise, some
1413 traditional decoder cannot recognize MVC profile streams with
1414 only the base view in there */
1415 if (profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH ||
1416 profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH)
1417 profile = GST_VAAPI_PROFILE_H264_HIGH;
1419 bs_write_sps (&bs, seq_param, profile, &hrd_params);
1421 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1422 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1423 data = GST_BIT_WRITER_DATA (&bs);
1425 packed_seq_param.type = VAEncPackedHeaderSequence;
1426 packed_seq_param.bit_length = data_bit_size;
1427 packed_seq_param.has_emulation_bytes = 0;
1429 packed_seq = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1430 &packed_seq_param, sizeof (packed_seq_param),
1431 data, (data_bit_size + 7) / 8);
1432 g_assert (packed_seq);
1434 gst_vaapi_enc_picture_add_packed_header (picture, packed_seq);
1435 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) & packed_seq, NULL);
1437 /* store sps data */
1438 _check_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1439 gst_bit_writer_reset (&bs);
1445 GST_WARNING ("failed to write SPS NAL unit");
1446 gst_bit_writer_reset (&bs);
1452 add_packed_sequence_header_mvc (GstVaapiEncoderH264Fei * encoder,
1453 GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1455 GstVaapiEncPackedHeader *packed_seq;
1457 VAEncPackedHeaderParameterBuffer packed_header_param_buffer = { 0 };
1458 const VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1459 VAEncMiscParameterHRD hrd_params;
1460 guint32 data_bit_size;
1463 fill_hrd_params (encoder, &hrd_params);
1465 /* non-base layer, pack one subset sps */
1466 gst_bit_writer_init_with_size (&bs, 128, FALSE);
1467 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1468 bs_write_nal_header (&bs, GST_H264_NAL_REF_IDC_HIGH, GST_H264_NAL_SUBSET_SPS);
1470 bs_write_subset_sps (&bs, seq_param, encoder->profile, encoder->num_views,
1471 encoder->view_ids, &hrd_params);
1473 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1474 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1475 data = GST_BIT_WRITER_DATA (&bs);
1477 packed_header_param_buffer.type = VAEncPackedHeaderSequence;
1478 packed_header_param_buffer.bit_length = data_bit_size;
1479 packed_header_param_buffer.has_emulation_bytes = 0;
1481 packed_seq = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1482 &packed_header_param_buffer, sizeof (packed_header_param_buffer),
1483 data, (data_bit_size + 7) / 8);
1484 g_assert (packed_seq);
1486 gst_vaapi_enc_picture_add_packed_header (picture, packed_seq);
1487 gst_vaapi_mini_object_replace ((GstVaapiMiniObject **) & packed_seq, NULL);
1489 /* store subset sps data */
1490 _check_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1491 gst_bit_writer_reset (&bs);
1497 GST_WARNING ("failed to write SPS NAL unit");
1498 gst_bit_writer_reset (&bs);
1503 /* Adds the supplied picture header (PPS) to the list of packed
1504 headers to pass down as-is to the encoder */
1506 add_packed_picture_header (GstVaapiEncoderH264Fei * encoder,
1507 GstVaapiEncPicture * picture)
1509 GstVaapiEncPackedHeader *packed_pic;
1511 VAEncPackedHeaderParameterBuffer packed_pic_param = { 0 };
1512 const VAEncPictureParameterBufferH264 *const pic_param = picture->param;
1513 guint32 data_bit_size;
1516 gst_bit_writer_init_with_size (&bs, 128, FALSE);
1517 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1518 bs_write_nal_header (&bs, GST_H264_NAL_REF_IDC_HIGH, GST_H264_NAL_PPS);
1519 bs_write_pps (&bs, pic_param, encoder->profile);
1520 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1521 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1522 data = GST_BIT_WRITER_DATA (&bs);
1524 packed_pic_param.type = VAEncPackedHeaderPicture;
1525 packed_pic_param.bit_length = data_bit_size;
1526 packed_pic_param.has_emulation_bytes = 0;
1528 packed_pic = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1529 &packed_pic_param, sizeof (packed_pic_param),
1530 data, (data_bit_size + 7) / 8);
1531 g_assert (packed_pic);
1533 gst_vaapi_enc_picture_add_packed_header (picture, packed_pic);
1534 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) & packed_pic, NULL);
1536 /* store pps data */
1537 _check_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1538 gst_bit_writer_reset (&bs);
1544 GST_WARNING ("failed to write PPS NAL unit");
1545 gst_bit_writer_reset (&bs);
1551 add_packed_sei_header (GstVaapiEncoderH264Fei * encoder,
1552 GstVaapiEncPicture * picture, GstVaapiH264SeiPayloadType payloadtype)
1554 GstVaapiEncPackedHeader *packed_sei;
1555 GstBitWriter bs, bs_buf_period, bs_pic_timing;
1556 VAEncPackedHeaderParameterBuffer packed_sei_param = { 0 };
1557 guint32 data_bit_size;
1558 guint8 buf_period_payload_size = 0, pic_timing_payload_size = 0;
1559 guint8 *data, *buf_period_payload = NULL, *pic_timing_payload = NULL;
1560 gboolean need_buf_period, need_pic_timing;
1562 gst_bit_writer_init_with_size (&bs_buf_period, 128, FALSE);
1563 gst_bit_writer_init_with_size (&bs_pic_timing, 128, FALSE);
1564 gst_bit_writer_init_with_size (&bs, 128, FALSE);
1566 need_buf_period = GST_VAAPI_H264_SEI_BUF_PERIOD & payloadtype;
1567 need_pic_timing = GST_VAAPI_H264_SEI_PIC_TIMING & payloadtype;
1569 if (need_buf_period) {
1570 /* Write a Buffering Period SEI message */
1571 bs_write_sei_buf_period (&bs_buf_period, encoder, picture);
1572 /* Write byte alignment bits */
1573 if (GST_BIT_WRITER_BIT_SIZE (&bs_buf_period) % 8 != 0)
1574 bs_write_trailing_bits (&bs_buf_period);
1575 buf_period_payload_size = (GST_BIT_WRITER_BIT_SIZE (&bs_buf_period)) / 8;
1576 buf_period_payload = GST_BIT_WRITER_DATA (&bs_buf_period);
1579 if (need_pic_timing) {
1580 /* Write a Picture Timing SEI message */
1581 if (GST_VAAPI_H264_SEI_PIC_TIMING & payloadtype)
1582 bs_write_sei_pic_timing (&bs_pic_timing, encoder, picture);
1583 /* Write byte alignment bits */
1584 if (GST_BIT_WRITER_BIT_SIZE (&bs_pic_timing) % 8 != 0)
1585 bs_write_trailing_bits (&bs_pic_timing);
1586 pic_timing_payload_size = (GST_BIT_WRITER_BIT_SIZE (&bs_pic_timing)) / 8;
1587 pic_timing_payload = GST_BIT_WRITER_DATA (&bs_pic_timing);
1590 /* Write the SEI message */
1591 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1592 bs_write_nal_header (&bs, GST_H264_NAL_REF_IDC_NONE, GST_H264_NAL_SEI);
1594 if (need_buf_period) {
1595 WRITE_UINT32 (&bs, GST_H264_SEI_BUF_PERIOD, 8);
1596 WRITE_UINT32 (&bs, buf_period_payload_size, 8);
1597 /* Add buffering period sei message */
1598 gst_bit_writer_put_bytes (&bs, buf_period_payload, buf_period_payload_size);
1601 if (need_pic_timing) {
1602 WRITE_UINT32 (&bs, GST_H264_SEI_PIC_TIMING, 8);
1603 WRITE_UINT32 (&bs, pic_timing_payload_size, 8);
1604 /* Add picture timing sei message */
1605 gst_bit_writer_put_bytes (&bs, pic_timing_payload, pic_timing_payload_size);
1608 /* rbsp_trailing_bits */
1609 bs_write_trailing_bits (&bs);
1611 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1612 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1613 data = GST_BIT_WRITER_DATA (&bs);
1615 packed_sei_param.type = VA_ENC_PACKED_HEADER_H264_SEI;
1616 packed_sei_param.bit_length = data_bit_size;
1617 packed_sei_param.has_emulation_bytes = 0;
1619 packed_sei = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1620 &packed_sei_param, sizeof (packed_sei_param),
1621 data, (data_bit_size + 7) / 8);
1622 g_assert (packed_sei);
1624 gst_vaapi_enc_picture_add_packed_header (picture, packed_sei);
1625 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) & packed_sei, NULL);
1627 gst_bit_writer_reset (&bs_buf_period);
1628 gst_bit_writer_reset (&bs_pic_timing);
1629 gst_bit_writer_reset (&bs);
1635 GST_WARNING ("failed to write SEI NAL unit");
1636 gst_bit_writer_reset (&bs_buf_period);
1637 gst_bit_writer_reset (&bs_pic_timing);
1638 gst_bit_writer_reset (&bs);
1644 get_nal_hdr_attributes (GstVaapiEncPicture * picture,
1645 guint8 * nal_ref_idc, guint8 * nal_unit_type)
1647 switch (picture->type) {
1648 case GST_VAAPI_PICTURE_TYPE_I:
1649 *nal_ref_idc = GST_H264_NAL_REF_IDC_HIGH;
1650 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
1651 *nal_unit_type = GST_H264_NAL_SLICE_IDR;
1653 *nal_unit_type = GST_H264_NAL_SLICE;
1655 case GST_VAAPI_PICTURE_TYPE_P:
1656 *nal_ref_idc = GST_H264_NAL_REF_IDC_MEDIUM;
1657 *nal_unit_type = GST_H264_NAL_SLICE;
1659 case GST_VAAPI_PICTURE_TYPE_B:
1660 *nal_ref_idc = GST_H264_NAL_REF_IDC_NONE;
1661 *nal_unit_type = GST_H264_NAL_SLICE;
1669 /* Adds the supplied prefix nal header to the list of packed
1670 headers to pass down as-is to the encoder */
1672 add_packed_prefix_nal_header (GstVaapiEncoderH264Fei * encoder,
1673 GstVaapiEncPicture * picture, GstVaapiEncSlice * slice)
1675 GstVaapiEncPackedHeader *packed_prefix_nal;
1677 VAEncPackedHeaderParameterBuffer packed_prefix_nal_param = { 0 };
1678 guint32 data_bit_size;
1680 guint8 nal_ref_idc, nal_unit_type;
1682 gst_bit_writer_init_with_size (&bs, 128, FALSE);
1683 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1685 if (!get_nal_hdr_attributes (picture, &nal_ref_idc, &nal_unit_type))
1687 nal_unit_type = GST_H264_NAL_PREFIX_UNIT;
1689 bs_write_nal_header (&bs, nal_ref_idc, nal_unit_type);
1690 bs_write_nal_header_mvc_extension (&bs, picture, encoder->view_idx);
1691 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1692 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1693 data = GST_BIT_WRITER_DATA (&bs);
1695 packed_prefix_nal_param.type = VAEncPackedHeaderRawData;
1696 packed_prefix_nal_param.bit_length = data_bit_size;
1697 packed_prefix_nal_param.has_emulation_bytes = 0;
1700 gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1701 &packed_prefix_nal_param, sizeof (packed_prefix_nal_param), data,
1702 (data_bit_size + 7) / 8);
1703 g_assert (packed_prefix_nal);
1705 gst_vaapi_enc_slice_add_packed_header (slice, packed_prefix_nal);
1706 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) & packed_prefix_nal,
1709 gst_bit_writer_reset (&bs);
1716 GST_WARNING ("failed to write Prefix NAL unit header");
1717 gst_bit_writer_reset (&bs);
1722 /* Adds the supplied slice header to the list of packed
1723 headers to pass down as-is to the encoder */
1725 add_packed_slice_header (GstVaapiEncoderH264Fei * encoder,
1726 GstVaapiEncPicture * picture, GstVaapiEncSlice * slice)
1728 GstVaapiEncPackedHeader *packed_slice;
1730 VAEncPackedHeaderParameterBuffer packed_slice_param = { 0 };
1731 const VAEncSliceParameterBufferH264 *const slice_param = slice->param;
1732 guint32 data_bit_size;
1734 guint8 nal_ref_idc, nal_unit_type;
1736 gst_bit_writer_init_with_size (&bs, 128, FALSE);
1737 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1739 if (!get_nal_hdr_attributes (picture, &nal_ref_idc, &nal_unit_type))
1741 /* pack nal_unit_header_mvc_extension() for the non base view */
1742 if (encoder->is_mvc && encoder->view_idx) {
1743 bs_write_nal_header (&bs, nal_ref_idc, GST_H264_NAL_SLICE_EXT);
1744 bs_write_nal_header_mvc_extension (&bs, picture,
1745 encoder->view_ids[encoder->view_idx]);
1747 bs_write_nal_header (&bs, nal_ref_idc, nal_unit_type);
1749 bs_write_slice (&bs, slice_param, encoder, picture);
1750 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1751 data = GST_BIT_WRITER_DATA (&bs);
1753 packed_slice_param.type = VAEncPackedHeaderSlice;
1754 packed_slice_param.bit_length = data_bit_size;
1755 packed_slice_param.has_emulation_bytes = 0;
1757 packed_slice = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1758 &packed_slice_param, sizeof (packed_slice_param),
1759 data, (data_bit_size + 7) / 8);
1760 g_assert (packed_slice);
1762 gst_vaapi_enc_slice_add_packed_header (slice, packed_slice);
1763 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) & packed_slice,
1766 gst_bit_writer_reset (&bs);
1772 GST_WARNING ("failed to write Slice NAL unit header");
1773 gst_bit_writer_reset (&bs);
1778 /* Reference picture management */
1780 reference_pic_free (GstVaapiEncoderH264Fei * encoder,
1781 GstVaapiEncoderH264FeiRef * ref)
1786 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), ref->pic);
1787 g_slice_free (GstVaapiEncoderH264FeiRef, ref);
1790 static inline GstVaapiEncoderH264FeiRef *
1791 reference_pic_create (GstVaapiEncoderH264Fei * encoder,
1792 GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1794 GstVaapiEncoderH264FeiRef *const ref =
1795 g_slice_new0 (GstVaapiEncoderH264FeiRef);
1798 ref->frame_num = picture->frame_num;
1799 ref->poc = picture->poc;
1804 reference_list_update (GstVaapiEncoderH264Fei * encoder,
1805 GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1807 GstVaapiEncoderH264FeiRef *ref;
1808 GstVaapiH264ViewRefPool *const ref_pool =
1809 &encoder->ref_pools[encoder->view_idx];
1811 if (GST_VAAPI_PICTURE_TYPE_B == picture->type) {
1812 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), surface);
1815 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture)) {
1816 while (!g_queue_is_empty (&ref_pool->ref_list))
1817 reference_pic_free (encoder, g_queue_pop_head (&ref_pool->ref_list));
1818 } else if (g_queue_get_length (&ref_pool->ref_list) >=
1819 ref_pool->max_ref_frames) {
1820 reference_pic_free (encoder, g_queue_pop_head (&ref_pool->ref_list));
1822 ref = reference_pic_create (encoder, picture, surface);
1823 g_queue_push_tail (&ref_pool->ref_list, ref);
1824 g_assert (g_queue_get_length (&ref_pool->ref_list) <=
1825 ref_pool->max_ref_frames);
1830 reference_list_init (GstVaapiEncoderH264Fei * encoder,
1831 GstVaapiEncPicture * picture,
1832 GstVaapiEncoderH264FeiRef ** reflist_0,
1833 guint * reflist_0_count,
1834 GstVaapiEncoderH264FeiRef ** reflist_1, guint * reflist_1_count)
1836 GstVaapiEncoderH264FeiRef *tmp;
1837 GstVaapiH264ViewRefPool *const ref_pool =
1838 &encoder->ref_pools[encoder->view_idx];
1839 GList *iter, *list_0_start = NULL, *list_1_start = NULL;
1842 *reflist_0_count = 0;
1843 *reflist_1_count = 0;
1844 if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
1847 iter = g_queue_peek_tail_link (&ref_pool->ref_list);
1848 for (; iter; iter = g_list_previous (iter)) {
1849 tmp = (GstVaapiEncoderH264FeiRef *) iter->data;
1850 g_assert (tmp && tmp->poc != picture->poc);
1851 if (_poc_greater_than (picture->poc, tmp->poc, encoder->max_pic_order_cnt)) {
1852 list_0_start = iter;
1853 list_1_start = g_list_next (iter);
1858 /* order reflist_0 */
1859 g_assert (list_0_start);
1860 iter = list_0_start;
1862 for (; iter; iter = g_list_previous (iter)) {
1863 reflist_0[count] = (GstVaapiEncoderH264FeiRef *) iter->data;
1866 *reflist_0_count = count;
1868 if (picture->type != GST_VAAPI_PICTURE_TYPE_B)
1871 /* order reflist_1 */
1873 iter = list_1_start;
1874 for (; iter; iter = g_list_next (iter)) {
1875 reflist_1[count] = (GstVaapiEncoderH264FeiRef *) iter->data;
1878 *reflist_1_count = count;
1882 /* Fills in VA sequence parameter buffer */
1884 fill_sequence (GstVaapiEncoderH264Fei * encoder, GstVaapiEncSequence * sequence)
1886 VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1887 GstVaapiH264ViewRefPool *const ref_pool =
1888 &encoder->ref_pools[encoder->view_idx];
1890 memset (seq_param, 0, sizeof (VAEncSequenceParameterBufferH264));
1891 seq_param->seq_parameter_set_id = encoder->view_idx;
1892 seq_param->level_idc = encoder->level_idc;
1893 seq_param->intra_period = GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder);
1894 seq_param->intra_idr_period = GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder);
1895 seq_param->ip_period = seq_param->intra_period > 1 ?
1896 (1 + encoder->num_bframes) : 0;
1897 seq_param->bits_per_second = encoder->bitrate_bits;
1899 seq_param->max_num_ref_frames = ref_pool->max_ref_frames;
1900 seq_param->picture_width_in_mbs = encoder->mb_width;
1901 seq_param->picture_height_in_mbs = encoder->mb_height;
1903 /*sequence field values */
1904 seq_param->seq_fields.value = 0;
1905 seq_param->seq_fields.bits.chroma_format_idc = 1;
1906 seq_param->seq_fields.bits.frame_mbs_only_flag = 1;
1907 seq_param->seq_fields.bits.mb_adaptive_frame_field_flag = FALSE;
1908 seq_param->seq_fields.bits.seq_scaling_matrix_present_flag = FALSE;
1909 /* direct_8x8_inference_flag default false */
1910 seq_param->seq_fields.bits.direct_8x8_inference_flag = FALSE;
1911 g_assert (encoder->log2_max_frame_num >= 4);
1912 seq_param->seq_fields.bits.log2_max_frame_num_minus4 =
1913 encoder->log2_max_frame_num - 4;
1914 /* picture order count */
1915 encoder->pic_order_cnt_type = seq_param->seq_fields.bits.pic_order_cnt_type =
1917 g_assert (encoder->log2_max_pic_order_cnt >= 4);
1918 seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 =
1919 encoder->log2_max_pic_order_cnt - 4;
1921 seq_param->bit_depth_luma_minus8 = 0;
1922 seq_param->bit_depth_chroma_minus8 = 0;
1924 /* not used if pic_order_cnt_type == 0 */
1925 if (seq_param->seq_fields.bits.pic_order_cnt_type == 1) {
1926 encoder->delta_pic_order_always_zero_flag =
1927 seq_param->seq_fields.bits.delta_pic_order_always_zero_flag = TRUE;
1928 seq_param->num_ref_frames_in_pic_order_cnt_cycle = 0;
1929 seq_param->offset_for_non_ref_pic = 0;
1930 seq_param->offset_for_top_to_bottom_field = 0;
1931 memset (seq_param->offset_for_ref_frame, 0,
1932 sizeof (seq_param->offset_for_ref_frame));
1935 /* frame_cropping_flag */
1936 if ((GST_VAAPI_ENCODER_WIDTH (encoder) & 15) ||
1937 (GST_VAAPI_ENCODER_HEIGHT (encoder) & 15)) {
1938 static const guint SubWidthC[] = { 1, 2, 2, 1 };
1939 static const guint SubHeightC[] = { 1, 2, 1, 1 };
1940 const guint CropUnitX =
1941 SubWidthC[seq_param->seq_fields.bits.chroma_format_idc];
1942 const guint CropUnitY =
1943 SubHeightC[seq_param->seq_fields.bits.chroma_format_idc] *
1944 (2 - seq_param->seq_fields.bits.frame_mbs_only_flag);
1946 seq_param->frame_cropping_flag = 1;
1947 seq_param->frame_crop_left_offset = 0;
1948 seq_param->frame_crop_right_offset =
1949 (16 * encoder->mb_width -
1950 GST_VAAPI_ENCODER_WIDTH (encoder)) / CropUnitX;
1951 seq_param->frame_crop_top_offset = 0;
1952 seq_param->frame_crop_bottom_offset =
1953 (16 * encoder->mb_height -
1954 GST_VAAPI_ENCODER_HEIGHT (encoder)) / CropUnitY;
1957 /* VUI parameters are always set, at least for timing_info (framerate) */
1958 seq_param->vui_parameters_present_flag = TRUE;
1959 if (seq_param->vui_parameters_present_flag) {
1960 seq_param->vui_fields.bits.aspect_ratio_info_present_flag = TRUE;
1961 if (seq_param->vui_fields.bits.aspect_ratio_info_present_flag) {
1962 const GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
1963 seq_param->aspect_ratio_idc = 0xff;
1964 seq_param->sar_width = GST_VIDEO_INFO_PAR_N (vip);
1965 seq_param->sar_height = GST_VIDEO_INFO_PAR_D (vip);
1967 seq_param->vui_fields.bits.bitstream_restriction_flag = FALSE;
1968 /* if vui_parameters_present_flag is TRUE and sps data belongs to
1969 * subset sps, timing_info_preset_flag should be zero (H.7.4.2.1.1) */
1970 seq_param->vui_fields.bits.timing_info_present_flag = !encoder->view_idx;
1971 if (seq_param->vui_fields.bits.timing_info_present_flag) {
1972 seq_param->num_units_in_tick = GST_VAAPI_ENCODER_FPS_D (encoder);
1973 seq_param->time_scale = GST_VAAPI_ENCODER_FPS_N (encoder) * 2;
1979 /* Fills in VA picture parameter buffer */
1981 fill_picture (GstVaapiEncoderH264Fei * encoder, GstVaapiEncPicture * picture,
1982 GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface)
1984 VAEncPictureParameterBufferH264 *const pic_param = picture->param;
1985 GstVaapiH264ViewRefPool *const ref_pool =
1986 &encoder->ref_pools[encoder->view_idx];
1987 GstVaapiEncoderH264FeiRef *ref_pic;
1991 memset (pic_param, 0, sizeof (VAEncPictureParameterBufferH264));
1993 /* reference list, */
1994 pic_param->CurrPic.picture_id = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface);
1995 pic_param->CurrPic.TopFieldOrderCnt = picture->poc;
1997 if (picture->type != GST_VAAPI_PICTURE_TYPE_I) {
1998 for (reflist = g_queue_peek_head_link (&ref_pool->ref_list);
1999 reflist; reflist = g_list_next (reflist)) {
2000 ref_pic = reflist->data;
2001 g_assert (ref_pic && ref_pic->pic &&
2002 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (ref_pic->pic) != VA_INVALID_ID);
2004 pic_param->ReferenceFrames[i].picture_id =
2005 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (ref_pic->pic);
2006 pic_param->ReferenceFrames[i].TopFieldOrderCnt = ref_pic->poc;
2007 pic_param->ReferenceFrames[i].flags |=
2008 VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2009 pic_param->ReferenceFrames[i].frame_idx = ref_pic->frame_num;
2013 g_assert (i <= 16 && i <= ref_pool->max_ref_frames);
2015 for (; i < 16; ++i) {
2016 pic_param->ReferenceFrames[i].picture_id = VA_INVALID_ID;
2018 pic_param->coded_buf = GST_VAAPI_OBJECT_ID (codedbuf);
2020 pic_param->pic_parameter_set_id = encoder->view_idx;
2021 pic_param->seq_parameter_set_id = encoder->view_idx ? 1 : 0;
2022 pic_param->last_picture = 0; /* means last encoding picture */
2023 pic_param->frame_num = picture->frame_num;
2024 pic_param->pic_init_qp = encoder->init_qp;
2025 pic_param->num_ref_idx_l0_active_minus1 =
2026 (ref_pool->max_reflist0_count ? (ref_pool->max_reflist0_count - 1) : 0);
2027 pic_param->num_ref_idx_l1_active_minus1 =
2028 (ref_pool->max_reflist1_count ? (ref_pool->max_reflist1_count - 1) : 0);
2029 pic_param->chroma_qp_index_offset = 0;
2030 pic_param->second_chroma_qp_index_offset = 0;
2032 /* set picture fields */
2033 pic_param->pic_fields.value = 0;
2034 pic_param->pic_fields.bits.idr_pic_flag =
2035 GST_VAAPI_ENC_PICTURE_IS_IDR (picture);
2036 pic_param->pic_fields.bits.reference_pic_flag =
2037 (picture->type != GST_VAAPI_PICTURE_TYPE_B);
2038 pic_param->pic_fields.bits.entropy_coding_mode_flag = encoder->use_cabac;
2039 pic_param->pic_fields.bits.weighted_pred_flag = FALSE;
2040 pic_param->pic_fields.bits.weighted_bipred_idc = 0;
2041 pic_param->pic_fields.bits.constrained_intra_pred_flag = 0;
2042 pic_param->pic_fields.bits.transform_8x8_mode_flag = encoder->use_dct8x8;
2043 /* enable debloking */
2044 pic_param->pic_fields.bits.deblocking_filter_control_present_flag = TRUE;
2045 pic_param->pic_fields.bits.redundant_pic_cnt_present_flag = FALSE;
2046 /* bottom_field_pic_order_in_frame_present_flag */
2047 pic_param->pic_fields.bits.pic_order_present_flag = FALSE;
2048 pic_param->pic_fields.bits.pic_scaling_matrix_present_flag = FALSE;
2053 /* Adds slice headers to picture */
2055 add_slice_headers (GstVaapiEncoderH264Fei * encoder,
2056 GstVaapiEncPicture * picture, GstVaapiEncoderH264FeiRef ** reflist_0,
2057 guint reflist_0_count, GstVaapiEncoderH264FeiRef ** reflist_1,
2058 guint reflist_1_count)
2060 VAEncSliceParameterBufferH264 *slice_param;
2061 GstVaapiEncSlice *slice;
2062 guint slice_of_mbs, slice_mod_mbs, cur_slice_mbs;
2064 guint last_mb_index;
2065 guint i_slice, i_ref;
2069 mb_size = encoder->mb_width * encoder->mb_height;
2071 g_assert (encoder->num_slices && encoder->num_slices < mb_size);
2072 slice_of_mbs = mb_size / encoder->num_slices;
2073 slice_mod_mbs = mb_size % encoder->num_slices;
2075 for (i_slice = 0; i_slice < encoder->num_slices; ++i_slice) {
2076 cur_slice_mbs = slice_of_mbs;
2077 if (slice_mod_mbs) {
2081 slice = GST_VAAPI_ENC_SLICE_NEW (H264, encoder);
2082 g_assert (slice && slice->param_id != VA_INVALID_ID);
2083 slice_param = slice->param;
2085 memset (slice_param, 0, sizeof (VAEncSliceParameterBufferH264));
2086 slice_param->macroblock_address = last_mb_index;
2087 slice_param->num_macroblocks = cur_slice_mbs;
2088 slice_param->macroblock_info = VA_INVALID_ID;
2089 slice_param->slice_type = h264_get_slice_type (picture->type);
2090 g_assert ((gint8) slice_param->slice_type != -1);
2091 slice_param->pic_parameter_set_id = encoder->view_idx;
2092 slice_param->idr_pic_id = encoder->idr_num;
2093 slice_param->pic_order_cnt_lsb = picture->poc;
2095 /* not used if pic_order_cnt_type = 0 */
2096 slice_param->delta_pic_order_cnt_bottom = 0;
2097 memset (slice_param->delta_pic_order_cnt, 0,
2098 sizeof (slice_param->delta_pic_order_cnt));
2100 /* only works for B frames */
2101 if (slice_param->slice_type == GST_H264_B_SLICE)
2102 slice_param->direct_spatial_mv_pred_flag = TRUE;
2103 /* default equal to picture parameters */
2104 slice_param->num_ref_idx_active_override_flag = FALSE;
2105 if (picture->type != GST_VAAPI_PICTURE_TYPE_I && reflist_0_count > 0)
2106 slice_param->num_ref_idx_l0_active_minus1 = reflist_0_count - 1;
2108 slice_param->num_ref_idx_l0_active_minus1 = 0;
2109 if (picture->type == GST_VAAPI_PICTURE_TYPE_B && reflist_1_count > 0)
2110 slice_param->num_ref_idx_l1_active_minus1 = reflist_1_count - 1;
2112 slice_param->num_ref_idx_l1_active_minus1 = 0;
2113 g_assert (slice_param->num_ref_idx_l0_active_minus1 == 0);
2114 g_assert (slice_param->num_ref_idx_l1_active_minus1 == 0);
2117 if (picture->type != GST_VAAPI_PICTURE_TYPE_I) {
2118 for (; i_ref < reflist_0_count; ++i_ref) {
2119 slice_param->RefPicList0[i_ref].picture_id =
2120 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (reflist_0[i_ref]->pic);
2121 slice_param->RefPicList0[i_ref].TopFieldOrderCnt =
2122 reflist_0[i_ref]->poc;
2123 slice_param->RefPicList0[i_ref].flags |=
2124 VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2125 slice_param->RefPicList0[i_ref].frame_idx = reflist_0[i_ref]->frame_num;
2127 g_assert (i_ref == 1);
2129 for (; i_ref < G_N_ELEMENTS (slice_param->RefPicList0); ++i_ref) {
2130 slice_param->RefPicList0[i_ref].picture_id = VA_INVALID_SURFACE;
2134 if (picture->type == GST_VAAPI_PICTURE_TYPE_B) {
2135 for (; i_ref < reflist_1_count; ++i_ref) {
2136 slice_param->RefPicList1[i_ref].picture_id =
2137 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (reflist_1[i_ref]->pic);
2138 slice_param->RefPicList1[i_ref].TopFieldOrderCnt =
2139 reflist_1[i_ref]->poc;
2140 slice_param->RefPicList1[i_ref].flags |=
2141 VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2142 slice_param->RefPicList1[i_ref].frame_idx = reflist_1[i_ref]->frame_num;
2144 g_assert (i_ref == 1);
2146 for (; i_ref < G_N_ELEMENTS (slice_param->RefPicList1); ++i_ref) {
2147 slice_param->RefPicList1[i_ref].picture_id = VA_INVALID_SURFACE;
2150 /* not used if pic_param.pic_fields.bits.weighted_pred_flag == FALSE */
2151 slice_param->luma_log2_weight_denom = 0;
2152 slice_param->chroma_log2_weight_denom = 0;
2153 slice_param->luma_weight_l0_flag = FALSE;
2154 memset (slice_param->luma_weight_l0, 0,
2155 sizeof (slice_param->luma_weight_l0));
2156 memset (slice_param->luma_offset_l0, 0,
2157 sizeof (slice_param->luma_offset_l0));
2158 slice_param->chroma_weight_l0_flag = FALSE;
2159 memset (slice_param->chroma_weight_l0, 0,
2160 sizeof (slice_param->chroma_weight_l0));
2161 memset (slice_param->chroma_offset_l0, 0,
2162 sizeof (slice_param->chroma_offset_l0));
2163 slice_param->luma_weight_l1_flag = FALSE;
2164 memset (slice_param->luma_weight_l1, 0,
2165 sizeof (slice_param->luma_weight_l1));
2166 memset (slice_param->luma_offset_l1, 0,
2167 sizeof (slice_param->luma_offset_l1));
2168 slice_param->chroma_weight_l1_flag = FALSE;
2169 memset (slice_param->chroma_weight_l1, 0,
2170 sizeof (slice_param->chroma_weight_l1));
2171 memset (slice_param->chroma_offset_l1, 0,
2172 sizeof (slice_param->chroma_offset_l1));
2174 slice_param->cabac_init_idc = 0;
2175 slice_param->slice_qp_delta = encoder->init_qp - encoder->min_qp;
2176 if (slice_param->slice_qp_delta > 4)
2177 slice_param->slice_qp_delta = 4;
2178 if ((gint) encoder->init_qp + slice_param->slice_qp_delta >
2179 (gint) encoder->max_qp) {
2180 slice_param->slice_qp_delta = encoder->max_qp - encoder->init_qp;
2182 slice_param->disable_deblocking_filter_idc = 0;
2183 slice_param->slice_alpha_c0_offset_div2 = 2;
2184 slice_param->slice_beta_offset_div2 = 2;
2186 /* set calculation for next slice */
2187 last_mb_index += cur_slice_mbs;
2189 /* add packed Prefix NAL unit before each Coded slice NAL in base view */
2190 if (encoder->is_mvc && !encoder->view_idx &&
2191 (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2192 VA_ENC_PACKED_HEADER_RAW_DATA)
2193 && !add_packed_prefix_nal_header (encoder, picture, slice))
2194 goto error_create_packed_prefix_nal_hdr;
2195 if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2196 VA_ENC_PACKED_HEADER_SLICE)
2197 && !add_packed_slice_header (encoder, picture, slice))
2198 goto error_create_packed_slice_hdr;
2200 gst_vaapi_enc_picture_add_slice (picture, slice);
2201 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) & slice, NULL);
2203 g_assert (last_mb_index == mb_size);
2206 error_create_packed_slice_hdr:
2208 GST_ERROR ("failed to create packed slice header buffer");
2209 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) & slice, NULL);
2212 error_create_packed_prefix_nal_hdr:
2214 GST_ERROR ("failed to create packed prefix nal header buffer");
2215 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) & slice, NULL);
2220 /* Generates and submits SPS header accordingly into the bitstream */
2222 ensure_sequence (GstVaapiEncoderH264Fei * encoder, GstVaapiEncPicture * picture)
2224 GstVaapiEncSequence *sequence = NULL;
2226 /* submit an SPS header before every new I-frame, if codec config changed */
2227 if (!encoder->config_changed || picture->type != GST_VAAPI_PICTURE_TYPE_I)
2230 sequence = GST_VAAPI_ENC_SEQUENCE_NEW (H264, encoder);
2231 if (!sequence || !fill_sequence (encoder, sequence))
2232 goto error_create_seq_param;
2234 /* add subset sps for non-base view and sps for base view */
2235 if (encoder->is_mvc && encoder->view_idx) {
2236 if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2237 VA_ENC_PACKED_HEADER_SEQUENCE)
2238 && !add_packed_sequence_header_mvc (encoder, picture, sequence))
2239 goto error_create_packed_seq_hdr;
2241 if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2242 VA_ENC_PACKED_HEADER_SEQUENCE)
2243 && !add_packed_sequence_header (encoder, picture, sequence))
2244 goto error_create_packed_seq_hdr;
2248 gst_vaapi_enc_picture_set_sequence (picture, sequence);
2249 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) & sequence, NULL);
2252 if (!encoder->is_mvc || encoder->view_idx > 0)
2253 encoder->config_changed = FALSE;
2257 error_create_seq_param:
2259 GST_ERROR ("failed to create sequence parameter buffer (SPS)");
2260 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) & sequence, NULL);
2263 error_create_packed_seq_hdr:
2265 GST_ERROR ("failed to create packed sequence header buffer");
2266 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) & sequence, NULL);
2271 /* Generates additional fei control parameters */
2273 ensure_fei_misc_params (GstVaapiEncoderH264Fei * encoder,
2274 GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf_proxy)
2276 GstVaapiEncMiscParam *misc = NULL;
2277 GstVaapiSurfaceProxy *surface_proxy = NULL;
2279 VAEncMiscParameterFEIFrameControlH264 *misc_fei_pic_control_param;
2280 guint mbcode_size = 0;
2282 guint dist_size = 0;
2283 gboolean enable_out = FALSE;
2285 /* fei pic control params */
2286 misc = GST_VAAPI_ENC_FEI_MISC_PARAM_NEW (H264, encoder);
2290 misc_fei_pic_control_param = misc->data;
2291 surface_proxy = picture->proxy;
2293 enable_out = ((encoder->is_stats_out_enabled &&
2294 (encoder->fei_mode == GST_VAAPI_FEI_MODE_ENC_PAK)) ||
2295 (encoder->fei_mode == GST_VAAPI_FEI_MODE_ENC)) ? TRUE : FALSE;
2297 misc_fei_pic_control_param->function = encoder->fei_mode;
2298 misc_fei_pic_control_param->search_path = encoder->search_path;
2299 misc_fei_pic_control_param->num_mv_predictors_l0 =
2300 encoder->num_mv_predictors_l0;
2301 misc_fei_pic_control_param->num_mv_predictors_l1 =
2302 encoder->num_mv_predictors_l1;
2303 misc_fei_pic_control_param->len_sp = encoder->len_sp;
2304 misc_fei_pic_control_param->sub_mb_part_mask = encoder->submb_part_mask;
2305 if (!encoder->use_dct8x8)
2306 misc_fei_pic_control_param->intra_part_mask = encoder->intra_part_mask | 2;
2307 misc_fei_pic_control_param->multi_pred_l0 = encoder->multi_predL0;
2308 misc_fei_pic_control_param->multi_pred_l1 = encoder->multi_predL1;
2309 misc_fei_pic_control_param->sub_pel_mode = encoder->subpel_mode;
2310 misc_fei_pic_control_param->inter_sad = encoder->inter_sad;
2311 misc_fei_pic_control_param->intra_sad = encoder->intra_sad;
2312 misc_fei_pic_control_param->distortion_type = 0;
2313 misc_fei_pic_control_param->repartition_check_enable = 0;
2314 misc_fei_pic_control_param->adaptive_search = encoder->adaptive_search;
2315 misc_fei_pic_control_param->mb_size_ctrl = 0;
2316 misc_fei_pic_control_param->ref_width = encoder->ref_width;
2317 misc_fei_pic_control_param->ref_height = encoder->ref_height;
2318 misc_fei_pic_control_param->search_window = encoder->search_window;
2320 if ((encoder->fei_mode == GST_VAAPI_FEI_MODE_ENC_PAK) ||
2321 (encoder->fei_mode == GST_VAAPI_FEI_MODE_ENC)) {
2323 /***** ENC_PAK/ENC input: mv_predictor *****/
2324 if (surface_proxy->mvpred) {
2325 misc_fei_pic_control_param->mv_predictor =
2326 GST_VAAPI_FEI_CODEC_OBJECT (surface_proxy->mvpred)->param_id;
2327 misc_fei_pic_control_param->mv_predictor_enable = TRUE;
2328 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) &
2329 picture->mvpred, surface_proxy->mvpred);
2331 misc_fei_pic_control_param->mv_predictor = VA_INVALID_ID;
2332 misc_fei_pic_control_param->mv_predictor_enable = FALSE;
2333 picture->mvpred = NULL;
2336 /***** ENC_PAK/ENC input: qp ******/
2337 if (surface_proxy->qp) {
2338 misc_fei_pic_control_param->qp =
2339 GST_VAAPI_FEI_CODEC_OBJECT (surface_proxy->qp)->param_id;
2340 misc_fei_pic_control_param->mb_qp = TRUE;
2341 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) &
2342 picture->qp, surface_proxy->qp);
2344 misc_fei_pic_control_param->qp = VA_INVALID_ID;
2345 misc_fei_pic_control_param->mb_qp = FALSE;
2349 /***** ENC_PAK/ENC input: mb_control ******/
2350 if (surface_proxy->mbcntrl) {
2351 misc_fei_pic_control_param->mb_ctrl =
2352 GST_VAAPI_FEI_CODEC_OBJECT (surface_proxy->mbcntrl)->param_id;
2353 misc_fei_pic_control_param->mb_input = TRUE;
2354 gst_vaapi_codec_object_replace ((GstVaapiCodecObject **) &
2355 picture->mbcntrl, surface_proxy->mbcntrl);
2357 misc_fei_pic_control_param->mb_ctrl = VA_INVALID_ID;
2358 misc_fei_pic_control_param->mb_input = FALSE;
2359 picture->mbcntrl = NULL;
2365 mbcode_size = sizeof (VAEncFEIMBCodeH264) *
2366 encoder->mb_width * encoder->mb_height;
2367 mv_size = sizeof (VAMotionVector) * 16 *
2368 encoder->mb_width * encoder->mb_height;
2369 dist_size = sizeof (VAEncFEIDistortionH264) *
2370 encoder->mb_width * encoder->mb_height;
2372 /***** ENC_PAK/ENC output: macroblock code buffer *****/
2373 codedbuf_proxy->mbcode =
2374 gst_vaapi_enc_fei_mb_code_new (GST_VAAPI_ENCODER_CAST (encoder),
2376 misc_fei_pic_control_param->mb_code_data =
2377 GST_VAAPI_FEI_CODEC_OBJECT (codedbuf_proxy->mbcode)->param_id;
2378 picture->mbcode = gst_vaapi_codec_object_ref (codedbuf_proxy->mbcode);
2380 /***** ENC_PAK/ENC output: motion vector buffer *****/
2381 codedbuf_proxy->mv =
2382 gst_vaapi_enc_fei_mv_new (GST_VAAPI_ENCODER_CAST (encoder), NULL,
2384 misc_fei_pic_control_param->mv_data =
2385 GST_VAAPI_FEI_CODEC_OBJECT (codedbuf_proxy->mv)->param_id;
2386 picture->mv = gst_vaapi_codec_object_ref (codedbuf_proxy->mv);
2388 /***** ENC_PAK/ENC output: distortion buffer *****/
2389 codedbuf_proxy->dist =
2390 gst_vaapi_enc_fei_distortion_new (GST_VAAPI_ENCODER_CAST (encoder),
2392 misc_fei_pic_control_param->distortion =
2393 GST_VAAPI_FEI_CODEC_OBJECT (codedbuf_proxy->dist)->param_id;
2394 picture->dist = gst_vaapi_codec_object_ref (codedbuf_proxy->dist);
2396 } else if (encoder->fei_mode == GST_VAAPI_FEI_MODE_PAK) {
2398 g_assert (surface_proxy->mbcode != NULL);
2399 g_assert (surface_proxy->mv != NULL);
2401 /***** PAK input: macroblock code buffer *****/
2402 misc_fei_pic_control_param->mb_code_data =
2403 GST_VAAPI_FEI_CODEC_OBJECT (surface_proxy->mbcode)->param_id;
2404 picture->mbcode = gst_vaapi_codec_object_ref (surface_proxy->mbcode);
2406 /***** PAK input: motion vector buffer *****/
2407 misc_fei_pic_control_param->mv_data =
2408 GST_VAAPI_FEI_CODEC_OBJECT (surface_proxy->mv)->param_id;
2409 picture->mv = gst_vaapi_codec_object_ref (surface_proxy->mv);
2412 codedbuf_proxy->mbcode = picture->mbcode = NULL;
2413 codedbuf_proxy->mv = picture->mv = NULL;
2414 codedbuf_proxy->dist = picture->dist = NULL;
2415 misc_fei_pic_control_param->mb_code_data = VA_INVALID_ID;
2416 misc_fei_pic_control_param->mv_data = VA_INVALID_ID;
2417 misc_fei_pic_control_param->distortion = VA_INVALID_ID;
2420 gst_vaapi_enc_picture_add_misc_param (picture, misc);
2421 gst_vaapi_codec_object_replace (&misc, NULL);
2425 /* Generates additional control parameters */
2427 ensure_misc_params (GstVaapiEncoderH264Fei * encoder,
2428 GstVaapiEncPicture * picture)
2430 GstVaapiEncMiscParam *misc = NULL;
2431 VAEncMiscParameterRateControl *rate_control;
2434 misc = GST_VAAPI_ENC_MISC_PARAM_NEW (HRD, encoder);
2438 fill_hrd_params (encoder, misc->data);
2439 gst_vaapi_enc_picture_add_misc_param (picture, misc);
2440 gst_vaapi_codec_object_replace (&misc, NULL);
2442 /* RateControl params */
2443 if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CBR ||
2444 GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_VBR) {
2445 misc = GST_VAAPI_ENC_MISC_PARAM_NEW (RateControl, encoder);
2449 rate_control = misc->data;
2450 memset (rate_control, 0, sizeof (VAEncMiscParameterRateControl));
2451 rate_control->bits_per_second = encoder->bitrate_bits;
2452 rate_control->target_percentage = 70;
2453 rate_control->window_size = encoder->cpb_length;
2454 rate_control->initial_qp = encoder->init_qp;
2455 rate_control->min_qp = encoder->min_qp;
2457 #if VA_CHECK_VERSION(1,1,0)
2458 rate_control->max_qp = encoder->max_qp;
2461 rate_control->basic_unit_size = 0;
2462 gst_vaapi_enc_picture_add_misc_param (picture, misc);
2463 gst_vaapi_codec_object_replace (&misc, NULL);
2465 if (!encoder->view_idx) {
2466 if ((GST_VAAPI_ENC_PICTURE_IS_IDR (picture)) &&
2467 (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2468 VA_ENC_PACKED_HEADER_MISC) &&
2469 !add_packed_sei_header (encoder, picture,
2470 GST_VAAPI_H264_SEI_BUF_PERIOD | GST_VAAPI_H264_SEI_PIC_TIMING))
2471 goto error_create_packed_sei_hdr;
2473 else if (!GST_VAAPI_ENC_PICTURE_IS_IDR (picture) &&
2474 (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2475 VA_ENC_PACKED_HEADER_MISC) &&
2476 !add_packed_sei_header (encoder, picture,
2477 GST_VAAPI_H264_SEI_PIC_TIMING))
2478 goto error_create_packed_sei_hdr;
2484 error_create_packed_sei_hdr:
2486 GST_ERROR ("failed to create packed SEI header");
2491 /* Generates and submits PPS header accordingly into the bitstream */
2493 ensure_picture (GstVaapiEncoderH264Fei * encoder, GstVaapiEncPicture * picture,
2494 GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface)
2496 GstVaapiCodedBuffer *const codedbuf =
2497 GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy);
2498 gboolean res = FALSE;
2500 res = fill_picture (encoder, picture, codedbuf, surface);
2505 if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
2506 (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2507 VA_ENC_PACKED_HEADER_PICTURE)
2508 && !add_packed_picture_header (encoder, picture)) {
2509 GST_ERROR ("set picture packed header failed");
2515 /* Generates slice headers */
2517 ensure_slices (GstVaapiEncoderH264Fei * encoder, GstVaapiEncPicture * picture)
2519 GstVaapiEncoderH264FeiRef *reflist_0[16];
2520 GstVaapiEncoderH264FeiRef *reflist_1[16];
2521 GstVaapiH264ViewRefPool *const ref_pool =
2522 &encoder->ref_pools[encoder->view_idx];
2523 guint reflist_0_count = 0, reflist_1_count = 0;
2527 if (picture->type != GST_VAAPI_PICTURE_TYPE_I &&
2528 !reference_list_init (encoder, picture,
2529 reflist_0, &reflist_0_count, reflist_1, &reflist_1_count)) {
2530 GST_ERROR ("reference list reorder failed");
2534 g_assert (reflist_0_count + reflist_1_count <= ref_pool->max_ref_frames);
2535 if (reflist_0_count > ref_pool->max_reflist0_count)
2536 reflist_0_count = ref_pool->max_reflist0_count;
2537 if (reflist_1_count > ref_pool->max_reflist1_count)
2538 reflist_1_count = ref_pool->max_reflist1_count;
2540 if (!add_slice_headers (encoder, picture,
2541 reflist_0, reflist_0_count, reflist_1, reflist_1_count))
2547 /* Normalizes bitrate (and CPB size) for HRD conformance */
2549 ensure_bitrate_hrd (GstVaapiEncoderH264Fei * encoder)
2551 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2552 guint bitrate, cpb_size;
2554 if (!base_encoder->bitrate) {
2555 encoder->bitrate_bits = 0;
2559 /* Round down bitrate. This is a hard limit mandated by the user */
2560 g_assert (SX_BITRATE >= 6);
2561 bitrate = (base_encoder->bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
2562 if (bitrate != encoder->bitrate_bits) {
2563 GST_DEBUG ("HRD bitrate: %u bits/sec", bitrate);
2564 encoder->bitrate_bits = bitrate;
2565 encoder->config_changed = TRUE;
2568 /* Round up CPB size. This is an HRD compliance detail */
2569 g_assert (SX_CPB_SIZE >= 4);
2570 cpb_size = gst_util_uint64_scale (bitrate, encoder->cpb_length, 1000) &
2571 ~((1U << SX_CPB_SIZE) - 1);
2572 if (cpb_size != encoder->cpb_length_bits) {
2573 GST_DEBUG ("HRD CPB size: %u bits", cpb_size);
2574 encoder->cpb_length_bits = cpb_size;
2575 encoder->config_changed = TRUE;
2579 /* Estimates a good enough bitrate if none was supplied */
2581 ensure_bitrate (GstVaapiEncoderH264Fei * encoder)
2583 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2585 /* Default compression: 48 bits per macroblock in "high-compression" mode */
2586 switch (GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
2587 case GST_VAAPI_RATECONTROL_CBR:
2588 case GST_VAAPI_RATECONTROL_VBR:
2589 case GST_VAAPI_RATECONTROL_VBR_CONSTRAINED:
2590 if (!base_encoder->bitrate) {
2591 /* According to the literature and testing, CABAC entropy coding
2592 mode could provide for +10% to +18% improvement in general,
2593 thus estimating +15% here ; and using adaptive 8x8 transforms
2594 in I-frames could bring up to +10% improvement. */
2595 guint bits_per_mb = 48;
2598 if (!encoder->use_cabac)
2599 bits_per_mb += (bits_per_mb * 15) / 100;
2600 if (!encoder->use_dct8x8)
2601 bits_per_mb += (bits_per_mb * 10) / 100;
2603 factor = encoder->mb_width * encoder->mb_height * bits_per_mb;
2604 base_encoder->bitrate =
2605 gst_util_uint64_scale (factor, GST_VAAPI_ENCODER_FPS_N (encoder),
2606 GST_VAAPI_ENCODER_FPS_D (encoder)) / 1000;
2607 GST_INFO ("target bitrate computed to %u kbps", base_encoder->bitrate);
2611 base_encoder->bitrate = 0;
2614 ensure_bitrate_hrd (encoder);
2617 /* Constructs profile and level information based on user-defined limits */
2618 static GstVaapiEncoderStatus
2619 ensure_profile_and_level (GstVaapiEncoderH264Fei * encoder)
2621 const GstVaapiProfile profile = encoder->profile;
2622 const GstVaapiLevelH264 level = encoder->level;
2624 if (!ensure_tuning (encoder))
2625 GST_WARNING ("Failed to set some of the tuning option as expected! ");
2627 if (!ensure_profile (encoder) || !ensure_profile_limits (encoder))
2628 return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2630 /* Check HW constraints */
2631 if (!ensure_hw_profile_limits (encoder))
2632 return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2633 if (encoder->profile_idc > encoder->hw_max_profile_idc)
2634 return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2636 /* Ensure bitrate if not set already and derive the right level to use */
2637 ensure_bitrate (encoder);
2638 if (!ensure_level (encoder))
2639 return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
2641 if (encoder->profile != profile || encoder->level != level) {
2642 GST_DEBUG ("selected %s profile at level %s",
2643 gst_vaapi_utils_h264_get_profile_string (encoder->profile),
2644 gst_vaapi_utils_h264_get_level_string (encoder->level));
2645 encoder->config_changed = TRUE;
2647 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2651 reset_properties (GstVaapiEncoderH264Fei * encoder)
2653 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2656 if (encoder->idr_period < base_encoder->keyframe_period)
2657 encoder->idr_period = base_encoder->keyframe_period;
2659 g_assert (encoder->min_qp <= encoder->max_qp);
2660 if (encoder->min_qp > encoder->init_qp ||
2661 (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP &&
2662 encoder->min_qp < encoder->init_qp))
2663 encoder->min_qp = encoder->init_qp;
2664 if (encoder->max_qp < encoder->init_qp)
2665 encoder->max_qp = encoder->init_qp;
2667 mb_size = encoder->mb_width * encoder->mb_height;
2668 if (encoder->num_slices > (mb_size + 1) / 2)
2669 encoder->num_slices = (mb_size + 1) / 2;
2670 g_assert (encoder->num_slices);
2672 if (encoder->num_bframes > (base_encoder->keyframe_period + 1) / 2)
2673 encoder->num_bframes = (base_encoder->keyframe_period + 1) / 2;
2675 /* Workaround : vaapi-intel-driver doesn't have support for
2676 * B-frame encode when utilizing low-power encode hardware block.
2677 * So Disabling b-frame encoding in low-pwer encode.
2679 * Fixme :We should query the VAConfigAttribEncMaxRefFrames
2680 * instead of blindly disabling b-frame support and set b/p frame count,
2681 * buffer pool size etc based on that.*/
2682 if ((encoder->num_bframes > 0)
2683 && (encoder->entrypoint == GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_LP)) {
2685 ("Disabling b-frame since the driver doesn't supporting it in low-power encode");
2686 encoder->num_bframes = 0;
2689 if (encoder->num_bframes > 0 && GST_VAAPI_ENCODER_FPS_N (encoder) > 0)
2690 encoder->cts_offset = gst_util_uint64_scale (GST_SECOND,
2691 GST_VAAPI_ENCODER_FPS_D (encoder), GST_VAAPI_ENCODER_FPS_N (encoder));
2693 encoder->cts_offset = 0;
2695 /* init max_frame_num, max_poc */
2696 encoder->log2_max_frame_num =
2697 h264_get_log2_max_frame_num (encoder->idr_period);
2698 g_assert (encoder->log2_max_frame_num >= 4);
2699 encoder->max_frame_num = (1 << encoder->log2_max_frame_num);
2700 encoder->log2_max_pic_order_cnt = encoder->log2_max_frame_num + 1;
2701 encoder->max_pic_order_cnt = (1 << encoder->log2_max_pic_order_cnt);
2702 encoder->idr_num = 0;
2704 for (i = 0; i < encoder->num_views; i++) {
2705 GstVaapiH264ViewRefPool *const ref_pool = &encoder->ref_pools[i];
2706 GstVaapiH264ViewReorderPool *const reorder_pool =
2707 &encoder->reorder_pools[i];
2709 ref_pool->max_reflist0_count = 1;
2710 ref_pool->max_reflist1_count = encoder->num_bframes > 0;
2711 ref_pool->max_ref_frames = ref_pool->max_reflist0_count
2712 + ref_pool->max_reflist1_count;
2714 reorder_pool->frame_index = 0;
2719 copy_picture_attrib (GstVaapiEncPicture * dst, GstVaapiEncPicture * src)
2724 dst->proxy = src->proxy;
2725 dst->surface = src->surface;
2726 dst->type = src->type;
2727 dst->surface_id = src->surface_id;
2728 dst->frame_num = src->frame_num;
2729 dst->poc = src->poc;
2734 static GstVaapiEncoderStatus
2735 gst_vaapi_encoder_h264_fei_encode (GstVaapiEncoder * base_encoder,
2736 GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf)
2738 GstVaapiEncoderH264Fei *const encoder =
2739 GST_VAAPI_ENCODER_H264_FEI_CAST (base_encoder);
2740 GstVaapiEncoder *enc_base_encoder = GST_VAAPI_ENCODER_CAST (encoder->feienc);
2741 GstVaapiEncoderStatus status = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2742 GstVaapiSurfaceProxy *reconstruct = NULL;
2743 GstVaapiEncPicture *picture2 = NULL;
2744 GstVaapiFeiInfoToPakH264 info_to_pak;
2746 reconstruct = gst_vaapi_encoder_create_surface (base_encoder);
2748 g_assert (GST_VAAPI_SURFACE_PROXY_SURFACE (reconstruct));
2750 if ((encoder->fei_mode == GST_VAAPI_FEI_MODE_ENC_PAK)
2751 || (encoder->fei_mode == GST_VAAPI_FEI_MODE_ENC)
2752 || (encoder->fei_mode == GST_VAAPI_FEI_MODE_PAK)) {
2754 if (!ensure_sequence (encoder, picture))
2756 if (!ensure_misc_params (encoder, picture))
2758 if (!encoder->is_fei_disabled
2759 && !ensure_fei_misc_params (encoder, picture, codedbuf))
2761 if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
2763 if (!ensure_slices (encoder, picture))
2765 if (!gst_vaapi_enc_picture_encode (picture))
2768 if (!reference_list_update (encoder, picture, reconstruct))
2771 } else if (encoder->fei_mode ==
2772 (GST_VAAPI_FEI_MODE_ENC | GST_VAAPI_FEI_MODE_PAK)) {
2774 * ref pool is managed by pak.
2775 * enc will copy from it.
2777 if (picture->type != GST_VAAPI_PICTURE_TYPE_I
2778 && !gst_vaapi_feipak_h264_get_ref_pool (encoder->feipak,
2779 &encoder->ref_pool_ptr)) {
2780 GST_ERROR ("failed to get pak ref pool");
2781 status = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2785 if (picture->type != GST_VAAPI_PICTURE_TYPE_I
2786 && !gst_vaapi_feienc_h264_set_ref_pool (encoder->feienc,
2787 encoder->ref_pool_ptr)) {
2788 GST_ERROR ("failed to set enc ref pool");
2789 status = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2794 gst_vaapi_feienc_h264_encode (enc_base_encoder, picture, reconstruct,
2795 codedbuf, &info_to_pak);
2796 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) {
2797 GST_ERROR ("failed to process enc class encode");
2801 /* duplicate a picture for pak */
2802 picture2 = GST_VAAPI_ENC_PICTURE_NEW (H264, base_encoder, picture->frame);
2804 GST_WARNING ("create H264 picture failed, frame timestamp:%"
2805 GST_TIME_FORMAT, GST_TIME_ARGS (picture->frame->pts));
2806 status = GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2809 if (!copy_picture_attrib (picture2, picture)) {
2810 status = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2813 /* need set picture IDR info for PAK */
2814 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
2815 GST_VAAPI_ENC_PICTURE_FLAG_SET (picture2, GST_VAAPI_ENC_PICTURE_FLAG_IDR);
2818 gst_vaapi_feipak_h264_encode (encoder->feipak, picture2, codedbuf,
2819 reconstruct, &info_to_pak);
2820 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) {
2821 GST_ERROR ("failed to process pak class encode");
2825 /* Free the slice array */
2826 if (info_to_pak.h264_slice_headers)
2827 g_array_free (info_to_pak.h264_slice_headers, TRUE);
2829 gst_vaapi_enc_picture_unref (picture2);
2833 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2839 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
2842 gst_vaapi_enc_picture_unref (picture2);
2847 static GstVaapiEncoderStatus
2848 gst_vaapi_encoder_h264_fei_flush (GstVaapiEncoder * base_encoder)
2850 GstVaapiEncoderH264Fei *const encoder =
2851 GST_VAAPI_ENCODER_H264_FEI_CAST (base_encoder);
2852 GstVaapiEncoder *enc_base_encoder = GST_VAAPI_ENCODER_CAST (encoder->feienc);
2853 GstVaapiH264ViewReorderPool *reorder_pool;
2854 GstVaapiEncPicture *pic;
2855 GstVaapiEncoderStatus status;
2858 if ((encoder->fei_mode == GST_VAAPI_FEI_MODE_ENC_PAK)
2859 || (encoder->fei_mode == GST_VAAPI_FEI_MODE_PAK)) {
2860 for (i = 0; i < encoder->num_views; i++) {
2861 reorder_pool = &encoder->reorder_pools[i];
2862 reorder_pool->frame_index = 0;
2863 reorder_pool->cur_frame_num = 0;
2864 reorder_pool->cur_present_index = 0;
2866 while (!g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2867 pic = (GstVaapiEncPicture *)
2868 g_queue_pop_head (&reorder_pool->reorder_frame_list);
2869 gst_vaapi_enc_picture_unref (pic);
2871 g_queue_clear (&reorder_pool->reorder_frame_list);
2873 } else if (encoder->fei_mode ==
2874 (GST_VAAPI_FEI_MODE_ENC | GST_VAAPI_FEI_MODE_PAK)) {
2876 status = gst_vaapi_feienc_h264_flush (enc_base_encoder);
2877 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) {
2878 GST_ERROR ("failed to process enc class flush");
2882 status = gst_vaapi_feipak_h264_flush (encoder->feipak);
2883 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) {
2884 GST_ERROR ("failed to process pak class flush");
2888 g_assert (encoder->fei_mode == GST_VAAPI_FEI_MODE_ENC);
2891 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2894 /* Generate "codec-data" buffer */
2895 static GstVaapiEncoderStatus
2896 gst_vaapi_encoder_h264_fei_get_codec_data (GstVaapiEncoder * base_encoder,
2897 GstBuffer ** out_buffer_ptr)
2899 GstVaapiEncoderH264Fei *const encoder =
2900 GST_VAAPI_ENCODER_H264_FEI_CAST (base_encoder);
2901 const guint32 configuration_version = 0x01;
2902 const guint32 nal_length_size = 4;
2903 guint8 profile_idc, profile_comp, level_idc;
2904 GstMapInfo sps_info, pps_info;
2908 if (!encoder->sps_data || !encoder->pps_data)
2909 return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
2910 if (gst_buffer_get_size (encoder->sps_data) < 4)
2911 return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
2913 if (!gst_buffer_map (encoder->sps_data, &sps_info, GST_MAP_READ))
2914 goto error_map_sps_buffer;
2916 if (!gst_buffer_map (encoder->pps_data, &pps_info, GST_MAP_READ))
2917 goto error_map_pps_buffer;
2919 /* skip sps_data[0], which is the nal_unit_type */
2920 profile_idc = sps_info.data[1];
2921 profile_comp = sps_info.data[2];
2922 level_idc = sps_info.data[3];
2925 gst_bit_writer_init_with_size (&bs, (sps_info.size + pps_info.size + 64),
2927 WRITE_UINT32 (&bs, configuration_version, 8);
2928 WRITE_UINT32 (&bs, profile_idc, 8);
2929 WRITE_UINT32 (&bs, profile_comp, 8);
2930 WRITE_UINT32 (&bs, level_idc, 8);
2931 WRITE_UINT32 (&bs, 0x3f, 6); /* 111111 */
2932 WRITE_UINT32 (&bs, nal_length_size - 1, 2);
2933 WRITE_UINT32 (&bs, 0x07, 3); /* 111 */
2936 WRITE_UINT32 (&bs, 1, 5); /* SPS count = 1 */
2937 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
2938 WRITE_UINT32 (&bs, sps_info.size, 16);
2939 gst_bit_writer_put_bytes (&bs, sps_info.data, sps_info.size);
2942 WRITE_UINT32 (&bs, 1, 8); /* PPS count = 1 */
2943 WRITE_UINT32 (&bs, pps_info.size, 16);
2944 gst_bit_writer_put_bytes (&bs, pps_info.data, pps_info.size);
2946 gst_buffer_unmap (encoder->pps_data, &pps_info);
2947 gst_buffer_unmap (encoder->sps_data, &sps_info);
2949 buffer = gst_bit_writer_reset_and_get_buffer (&bs);
2951 goto error_alloc_buffer;
2952 *out_buffer_ptr = buffer;
2954 gst_bit_writer_reset (&bs);
2955 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2960 GST_ERROR ("failed to write codec-data");
2961 gst_buffer_unmap (encoder->sps_data, &sps_info);
2962 gst_buffer_unmap (encoder->pps_data, &pps_info);
2963 gst_bit_writer_reset (&bs);
2966 error_map_sps_buffer:
2968 GST_ERROR ("failed to map SPS packed header");
2969 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2971 error_map_pps_buffer:
2973 GST_ERROR ("failed to map PPS packed header");
2974 gst_buffer_unmap (encoder->sps_data, &sps_info);
2975 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2979 GST_ERROR ("failed to allocate codec-data buffer");
2980 gst_bit_writer_reset (&bs);
2981 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2985 static GstVaapiEncoderStatus
2986 gst_vaapi_encoder_h264_fei_reordering (GstVaapiEncoder * base_encoder,
2987 GstVideoCodecFrame * frame, GstVaapiEncPicture ** output)
2989 GstVaapiEncoderH264Fei *const encoder =
2990 GST_VAAPI_ENCODER_H264_FEI_CAST (base_encoder);
2991 GstVaapiH264ViewReorderPool *reorder_pool = NULL;
2992 GstVaapiEncPicture *picture;
2993 gboolean is_idr = FALSE;
2997 if ((encoder->fei_mode != GST_VAAPI_FEI_MODE_ENC_PAK)
2998 && (encoder->fei_mode != GST_VAAPI_FEI_MODE_PAK)) {
2999 GstVaapiEncoder *enc_base_encoder =
3000 GST_VAAPI_ENCODER_CAST (encoder->feienc);
3001 GstVaapiEncoderStatus status;
3003 status = gst_vaapi_feienc_h264_reordering (enc_base_encoder, frame, output);
3004 if ((status != GST_VAAPI_ENCODER_STATUS_SUCCESS) &&
3005 (status != GST_VAAPI_ENCODER_STATUS_NO_SURFACE))
3006 GST_ERROR ("failed to process enc reordering");
3011 /* encoding views alternatively for MVC */
3012 if (encoder->is_mvc) {
3013 /* FIXME: Use first-in-bundle flag on buffers to reset view idx? */
3015 encoder->view_idx = frame->system_frame_number % encoder->num_views;
3017 encoder->view_idx = (encoder->view_idx + 1) % encoder->num_views;
3019 reorder_pool = &encoder->reorder_pools[encoder->view_idx];
3022 if (reorder_pool->reorder_state != GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES)
3023 return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
3025 /* reorder_state = GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES
3026 dump B frames from queue, sometime, there may also have P frame or I frame */
3027 g_assert (encoder->num_bframes > 0);
3028 g_return_val_if_fail (!g_queue_is_empty (&reorder_pool->reorder_frame_list),
3029 GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN);
3030 picture = g_queue_pop_head (&reorder_pool->reorder_frame_list);
3032 if (g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
3033 reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES;
3038 /* new frame coming */
3039 picture = GST_VAAPI_ENC_PICTURE_NEW (H264, encoder, frame);
3041 GST_WARNING ("create H264 picture failed, frame timestamp:%"
3042 GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts));
3043 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
3045 ++reorder_pool->cur_present_index;
3046 picture->poc = ((reorder_pool->cur_present_index * 2) %
3047 encoder->max_pic_order_cnt);
3049 is_idr = (reorder_pool->frame_index == 0 ||
3050 reorder_pool->frame_index >= encoder->idr_period);
3052 /* check key frames */
3053 if (is_idr || GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame) ||
3054 (reorder_pool->frame_index %
3055 GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder)) == 0) {
3056 ++reorder_pool->cur_frame_num;
3057 ++reorder_pool->frame_index;
3059 /* b frame enabled, check queue of reorder_frame_list */
3060 if (encoder->num_bframes
3061 && !g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
3062 GstVaapiEncPicture *p_pic;
3064 p_pic = g_queue_pop_tail (&reorder_pool->reorder_frame_list);
3065 set_p_frame (p_pic, encoder);
3066 g_queue_foreach (&reorder_pool->reorder_frame_list,
3067 (GFunc) set_b_frame, encoder);
3068 ++reorder_pool->cur_frame_num;
3069 set_key_frame (picture, encoder, is_idr);
3070 g_queue_push_tail (&reorder_pool->reorder_frame_list, picture);
3072 reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES;
3073 } else { /* no b frames in queue */
3074 set_key_frame (picture, encoder, is_idr);
3075 g_assert (g_queue_is_empty (&reorder_pool->reorder_frame_list));
3076 if (encoder->num_bframes)
3077 reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES;
3082 /* new p/b frames coming */
3083 ++reorder_pool->frame_index;
3084 if (reorder_pool->reorder_state == GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES &&
3085 g_queue_get_length (&reorder_pool->reorder_frame_list) <
3086 encoder->num_bframes) {
3087 g_queue_push_tail (&reorder_pool->reorder_frame_list, picture);
3088 return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
3091 ++reorder_pool->cur_frame_num;
3092 set_p_frame (picture, encoder);
3094 if (reorder_pool->reorder_state == GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES) {
3095 g_queue_foreach (&reorder_pool->reorder_frame_list, (GFunc) set_b_frame,
3097 reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES;
3098 g_assert (!g_queue_is_empty (&reorder_pool->reorder_frame_list));
3103 frame = picture->frame;
3104 if (GST_CLOCK_TIME_IS_VALID (frame->pts))
3105 frame->pts += encoder->cts_offset;
3108 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
3111 static GstVaapiEncoderStatus
3112 set_context_info (GstVaapiEncoder * base_encoder)
3114 GstVaapiEncoderH264Fei *const encoder =
3115 GST_VAAPI_ENCODER_H264_FEI_CAST (base_encoder);
3116 GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
3117 const guint DEFAULT_SURFACES_COUNT = 3;
3119 /* Maximum sizes for common headers (in bits) */
3122 MAX_SPS_HDR_SIZE = 16473,
3123 MAX_VUI_PARAMS_SIZE = 210,
3124 MAX_HRD_PARAMS_SIZE = 4103,
3125 MAX_PPS_HDR_SIZE = 101,
3126 MAX_SLICE_HDR_SIZE = 397 + 2572 + 6670 + 2402,
3129 if (!ensure_hw_profile (encoder))
3130 return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
3132 base_encoder->num_ref_frames =
3133 ((encoder->num_bframes ? 2 : 1) + DEFAULT_SURFACES_COUNT)
3134 * encoder->num_views;
3136 /* Only YUV 4:2:0 formats are supported for now. This means that we
3137 have a limit of 3200 bits per macroblock. */
3138 /* XXX: check profile and compute RawMbBits */
3139 base_encoder->codedbuf_size = (GST_ROUND_UP_16 (vip->width) *
3140 GST_ROUND_UP_16 (vip->height) / 256) * 400;
3142 /* Account for SPS header */
3143 /* XXX: exclude scaling lists, MVC/SVC extensions */
3144 base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
3145 MAX_VUI_PARAMS_SIZE + 2 * MAX_HRD_PARAMS_SIZE) / 8;
3147 /* Account for PPS header */
3148 /* XXX: exclude slice groups, scaling lists, MVC/SVC extensions */
3149 base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
3151 /* Account for slice header */
3152 base_encoder->codedbuf_size += encoder->num_slices * (4 +
3153 GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8);
3155 base_encoder->context_info.entrypoint = encoder->entrypoint;
3157 /* Fixme: Add a method to get VA_FEI_FUNCTION_* from GstVaapiFeiMode */
3158 base_encoder->context_info.config.encoder.fei_function = encoder->fei_mode;
3160 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
3164 copy_encoder_common_property (GstVaapiEncoder * dst, GstVaapiEncoder * src)
3169 dst->tune = src->tune;
3170 dst->rate_control = src->rate_control;
3171 dst->rate_control_mask = src->rate_control_mask;
3172 dst->bitrate = src->bitrate;
3173 dst->keyframe_period = src->keyframe_period;
3178 static GstVaapiEncoderStatus
3179 gst_vaapi_encoder_h264_fei_reconfigure (GstVaapiEncoder * base_encoder)
3181 GstVaapiEncoderH264Fei *const encoder =
3182 GST_VAAPI_ENCODER_H264_FEI_CAST (base_encoder);
3183 GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
3184 GstVaapiEncoder *enc_base_encoder = GST_VAAPI_ENCODER_CAST (encoder->feienc);
3185 GstVideoInfo *vip_enc = GST_VAAPI_ENCODER_VIDEO_INFO (encoder->feienc);
3186 GstVaapiEncoderStatus status;
3187 guint mb_width, mb_height;
3188 const guint DEFAULT_SURFACES_COUNT = 3;
3190 if (encoder->fei_mode != (GST_VAAPI_FEI_MODE_ENC | GST_VAAPI_FEI_MODE_PAK)) {
3191 /* ENC_PAK, ENC and PAK modes doesn't need to care about ENC and PAK
3192 * abstrct objects */
3193 mb_width = (GST_VAAPI_ENCODER_WIDTH (encoder) + 15) / 16;
3194 mb_height = (GST_VAAPI_ENCODER_HEIGHT (encoder) + 15) / 16;
3195 if (mb_width != encoder->mb_width || mb_height != encoder->mb_height) {
3196 GST_DEBUG ("resolution: %dx%d", GST_VAAPI_ENCODER_WIDTH (encoder),
3197 GST_VAAPI_ENCODER_HEIGHT (encoder));
3198 encoder->mb_width = mb_width;
3199 encoder->mb_height = mb_height;
3200 encoder->config_changed = TRUE;
3203 /* Take number of MVC views from input caps if provided */
3204 if (GST_VIDEO_INFO_MULTIVIEW_MODE (vip) ==
3205 GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME
3206 || GST_VIDEO_INFO_MULTIVIEW_MODE (vip) ==
3207 GST_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME)
3208 encoder->num_views = GST_VIDEO_INFO_VIEWS (vip);
3210 encoder->is_mvc = encoder->num_views > 1;
3212 status = ensure_profile_and_level (encoder);
3213 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
3216 reset_properties (encoder);
3217 status = set_context_info (base_encoder);
3218 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
3222 /* ENC+PAK mode requires two separate objects
3225 /* Maximum sizes for common headers (in bits) */
3228 MAX_SPS_HDR_SIZE = 16473,
3229 MAX_VUI_PARAMS_SIZE = 210,
3230 MAX_HRD_PARAMS_SIZE = 4103,
3231 MAX_PPS_HDR_SIZE = 101,
3232 MAX_SLICE_HDR_SIZE = 397 + 2572 + 6670 + 2402,
3235 /* copy encoder-fei common property to feienc */
3236 if (!copy_encoder_common_property (enc_base_encoder, base_encoder))
3237 return GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
3239 /* copy video info to feienc */
3242 status = gst_vaapi_feienc_h264_reconfigure (enc_base_encoder);
3243 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) {
3244 GST_ERROR ("failed to process enc reconfigure");
3248 if (!gst_vaapi_feienc_h264_get_profile_and_idc (encoder->feienc,
3249 &encoder->profile, &encoder->profile_idc))
3250 return GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
3252 base_encoder->profile = enc_base_encoder->profile;
3254 mb_width = (GST_VAAPI_ENCODER_WIDTH (encoder) + 15) / 16;
3255 mb_height = (GST_VAAPI_ENCODER_HEIGHT (encoder) + 15) / 16;
3256 if (mb_width != encoder->mb_width || mb_height != encoder->mb_height) {
3257 GST_DEBUG ("resolution: %dx%d", GST_VAAPI_ENCODER_WIDTH (encoder),
3258 GST_VAAPI_ENCODER_HEIGHT (encoder));
3259 encoder->mb_width = mb_width;
3260 encoder->mb_height = mb_height;
3261 encoder->config_changed = TRUE;
3265 gst_vaapi_feipak_h264_reconfigure (encoder->feipak,
3266 base_encoder->va_context, encoder->profile, encoder->profile_idc,
3267 encoder->mb_width, encoder->mb_height, encoder->num_views,
3268 encoder->num_slices, encoder->num_ref_frames);
3269 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) {
3270 GST_ERROR ("failed to process pak reconfigure");
3274 base_encoder->num_ref_frames =
3275 (encoder->num_ref_frames + DEFAULT_SURFACES_COUNT) * encoder->num_views;
3277 /* Only YUV 4:2:0 formats are supported for now. This means that we
3278 have a limit of 3200 bits per macroblock. */
3279 /* XXX: check profile and compute RawMbBits */
3280 base_encoder->codedbuf_size = (GST_ROUND_UP_16 (vip->width) *
3281 GST_ROUND_UP_16 (vip->height) / 256) * 400;
3283 /* Account for SPS header */
3284 /* XXX: exclude scaling lists, MVC/SVC extensions */
3285 base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
3286 MAX_VUI_PARAMS_SIZE + 2 * MAX_HRD_PARAMS_SIZE) / 8;
3288 /* Account for PPS header */
3289 /* XXX: exclude slice groups, scaling lists, MVC/SVC extensions */
3290 base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
3292 /* Account for slice header */
3293 base_encoder->codedbuf_size += encoder->num_slices * (4 +
3294 GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8);
3296 base_encoder->context_info.entrypoint = encoder->entrypoint;
3298 /* ENC+PAK mode use the base encoder context for PAK
3299 * ENC handled separately */
3300 if (encoder->fei_mode == (GST_VAAPI_FEI_MODE_ENC | GST_VAAPI_FEI_MODE_PAK))
3301 base_encoder->context_info.config.encoder.fei_function =
3302 GST_VAAPI_FEI_MODE_PAK;
3308 struct _GstVaapiEncoderH264FeiClass
3310 GstVaapiEncoderClass parent_class;
3313 G_DEFINE_TYPE (GstVaapiEncoderH264Fei, gst_vaapi_encoder_h264_fei,
3314 GST_TYPE_VAAPI_ENCODER);
3317 gst_vaapi_encoder_h264_fei_init (GstVaapiEncoderH264Fei * encoder)
3321 /* Default encoding entrypoint */
3322 encoder->entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
3323 encoder->is_fei_disabled = FALSE;
3324 encoder->is_stats_out_enabled = FALSE;
3325 encoder->fei_mode = GST_VAAPI_FEI_MODE_ENC_PAK;
3326 encoder->search_path = GST_VAAPI_FEI_H264_SEARCH_PATH_DEFAULT;
3327 encoder->len_sp = GST_VAAPI_FEI_H264_SEARCH_PATH_LENGTH_DEFAULT;
3328 encoder->ref_width = GST_VAAPI_FEI_H264_REF_WIDTH_DEFAULT;
3329 encoder->ref_height = GST_VAAPI_FEI_H264_REF_HEIGHT_DEFAULT;
3330 encoder->intra_part_mask = GST_VAAPI_FEI_H264_INTRA_PART_MASK_DEFAULT;
3331 encoder->submb_part_mask = GST_VAAPI_FEI_H264_SUB_MB_PART_MASK_DEFAULT;
3332 /* default num ref frames */
3333 encoder->num_ref_frames = 1;
3334 /* Multi-view coding information */
3335 encoder->is_mvc = FALSE;
3336 encoder->num_views = 1;
3337 encoder->view_idx = 0;
3338 memset (encoder->view_ids, 0, sizeof (encoder->view_ids));
3340 /* re-ordering list initialize */
3341 for (i = 0; i < MAX_NUM_VIEWS; i++) {
3342 GstVaapiH264ViewReorderPool *const reorder_pool =
3343 &encoder->reorder_pools[i];
3344 g_queue_init (&reorder_pool->reorder_frame_list);
3345 reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_NONE;
3346 reorder_pool->frame_index = 0;
3347 reorder_pool->cur_frame_num = 0;
3348 reorder_pool->cur_present_index = 0;
3351 /* reference list info initialize */
3352 for (i = 0; i < MAX_NUM_VIEWS; i++) {
3353 GstVaapiH264ViewRefPool *const ref_pool = &encoder->ref_pools[i];
3354 g_queue_init (&ref_pool->ref_list);
3355 ref_pool->max_ref_frames = 0;
3356 ref_pool->max_reflist0_count = 1;
3357 ref_pool->max_reflist1_count = 1;
3362 gst_vaapi_encoder_h264_fei_finalize (GObject * gobject)
3364 /*free private buffers */
3365 GstVaapiEncoderH264Fei *const encoder = GST_VAAPI_ENCODER_H264_FEI (gobject);
3366 GstVaapiEncoder *base_encoder = GST_VAAPI_ENCODER (gobject);
3367 GstVaapiEncoder *enc_base_encoder = GST_VAAPI_ENCODER_CAST (encoder->feienc);
3368 GstVaapiMiniObject *object = GST_VAAPI_MINI_OBJECT (encoder->feipak);
3369 GstVaapiEncPicture *pic;
3370 GstVaapiEncoderH264FeiRef *ref;
3373 if ((encoder->fei_mode == GST_VAAPI_FEI_MODE_ENC_PAK)
3374 || (encoder->fei_mode == GST_VAAPI_FEI_MODE_PAK)) {
3376 gst_buffer_replace (&encoder->sps_data, NULL);
3377 gst_buffer_replace (&encoder->subset_sps_data, NULL);
3378 gst_buffer_replace (&encoder->pps_data, NULL);
3380 /* reference list info de-init */
3381 for (i = 0; i < MAX_NUM_VIEWS; i++) {
3382 GstVaapiH264ViewRefPool *const ref_pool = &encoder->ref_pools[i];
3383 while (!g_queue_is_empty (&ref_pool->ref_list)) {
3384 ref = (GstVaapiEncoderH264FeiRef *)
3385 g_queue_pop_head (&ref_pool->ref_list);
3386 reference_pic_free (encoder, ref);
3388 g_queue_clear (&ref_pool->ref_list);
3391 /* re-ordering list initialize */
3392 for (i = 0; i < MAX_NUM_VIEWS; i++) {
3393 GstVaapiH264ViewReorderPool *const reorder_pool =
3394 &encoder->reorder_pools[i];
3395 while (!g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
3396 pic = (GstVaapiEncPicture *)
3397 g_queue_pop_head (&reorder_pool->reorder_frame_list);
3398 gst_vaapi_enc_picture_unref (pic);
3400 g_queue_clear (&reorder_pool->reorder_frame_list);
3404 if (encoder->coded_buf != VA_INVALID_ID) {
3405 GST_VAAPI_DISPLAY_LOCK (base_encoder->display);
3406 vaapi_destroy_buffer (base_encoder->va_display, &encoder->coded_buf);
3407 GST_VAAPI_DISPLAY_UNLOCK (base_encoder->display);
3408 encoder->coded_buf = VA_INVALID_ID;
3411 if (enc_base_encoder->va_context != VA_INVALID_ID) {
3412 GST_VAAPI_DISPLAY_LOCK (base_encoder->display);
3413 vaDestroyContext (base_encoder->va_display, enc_base_encoder->va_context);
3414 GST_VAAPI_DISPLAY_UNLOCK (base_encoder->display);
3415 enc_base_encoder->va_context = VA_INVALID_ID;
3418 if (encoder->va_config != VA_INVALID_ID) {
3419 GST_VAAPI_DISPLAY_LOCK (base_encoder->display);
3420 vaDestroyConfig (base_encoder->va_display, encoder->va_config);
3421 GST_VAAPI_DISPLAY_UNLOCK (base_encoder->display);
3422 encoder->va_config = VA_INVALID_ID;
3425 gst_vaapi_encoder_replace (&enc_base_encoder, NULL);
3426 gst_vaapi_mini_object_replace (&object, NULL);
3428 encoder->ref_pool_ptr = NULL;
3429 encoder->feienc = NULL;
3432 G_OBJECT_CLASS (gst_vaapi_encoder_h264_fei_parent_class)->finalize (gobject);
3436 set_view_ids (GstVaapiEncoderH264Fei * const encoder, const GValue * value)
3439 guint len = gst_value_array_get_size (value);
3442 goto set_default_ids;
3444 if (len != encoder->num_views) {
3445 GST_WARNING ("The view number is %d, but %d view IDs are provided. Just "
3446 "fallback to use default view IDs.", encoder->num_views, len);
3447 goto set_default_ids;
3450 for (i = 0; i < len; i++) {
3451 const GValue *val = gst_value_array_get_value (value, i);
3452 encoder->view_ids[i] = g_value_get_uint (val);
3455 /* check whether duplicated ID */
3456 for (i = 0; i < len; i++) {
3457 for (j = i + 1; j < len; j++) {
3458 if (encoder->view_ids[i] == encoder->view_ids[j]) {
3459 GST_WARNING ("The view %d and view %d have same view ID %d. Just "
3460 "fallback to use default view IDs.", i, j, encoder->view_ids[i]);
3461 goto set_default_ids;
3470 for (i = 0; i < encoder->num_views; i++)
3471 encoder->view_ids[i] = i;
3476 get_view_ids (GstVaapiEncoderH264Fei * const encoder, GValue * value)
3479 GValue id = G_VALUE_INIT;
3481 g_value_reset (value);
3482 g_value_init (&id, G_TYPE_UINT);
3484 for (i = 0; i < encoder->num_views; i++) {
3485 g_value_set_uint (&id, encoder->view_ids[i]);
3486 gst_value_array_append_value (value, &id);
3488 g_value_unset (&id);
3492 * @ENCODER_H264_FEI_PROP_RATECONTROL: Rate control (#GstVaapiRateControl).
3493 * @ENCODER_H264_FEI_PROP_TUNE: The tuning options (#GstVaapiEncoderTune).
3494 * @ENCODER_H264_FEI_PROP_MAX_BFRAMES: Number of B-frames between I
3496 * @ENCODER_H264_FEI_PROP_INIT_QP: Initial quantizer value (uint).
3497 * @ENCODER_H264_FEI_PROP_MIN_QP: Minimal quantizer value (uint).
3498 * @ENCODER_H264_FEI_PROP_NUM_SLICES: Number of slices per frame (uint).
3499 * @ENCODER_H264_FEI_PROP_CABAC: Enable CABAC entropy coding mode (bool).
3500 * @ENCODER_H264_FEI_PROP_DCT8X8: Enable adaptive use of 8x8
3501 * transforms in I-frames (bool).
3502 * @ENCODER_H264_FEI_PROP_CPB_LENGTH: Length of the CPB buffer
3503 * in milliseconds (uint).
3504 * @ENCODER_H264_FEI_PROP_NUM_VIEWS: Number of views per frame.
3505 * @ENCODER_H264_FEI_PROP_VIEW_IDS: View IDs
3506 * @ENCODER_H264_FEI_PROP_MAX_QP: Maximal quantizer value (uint).
3508 * The set of H.264 encoder specific configurable properties.
3512 ENCODER_H264_FEI_PROP_RATECONTROL = 1,
3513 ENCODER_H264_FEI_PROP_TUNE,
3514 ENCODER_H264_FEI_PROP_MAX_BFRAMES,
3515 ENCODER_H264_FEI_PROP_INIT_QP,
3516 ENCODER_H264_FEI_PROP_MIN_QP,
3517 ENCODER_H264_FEI_PROP_NUM_SLICES,
3518 ENCODER_H264_FEI_PROP_CABAC,
3519 ENCODER_H264_FEI_PROP_DCT8X8,
3520 ENCODER_H264_FEI_PROP_CPB_LENGTH,
3521 ENCODER_H264_FEI_PROP_NUM_VIEWS,
3522 ENCODER_H264_FEI_PROP_VIEW_IDS,
3523 ENCODER_H264_PROP_FEI_DISABLE,
3524 ENCODER_H264_PROP_NUM_MV_PREDICT_L0,
3525 ENCODER_H264_PROP_NUM_MV_PREDICT_L1,
3526 ENCODER_H264_PROP_SEARCH_WINDOW,
3527 ENCODER_H264_PROP_LEN_SP,
3528 ENCODER_H264_PROP_SEARCH_PATH,
3529 ENCODER_H264_PROP_REF_WIDTH,
3530 ENCODER_H264_PROP_REF_HEIGHT,
3531 ENCODER_H264_PROP_SUBMB_MASK,
3532 ENCODER_H264_PROP_SUBPEL_MODE,
3533 ENCODER_H264_PROP_INTRA_PART_MASK,
3534 ENCODER_H264_PROP_INTRA_SAD,
3535 ENCODER_H264_PROP_INTER_SAD,
3536 ENCODER_H264_PROP_ADAPT_SEARCH,
3537 ENCODER_H264_PROP_MULTI_PRED_L0,
3538 ENCODER_H264_PROP_MULTI_PRED_L1,
3539 ENCODER_H264_PROP_ENABLE_STATS_OUT,
3540 ENCODER_H264_PROP_FEI_MODE,
3541 ENCODER_H264_FEI_PROP_MAX_QP,
3542 ENCODER_H264_FEI_N_PROPERTIES
3545 static GParamSpec *properties[ENCODER_H264_FEI_N_PROPERTIES];
3548 gst_vaapi_encoder_h264_fei_set_property (GObject * object, guint prop_id,
3549 const GValue * value, GParamSpec * pspec)
3551 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER (object);
3552 GstVaapiEncoderH264Fei *const encoder =
3553 GST_VAAPI_ENCODER_H264_FEI_CAST (base_encoder);
3554 GstVaapiEncoder *enc_base_encoder = GST_VAAPI_ENCODER_CAST (encoder->feienc);
3555 GstVaapiEncoderStatus status;
3558 case ENCODER_H264_FEI_PROP_RATECONTROL:
3559 gst_vaapi_encoder_set_rate_control (base_encoder,
3560 g_value_get_enum (value));
3562 case ENCODER_H264_FEI_PROP_TUNE:
3563 gst_vaapi_encoder_set_tuning (base_encoder, g_value_get_enum (value));
3565 case ENCODER_H264_FEI_PROP_MAX_BFRAMES:
3566 encoder->num_bframes = g_value_get_uint (value);
3568 case ENCODER_H264_FEI_PROP_INIT_QP:
3569 encoder->init_qp = g_value_get_uint (value);
3571 case ENCODER_H264_FEI_PROP_MIN_QP:
3572 encoder->min_qp = g_value_get_uint (value);
3574 case ENCODER_H264_FEI_PROP_NUM_SLICES:
3575 encoder->num_slices = g_value_get_uint (value);
3577 case ENCODER_H264_FEI_PROP_CABAC:
3578 encoder->use_cabac = g_value_get_boolean (value);
3580 case ENCODER_H264_FEI_PROP_DCT8X8:
3581 encoder->use_dct8x8 = g_value_get_boolean (value);
3583 case ENCODER_H264_FEI_PROP_CPB_LENGTH:
3584 encoder->cpb_length = g_value_get_uint (value);
3586 case ENCODER_H264_FEI_PROP_NUM_VIEWS:
3587 encoder->num_views = g_value_get_uint (value);
3589 case ENCODER_H264_FEI_PROP_VIEW_IDS:
3590 set_view_ids (encoder, value);
3592 case ENCODER_H264_PROP_FEI_DISABLE:
3593 encoder->is_fei_disabled = g_value_get_boolean (value);
3594 if (!encoder->is_fei_disabled)
3595 encoder->entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_FEI;
3597 case ENCODER_H264_PROP_NUM_MV_PREDICT_L0:
3598 encoder->num_mv_predictors_l0 = g_value_get_uint (value);
3600 case ENCODER_H264_PROP_NUM_MV_PREDICT_L1:
3601 encoder->num_mv_predictors_l1 = g_value_get_uint (value);
3603 case ENCODER_H264_PROP_SEARCH_WINDOW:
3604 encoder->search_window = g_value_get_enum (value);
3606 case ENCODER_H264_PROP_LEN_SP:
3607 encoder->len_sp = g_value_get_uint (value);
3609 case ENCODER_H264_PROP_SEARCH_PATH:
3610 encoder->search_path = g_value_get_enum (value);
3612 case ENCODER_H264_PROP_REF_WIDTH:
3613 encoder->ref_width = g_value_get_uint (value);
3615 case ENCODER_H264_PROP_REF_HEIGHT:
3616 encoder->ref_height = g_value_get_uint (value);
3618 case ENCODER_H264_PROP_SUBMB_MASK:
3619 encoder->submb_part_mask = g_value_get_flags (value);
3621 case ENCODER_H264_PROP_SUBPEL_MODE:
3622 encoder->subpel_mode = g_value_get_enum (value);
3624 case ENCODER_H264_PROP_INTRA_PART_MASK:
3625 encoder->intra_part_mask = g_value_get_flags (value);
3627 case ENCODER_H264_PROP_INTRA_SAD:
3628 encoder->intra_sad = g_value_get_enum (value);
3630 case ENCODER_H264_PROP_INTER_SAD:
3631 encoder->inter_sad = g_value_get_enum (value);
3633 case ENCODER_H264_PROP_ADAPT_SEARCH:
3634 encoder->adaptive_search = g_value_get_boolean (value) ? 1 : 0;
3636 case ENCODER_H264_PROP_MULTI_PRED_L0:
3637 encoder->multi_predL0 = g_value_get_boolean (value) ? 1 : 0;
3639 case ENCODER_H264_PROP_MULTI_PRED_L1:
3640 encoder->multi_predL1 = g_value_get_boolean (value) ? 1 : 0;
3642 case ENCODER_H264_PROP_ENABLE_STATS_OUT:
3643 encoder->is_stats_out_enabled = g_value_get_boolean (value);
3645 case ENCODER_H264_PROP_FEI_MODE:
3646 encoder->fei_mode = g_value_get_flags (value);
3647 if (encoder->fei_mode == GST_VAAPI_FEI_MODE_ENC) {
3648 g_warning ("============= ENC only mode selected ============ \n"
3649 "We internally run the PAK stage because, the ENC operation requires the reconstructed output of PAK mode. Right now we have no infrastructure to provide reconstructed surfaces to ENC with out running the PAK \n");
3650 /*Fixme: Support ENC only mode with out running PAK */
3651 encoder->fei_mode = GST_VAAPI_FEI_MODE_ENC | GST_VAAPI_FEI_MODE_PAK;
3652 } else if (encoder->fei_mode == GST_VAAPI_FEI_MODE_PAK) {
3653 g_warning ("============ PAK only mode selected ============ \n"
3654 "This mode can work as expected, only if there is a custom user specific upstream element which provides mb_code and mv_vectors. If you are running the pipeline only for verification, We recommand to use the fei-mod ENC+PAK which will run the ENC operation and generate what ever input needed for PAK \n");
3658 case ENCODER_H264_FEI_PROP_MAX_QP:
3659 encoder->max_qp = g_value_get_uint (value);
3663 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3666 if ((prop_id != ENCODER_H264_PROP_FEI_MODE) &&
3667 (prop_id != ENCODER_H264_PROP_FEI_DISABLE) &&
3668 (prop_id != ENCODER_H264_PROP_ENABLE_STATS_OUT)) {
3670 if (enc_base_encoder) {
3671 g_object_set_property ((GObject *) enc_base_encoder,
3672 g_param_spec_get_name (pspec), value);
3675 if ((prop_id == ENCODER_H264_FEI_PROP_MAX_BFRAMES) ||
3676 (prop_id == ENCODER_H264_FEI_PROP_VIEW_IDS) ||
3677 (prop_id == ENCODER_H264_FEI_PROP_NUM_VIEWS)) {
3678 if (encoder->feipak) {
3680 gst_vaapi_feipak_h264_set_property (encoder->feipak, prop_id,
3682 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) {
3683 GST_ERROR ("failed to set pak property");
3692 gst_vaapi_encoder_h264_fei_get_property (GObject * object, guint prop_id,
3693 GValue * value, GParamSpec * pspec)
3695 GstVaapiEncoderH264Fei *const encoder =
3696 GST_VAAPI_ENCODER_H264_FEI_CAST (object);
3697 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER (object);
3700 case ENCODER_H264_FEI_PROP_RATECONTROL:
3701 g_value_set_enum (value, base_encoder->rate_control);
3703 case ENCODER_H264_FEI_PROP_TUNE:
3704 g_value_set_enum (value, base_encoder->tune);
3706 case ENCODER_H264_FEI_PROP_MAX_BFRAMES:
3707 g_value_set_uint (value, encoder->num_bframes);
3709 case ENCODER_H264_FEI_PROP_INIT_QP:
3710 g_value_set_uint (value, encoder->init_qp);
3712 case ENCODER_H264_FEI_PROP_MIN_QP:
3713 g_value_set_uint (value, encoder->min_qp);
3715 case ENCODER_H264_FEI_PROP_NUM_SLICES:
3716 g_value_set_uint (value, encoder->num_slices);
3718 case ENCODER_H264_FEI_PROP_CABAC:
3719 g_value_set_boolean (value, encoder->use_cabac);
3721 case ENCODER_H264_FEI_PROP_DCT8X8:
3722 g_value_set_boolean (value, encoder->use_dct8x8);
3724 case ENCODER_H264_FEI_PROP_CPB_LENGTH:
3725 g_value_set_uint (value, encoder->cpb_length);
3727 case ENCODER_H264_FEI_PROP_NUM_VIEWS:
3728 g_value_set_uint (value, encoder->num_views);
3730 case ENCODER_H264_FEI_PROP_VIEW_IDS:
3731 get_view_ids (encoder, value);
3733 case ENCODER_H264_PROP_FEI_DISABLE:
3734 g_value_set_boolean (value, encoder->is_fei_disabled);
3736 case ENCODER_H264_PROP_NUM_MV_PREDICT_L0:
3737 g_value_set_uint (value, encoder->num_mv_predictors_l0);
3739 case ENCODER_H264_PROP_NUM_MV_PREDICT_L1:
3740 g_value_set_uint (value, encoder->num_mv_predictors_l1);
3742 case ENCODER_H264_PROP_SEARCH_WINDOW:
3743 g_value_set_enum (value, encoder->search_window);
3745 case ENCODER_H264_PROP_LEN_SP:
3746 g_value_set_uint (value, encoder->len_sp);
3748 case ENCODER_H264_PROP_SEARCH_PATH:
3749 g_value_set_enum (value, encoder->search_path);
3751 case ENCODER_H264_PROP_REF_WIDTH:
3752 g_value_set_uint (value, encoder->ref_width);
3754 case ENCODER_H264_PROP_REF_HEIGHT:
3755 g_value_set_uint (value, encoder->ref_height);
3757 case ENCODER_H264_PROP_SUBMB_MASK:
3758 g_value_set_flags (value, encoder->submb_part_mask);
3760 case ENCODER_H264_PROP_SUBPEL_MODE:
3761 g_value_set_enum (value, encoder->subpel_mode);
3763 case ENCODER_H264_PROP_INTRA_PART_MASK:
3764 g_value_set_flags (value, encoder->intra_part_mask);
3766 case ENCODER_H264_PROP_INTRA_SAD:
3767 g_value_set_enum (value, encoder->intra_sad);
3769 case ENCODER_H264_PROP_INTER_SAD:
3770 g_value_set_enum (value, encoder->inter_sad);
3772 case ENCODER_H264_PROP_ADAPT_SEARCH:
3773 g_value_set_boolean (value, encoder->adaptive_search);
3775 case ENCODER_H264_PROP_MULTI_PRED_L0:
3776 g_value_set_boolean (value, encoder->multi_predL0);
3778 case ENCODER_H264_PROP_MULTI_PRED_L1:
3779 g_value_set_boolean (value, encoder->multi_predL1);
3781 case ENCODER_H264_PROP_ENABLE_STATS_OUT:
3782 g_value_set_boolean (value, encoder->is_stats_out_enabled);
3784 case ENCODER_H264_PROP_FEI_MODE:
3785 g_value_set_flags (value, encoder->fei_mode);
3787 case ENCODER_H264_FEI_PROP_MAX_QP:
3788 g_value_set_uint (value, encoder->max_qp);
3791 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3795 static inline gboolean
3796 context_get_attribute (GstVaapiContext * context, VAConfigAttribType type,
3797 guint * out_value_ptr)
3799 return gst_vaapi_get_config_attribute (GST_VAAPI_OBJECT_DISPLAY (context),
3800 context->va_profile, context->va_entrypoint, type, out_value_ptr);
3804 create_context_for_enc (GstVaapiEncoder * fei_encoder,
3805 GstVaapiEncoder * enc_encoder)
3807 GstVaapiEncoderH264Fei *const feiencoder =
3808 GST_VAAPI_ENCODER_H264_FEI (fei_encoder);
3809 GstVaapiContext *context = fei_encoder->context;
3810 const GstVaapiContextInfo *const cip = &context->info;
3811 GstVaapiDisplay *const display = fei_encoder->display;
3812 const GstVaapiConfigInfoEncoder *const config = &cip->config.encoder;
3813 guint va_rate_control;
3814 VAConfigAttrib attribs[5], *attrib = attribs;
3815 VASurfaceID surface_id;
3817 GArray *surfaces = NULL;
3818 gboolean success = FALSE;
3819 guint i, value, va_chroma_format;
3821 if (!context->surfaces)
3824 /* Create VA surfaces list for vaCreateContext() */
3825 surfaces = g_array_sized_new (FALSE,
3826 FALSE, sizeof (VASurfaceID), context->surfaces->len);
3830 for (i = 0; i < context->surfaces->len; i++) {
3831 GstVaapiSurface *const surface = g_ptr_array_index (context->surfaces, i);
3834 surface_id = GST_VAAPI_OBJECT_ID (surface);
3835 g_array_append_val (surfaces, surface_id);
3837 g_assert (surfaces->len == context->surfaces->len);
3838 if (!cip->profile || !cip->entrypoint)
3841 /* Validate VA surface format */
3842 va_chroma_format = from_GstVaapiChromaType (cip->chroma_type);
3843 if (!va_chroma_format)
3845 attrib->type = VAConfigAttribRTFormat;
3846 if (!context_get_attribute (context, attrib->type, &value))
3848 if (!(value & va_chroma_format)) {
3849 GST_ERROR ("unsupported chroma format (%s)",
3850 string_of_va_chroma_format (va_chroma_format));
3853 attrib->value = va_chroma_format;
3857 va_rate_control = from_GstVaapiRateControl (config->rc_mode);
3858 if (va_rate_control != VA_RC_NONE) {
3859 attrib->type = VAConfigAttribRateControl;
3860 if (!context_get_attribute (context, attrib->type, &value))
3863 if ((value & va_rate_control) != va_rate_control) {
3864 GST_ERROR ("unsupported %s rate control",
3865 string_of_VARateControl (va_rate_control));
3868 attrib->value = va_rate_control;
3872 /* Packed headers */
3873 if (config->packed_headers) {
3874 attrib->type = VAConfigAttribEncPackedHeaders;
3875 attrib->value = VA_ENC_PACKED_HEADER_NONE;
3879 if (cip->entrypoint == GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_FEI) {
3880 attrib->type = (VAConfigAttribType) VAConfigAttribFEIFunctionType;
3881 attrib->value = VA_FEI_FUNCTION_ENC;
3883 attrib->type = (VAConfigAttribType) VAConfigAttribFEIMVPredictors;
3888 GST_VAAPI_DISPLAY_LOCK (display);
3889 status = vaCreateConfig (GST_VAAPI_DISPLAY_VADISPLAY (display),
3890 context->va_profile, context->va_entrypoint, attribs, attrib - attribs,
3891 &feiencoder->va_config);
3892 GST_VAAPI_DISPLAY_UNLOCK (display);
3893 if (!vaapi_check_status (status, "vaCreateConfig()"))
3896 GST_VAAPI_DISPLAY_LOCK (display);
3897 status = vaCreateContext (GST_VAAPI_DISPLAY_VADISPLAY (display),
3898 feiencoder->va_config, GST_ROUND_UP_16 (cip->width),
3899 GST_ROUND_UP_16 (cip->height), VA_PROGRESSIVE,
3900 (VASurfaceID *) surfaces->data, surfaces->len, &enc_encoder->va_context);
3901 GST_VAAPI_DISPLAY_UNLOCK (display);
3902 if (!vaapi_check_status (status, "vaCreateContext()"))
3909 g_array_free (surfaces, TRUE);
3913 static const GstVaapiEncoderClassData fei_encoder_class_data = {
3914 .codec = GST_VAAPI_CODEC_H264,
3915 .packed_headers = SUPPORTED_PACKED_HEADERS,
3916 .rate_control_get_type = gst_vaapi_rate_control_get_type,
3917 .default_rate_control = DEFAULT_RATECONTROL,
3918 .rate_control_mask = SUPPORTED_RATECONTROLS,
3919 .encoder_tune_get_type = gst_vaapi_encoder_tune_get_type,
3920 .default_encoder_tune = GST_VAAPI_ENCODER_TUNE_NONE,
3921 .encoder_tune_mask = SUPPORTED_TUNE_OPTIONS,
3925 gst_vaapi_encoder_h264_fei_class_init (GstVaapiEncoderH264FeiClass * klass)
3927 GObjectClass *const object_class = G_OBJECT_CLASS (klass);
3928 GstVaapiEncoderClass *const encoder_class = GST_VAAPI_ENCODER_CLASS (klass);
3930 encoder_class->class_data = &fei_encoder_class_data;
3931 encoder_class->reconfigure = gst_vaapi_encoder_h264_fei_reconfigure;
3932 encoder_class->reordering = gst_vaapi_encoder_h264_fei_reordering;
3933 encoder_class->encode = gst_vaapi_encoder_h264_fei_encode;
3934 encoder_class->flush = gst_vaapi_encoder_h264_fei_flush;
3935 encoder_class->get_codec_data = gst_vaapi_encoder_h264_fei_get_codec_data;
3936 encoder_class->ensure_secondary_context =
3937 gst_vaapi_encoder_h264_fei_ensure_secondary_context;
3939 object_class->set_property = gst_vaapi_encoder_h264_fei_set_property;
3940 object_class->get_property = gst_vaapi_encoder_h264_fei_get_property;
3941 object_class->finalize = gst_vaapi_encoder_h264_fei_finalize;
3944 * GstVaapiEncoderH264Fei:rate-control:
3946 * The desired rate control mode, expressed as a #GstVaapiRateControl.
3948 properties[ENCODER_H264_FEI_PROP_RATECONTROL] =
3949 g_param_spec_enum ("rate-control", "Rate Control", "Rate control mode",
3950 fei_encoder_class_data.rate_control_get_type (),
3951 fei_encoder_class_data.default_rate_control,
3952 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3953 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3956 * GstVaapiEncoderH264Fei:tune:
3958 * The desired encoder tuning option.
3960 properties[ENCODER_H264_FEI_PROP_TUNE] =
3961 g_param_spec_enum ("tune",
3963 "Encoder tuning option",
3964 fei_encoder_class_data.encoder_tune_get_type (),
3965 fei_encoder_class_data.default_encoder_tune,
3966 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3967 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3970 * GstVaapiEncoderH264Fei:max-bframes:
3972 * The number of B-frames between I and P.
3974 properties[ENCODER_H264_FEI_PROP_MAX_BFRAMES] =
3975 g_param_spec_uint ("max-bframes",
3976 "Max B-Frames", "Number of B-frames between I and P", 0, 10, 1,
3977 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3978 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3981 * GstVaapiEncoderH264Fei:init-qp:
3983 * The initial quantizer value.
3985 properties[ENCODER_H264_FEI_PROP_INIT_QP] =
3986 g_param_spec_uint ("init-qp",
3987 "Initial QP", "Initial quantizer value", 0, 51, 26,
3988 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3989 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3992 * GstVaapiEncoderH264Fei:min-qp:
3994 * The minimum quantizer value.
3996 properties[ENCODER_H264_FEI_PROP_MIN_QP] =
3997 g_param_spec_uint ("min-qp",
3998 "Minimum QP", "Minimum quantizer value", 0, 51, 1,
3999 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4000 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4003 * GstVaapiEncoderH264Fei:max-qp:
4005 * The maximum quantizer value.
4009 properties[ENCODER_H264_FEI_PROP_MAX_QP] =
4010 g_param_spec_uint ("max-qp",
4011 "Maximum QP", "Maximum quantizer value", 0, 51, 51,
4012 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4013 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4016 * GstVaapiEncoderH264Fei:num-slices:
4018 * The number of slices per frame.
4020 properties[ENCODER_H264_FEI_PROP_NUM_SLICES] =
4021 g_param_spec_uint ("num-slices",
4023 "Number of slices per frame",
4025 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4026 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4029 * GstVaapiEncoderH264Fei:cabac:
4031 * Enable CABAC entropy coding mode for improved compression ratio,
4032 * at the expense that the minimum target profile is Main. Default
4033 * is CAVLC entropy coding mode.
4035 properties[ENCODER_H264_FEI_PROP_CABAC] =
4036 g_param_spec_boolean ("cabac",
4038 "Enable CABAC entropy coding mode",
4039 TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4040 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4043 * GstVaapiEncoderH264Fei:dct8x8:
4045 * Enable adaptive use of 8x8 transforms in I-frames. This improves
4046 * the compression ratio by the minimum target profile is High.
4047 * Default is to use 4x4 DCT only.
4049 properties[ENCODER_H264_FEI_PROP_DCT8X8] =
4050 g_param_spec_boolean ("dct8x8",
4052 "Enable adaptive use of 8x8 transforms in I-frames",
4053 TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4054 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4057 * GstVaapiEncoderH264Fei:cpb-length:
4059 * The size of the CPB buffer in milliseconds.
4061 properties[ENCODER_H264_FEI_PROP_CPB_LENGTH] =
4062 g_param_spec_uint ("cpb-length",
4063 "CPB Length", "Length of the CPB buffer in milliseconds",
4064 1, 10000, DEFAULT_CPB_LENGTH,
4065 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4066 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4069 * GstVaapiEncoderH264Fei:num-views:
4071 * The number of views for MVC encoding .
4073 properties[ENCODER_H264_FEI_PROP_NUM_VIEWS] =
4074 g_param_spec_uint ("num-views",
4076 "Number of Views for MVC encoding",
4077 1, MAX_NUM_VIEWS, 1,
4078 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4079 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4081 * GstVaapiEncoderH264Fei:view-ids:
4083 * The view ids for MVC encoding .
4085 properties[ENCODER_H264_FEI_PROP_VIEW_IDS] =
4086 gst_param_spec_array ("view-ids",
4087 "View IDs", "Set of View Ids used for MVC encoding",
4088 g_param_spec_uint ("view-id-value", "View id value",
4089 "view id values used for mvc encoding", 0, MAX_VIEW_ID, 0,
4090 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
4091 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4092 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4095 * GstVaapiEncoderH264: disable-fei:
4097 * Disable FEI mode Encode: disabling fei will results
4098 * the encoder to use VAEntrypointEncSlice, which means
4099 * vaapi-intel-driver will be using a different media kerenl.
4100 * And most of the properties associated with this element
4101 * will be non functional.
4103 properties[ENCODER_H264_PROP_FEI_DISABLE] =
4104 g_param_spec_boolean ("disable-fei",
4105 "Disable FEI Mode Encode",
4106 "Disable Flexible Encoding Infrasturcture", FALSE,
4107 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4108 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4112 * GstVaapiEncoderH264: stats-out:
4114 * Enable outputting fei buffers MV, MBCode and Distortion.
4115 * If enabled, encoder will allocate memory for these buffers
4116 * and submit to the driver even for ENC_PAK mode so that
4117 * the output data can be extraced for analysis after the
4118 * complettion of each frame ncode
4120 properties[ENCODER_H264_PROP_ENABLE_STATS_OUT] =
4121 g_param_spec_boolean ("stats-out",
4123 "Enable stats out for fei",
4124 TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4125 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4128 * GstVaapiEncoderH264:num_mv_predictors_l0:
4129 * Indicate how many mv predictors should be used for l0 frames.
4130 * Only valid if MVPredictor input has been enabled.
4132 properties[ENCODER_H264_PROP_NUM_MV_PREDICT_L0] =
4133 g_param_spec_uint ("num-mvpredict-l0",
4134 "Num mv predict l0",
4135 "Indicate how many predictors should be used for l0,"
4136 "only valid if MVPredictor input enabled",
4137 0, 3, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4138 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4140 * GstVaapiEncoderH264:num_mv_predictors_l1:
4141 * Indicate how many mv predictors should be used for l1 frames.
4142 * Only valid if MVPredictor input has been enabled.
4145 properties[ENCODER_H264_PROP_NUM_MV_PREDICT_L1] =
4146 g_param_spec_uint ("num-mvpredict-l1",
4147 "Num mv predict l1",
4148 "Indicate how many predictors should be used for l1,"
4149 "only valid if MVPredictor input enabled",
4150 0, 3, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4151 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4153 * GstVaapiEncoderH264:search-window:
4154 * Use predefined Search Window
4156 properties[ENCODER_H264_PROP_SEARCH_WINDOW] =
4157 g_param_spec_enum ("search-window",
4159 "Specify one of the predefined search path",
4160 GST_VAAPI_TYPE_FEI_H264_SEARCH_WINDOW,
4161 GST_VAAPI_FEI_H264_SEARCH_WINDOW_DEFAULT,
4162 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4163 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4166 * GstVaapiEncoderH264:len-sp:
4167 * Defines the maximum number of Search Units per reference.
4169 properties[ENCODER_H264_PROP_LEN_SP] =
4170 g_param_spec_uint ("len-sp",
4171 "length of search path",
4172 "This value defines number of search units in search path",
4174 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4175 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4178 * GstVaapiEncoderH264:search-path:
4179 * SearchPath defines the motion search method.
4180 * Zero means full search, 1 indicate diamond search.
4182 properties[ENCODER_H264_PROP_SEARCH_PATH] =
4183 g_param_spec_enum ("search-path",
4185 "Specify search path",
4186 GST_VAAPI_TYPE_FEI_H264_SEARCH_PATH,
4187 GST_VAAPI_FEI_H264_SEARCH_PATH_DEFAULT,
4188 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4189 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4192 * GstVaapiEncoderH264:ref-width:
4193 * Specifies the search region width in pixels.
4195 properties[ENCODER_H264_PROP_REF_WIDTH] =
4196 g_param_spec_uint ("ref-width",
4198 "Width of search region in pixel, must be multiple of 4",
4200 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4201 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4204 * GstVaapiEncoderH264:ref-height:
4205 * Specifies the search region height in pixels.
4207 properties[ENCODER_H264_PROP_REF_HEIGHT] =
4208 g_param_spec_uint ("ref-height",
4210 "Height of search region in pixel, must be multiple of 4",
4212 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4213 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4215 * GstVaapiEncoderH264:submb-mask:
4216 * Defines the bit-mask for disabling sub-partition
4219 properties[ENCODER_H264_PROP_SUBMB_MASK] =
4220 g_param_spec_flags ("submbpart-mask",
4222 "defines the bit-mask for disabling sub mb partition",
4223 GST_VAAPI_TYPE_FEI_H264_SUB_MB_PART_MASK,
4224 GST_VAAPI_FEI_H264_SUB_MB_PART_MASK_DEFAULT,
4225 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4226 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4229 * GstVaapiEncoderH264:subpel-mode:
4230 * defines the half/quarter pel modes
4231 * 00: integer mode searching
4232 * 01: half-pel mode searching
4233 * 11: quarter-pel mode searching
4235 properties[ENCODER_H264_PROP_SUBPEL_MODE] =
4236 g_param_spec_enum ("subpel-mode",
4238 "Sub pixel precision for motion estimation",
4239 GST_VAAPI_TYPE_FEI_H264_SUB_PEL_MODE,
4240 GST_VAAPI_FEI_H264_SUB_PEL_MODE_DEFAULT,
4241 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4242 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4244 * GstVaapiEncoderH264:intrapart-mask:
4245 * Specifies which Luma Intra partition is enabled/disabled
4246 * for intra mode decision
4248 properties[ENCODER_H264_PROP_INTRA_PART_MASK] =
4249 g_param_spec_flags ("intrapart-mask",
4251 "Specifies which Luma Intra partition is enabled/disabled for"
4252 "intra mode decision",
4253 GST_VAAPI_TYPE_FEI_H264_INTRA_PART_MASK,
4254 GST_VAAPI_FEI_H264_INTRA_PART_MASK_DEFAULT,
4255 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4256 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4259 * GstVaapiEncoderH264:intra-sad:
4260 * Specifies distortion measure adjustments used for
4261 * the motion search SAD comparison.
4263 properties[ENCODER_H264_PROP_INTRA_SAD] =
4264 g_param_spec_enum ("intra-sad",
4266 "Specifies distortion measure adjustments used"
4267 "in the motion search SAD comparison for intra MB",
4268 GST_VAAPI_TYPE_FEI_H264_SAD_MODE, GST_VAAPI_FEI_H264_SAD_MODE_DEFAULT,
4269 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4270 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4273 * GstVaapiEncoderH264:inter-sad:
4274 * Specifies distortion measure adjustments used
4275 * in the motion search SAD comparison for inter MB
4277 properties[ENCODER_H264_PROP_INTER_SAD] =
4278 g_param_spec_enum ("inter-sad",
4280 "Specifies distortion measure adjustments used"
4281 "in the motion search SAD comparison for inter MB",
4282 GST_VAAPI_TYPE_FEI_H264_SAD_MODE, GST_VAAPI_FEI_H264_SAD_MODE_DEFAULT,
4283 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4284 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4287 * GstVaapiEncoderH264:adaptive-search:
4288 * Defines whether adaptive searching is enabled for IME
4290 properties[ENCODER_H264_PROP_ADAPT_SEARCH] =
4291 g_param_spec_boolean ("adaptive-search",
4293 "Enable adaptive search",
4294 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4295 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4297 * GstVaapiEncoderH264:multi-predL0:
4298 * When set to 1, neighbor MV will be used as predictor for list L0,
4299 * otherwise no neighbor MV will be used as predictor
4301 properties[ENCODER_H264_PROP_MULTI_PRED_L0] =
4302 g_param_spec_boolean ("multi-predL0",
4304 "Enable multi prediction for ref L0 list, when set neighbor MV will be used"
4305 "as predictor, no neighbor MV will be used otherwise",
4306 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4307 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4310 * GstVaapiEncoderH264:multi-predL1:
4311 * When set to 1, neighbor MV will be used as predictor
4312 * when set to 0, no neighbor MV will be used as predictor.
4314 properties[ENCODER_H264_PROP_MULTI_PRED_L1] =
4315 g_param_spec_boolean ("multi-predL1",
4317 "Enable multi prediction for ref L1 list, when set neighbor MV will be used"
4318 "as predictor, no neighbor MV will be used otherwise",
4319 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4320 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4323 * GstVaapiEncoderH264Fei: fei-mode:
4325 * Cose ENC, PAK, ENC_PAK, or ENC+PAK
4326 * ENC: Only the Motion Estimation, no transformation or entropy coding
4327 * PAK: transformation, quantization and entropy coding
4328 * ENC_PAK: default mode, enc an pak are invoked by driver, middleware has
4329 control over ENC input only
4330 * ENC+PAK: enc and pak invoked separately, middleware has control over the ENC input,
4331 ENC output, and PAK input
4332 * Encoding mode which can be used for FEI
4334 properties[ENCODER_H264_PROP_FEI_MODE] =
4335 g_param_spec_flags ("fei-mode",
4336 "FEI Encoding Mode",
4337 "Functional mode of FEI Encoding",
4338 GST_VAAPI_TYPE_FEI_MODE, GST_VAAPI_FEI_MODE_DEFAULT,
4339 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
4340 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
4342 g_object_class_install_properties (object_class,
4343 ENCODER_H264_FEI_N_PROPERTIES, properties);
4347 * gst_vaapi_encoder_h264_fei_set_max_profile:
4348 * @encoder: a #GstVaapiEncoderH264Fei
4349 * @profile: an H.264 #GstVaapiProfile
4351 * Notifies the @encoder to use coding tools from the supplied
4354 * This means that if the minimal profile derived to
4355 * support the specified coding tools is greater than this @profile,
4356 * then an error is returned when the @encoder is configured.
4358 * Return value: %TRUE on success
4361 gst_vaapi_encoder_h264_fei_set_max_profile (GstVaapiEncoderH264Fei *
4362 encoder, GstVaapiProfile profile)
4366 g_return_val_if_fail (encoder != NULL, FALSE);
4367 g_return_val_if_fail (profile != GST_VAAPI_PROFILE_UNKNOWN, FALSE);
4369 if (encoder->fei_mode == (GST_VAAPI_FEI_MODE_ENC | GST_VAAPI_FEI_MODE_PAK)) {
4370 if (!gst_vaapi_feienc_h264_set_max_profile (encoder->feienc, profile))
4375 if (gst_vaapi_profile_get_codec (profile) != GST_VAAPI_CODEC_H264)
4378 profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
4382 encoder->max_profile_idc = profile_idc;
4387 * gst_vaapi_encoder_h264_fei_get_profile_and_level:
4388 * @encoder: a #GstVaapiEncoderH264Fei
4389 * @out_profile_ptr: return location for the #GstVaapiProfile
4390 * @out_level_ptr: return location for the #GstVaapiLevelH264
4392 * Queries the H.264 @encoder for the active profile and level. That
4393 * information is only constructed and valid after the encoder is
4394 * configured, i.e. after the gst_vaapi_encoder_set_codec_state()
4395 * function is called.
4397 * Return value: %TRUE on success
4400 gst_vaapi_encoder_h264_fei_get_profile_and_level (GstVaapiEncoderH264Fei *
4401 encoder, GstVaapiProfile * out_profile_ptr,
4402 GstVaapiLevelH264 * out_level_ptr)
4404 g_return_val_if_fail (encoder != NULL, FALSE);
4406 if (!encoder->profile || !encoder->level)
4409 if (out_profile_ptr)
4410 *out_profile_ptr = encoder->profile;
4412 *out_level_ptr = encoder->level;
4417 * gst_vaapi_encoder_h264_is_fei_stats_out_enabled
4418 * @encoder: a #GstVaapiEncoderH264
4420 * check if fei output statis is needed
4422 * Return value: %TRUE if output statistic is needed
4425 gst_vaapi_encoder_h264_is_fei_stats_out_enabled (GstVaapiEncoderH264Fei *
4428 return !encoder->is_fei_disabled && encoder->is_stats_out_enabled;
4432 * gst_vaapi_encoder_h264_fei_get_function_mode
4433 * @encoder: a #GstVaapiEncoderH264Fei
4435 * return the configured FEI Encoding mode
4437 * Return value: a #GstVaapiFeiMode
4440 gst_vaapi_encoder_h264_fei_get_function_mode (GstVaapiEncoderH264Fei * encoder)
4442 return encoder->fei_mode;
4446 * gst_vaapi_encoder_h264_fei_set_function_mode
4447 * @encoder: a #GstVaapiEncoderH264Fei
4449 * set the configured FEI Encoding mode
4453 gst_vaapi_encoder_h264_fei_set_function_mode (GstVaapiEncoderH264Fei * encoder,
4456 encoder->fei_mode = fei_mode;
4460 gst_vaapi_encoder_h264_fei_ensure_secondary_context (GstVaapiEncoder *
4463 GstVaapiEncoderH264Fei *const feiencoder =
4464 GST_VAAPI_ENCODER_H264_FEI_CAST (base_encoder);
4465 GstVaapiEncoder *enc_base_encoder =
4466 GST_VAAPI_ENCODER_CAST (feiencoder->feienc);
4469 if (feiencoder->fei_mode != (GST_VAAPI_FEI_MODE_ENC | GST_VAAPI_FEI_MODE_PAK))
4472 /* Create separate context for ENC */
4473 if (!create_context_for_enc (base_encoder, enc_base_encoder)) {
4474 GST_ERROR ("create vacontext for enc failed.\n");
4479 * create coded-buf for ENC.
4480 * PAK coded-buf is created by parent encoder.
4483 vaapi_create_buffer (enc_base_encoder->va_display,
4484 enc_base_encoder->va_context, VAEncCodedBufferType,
4485 base_encoder->codedbuf_size, NULL, &feiencoder->coded_buf, NULL);
4487 g_error ("failed to create coded buf for feienc.\n");
4495 * gst_vaapi_encoder_h264_fei_new:
4496 * @display: a #GstVaapiDisplay
4498 * Creates a new #GstVaapiEncoder for H.264 encoding. Note that the
4499 * only supported output stream format is "byte-stream" format.
4501 * Return value: the newly allocated #GstVaapiEncoder object
4504 gst_vaapi_encoder_h264_fei_new (GstVaapiDisplay * display)
4506 GstVaapiEncoder *base_encoder;
4507 GstVaapiEncoderH264Fei *feiencoder = NULL;
4508 GstVaapiFeiEncH264 *feienc = NULL;
4509 GstVaapiFEIPakH264 *feipak = NULL;
4511 /* create FEIEncoderObject: Default mode of operation in ENC_PAK */
4513 g_object_new (GST_TYPE_VAAPI_ENCODER_H264_FEI, "display", display, NULL);
4516 feiencoder = GST_VAAPI_ENCODER_H264_FEI_CAST (base_encoder);
4518 /* create an enc object */
4519 feienc = GST_VAAPI_FEI_ENC_H264 (gst_vaapi_feienc_h264_new (display));
4523 /* create a pak object */
4525 gst_vaapi_feipak_h264_new (base_encoder, display,
4526 base_encoder->va_context);
4530 feiencoder->feienc = feienc;
4531 feiencoder->feipak = feipak;
4533 return base_encoder;
4537 g_object_unref (feienc);
4539 gst_vaapi_mini_object_replace ((GstVaapiMiniObject **) & feipak, NULL);
4541 g_object_unref (feiencoder);