2 * gstvaapiencoder_h264.c - H.264 encoder
4 * Copyright (C) 2012-2014 Intel Corporation
5 * Author: Wind Yuan <feng.yuan@intel.com>
6 * Author: Gwenole Beauchesne <gwenole.beauchesne@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 "gstvaapiencoder_h264.h"
37 #include "gstvaapiutils_h264.h"
38 #include "gstvaapiutils_h264_priv.h"
39 #include "gstvaapiutils_h26x_priv.h"
40 #include "gstvaapicodedbufferproxy_priv.h"
41 #include "gstvaapisurface.h"
44 #include "gstvaapidebug.h"
47 /* Define the maximum number of views supported */
48 #define MAX_NUM_VIEWS 10
50 /* Define the maximum value for view-id */
51 #define MAX_VIEW_ID 1023
53 /* Supported set of VA rate controls, within this implementation */
54 #define SUPPORTED_RATECONTROLS \
55 (GST_VAAPI_RATECONTROL_MASK (CQP) | \
56 GST_VAAPI_RATECONTROL_MASK (CBR) | \
57 GST_VAAPI_RATECONTROL_MASK (VBR) | \
58 GST_VAAPI_RATECONTROL_MASK (VBR_CONSTRAINED))
60 /* Supported set of tuning options, within this implementation */
61 #define SUPPORTED_TUNE_OPTIONS \
62 (GST_VAAPI_ENCODER_TUNE_MASK (NONE) | \
63 GST_VAAPI_ENCODER_TUNE_MASK (HIGH_COMPRESSION) | \
64 GST_VAAPI_ENCODER_TUNE_MASK (LOW_POWER))
66 /* Supported set of VA packed headers, within this implementation */
67 #define SUPPORTED_PACKED_HEADERS \
68 (VA_ENC_PACKED_HEADER_SEQUENCE | \
69 VA_ENC_PACKED_HEADER_PICTURE | \
70 VA_ENC_PACKED_HEADER_SLICE | \
71 VA_ENC_PACKED_HEADER_RAW_DATA | \
72 VA_ENC_PACKED_HEADER_MISC)
74 #define GST_H264_NAL_REF_IDC_NONE 0
75 #define GST_H264_NAL_REF_IDC_LOW 1
76 #define GST_H264_NAL_REF_IDC_MEDIUM 2
77 #define GST_H264_NAL_REF_IDC_HIGH 3
79 /* only for internal usage, values won't be equal to actual payload type */
82 GST_VAAPI_H264_SEI_UNKNOWN = 0,
83 GST_VAAPI_H264_SEI_BUF_PERIOD = (1 << 0),
84 GST_VAAPI_H264_SEI_PIC_TIMING = (1 << 1)
85 } GstVaapiH264SeiPayloadType;
89 GstVaapiSurfaceProxy *pic;
92 } GstVaapiEncoderH264Ref;
96 GST_VAAPI_ENC_H264_REORD_NONE = 0,
97 GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES = 1,
98 GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES = 2
99 } GstVaapiEncH264ReorderState;
101 typedef struct _GstVaapiH264ViewRefPool
104 guint max_ref_frames;
105 guint max_reflist0_count;
106 guint max_reflist1_count;
107 } GstVaapiH264ViewRefPool;
109 typedef struct _GstVaapiH264ViewReorderPool
111 GQueue reorder_frame_list;
114 guint frame_count; /* monotonically increasing with in every idr period */
116 guint cur_present_index;
117 } GstVaapiH264ViewReorderPool;
119 static inline gboolean
120 _poc_greater_than (guint poc1, guint poc2, guint max_poc)
122 return (((poc1 - poc2) & (max_poc - 1)) < max_poc / 2);
125 /* Get slice_type value for H.264 specification */
127 h264_get_slice_type (GstVaapiPictureType type)
130 case GST_VAAPI_PICTURE_TYPE_I:
131 return GST_H264_I_SLICE;
132 case GST_VAAPI_PICTURE_TYPE_P:
133 return GST_H264_P_SLICE;
134 case GST_VAAPI_PICTURE_TYPE_B:
135 return GST_H264_B_SLICE;
142 /* Get log2_max_frame_num value for H.264 specification */
144 h264_get_log2_max_frame_num (guint num)
156 /* must be greater than 4 */
160 /* Determines the cpbBrNalFactor based on the supplied profile */
162 h264_get_cpb_nal_factor (GstVaapiProfile profile)
168 case GST_VAAPI_PROFILE_H264_HIGH:
171 case GST_VAAPI_PROFILE_H264_HIGH10:
174 case GST_VAAPI_PROFILE_H264_HIGH_422:
175 case GST_VAAPI_PROFILE_H264_HIGH_444:
178 case GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH:
179 case GST_VAAPI_PROFILE_H264_STEREO_HIGH:
180 f = 1500; /* H.10.2.1 (r) */
189 /* Write the NAL unit header */
191 bs_write_nal_header (GstBitWriter * bs, guint32 nal_ref_idc,
192 guint32 nal_unit_type)
194 WRITE_UINT32 (bs, 0, 1);
195 WRITE_UINT32 (bs, nal_ref_idc, 2);
196 WRITE_UINT32 (bs, nal_unit_type, 5);
202 GST_WARNING ("failed to write NAL unit header");
207 /* Write the MVC NAL unit header extension */
209 bs_write_nal_header_mvc_extension (GstBitWriter * bs,
210 GstVaapiEncPicture * picture, guint32 view_id)
212 guint32 svc_extension_flag = 0;
213 guint32 non_idr_flag = 1;
214 guint32 priority_id = 0;
215 guint32 temporal_id = 0;
216 guint32 anchor_pic_flag = 0;
217 guint32 inter_view_flag = 0;
219 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
222 if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
224 /* svc_extension_flag == 0 for mvc stream */
225 WRITE_UINT32 (bs, svc_extension_flag, 1);
227 WRITE_UINT32 (bs, non_idr_flag, 1);
228 WRITE_UINT32 (bs, priority_id, 6);
229 WRITE_UINT32 (bs, view_id, 10);
230 WRITE_UINT32 (bs, temporal_id, 3);
231 WRITE_UINT32 (bs, anchor_pic_flag, 1);
232 WRITE_UINT32 (bs, inter_view_flag, 1);
233 WRITE_UINT32 (bs, 1, 1);
240 GST_WARNING ("failed to write NAL unit header");
245 /* Write the NAL unit trailing bits */
247 bs_write_trailing_bits (GstBitWriter * bs)
249 if (!gst_bit_writer_put_bits_uint32 (bs, 1, 1))
251 gst_bit_writer_align_bytes_unchecked (bs, 0);
257 GST_WARNING ("failed to write NAL unit trailing bits");
262 /* Write an SPS NAL unit */
264 bs_write_sps_data (GstBitWriter * bs,
265 const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
266 const VAEncMiscParameterHRD * hrd_params)
269 guint32 constraint_set0_flag, constraint_set1_flag;
270 guint32 constraint_set2_flag, constraint_set3_flag;
271 guint32 gaps_in_frame_num_value_allowed_flag = 0; // ??
272 gboolean nal_hrd_parameters_present_flag;
274 guint32 b_qpprime_y_zero_transform_bypass = 0;
275 guint32 residual_color_transform_flag = 0;
276 guint32 pic_height_in_map_units =
277 (seq_param->seq_fields.bits.frame_mbs_only_flag ?
278 seq_param->picture_height_in_mbs : seq_param->picture_height_in_mbs / 2);
279 guint32 mb_adaptive_frame_field =
280 !seq_param->seq_fields.bits.frame_mbs_only_flag;
283 profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
284 constraint_set0_flag = /* A.2.1 (baseline profile constraints) */
285 profile == GST_VAAPI_PROFILE_H264_BASELINE ||
286 profile == GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
287 constraint_set1_flag = /* A.2.2 (main profile constraints) */
288 profile == GST_VAAPI_PROFILE_H264_MAIN ||
289 profile == GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
290 constraint_set2_flag = 0;
291 constraint_set3_flag = 0;
294 WRITE_UINT32 (bs, profile_idc, 8);
295 /* constraint_set0_flag */
296 WRITE_UINT32 (bs, constraint_set0_flag, 1);
297 /* constraint_set1_flag */
298 WRITE_UINT32 (bs, constraint_set1_flag, 1);
299 /* constraint_set2_flag */
300 WRITE_UINT32 (bs, constraint_set2_flag, 1);
301 /* constraint_set3_flag */
302 WRITE_UINT32 (bs, constraint_set3_flag, 1);
303 /* reserved_zero_4bits */
304 WRITE_UINT32 (bs, 0, 4);
306 WRITE_UINT32 (bs, seq_param->level_idc, 8);
307 /* seq_parameter_set_id */
308 WRITE_UE (bs, seq_param->seq_parameter_set_id);
310 if (profile == GST_VAAPI_PROFILE_H264_HIGH ||
311 profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH ||
312 profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH) {
313 /* for high profile */
314 /* chroma_format_idc = 1, 4:2:0 */
315 WRITE_UE (bs, seq_param->seq_fields.bits.chroma_format_idc);
316 if (3 == seq_param->seq_fields.bits.chroma_format_idc) {
317 WRITE_UINT32 (bs, residual_color_transform_flag, 1);
319 /* bit_depth_luma_minus8 */
320 WRITE_UE (bs, seq_param->bit_depth_luma_minus8);
321 /* bit_depth_chroma_minus8 */
322 WRITE_UE (bs, seq_param->bit_depth_chroma_minus8);
323 /* b_qpprime_y_zero_transform_bypass */
324 WRITE_UINT32 (bs, b_qpprime_y_zero_transform_bypass, 1);
326 /* seq_scaling_matrix_present_flag */
327 g_assert (seq_param->seq_fields.bits.seq_scaling_matrix_present_flag == 0);
329 seq_param->seq_fields.bits.seq_scaling_matrix_present_flag, 1);
332 if (seq_param->seq_fields.bits.seq_scaling_matrix_present_flag) {
334 i < (seq_param->seq_fields.bits.chroma_format_idc != 3 ? 8 : 12);
336 gst_bit_writer_put_bits_uint8 (bs,
337 seq_param->seq_fields.bits.seq_scaling_list_present_flag, 1);
338 if (seq_param->seq_fields.bits.seq_scaling_list_present_flag) {
340 /* FIXME, need write scaling list if seq_scaling_matrix_present_flag ==1 */
347 /* log2_max_frame_num_minus4 */
348 WRITE_UE (bs, seq_param->seq_fields.bits.log2_max_frame_num_minus4);
349 /* pic_order_cnt_type */
350 WRITE_UE (bs, seq_param->seq_fields.bits.pic_order_cnt_type);
352 if (seq_param->seq_fields.bits.pic_order_cnt_type == 0) {
353 /* log2_max_pic_order_cnt_lsb_minus4 */
354 WRITE_UE (bs, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4);
355 } else if (seq_param->seq_fields.bits.pic_order_cnt_type == 1) {
356 g_assert (0 && "only POC type 0 is supported");
358 seq_param->seq_fields.bits.delta_pic_order_always_zero_flag, 1);
359 WRITE_SE (bs, seq_param->offset_for_non_ref_pic);
360 WRITE_SE (bs, seq_param->offset_for_top_to_bottom_field);
361 WRITE_UE (bs, seq_param->num_ref_frames_in_pic_order_cnt_cycle);
362 for (i = 0; i < seq_param->num_ref_frames_in_pic_order_cnt_cycle; i++) {
363 WRITE_SE (bs, seq_param->offset_for_ref_frame[i]);
368 WRITE_UE (bs, seq_param->max_num_ref_frames);
369 /* gaps_in_frame_num_value_allowed_flag */
370 WRITE_UINT32 (bs, gaps_in_frame_num_value_allowed_flag, 1);
372 /* pic_width_in_mbs_minus1 */
373 WRITE_UE (bs, seq_param->picture_width_in_mbs - 1);
374 /* pic_height_in_map_units_minus1 */
375 WRITE_UE (bs, pic_height_in_map_units - 1);
376 /* frame_mbs_only_flag */
377 WRITE_UINT32 (bs, seq_param->seq_fields.bits.frame_mbs_only_flag, 1);
379 if (!seq_param->seq_fields.bits.frame_mbs_only_flag) { //ONLY mbs
380 g_assert (0 && "only progressive frames encoding is supported");
381 WRITE_UINT32 (bs, mb_adaptive_frame_field, 1);
384 /* direct_8x8_inference_flag */
385 WRITE_UINT32 (bs, 0, 1);
386 /* frame_cropping_flag */
387 WRITE_UINT32 (bs, seq_param->frame_cropping_flag, 1);
389 if (seq_param->frame_cropping_flag) {
390 /* frame_crop_left_offset */
391 WRITE_UE (bs, seq_param->frame_crop_left_offset);
392 /* frame_crop_right_offset */
393 WRITE_UE (bs, seq_param->frame_crop_right_offset);
394 /* frame_crop_top_offset */
395 WRITE_UE (bs, seq_param->frame_crop_top_offset);
396 /* frame_crop_bottom_offset */
397 WRITE_UE (bs, seq_param->frame_crop_bottom_offset);
400 /* vui_parameters_present_flag */
401 WRITE_UINT32 (bs, seq_param->vui_parameters_present_flag, 1);
402 if (seq_param->vui_parameters_present_flag) {
403 /* aspect_ratio_info_present_flag */
405 seq_param->vui_fields.bits.aspect_ratio_info_present_flag, 1);
406 if (seq_param->vui_fields.bits.aspect_ratio_info_present_flag) {
407 WRITE_UINT32 (bs, seq_param->aspect_ratio_idc, 8);
408 if (seq_param->aspect_ratio_idc == 0xFF) {
409 WRITE_UINT32 (bs, seq_param->sar_width, 16);
410 WRITE_UINT32 (bs, seq_param->sar_height, 16);
414 /* overscan_info_present_flag */
415 WRITE_UINT32 (bs, 0, 1);
416 /* video_signal_type_present_flag */
417 WRITE_UINT32 (bs, 0, 1);
418 /* chroma_loc_info_present_flag */
419 WRITE_UINT32 (bs, 0, 1);
421 /* timing_info_present_flag */
422 WRITE_UINT32 (bs, seq_param->vui_fields.bits.timing_info_present_flag, 1);
423 if (seq_param->vui_fields.bits.timing_info_present_flag) {
424 WRITE_UINT32 (bs, seq_param->num_units_in_tick, 32);
425 WRITE_UINT32 (bs, seq_param->time_scale, 32);
426 WRITE_UINT32 (bs, 1, 1); /* fixed_frame_rate_flag */
429 /* nal_hrd_parameters_present_flag */
430 nal_hrd_parameters_present_flag = seq_param->bits_per_second > 0;
431 WRITE_UINT32 (bs, nal_hrd_parameters_present_flag, 1);
432 if (nal_hrd_parameters_present_flag) {
436 WRITE_UINT32 (bs, SX_BITRATE - 6, 4); /* bit_rate_scale */
437 WRITE_UINT32 (bs, SX_CPB_SIZE - 4, 4); /* cpb_size_scale */
439 for (i = 0; i < 1; ++i) {
440 /* bit_rate_value_minus1[0] */
441 WRITE_UE (bs, (seq_param->bits_per_second >> SX_BITRATE) - 1);
442 /* cpb_size_value_minus1[0] */
443 WRITE_UE (bs, (hrd_params->buffer_size >> SX_CPB_SIZE) - 1);
445 WRITE_UINT32 (bs, 1, 1);
447 /* initial_cpb_removal_delay_length_minus1 */
448 WRITE_UINT32 (bs, 23, 5);
449 /* cpb_removal_delay_length_minus1 */
450 WRITE_UINT32 (bs, 23, 5);
451 /* dpb_output_delay_length_minus1 */
452 WRITE_UINT32 (bs, 23, 5);
453 /* time_offset_length */
454 WRITE_UINT32 (bs, 23, 5);
457 /* vcl_hrd_parameters_present_flag */
458 WRITE_UINT32 (bs, 0, 1);
460 if (nal_hrd_parameters_present_flag
461 || 0 /*vcl_hrd_parameters_present_flag */ ) {
462 /* low_delay_hrd_flag */
463 WRITE_UINT32 (bs, 0, 1);
465 /* pic_struct_present_flag */
466 WRITE_UINT32 (bs, 1, 1);
467 /* bs_restriction_flag */
468 WRITE_UINT32 (bs, 0, 1);
475 GST_WARNING ("failed to write SPS NAL unit");
481 bs_write_sps (GstBitWriter * bs,
482 const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
483 const VAEncMiscParameterHRD * hrd_params)
485 if (!bs_write_sps_data (bs, seq_param, profile, hrd_params))
488 /* rbsp_trailing_bits */
489 bs_write_trailing_bits (bs);
495 bs_write_subset_sps (GstBitWriter * bs,
496 const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
497 guint num_views, guint16 * view_ids,
498 const VAEncMiscParameterHRD * hrd_params)
502 if (!bs_write_sps_data (bs, seq_param, profile, hrd_params))
505 if (profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH ||
506 profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH) {
507 guint32 num_views_minus1, num_level_values_signalled_minus1;
509 num_views_minus1 = num_views - 1;
510 g_assert (num_views_minus1 < 1024);
512 /* bit equal to one */
513 WRITE_UINT32 (bs, 1, 1);
515 WRITE_UE (bs, num_views_minus1);
517 for (i = 0; i <= num_views_minus1; i++)
518 WRITE_UE (bs, view_ids[i]);
520 for (i = 1; i <= num_views_minus1; i++) {
521 guint32 num_anchor_refs_l0 = 0;
522 guint32 num_anchor_refs_l1 = 0;
524 WRITE_UE (bs, num_anchor_refs_l0);
525 for (j = 0; j < num_anchor_refs_l0; j++)
528 WRITE_UE (bs, num_anchor_refs_l1);
529 for (j = 0; j < num_anchor_refs_l1; j++)
533 for (i = 1; i <= num_views_minus1; i++) {
534 guint32 num_non_anchor_refs_l0 = 0;
535 guint32 num_non_anchor_refs_l1 = 0;
537 WRITE_UE (bs, num_non_anchor_refs_l0);
538 for (j = 0; j < num_non_anchor_refs_l0; j++)
541 WRITE_UE (bs, num_non_anchor_refs_l1);
542 for (j = 0; j < num_non_anchor_refs_l1; j++)
546 /* num level values signalled minus1 */
547 num_level_values_signalled_minus1 = 0;
548 g_assert (num_level_values_signalled_minus1 < 64);
549 WRITE_UE (bs, num_level_values_signalled_minus1);
551 for (i = 0; i <= num_level_values_signalled_minus1; i++) {
552 guint16 num_applicable_ops_minus1 = 0;
553 g_assert (num_applicable_ops_minus1 < 1024);
555 WRITE_UINT32 (bs, seq_param->level_idc, 8);
556 WRITE_UE (bs, num_applicable_ops_minus1);
558 for (j = 0; j <= num_applicable_ops_minus1; j++) {
559 guint8 temporal_id = 0;
560 guint16 num_target_views_minus1 = 1;
562 WRITE_UINT32 (bs, temporal_id, 3);
563 WRITE_UE (bs, num_target_views_minus1);
565 for (k = 0; k <= num_target_views_minus1; k++)
568 WRITE_UE (bs, num_views_minus1);
572 /* mvc_vui_parameters_present_flag */
573 WRITE_UINT32 (bs, 0, 1);
576 /* additional_extension2_flag */
577 WRITE_UINT32 (bs, 0, 1);
579 /* rbsp_trailing_bits */
580 bs_write_trailing_bits (bs);
586 GST_WARNING ("failed to write subset SPS NAL unit");
592 /* Write a PPS NAL unit */
594 bs_write_pps (GstBitWriter * bs,
595 const VAEncPictureParameterBufferH264 * pic_param, GstVaapiProfile profile)
597 guint32 num_slice_groups_minus1 = 0;
598 guint32 pic_init_qs_minus26 = 0;
599 guint32 redundant_pic_cnt_present_flag = 0;
601 /* pic_parameter_set_id */
602 WRITE_UE (bs, pic_param->pic_parameter_set_id);
603 /* seq_parameter_set_id */
604 WRITE_UE (bs, pic_param->seq_parameter_set_id);
605 /* entropy_coding_mode_flag */
606 WRITE_UINT32 (bs, pic_param->pic_fields.bits.entropy_coding_mode_flag, 1);
607 /* pic_order_present_flag */
608 WRITE_UINT32 (bs, pic_param->pic_fields.bits.pic_order_present_flag, 1);
610 WRITE_UE (bs, num_slice_groups_minus1);
612 if (num_slice_groups_minus1 > 0) {
613 /*FIXME*/ g_assert (0 && "unsupported arbitrary slice ordering (ASO)");
615 WRITE_UE (bs, pic_param->num_ref_idx_l0_active_minus1);
616 WRITE_UE (bs, pic_param->num_ref_idx_l1_active_minus1);
617 WRITE_UINT32 (bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);
618 WRITE_UINT32 (bs, pic_param->pic_fields.bits.weighted_bipred_idc, 2);
619 /* pic_init_qp_minus26 */
620 WRITE_SE (bs, pic_param->pic_init_qp - 26);
621 /* pic_init_qs_minus26 */
622 WRITE_SE (bs, pic_init_qs_minus26);
623 /* chroma_qp_index_offset */
624 WRITE_SE (bs, pic_param->chroma_qp_index_offset);
627 pic_param->pic_fields.bits.deblocking_filter_control_present_flag, 1);
628 WRITE_UINT32 (bs, pic_param->pic_fields.bits.constrained_intra_pred_flag, 1);
629 WRITE_UINT32 (bs, redundant_pic_cnt_present_flag, 1);
632 if (profile == GST_VAAPI_PROFILE_H264_HIGH
633 || profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH
634 || profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH) {
635 WRITE_UINT32 (bs, pic_param->pic_fields.bits.transform_8x8_mode_flag, 1);
637 pic_param->pic_fields.bits.pic_scaling_matrix_present_flag, 1);
638 if (pic_param->pic_fields.bits.pic_scaling_matrix_present_flag) {
639 g_assert (0 && "unsupported scaling lists");
643 (6+(-( (chroma_format_idc ! = 3) ? 2 : 6) * -pic_param->pic_fields.bits.transform_8x8_mode_flag));
645 gst_bit_writer_put_bits_uint8(bs, pic_param->pic_fields.bits.pic_scaling_list_present_flag, 1);
649 WRITE_SE (bs, pic_param->second_chroma_qp_index_offset);
652 /* rbsp_trailing_bits */
653 bs_write_trailing_bits (bs);
659 GST_WARNING ("failed to write PPS NAL unit");
664 /* ------------------------------------------------------------------------- */
665 /* --- H.264 Encoder --- */
666 /* ------------------------------------------------------------------------- */
668 #define GST_VAAPI_ENCODER_H264_CAST(encoder) \
669 ((GstVaapiEncoderH264 *)(encoder))
671 struct _GstVaapiEncoderH264
673 GstVaapiEncoder parent_instance;
675 GstVaapiProfile profile;
676 GstVaapiLevelH264 level;
677 GstVaapiEntrypoint entrypoint;
679 guint8 max_profile_idc;
680 guint8 hw_max_profile_idc;
691 GstClockTime cts_offset;
692 gboolean config_changed;
695 guint32 max_frame_num;
696 guint32 log2_max_frame_num;
697 guint32 max_pic_order_cnt;
698 guint32 log2_max_pic_order_cnt;
700 guint8 pic_order_cnt_type;
701 guint8 delta_pic_order_always_zero_flag;
704 GstBuffer *subset_sps_data;
707 guint bitrate_bits; // bitrate (bits)
708 guint cpb_length; // length of CPB buffer (ms)
709 guint cpb_length_bits; // length of CPB buffer (bits)
713 guint32 view_idx; /* View Order Index (VOIdx) */
715 guint16 view_ids[MAX_NUM_VIEWS];
716 GstVaapiH264ViewRefPool ref_pools[MAX_NUM_VIEWS];
717 GstVaapiH264ViewReorderPool reorder_pools[MAX_NUM_VIEWS];
720 /* Write a SEI buffering period payload */
722 bs_write_sei_buf_period (GstBitWriter * bs,
723 GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
725 guint initial_cpb_removal_delay = 0;
726 guint initial_cpb_removal_delay_offset = 0;
727 guint8 initial_cpb_removal_delay_length = 24;
729 /* sequence_parameter_set_id */
730 WRITE_UE (bs, encoder->view_idx);
731 /* NalHrdBpPresentFlag == TRUE */
732 /* cpb_cnt_minus1 == 0 */
734 /* decoding should start when the CPB fullness reaches half of cpb size
735 * initial_cpb_remvoal_delay = (((cpb_length / 2) * 90000) / 1000) */
736 initial_cpb_removal_delay = encoder->cpb_length * 45;
738 /* initial_cpb_remvoal_dealy */
739 WRITE_UINT32 (bs, initial_cpb_removal_delay,
740 initial_cpb_removal_delay_length);
742 /* initial_cpb_removal_delay_offset */
743 WRITE_UINT32 (bs, initial_cpb_removal_delay_offset,
744 initial_cpb_removal_delay_length);
746 /* VclHrdBpPresentFlag == FALSE */
752 GST_WARNING ("failed to write Buffering Period SEI message");
757 /* Write a SEI picture timing payload */
759 bs_write_sei_pic_timing (GstBitWriter * bs,
760 GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
762 GstVaapiH264ViewReorderPool *reorder_pool = NULL;
763 guint cpb_removal_delay;
764 guint dpb_output_delay;
765 guint8 cpb_removal_delay_length = 24;
766 guint8 dpb_output_delay_length = 24;
767 guint pic_struct = 0;
768 guint clock_timestamp_flag = 0;
770 reorder_pool = &encoder->reorder_pools[encoder->view_idx];
771 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
772 reorder_pool->frame_count = 0;
774 reorder_pool->frame_count++;
776 /* clock-tick = no_units_in_tick/time_scale (C-1)
777 * time_scale = FPS_N * 2 (E.2.1)
778 * num_units_in_tick = FPS_D (E.2.1)
779 * frame_duration = clock-tick * 2
780 * so removal time for one frame is 2 clock-ticks.
781 * but adding a tolerance of one frame duration,
782 * which is 2 more clock-ticks */
783 cpb_removal_delay = (reorder_pool->frame_count * 2 + 2);
785 if (picture->type == GST_VAAPI_PICTURE_TYPE_B)
786 dpb_output_delay = 0;
788 dpb_output_delay = picture->poc - reorder_pool->frame_count * 2;
790 /* CpbDpbDelaysPresentFlag == 1 */
791 WRITE_UINT32 (bs, cpb_removal_delay, cpb_removal_delay_length);
792 WRITE_UINT32 (bs, dpb_output_delay, dpb_output_delay_length);
794 /* pic_struct_present_flag == 1 */
796 WRITE_UINT32 (bs, pic_struct, 4);
797 /* clock_timestamp_flag */
798 WRITE_UINT32 (bs, clock_timestamp_flag, 1);
805 GST_WARNING ("failed to write Picture Timing SEI message");
810 /* Write a Slice NAL unit */
812 bs_write_slice (GstBitWriter * bs,
813 const VAEncSliceParameterBufferH264 * slice_param,
814 GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
816 const VAEncPictureParameterBufferH264 *const pic_param = picture->param;
817 guint32 field_pic_flag = 0;
818 guint32 ref_pic_list_modification_flag_l0 = 0;
819 guint32 ref_pic_list_modification_flag_l1 = 0;
820 guint32 no_output_of_prior_pics_flag = 0;
821 guint32 long_term_reference_flag = 0;
822 guint32 adaptive_ref_pic_marking_mode_flag = 0;
824 /* first_mb_in_slice */
825 WRITE_UE (bs, slice_param->macroblock_address);
827 WRITE_UE (bs, slice_param->slice_type);
828 /* pic_parameter_set_id */
829 WRITE_UE (bs, slice_param->pic_parameter_set_id);
831 WRITE_UINT32 (bs, picture->frame_num, encoder->log2_max_frame_num);
833 /* XXX: only frames (i.e. non-interlaced) are supported for now */
834 /* frame_mbs_only_flag == 0 */
837 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
838 WRITE_UE (bs, slice_param->idr_pic_id);
840 /* XXX: only POC type 0 is supported */
841 if (!encoder->pic_order_cnt_type) {
842 WRITE_UINT32 (bs, slice_param->pic_order_cnt_lsb,
843 encoder->log2_max_pic_order_cnt);
844 /* bottom_field_pic_order_in_frame_present_flag is FALSE */
845 if (pic_param->pic_fields.bits.pic_order_present_flag && !field_pic_flag)
846 WRITE_SE (bs, slice_param->delta_pic_order_cnt_bottom);
847 } else if (encoder->pic_order_cnt_type == 1 &&
848 !encoder->delta_pic_order_always_zero_flag) {
849 WRITE_SE (bs, slice_param->delta_pic_order_cnt[0]);
850 if (pic_param->pic_fields.bits.pic_order_present_flag && !field_pic_flag)
851 WRITE_SE (bs, slice_param->delta_pic_order_cnt[1]);
853 /* redundant_pic_cnt_present_flag is FALSE, no redundant coded pictures */
855 /* only works for B-frames */
856 if (slice_param->slice_type == 1)
857 WRITE_UINT32 (bs, slice_param->direct_spatial_mv_pred_flag, 1);
859 /* not supporting SP slices */
860 if (slice_param->slice_type == 0 || slice_param->slice_type == 1) {
861 WRITE_UINT32 (bs, slice_param->num_ref_idx_active_override_flag, 1);
862 if (slice_param->num_ref_idx_active_override_flag) {
863 WRITE_UE (bs, slice_param->num_ref_idx_l0_active_minus1);
864 if (slice_param->slice_type == 1)
865 WRITE_UE (bs, slice_param->num_ref_idx_l1_active_minus1);
868 /* XXX: not supporting custom reference picture list modifications */
869 if ((slice_param->slice_type != 2) && (slice_param->slice_type != 4))
870 WRITE_UINT32 (bs, ref_pic_list_modification_flag_l0, 1);
871 if (slice_param->slice_type == 1)
872 WRITE_UINT32 (bs, ref_pic_list_modification_flag_l1, 1);
874 /* we have: weighted_pred_flag == FALSE and */
875 /* : weighted_bipred_idc == FALSE */
876 if ((pic_param->pic_fields.bits.weighted_pred_flag &&
877 (slice_param->slice_type == 0)) ||
878 ((pic_param->pic_fields.bits.weighted_bipred_idc == 1) &&
879 (slice_param->slice_type == 1))) {
880 /* XXXX: add pred_weight_table() */
883 /* dec_ref_pic_marking() */
884 if (slice_param->slice_type == 0 || slice_param->slice_type == 2) {
885 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture)) {
886 /* no_output_of_prior_pics_flag = 0 */
887 WRITE_UINT32 (bs, no_output_of_prior_pics_flag, 1);
888 /* long_term_reference_flag = 0 */
889 WRITE_UINT32 (bs, long_term_reference_flag, 1);
891 /* only sliding_window reference picture marking mode is supported */
892 /* adpative_ref_pic_marking_mode_flag = 0 */
893 WRITE_UINT32 (bs, adaptive_ref_pic_marking_mode_flag, 1);
898 if (pic_param->pic_fields.bits.entropy_coding_mode_flag &&
899 slice_param->slice_type != 2)
900 WRITE_UE (bs, slice_param->cabac_init_idc);
902 WRITE_SE (bs, slice_param->slice_qp_delta);
904 /* XXX: only supporting I, P and B type slices */
905 /* no sp_for_switch_flag and no slice_qs_delta */
907 if (pic_param->pic_fields.bits.deblocking_filter_control_present_flag) {
908 /* disable_deblocking_filter_idc */
909 WRITE_UE (bs, slice_param->disable_deblocking_filter_idc);
910 if (slice_param->disable_deblocking_filter_idc != 1) {
911 WRITE_SE (bs, slice_param->slice_alpha_c0_offset_div2);
912 WRITE_SE (bs, slice_param->slice_beta_offset_div2);
916 /* XXX: unsupported arbitrary slice ordering (ASO) */
917 /* num_slic_groups_minus1 should be zero */
923 GST_WARNING ("failed to write Slice NAL unit");
929 _check_sps_pps_status (GstVaapiEncoderH264 * encoder,
930 const guint8 * nal, guint32 size)
933 G_GNUC_UNUSED gsize ret; /* FIXME */
934 gboolean has_subset_sps;
938 has_subset_sps = !encoder->is_mvc || (encoder->subset_sps_data != NULL);
939 if (encoder->sps_data && encoder->pps_data && has_subset_sps)
942 nal_type = nal[0] & 0x1F;
944 case GST_H264_NAL_SPS:
945 encoder->sps_data = gst_buffer_new_allocate (NULL, size, NULL);
946 ret = gst_buffer_fill (encoder->sps_data, 0, nal, size);
947 g_assert (ret == size);
949 case GST_H264_NAL_SUBSET_SPS:
950 encoder->subset_sps_data = gst_buffer_new_allocate (NULL, size, NULL);
951 ret = gst_buffer_fill (encoder->subset_sps_data, 0, nal, size);
952 g_assert (ret == size);
954 case GST_H264_NAL_PPS:
955 encoder->pps_data = gst_buffer_new_allocate (NULL, size, NULL);
956 ret = gst_buffer_fill (encoder->pps_data, 0, nal, size);
957 g_assert (ret == size);
964 /* Determines the largest supported profile by the underlying hardware */
966 ensure_hw_profile_limits (GstVaapiEncoderH264 * encoder)
968 GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
970 guint i, profile_idc, max_profile_idc;
972 if (encoder->hw_max_profile_idc)
975 profiles = gst_vaapi_display_get_encode_profiles (display);
980 for (i = 0; i < profiles->len; i++) {
981 const GstVaapiProfile profile =
982 g_array_index (profiles, GstVaapiProfile, i);
983 profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
986 if (max_profile_idc < profile_idc)
987 max_profile_idc = profile_idc;
989 g_array_unref (profiles);
991 encoder->hw_max_profile_idc = max_profile_idc;
995 /* Derives the profile supported by the underlying hardware */
997 ensure_hw_profile (GstVaapiEncoderH264 * encoder)
999 GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
1000 GstVaapiEntrypoint entrypoint = encoder->entrypoint;
1001 GstVaapiProfile profile, profiles[4];
1002 guint i, num_profiles = 0;
1004 profiles[num_profiles++] = encoder->profile;
1005 switch (encoder->profile) {
1006 case GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE:
1007 profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_BASELINE;
1008 profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_MAIN;
1010 case GST_VAAPI_PROFILE_H264_MAIN:
1011 profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_HIGH;
1017 profile = GST_VAAPI_PROFILE_UNKNOWN;
1018 for (i = 0; i < num_profiles; i++) {
1019 if (gst_vaapi_display_has_encoder (display, profiles[i], entrypoint)) {
1020 profile = profiles[i];
1024 if (profile == GST_VAAPI_PROFILE_UNKNOWN)
1025 goto error_unsupported_profile;
1027 GST_VAAPI_ENCODER_CAST (encoder)->profile = profile;
1031 error_unsupported_profile:
1033 GST_ERROR ("unsupported HW profile %s",
1034 gst_vaapi_profile_get_name (encoder->profile));
1039 /* Check target decoder constraints */
1041 ensure_profile_limits (GstVaapiEncoderH264 * encoder)
1043 GstVaapiProfile profile;
1045 if (!encoder->max_profile_idc
1046 || encoder->profile_idc == encoder->max_profile_idc)
1049 /* Give an error if the given parameters are invalid for requested
1050 * profile rather than lowering profile.
1052 if (encoder->profile_idc > encoder->max_profile_idc) {
1053 GST_WARNING ("Invalid parameter for maximum profile");
1057 profile = GST_VAAPI_PROFILE_UNKNOWN;
1059 if (encoder->profile_idc < encoder->max_profile_idc) {
1060 /* Let profile be higher to fit in the maximum profile
1061 * without changing parameters */
1062 if (encoder->max_profile_idc > GST_H264_PROFILE_BASELINE)
1063 profile = GST_VAAPI_PROFILE_H264_MAIN;
1065 if (encoder->max_profile_idc > GST_H264_PROFILE_MAIN)
1066 profile = GST_VAAPI_PROFILE_H264_HIGH;
1068 if (encoder->max_profile_idc > GST_H264_PROFILE_HIGH) {
1069 if (encoder->num_views > 2)
1070 profile = GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH;
1071 else if (encoder->num_views == 2)
1072 profile = GST_VAAPI_PROFILE_H264_STEREO_HIGH;
1077 encoder->profile = profile;
1078 encoder->profile_idc = encoder->max_profile_idc;
1083 /* Derives the minimum profile from the active coding tools */
1085 ensure_profile (GstVaapiEncoderH264 * encoder)
1087 GstVaapiProfile profile;
1089 /* Always start from "constrained-baseline" profile for maximum
1091 profile = GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
1093 /* Main profile coding tools */
1094 if (encoder->num_bframes > 0 || encoder->use_cabac)
1095 profile = GST_VAAPI_PROFILE_H264_MAIN;
1097 /* High profile coding tools */
1098 if (encoder->use_dct8x8)
1099 profile = GST_VAAPI_PROFILE_H264_HIGH;
1101 /* MVC profiles coding tools */
1102 if (encoder->num_views == 2)
1103 profile = GST_VAAPI_PROFILE_H264_STEREO_HIGH;
1104 else if (encoder->num_views > 2)
1105 profile = GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH;
1107 encoder->profile = profile;
1108 encoder->profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
1112 /* Derives the level from the currently set limits */
1114 ensure_level (GstVaapiEncoderH264 * encoder)
1116 const guint cpb_factor = h264_get_cpb_nal_factor (encoder->profile);
1117 const GstVaapiH264LevelLimits *limits_table;
1118 guint i, num_limits, PicSizeMbs, MaxDpbMbs, MaxMBPS;
1120 PicSizeMbs = encoder->mb_width * encoder->mb_height;
1121 MaxDpbMbs = PicSizeMbs * ((encoder->num_bframes) ? 2 : 1);
1122 MaxMBPS = gst_util_uint64_scale_int_ceil (PicSizeMbs,
1123 GST_VAAPI_ENCODER_FPS_N (encoder), GST_VAAPI_ENCODER_FPS_D (encoder));
1125 limits_table = gst_vaapi_utils_h264_get_level_limits_table (&num_limits);
1126 for (i = 0; i < num_limits; i++) {
1127 const GstVaapiH264LevelLimits *const limits = &limits_table[i];
1128 if (PicSizeMbs <= limits->MaxFS &&
1129 MaxDpbMbs <= limits->MaxDpbMbs &&
1130 MaxMBPS <= limits->MaxMBPS && (!encoder->bitrate_bits
1131 || encoder->bitrate_bits <= (limits->MaxBR * cpb_factor)) &&
1132 (!encoder->cpb_length_bits ||
1133 encoder->cpb_length_bits <= (limits->MaxCPB * cpb_factor)))
1136 if (i == num_limits)
1137 goto error_unsupported_level;
1139 encoder->level = limits_table[i].level;
1140 encoder->level_idc = limits_table[i].level_idc;
1144 error_unsupported_level:
1146 GST_ERROR ("failed to find a suitable level matching codec config");
1151 /* Enable "high-compression" tuning options */
1153 ensure_tuning_high_compression (GstVaapiEncoderH264 * encoder)
1157 if (!ensure_hw_profile_limits (encoder))
1160 profile_idc = encoder->hw_max_profile_idc;
1161 if (encoder->max_profile_idc && encoder->max_profile_idc < profile_idc)
1162 profile_idc = encoder->max_profile_idc;
1164 /* Tuning options to enable Main profile */
1165 if (profile_idc >= GST_H264_PROFILE_MAIN
1166 && profile_idc != GST_H264_PROFILE_EXTENDED) {
1167 encoder->use_cabac = TRUE;
1168 if (!encoder->num_bframes)
1169 encoder->num_bframes = 1;
1172 /* Tuning options to enable High profile */
1173 if (profile_idc >= GST_H264_PROFILE_HIGH) {
1174 encoder->use_dct8x8 = TRUE;
1179 /* Ensure tuning options */
1181 ensure_tuning (GstVaapiEncoderH264 * encoder)
1185 switch (GST_VAAPI_ENCODER_TUNE (encoder)) {
1186 case GST_VAAPI_ENCODER_TUNE_HIGH_COMPRESSION:
1187 success = ensure_tuning_high_compression (encoder);
1189 case GST_VAAPI_ENCODER_TUNE_LOW_POWER:
1190 /* Set low-power encode entry point. If hardware doesn't have
1191 * support, it will fail in ensure_hw_profile() in later stage.
1192 * So not duplicating the profile/entrypont query mechanism
1193 * here as a part of optimization */
1194 encoder->entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_LP;
1204 /* Handle new GOP starts */
1206 reset_gop_start (GstVaapiEncoderH264 * encoder)
1208 GstVaapiH264ViewReorderPool *const reorder_pool =
1209 &encoder->reorder_pools[encoder->view_idx];
1211 reorder_pool->frame_index = 1;
1212 reorder_pool->cur_frame_num = 0;
1213 reorder_pool->cur_present_index = 0;
1217 /* Marks the supplied picture as a B-frame */
1219 set_b_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1221 GstVaapiH264ViewReorderPool *const reorder_pool =
1222 &encoder->reorder_pools[encoder->view_idx];
1224 g_assert (pic && encoder);
1225 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1226 pic->type = GST_VAAPI_PICTURE_TYPE_B;
1227 pic->frame_num = (reorder_pool->cur_frame_num % encoder->max_frame_num);
1230 /* Marks the supplied picture as a P-frame */
1232 set_p_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1234 GstVaapiH264ViewReorderPool *const reorder_pool =
1235 &encoder->reorder_pools[encoder->view_idx];
1237 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1238 pic->type = GST_VAAPI_PICTURE_TYPE_P;
1239 pic->frame_num = (reorder_pool->cur_frame_num % encoder->max_frame_num);
1242 /* Marks the supplied picture as an I-frame */
1244 set_i_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1246 GstVaapiH264ViewReorderPool *const reorder_pool =
1247 &encoder->reorder_pools[encoder->view_idx];
1249 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1250 pic->type = GST_VAAPI_PICTURE_TYPE_I;
1251 pic->frame_num = (reorder_pool->cur_frame_num % encoder->max_frame_num);
1253 g_assert (pic->frame);
1254 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1257 /* Marks the supplied picture as an IDR frame */
1259 set_idr_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1261 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1262 pic->type = GST_VAAPI_PICTURE_TYPE_I;
1265 GST_VAAPI_ENC_PICTURE_FLAG_SET (pic, GST_VAAPI_ENC_PICTURE_FLAG_IDR);
1267 g_assert (pic->frame);
1268 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1271 /* Marks the supplied picture a a key-frame */
1273 set_key_frame (GstVaapiEncPicture * picture,
1274 GstVaapiEncoderH264 * encoder, gboolean is_idr)
1277 reset_gop_start (encoder);
1278 set_idr_frame (picture, encoder);
1280 set_i_frame (picture, encoder);
1283 /* Fills in VA HRD parameters */
1285 fill_hrd_params (GstVaapiEncoderH264 * encoder, VAEncMiscParameterHRD * hrd)
1287 if (encoder->bitrate_bits > 0) {
1288 hrd->buffer_size = encoder->cpb_length_bits;
1289 hrd->initial_buffer_fullness = hrd->buffer_size / 2;
1291 hrd->buffer_size = 0;
1292 hrd->initial_buffer_fullness = 0;
1296 /* Adds the supplied sequence header (SPS) to the list of packed
1297 headers to pass down as-is to the encoder */
1299 add_packed_sequence_header (GstVaapiEncoderH264 * encoder,
1300 GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1302 GstVaapiEncPackedHeader *packed_seq;
1304 VAEncPackedHeaderParameterBuffer packed_seq_param = { 0 };
1305 const VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1306 GstVaapiProfile profile = encoder->profile;
1308 VAEncMiscParameterHRD hrd_params;
1309 guint32 data_bit_size;
1312 fill_hrd_params (encoder, &hrd_params);
1314 gst_bit_writer_init (&bs, 128 * 8);
1315 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1316 bs_write_nal_header (&bs, GST_H264_NAL_REF_IDC_HIGH, GST_H264_NAL_SPS);
1318 /* Set High profile for encoding the MVC base view. Otherwise, some
1319 traditional decoder cannot recognize MVC profile streams with
1320 only the base view in there */
1321 if (profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH ||
1322 profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH)
1323 profile = GST_VAAPI_PROFILE_H264_HIGH;
1325 bs_write_sps (&bs, seq_param, profile, &hrd_params);
1327 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1328 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1329 data = GST_BIT_WRITER_DATA (&bs);
1331 packed_seq_param.type = VAEncPackedHeaderSequence;
1332 packed_seq_param.bit_length = data_bit_size;
1333 packed_seq_param.has_emulation_bytes = 0;
1335 packed_seq = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1336 &packed_seq_param, sizeof (packed_seq_param),
1337 data, (data_bit_size + 7) / 8);
1338 g_assert (packed_seq);
1340 gst_vaapi_enc_picture_add_packed_header (picture, packed_seq);
1341 gst_vaapi_codec_object_replace (&packed_seq, NULL);
1343 /* store sps data */
1344 _check_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1345 gst_bit_writer_clear (&bs, TRUE);
1351 GST_WARNING ("failed to write SPS NAL unit");
1352 gst_bit_writer_clear (&bs, TRUE);
1358 add_packed_sequence_header_mvc (GstVaapiEncoderH264 * encoder,
1359 GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1361 GstVaapiEncPackedHeader *packed_seq;
1363 VAEncPackedHeaderParameterBuffer packed_header_param_buffer = { 0 };
1364 const VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1365 VAEncMiscParameterHRD hrd_params;
1366 guint32 data_bit_size;
1369 fill_hrd_params (encoder, &hrd_params);
1371 /* non-base layer, pack one subset sps */
1372 gst_bit_writer_init (&bs, 128 * 8);
1373 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1374 bs_write_nal_header (&bs, GST_H264_NAL_REF_IDC_HIGH, GST_H264_NAL_SUBSET_SPS);
1376 bs_write_subset_sps (&bs, seq_param, encoder->profile, encoder->num_views,
1377 encoder->view_ids, &hrd_params);
1379 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1380 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1381 data = GST_BIT_WRITER_DATA (&bs);
1383 packed_header_param_buffer.type = VAEncPackedHeaderSequence;
1384 packed_header_param_buffer.bit_length = data_bit_size;
1385 packed_header_param_buffer.has_emulation_bytes = 0;
1387 packed_seq = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1388 &packed_header_param_buffer, sizeof (packed_header_param_buffer),
1389 data, (data_bit_size + 7) / 8);
1390 g_assert (packed_seq);
1392 gst_vaapi_enc_picture_add_packed_header (picture, packed_seq);
1393 gst_vaapi_mini_object_replace ((GstVaapiMiniObject **) & packed_seq, NULL);
1395 /* store subset sps data */
1396 _check_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1397 gst_bit_writer_clear (&bs, TRUE);
1403 GST_WARNING ("failed to write SPS NAL unit");
1404 gst_bit_writer_clear (&bs, TRUE);
1409 /* Adds the supplied picture header (PPS) to the list of packed
1410 headers to pass down as-is to the encoder */
1412 add_packed_picture_header (GstVaapiEncoderH264 * encoder,
1413 GstVaapiEncPicture * picture)
1415 GstVaapiEncPackedHeader *packed_pic;
1417 VAEncPackedHeaderParameterBuffer packed_pic_param = { 0 };
1418 const VAEncPictureParameterBufferH264 *const pic_param = picture->param;
1419 guint32 data_bit_size;
1422 gst_bit_writer_init (&bs, 128 * 8);
1423 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1424 bs_write_nal_header (&bs, GST_H264_NAL_REF_IDC_HIGH, GST_H264_NAL_PPS);
1425 bs_write_pps (&bs, pic_param, encoder->profile);
1426 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1427 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1428 data = GST_BIT_WRITER_DATA (&bs);
1430 packed_pic_param.type = VAEncPackedHeaderPicture;
1431 packed_pic_param.bit_length = data_bit_size;
1432 packed_pic_param.has_emulation_bytes = 0;
1434 packed_pic = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1435 &packed_pic_param, sizeof (packed_pic_param),
1436 data, (data_bit_size + 7) / 8);
1437 g_assert (packed_pic);
1439 gst_vaapi_enc_picture_add_packed_header (picture, packed_pic);
1440 gst_vaapi_codec_object_replace (&packed_pic, NULL);
1442 /* store pps data */
1443 _check_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1444 gst_bit_writer_clear (&bs, TRUE);
1450 GST_WARNING ("failed to write PPS NAL unit");
1451 gst_bit_writer_clear (&bs, TRUE);
1457 add_packed_sei_header (GstVaapiEncoderH264 * encoder,
1458 GstVaapiEncPicture * picture, GstVaapiH264SeiPayloadType payloadtype)
1460 GstVaapiEncPackedHeader *packed_sei;
1461 GstBitWriter bs, bs_buf_period, bs_pic_timing;
1462 VAEncPackedHeaderParameterBuffer packed_sei_param = { 0 };
1463 guint32 data_bit_size;
1464 guint8 buf_period_payload_size = 0, pic_timing_payload_size = 0;
1465 guint8 *data, *buf_period_payload = NULL, *pic_timing_payload = NULL;
1466 gboolean need_buf_period, need_pic_timing;
1468 gst_bit_writer_init (&bs_buf_period, 128 * 8);
1469 gst_bit_writer_init (&bs_pic_timing, 128 * 8);
1470 gst_bit_writer_init (&bs, 128 * 8);
1472 need_buf_period = GST_VAAPI_H264_SEI_BUF_PERIOD & payloadtype;
1473 need_pic_timing = GST_VAAPI_H264_SEI_PIC_TIMING & payloadtype;
1475 if (need_buf_period) {
1476 /* Write a Buffering Period SEI message */
1477 bs_write_sei_buf_period (&bs_buf_period, encoder, picture);
1478 /* Write byte alignment bits */
1479 if (GST_BIT_WRITER_BIT_SIZE (&bs_buf_period) % 8 != 0)
1480 bs_write_trailing_bits (&bs_buf_period);
1481 buf_period_payload_size = (GST_BIT_WRITER_BIT_SIZE (&bs_buf_period)) / 8;
1482 buf_period_payload = GST_BIT_WRITER_DATA (&bs_buf_period);
1485 if (need_pic_timing) {
1486 /* Write a Picture Timing SEI message */
1487 if (GST_VAAPI_H264_SEI_PIC_TIMING & payloadtype)
1488 bs_write_sei_pic_timing (&bs_pic_timing, encoder, picture);
1489 /* Write byte alignment bits */
1490 if (GST_BIT_WRITER_BIT_SIZE (&bs_pic_timing) % 8 != 0)
1491 bs_write_trailing_bits (&bs_pic_timing);
1492 pic_timing_payload_size = (GST_BIT_WRITER_BIT_SIZE (&bs_pic_timing)) / 8;
1493 pic_timing_payload = GST_BIT_WRITER_DATA (&bs_pic_timing);
1496 /* Write the SEI message */
1497 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1498 bs_write_nal_header (&bs, GST_H264_NAL_REF_IDC_NONE, GST_H264_NAL_SEI);
1500 if (need_buf_period) {
1501 WRITE_UINT32 (&bs, GST_H264_SEI_BUF_PERIOD, 8);
1502 WRITE_UINT32 (&bs, buf_period_payload_size, 8);
1503 /* Add buffering period sei message */
1504 gst_bit_writer_put_bytes (&bs, buf_period_payload, buf_period_payload_size);
1507 if (need_pic_timing) {
1508 WRITE_UINT32 (&bs, GST_H264_SEI_PIC_TIMING, 8);
1509 WRITE_UINT32 (&bs, pic_timing_payload_size, 8);
1510 /* Add picture timing sei message */
1511 gst_bit_writer_put_bytes (&bs, pic_timing_payload, pic_timing_payload_size);
1514 /* rbsp_trailing_bits */
1515 bs_write_trailing_bits (&bs);
1517 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1518 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1519 data = GST_BIT_WRITER_DATA (&bs);
1521 packed_sei_param.type = VAEncPackedHeaderH264_SEI;
1522 packed_sei_param.bit_length = data_bit_size;
1523 packed_sei_param.has_emulation_bytes = 0;
1525 packed_sei = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1526 &packed_sei_param, sizeof (packed_sei_param),
1527 data, (data_bit_size + 7) / 8);
1528 g_assert (packed_sei);
1530 gst_vaapi_enc_picture_add_packed_header (picture, packed_sei);
1531 gst_vaapi_codec_object_replace (&packed_sei, NULL);
1533 gst_bit_writer_clear (&bs_buf_period, TRUE);
1534 gst_bit_writer_clear (&bs_pic_timing, TRUE);
1535 gst_bit_writer_clear (&bs, TRUE);
1541 GST_WARNING ("failed to write SEI NAL unit");
1542 gst_bit_writer_clear (&bs_buf_period, TRUE);
1543 gst_bit_writer_clear (&bs_pic_timing, TRUE);
1544 gst_bit_writer_clear (&bs, TRUE);
1550 get_nal_hdr_attributes (GstVaapiEncPicture * picture,
1551 guint8 * nal_ref_idc, guint8 * nal_unit_type)
1553 switch (picture->type) {
1554 case GST_VAAPI_PICTURE_TYPE_I:
1555 *nal_ref_idc = GST_H264_NAL_REF_IDC_HIGH;
1556 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
1557 *nal_unit_type = GST_H264_NAL_SLICE_IDR;
1559 *nal_unit_type = GST_H264_NAL_SLICE;
1561 case GST_VAAPI_PICTURE_TYPE_P:
1562 *nal_ref_idc = GST_H264_NAL_REF_IDC_MEDIUM;
1563 *nal_unit_type = GST_H264_NAL_SLICE;
1565 case GST_VAAPI_PICTURE_TYPE_B:
1566 *nal_ref_idc = GST_H264_NAL_REF_IDC_NONE;
1567 *nal_unit_type = GST_H264_NAL_SLICE;
1575 /* Adds the supplied prefix nal header to the list of packed
1576 headers to pass down as-is to the encoder */
1578 add_packed_prefix_nal_header (GstVaapiEncoderH264 * encoder,
1579 GstVaapiEncPicture * picture, GstVaapiEncSlice * slice)
1581 GstVaapiEncPackedHeader *packed_prefix_nal;
1583 VAEncPackedHeaderParameterBuffer packed_prefix_nal_param = { 0 };
1584 guint32 data_bit_size;
1586 guint8 nal_ref_idc, nal_unit_type;
1588 gst_bit_writer_init (&bs, 128 * 8);
1589 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1591 if (!get_nal_hdr_attributes (picture, &nal_ref_idc, &nal_unit_type))
1593 nal_unit_type = GST_H264_NAL_PREFIX_UNIT;
1595 bs_write_nal_header (&bs, nal_ref_idc, nal_unit_type);
1596 bs_write_nal_header_mvc_extension (&bs, picture, encoder->view_idx);
1597 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1598 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1599 data = GST_BIT_WRITER_DATA (&bs);
1601 packed_prefix_nal_param.type = VAEncPackedHeaderRawData;
1602 packed_prefix_nal_param.bit_length = data_bit_size;
1603 packed_prefix_nal_param.has_emulation_bytes = 0;
1606 gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1607 &packed_prefix_nal_param, sizeof (packed_prefix_nal_param), data,
1608 (data_bit_size + 7) / 8);
1609 g_assert (packed_prefix_nal);
1611 gst_vaapi_enc_slice_add_packed_header (slice, packed_prefix_nal);
1612 gst_vaapi_codec_object_replace (&packed_prefix_nal, NULL);
1614 gst_bit_writer_clear (&bs, TRUE);
1621 GST_WARNING ("failed to write Prefix NAL unit header");
1622 gst_bit_writer_clear (&bs, TRUE);
1627 /* Adds the supplied slice header to the list of packed
1628 headers to pass down as-is to the encoder */
1630 add_packed_slice_header (GstVaapiEncoderH264 * encoder,
1631 GstVaapiEncPicture * picture, GstVaapiEncSlice * slice)
1633 GstVaapiEncPackedHeader *packed_slice;
1635 VAEncPackedHeaderParameterBuffer packed_slice_param = { 0 };
1636 const VAEncSliceParameterBufferH264 *const slice_param = slice->param;
1637 guint32 data_bit_size;
1639 guint8 nal_ref_idc, nal_unit_type;
1641 gst_bit_writer_init (&bs, 128 * 8);
1642 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1644 if (!get_nal_hdr_attributes (picture, &nal_ref_idc, &nal_unit_type))
1646 /* pack nal_unit_header_mvc_extension() for the non base view */
1647 if (encoder->is_mvc && encoder->view_idx) {
1648 bs_write_nal_header (&bs, nal_ref_idc, GST_H264_NAL_SLICE_EXT);
1649 bs_write_nal_header_mvc_extension (&bs, picture,
1650 encoder->view_ids[encoder->view_idx]);
1652 bs_write_nal_header (&bs, nal_ref_idc, nal_unit_type);
1654 bs_write_slice (&bs, slice_param, encoder, picture);
1655 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1656 data = GST_BIT_WRITER_DATA (&bs);
1658 packed_slice_param.type = VAEncPackedHeaderSlice;
1659 packed_slice_param.bit_length = data_bit_size;
1660 packed_slice_param.has_emulation_bytes = 0;
1662 packed_slice = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1663 &packed_slice_param, sizeof (packed_slice_param),
1664 data, (data_bit_size + 7) / 8);
1665 g_assert (packed_slice);
1667 gst_vaapi_enc_slice_add_packed_header (slice, packed_slice);
1668 gst_vaapi_codec_object_replace (&packed_slice, NULL);
1670 gst_bit_writer_clear (&bs, TRUE);
1676 GST_WARNING ("failed to write Slice NAL unit header");
1677 gst_bit_writer_clear (&bs, TRUE);
1682 /* Reference picture management */
1684 reference_pic_free (GstVaapiEncoderH264 * encoder, GstVaapiEncoderH264Ref * ref)
1689 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), ref->pic);
1690 g_slice_free (GstVaapiEncoderH264Ref, ref);
1693 static inline GstVaapiEncoderH264Ref *
1694 reference_pic_create (GstVaapiEncoderH264 * encoder,
1695 GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1697 GstVaapiEncoderH264Ref *const ref = g_slice_new0 (GstVaapiEncoderH264Ref);
1700 ref->frame_num = picture->frame_num;
1701 ref->poc = picture->poc;
1706 reference_list_update (GstVaapiEncoderH264 * encoder,
1707 GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1709 GstVaapiEncoderH264Ref *ref;
1710 GstVaapiH264ViewRefPool *const ref_pool =
1711 &encoder->ref_pools[encoder->view_idx];
1713 if (GST_VAAPI_PICTURE_TYPE_B == picture->type) {
1714 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), surface);
1717 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture)) {
1718 while (!g_queue_is_empty (&ref_pool->ref_list))
1719 reference_pic_free (encoder, g_queue_pop_head (&ref_pool->ref_list));
1720 } else if (g_queue_get_length (&ref_pool->ref_list) >=
1721 ref_pool->max_ref_frames) {
1722 reference_pic_free (encoder, g_queue_pop_head (&ref_pool->ref_list));
1724 ref = reference_pic_create (encoder, picture, surface);
1725 g_queue_push_tail (&ref_pool->ref_list, ref);
1726 g_assert (g_queue_get_length (&ref_pool->ref_list) <=
1727 ref_pool->max_ref_frames);
1732 reference_list_init (GstVaapiEncoderH264 * encoder,
1733 GstVaapiEncPicture * picture,
1734 GstVaapiEncoderH264Ref ** reflist_0,
1735 guint * reflist_0_count,
1736 GstVaapiEncoderH264Ref ** reflist_1, guint * reflist_1_count)
1738 GstVaapiEncoderH264Ref *tmp;
1739 GstVaapiH264ViewRefPool *const ref_pool =
1740 &encoder->ref_pools[encoder->view_idx];
1741 GList *iter, *list_0_start = NULL, *list_1_start = NULL;
1744 *reflist_0_count = 0;
1745 *reflist_1_count = 0;
1746 if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
1749 iter = g_queue_peek_tail_link (&ref_pool->ref_list);
1750 for (; iter; iter = g_list_previous (iter)) {
1751 tmp = (GstVaapiEncoderH264Ref *) iter->data;
1752 g_assert (tmp && tmp->poc != picture->poc);
1753 if (_poc_greater_than (picture->poc, tmp->poc, encoder->max_pic_order_cnt)) {
1754 list_0_start = iter;
1755 list_1_start = g_list_next (iter);
1760 /* order reflist_0 */
1761 g_assert (list_0_start);
1762 iter = list_0_start;
1764 for (; iter; iter = g_list_previous (iter)) {
1765 reflist_0[count] = (GstVaapiEncoderH264Ref *) iter->data;
1768 *reflist_0_count = count;
1770 if (picture->type != GST_VAAPI_PICTURE_TYPE_B)
1773 /* order reflist_1 */
1775 iter = list_1_start;
1776 for (; iter; iter = g_list_next (iter)) {
1777 reflist_1[count] = (GstVaapiEncoderH264Ref *) iter->data;
1780 *reflist_1_count = count;
1784 /* Fills in VA sequence parameter buffer */
1786 fill_sequence (GstVaapiEncoderH264 * encoder, GstVaapiEncSequence * sequence)
1788 VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1789 GstVaapiH264ViewRefPool *const ref_pool =
1790 &encoder->ref_pools[encoder->view_idx];
1792 memset (seq_param, 0, sizeof (VAEncSequenceParameterBufferH264));
1793 seq_param->seq_parameter_set_id = encoder->view_idx;
1794 seq_param->level_idc = encoder->level_idc;
1795 seq_param->intra_period = GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder);
1796 seq_param->intra_idr_period = GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder);
1797 seq_param->ip_period = 1 + encoder->num_bframes;
1798 seq_param->ip_period = seq_param->intra_period > 1 ?
1799 (1 + encoder->num_bframes) : 0;
1800 seq_param->bits_per_second = encoder->bitrate_bits;
1802 seq_param->max_num_ref_frames = ref_pool->max_ref_frames;
1803 seq_param->picture_width_in_mbs = encoder->mb_width;
1804 seq_param->picture_height_in_mbs = encoder->mb_height;
1806 /*sequence field values */
1807 seq_param->seq_fields.value = 0;
1808 seq_param->seq_fields.bits.chroma_format_idc = 1;
1809 seq_param->seq_fields.bits.frame_mbs_only_flag = 1;
1810 seq_param->seq_fields.bits.mb_adaptive_frame_field_flag = FALSE;
1811 seq_param->seq_fields.bits.seq_scaling_matrix_present_flag = FALSE;
1812 /* direct_8x8_inference_flag default false */
1813 seq_param->seq_fields.bits.direct_8x8_inference_flag = FALSE;
1814 g_assert (encoder->log2_max_frame_num >= 4);
1815 seq_param->seq_fields.bits.log2_max_frame_num_minus4 =
1816 encoder->log2_max_frame_num - 4;
1817 /* picture order count */
1818 encoder->pic_order_cnt_type = seq_param->seq_fields.bits.pic_order_cnt_type =
1820 g_assert (encoder->log2_max_pic_order_cnt >= 4);
1821 seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 =
1822 encoder->log2_max_pic_order_cnt - 4;
1824 seq_param->bit_depth_luma_minus8 = 0;
1825 seq_param->bit_depth_chroma_minus8 = 0;
1827 /* not used if pic_order_cnt_type == 0 */
1828 if (seq_param->seq_fields.bits.pic_order_cnt_type == 1) {
1829 encoder->delta_pic_order_always_zero_flag =
1830 seq_param->seq_fields.bits.delta_pic_order_always_zero_flag = TRUE;
1831 seq_param->num_ref_frames_in_pic_order_cnt_cycle = 0;
1832 seq_param->offset_for_non_ref_pic = 0;
1833 seq_param->offset_for_top_to_bottom_field = 0;
1834 memset (seq_param->offset_for_ref_frame, 0,
1835 sizeof (seq_param->offset_for_ref_frame));
1838 /* frame_cropping_flag */
1839 if ((GST_VAAPI_ENCODER_WIDTH (encoder) & 15) ||
1840 (GST_VAAPI_ENCODER_HEIGHT (encoder) & 15)) {
1841 static const guint SubWidthC[] = { 1, 2, 2, 1 };
1842 static const guint SubHeightC[] = { 1, 2, 1, 1 };
1843 const guint CropUnitX =
1844 SubWidthC[seq_param->seq_fields.bits.chroma_format_idc];
1845 const guint CropUnitY =
1846 SubHeightC[seq_param->seq_fields.bits.chroma_format_idc] *
1847 (2 - seq_param->seq_fields.bits.frame_mbs_only_flag);
1849 seq_param->frame_cropping_flag = 1;
1850 seq_param->frame_crop_left_offset = 0;
1851 seq_param->frame_crop_right_offset =
1852 (16 * encoder->mb_width -
1853 GST_VAAPI_ENCODER_WIDTH (encoder)) / CropUnitX;
1854 seq_param->frame_crop_top_offset = 0;
1855 seq_param->frame_crop_bottom_offset =
1856 (16 * encoder->mb_height -
1857 GST_VAAPI_ENCODER_HEIGHT (encoder)) / CropUnitY;
1860 /* VUI parameters are always set, at least for timing_info (framerate) */
1861 seq_param->vui_parameters_present_flag = TRUE;
1862 if (seq_param->vui_parameters_present_flag) {
1863 seq_param->vui_fields.bits.aspect_ratio_info_present_flag = TRUE;
1864 if (seq_param->vui_fields.bits.aspect_ratio_info_present_flag) {
1865 const GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
1866 seq_param->aspect_ratio_idc = 0xff;
1867 seq_param->sar_width = GST_VIDEO_INFO_PAR_N (vip);
1868 seq_param->sar_height = GST_VIDEO_INFO_PAR_D (vip);
1870 seq_param->vui_fields.bits.bitstream_restriction_flag = FALSE;
1871 /* if vui_parameters_present_flag is TRUE and sps data belongs to
1872 * subset sps, timing_info_preset_flag should be zero (H.7.4.2.1.1) */
1873 seq_param->vui_fields.bits.timing_info_present_flag = !encoder->view_idx;
1874 if (seq_param->vui_fields.bits.timing_info_present_flag) {
1875 seq_param->num_units_in_tick = GST_VAAPI_ENCODER_FPS_D (encoder);
1876 seq_param->time_scale = GST_VAAPI_ENCODER_FPS_N (encoder) * 2;
1882 /* Fills in VA picture parameter buffer */
1884 fill_picture (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture,
1885 GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface)
1887 VAEncPictureParameterBufferH264 *const pic_param = picture->param;
1888 GstVaapiH264ViewRefPool *const ref_pool =
1889 &encoder->ref_pools[encoder->view_idx];
1890 GstVaapiEncoderH264Ref *ref_pic;
1894 memset (pic_param, 0, sizeof (VAEncPictureParameterBufferH264));
1896 /* reference list, */
1897 pic_param->CurrPic.picture_id = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface);
1898 pic_param->CurrPic.TopFieldOrderCnt = picture->poc;
1900 if (picture->type != GST_VAAPI_PICTURE_TYPE_I) {
1901 for (reflist = g_queue_peek_head_link (&ref_pool->ref_list);
1902 reflist; reflist = g_list_next (reflist)) {
1903 ref_pic = reflist->data;
1904 g_assert (ref_pic && ref_pic->pic &&
1905 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (ref_pic->pic) != VA_INVALID_ID);
1907 pic_param->ReferenceFrames[i].picture_id =
1908 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (ref_pic->pic);
1909 pic_param->ReferenceFrames[i].TopFieldOrderCnt = ref_pic->poc;
1910 pic_param->ReferenceFrames[i].flags |=
1911 VA_PICTURE_H264_SHORT_TERM_REFERENCE;
1912 pic_param->ReferenceFrames[i].frame_idx = ref_pic->frame_num;
1915 g_assert (i <= 16 && i <= ref_pool->max_ref_frames);
1917 for (; i < 16; ++i) {
1918 pic_param->ReferenceFrames[i].picture_id = VA_INVALID_ID;
1920 pic_param->coded_buf = GST_VAAPI_OBJECT_ID (codedbuf);
1922 pic_param->pic_parameter_set_id = encoder->view_idx;
1923 pic_param->seq_parameter_set_id = encoder->view_idx ? 1 : 0;
1924 pic_param->last_picture = 0; /* means last encoding picture */
1925 pic_param->frame_num = picture->frame_num;
1926 pic_param->pic_init_qp = encoder->init_qp;
1927 pic_param->num_ref_idx_l0_active_minus1 =
1928 (ref_pool->max_reflist0_count ? (ref_pool->max_reflist0_count - 1) : 0);
1929 pic_param->num_ref_idx_l1_active_minus1 =
1930 (ref_pool->max_reflist1_count ? (ref_pool->max_reflist1_count - 1) : 0);
1931 pic_param->chroma_qp_index_offset = 0;
1932 pic_param->second_chroma_qp_index_offset = 0;
1934 /* set picture fields */
1935 pic_param->pic_fields.value = 0;
1936 pic_param->pic_fields.bits.idr_pic_flag =
1937 GST_VAAPI_ENC_PICTURE_IS_IDR (picture);
1938 pic_param->pic_fields.bits.reference_pic_flag =
1939 (picture->type != GST_VAAPI_PICTURE_TYPE_B);
1940 pic_param->pic_fields.bits.entropy_coding_mode_flag = encoder->use_cabac;
1941 pic_param->pic_fields.bits.weighted_pred_flag = FALSE;
1942 pic_param->pic_fields.bits.weighted_bipred_idc = 0;
1943 pic_param->pic_fields.bits.constrained_intra_pred_flag = 0;
1944 pic_param->pic_fields.bits.transform_8x8_mode_flag = encoder->use_dct8x8;
1945 /* enable debloking */
1946 pic_param->pic_fields.bits.deblocking_filter_control_present_flag = TRUE;
1947 pic_param->pic_fields.bits.redundant_pic_cnt_present_flag = FALSE;
1948 /* bottom_field_pic_order_in_frame_present_flag */
1949 pic_param->pic_fields.bits.pic_order_present_flag = FALSE;
1950 pic_param->pic_fields.bits.pic_scaling_matrix_present_flag = FALSE;
1955 /* Adds slice headers to picture */
1957 add_slice_headers (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture,
1958 GstVaapiEncoderH264Ref ** reflist_0, guint reflist_0_count,
1959 GstVaapiEncoderH264Ref ** reflist_1, guint reflist_1_count)
1961 VAEncSliceParameterBufferH264 *slice_param;
1962 GstVaapiEncSlice *slice;
1963 guint slice_of_mbs, slice_mod_mbs, cur_slice_mbs;
1965 guint last_mb_index;
1966 guint i_slice, i_ref;
1970 mb_size = encoder->mb_width * encoder->mb_height;
1972 g_assert (encoder->num_slices && encoder->num_slices < mb_size);
1973 slice_of_mbs = mb_size / encoder->num_slices;
1974 slice_mod_mbs = mb_size % encoder->num_slices;
1976 for (i_slice = 0; i_slice < encoder->num_slices; ++i_slice) {
1977 cur_slice_mbs = slice_of_mbs;
1978 if (slice_mod_mbs) {
1982 slice = GST_VAAPI_ENC_SLICE_NEW (H264, encoder);
1983 g_assert (slice && slice->param_id != VA_INVALID_ID);
1984 slice_param = slice->param;
1986 memset (slice_param, 0, sizeof (VAEncSliceParameterBufferH264));
1987 slice_param->macroblock_address = last_mb_index;
1988 slice_param->num_macroblocks = cur_slice_mbs;
1989 slice_param->macroblock_info = VA_INVALID_ID;
1990 slice_param->slice_type = h264_get_slice_type (picture->type);
1991 g_assert ((gint8) slice_param->slice_type != -1);
1992 slice_param->pic_parameter_set_id = encoder->view_idx;
1993 slice_param->idr_pic_id = encoder->idr_num;
1994 slice_param->pic_order_cnt_lsb = picture->poc;
1996 /* not used if pic_order_cnt_type = 0 */
1997 slice_param->delta_pic_order_cnt_bottom = 0;
1998 memset (slice_param->delta_pic_order_cnt, 0,
1999 sizeof (slice_param->delta_pic_order_cnt));
2001 /* only works for B frames */
2002 slice_param->direct_spatial_mv_pred_flag = FALSE;
2003 /* default equal to picture parameters */
2004 slice_param->num_ref_idx_active_override_flag = FALSE;
2005 if (picture->type != GST_VAAPI_PICTURE_TYPE_I && reflist_0_count > 0)
2006 slice_param->num_ref_idx_l0_active_minus1 = reflist_0_count - 1;
2008 slice_param->num_ref_idx_l0_active_minus1 = 0;
2009 if (picture->type == GST_VAAPI_PICTURE_TYPE_B && reflist_1_count > 0)
2010 slice_param->num_ref_idx_l1_active_minus1 = reflist_1_count - 1;
2012 slice_param->num_ref_idx_l1_active_minus1 = 0;
2013 g_assert (slice_param->num_ref_idx_l0_active_minus1 == 0);
2014 g_assert (slice_param->num_ref_idx_l1_active_minus1 == 0);
2017 if (picture->type != GST_VAAPI_PICTURE_TYPE_I) {
2018 for (; i_ref < reflist_0_count; ++i_ref) {
2019 slice_param->RefPicList0[i_ref].picture_id =
2020 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (reflist_0[i_ref]->pic);
2021 slice_param->RefPicList0[i_ref].TopFieldOrderCnt =
2022 reflist_0[i_ref]->poc;
2023 slice_param->RefPicList0[i_ref].flags |=
2024 VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2025 slice_param->RefPicList0[i_ref].frame_idx = reflist_0[i_ref]->frame_num;
2027 g_assert (i_ref == 1);
2029 for (; i_ref < G_N_ELEMENTS (slice_param->RefPicList0); ++i_ref) {
2030 slice_param->RefPicList0[i_ref].picture_id = VA_INVALID_SURFACE;
2034 if (picture->type == GST_VAAPI_PICTURE_TYPE_B) {
2035 for (; i_ref < reflist_1_count; ++i_ref) {
2036 slice_param->RefPicList1[i_ref].picture_id =
2037 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (reflist_1[i_ref]->pic);
2038 slice_param->RefPicList1[i_ref].TopFieldOrderCnt =
2039 reflist_1[i_ref]->poc;
2040 slice_param->RefPicList1[i_ref].flags |=
2041 VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2042 slice_param->RefPicList1[i_ref].frame_idx |=
2043 reflist_1[i_ref]->frame_num;
2045 g_assert (i_ref == 1);
2047 for (; i_ref < G_N_ELEMENTS (slice_param->RefPicList1); ++i_ref) {
2048 slice_param->RefPicList1[i_ref].picture_id = VA_INVALID_SURFACE;
2051 /* not used if pic_param.pic_fields.bits.weighted_pred_flag == FALSE */
2052 slice_param->luma_log2_weight_denom = 0;
2053 slice_param->chroma_log2_weight_denom = 0;
2054 slice_param->luma_weight_l0_flag = FALSE;
2055 memset (slice_param->luma_weight_l0, 0,
2056 sizeof (slice_param->luma_weight_l0));
2057 memset (slice_param->luma_offset_l0, 0,
2058 sizeof (slice_param->luma_offset_l0));
2059 slice_param->chroma_weight_l0_flag = FALSE;
2060 memset (slice_param->chroma_weight_l0, 0,
2061 sizeof (slice_param->chroma_weight_l0));
2062 memset (slice_param->chroma_offset_l0, 0,
2063 sizeof (slice_param->chroma_offset_l0));
2064 slice_param->luma_weight_l1_flag = FALSE;
2065 memset (slice_param->luma_weight_l1, 0,
2066 sizeof (slice_param->luma_weight_l1));
2067 memset (slice_param->luma_offset_l1, 0,
2068 sizeof (slice_param->luma_offset_l1));
2069 slice_param->chroma_weight_l1_flag = FALSE;
2070 memset (slice_param->chroma_weight_l1, 0,
2071 sizeof (slice_param->chroma_weight_l1));
2072 memset (slice_param->chroma_offset_l1, 0,
2073 sizeof (slice_param->chroma_offset_l1));
2075 slice_param->cabac_init_idc = 0;
2076 slice_param->slice_qp_delta = encoder->init_qp - encoder->min_qp;
2077 if (slice_param->slice_qp_delta > 4)
2078 slice_param->slice_qp_delta = 4;
2079 slice_param->disable_deblocking_filter_idc = 0;
2080 slice_param->slice_alpha_c0_offset_div2 = 2;
2081 slice_param->slice_beta_offset_div2 = 2;
2083 /* set calculation for next slice */
2084 last_mb_index += cur_slice_mbs;
2086 /* add packed Prefix NAL unit before each Coded slice NAL in base view */
2087 if (encoder->is_mvc && !encoder->view_idx &&
2088 (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2089 VA_ENC_PACKED_HEADER_RAW_DATA)
2090 && !add_packed_prefix_nal_header (encoder, picture, slice))
2091 goto error_create_packed_prefix_nal_hdr;
2092 if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2093 VA_ENC_PACKED_HEADER_SLICE)
2094 && !add_packed_slice_header (encoder, picture, slice))
2095 goto error_create_packed_slice_hdr;
2097 gst_vaapi_enc_picture_add_slice (picture, slice);
2098 gst_vaapi_codec_object_replace (&slice, NULL);
2100 g_assert (last_mb_index == mb_size);
2103 error_create_packed_slice_hdr:
2105 GST_ERROR ("failed to create packed slice header buffer");
2106 gst_vaapi_codec_object_replace (&slice, NULL);
2109 error_create_packed_prefix_nal_hdr:
2111 GST_ERROR ("failed to create packed prefix nal header buffer");
2112 gst_vaapi_codec_object_replace (&slice, NULL);
2117 /* Generates and submits SPS header accordingly into the bitstream */
2119 ensure_sequence (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
2121 GstVaapiEncSequence *sequence = NULL;
2123 /* submit an SPS header before every new I-frame, if codec config changed */
2124 if (!encoder->config_changed || picture->type != GST_VAAPI_PICTURE_TYPE_I)
2127 sequence = GST_VAAPI_ENC_SEQUENCE_NEW (H264, encoder);
2128 if (!sequence || !fill_sequence (encoder, sequence))
2129 goto error_create_seq_param;
2131 /* add subset sps for non-base view and sps for base view */
2132 if (encoder->is_mvc && encoder->view_idx) {
2133 if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2134 VA_ENC_PACKED_HEADER_SEQUENCE)
2135 && !add_packed_sequence_header_mvc (encoder, picture, sequence))
2136 goto error_create_packed_seq_hdr;
2138 if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2139 VA_ENC_PACKED_HEADER_SEQUENCE)
2140 && !add_packed_sequence_header (encoder, picture, sequence))
2141 goto error_create_packed_seq_hdr;
2145 gst_vaapi_enc_picture_set_sequence (picture, sequence);
2146 gst_vaapi_codec_object_replace (&sequence, NULL);
2149 if (!encoder->is_mvc || encoder->view_idx > 0)
2150 encoder->config_changed = FALSE;
2154 error_create_seq_param:
2156 GST_ERROR ("failed to create sequence parameter buffer (SPS)");
2157 gst_vaapi_codec_object_replace (&sequence, NULL);
2160 error_create_packed_seq_hdr:
2162 GST_ERROR ("failed to create packed sequence header buffer");
2163 gst_vaapi_codec_object_replace (&sequence, NULL);
2169 ensure_control_rate_params (GstVaapiEncoderH264 * encoder)
2171 if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP)
2174 /* RateControl params */
2175 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).bits_per_second =
2176 encoder->bitrate_bits;
2177 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).window_size = encoder->cpb_length;
2178 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).initial_qp = encoder->init_qp;
2179 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).min_qp = encoder->min_qp;
2182 fill_hrd_params (encoder, &GST_VAAPI_ENCODER_VA_HRD (encoder));
2187 /* Generates additional control parameters */
2189 ensure_misc_params (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
2191 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2192 #if VA_CHECK_VERSION(0,39,1)
2193 GstVaapiEncMiscParam *misc;
2197 if (!gst_vaapi_encoder_ensure_param_control_rate (base_encoder, picture))
2200 if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CBR ||
2201 GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_VBR) {
2202 if (!encoder->view_idx) {
2203 if ((GST_VAAPI_ENC_PICTURE_IS_IDR (picture)) &&
2204 (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2205 VA_ENC_PACKED_HEADER_MISC) &&
2206 !add_packed_sei_header (encoder, picture,
2207 GST_VAAPI_H264_SEI_BUF_PERIOD | GST_VAAPI_H264_SEI_PIC_TIMING))
2208 goto error_create_packed_sei_hdr;
2210 else if (!GST_VAAPI_ENC_PICTURE_IS_IDR (picture) &&
2211 (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2212 VA_ENC_PACKED_HEADER_MISC) &&
2213 !add_packed_sei_header (encoder, picture,
2214 GST_VAAPI_H264_SEI_PIC_TIMING))
2215 goto error_create_packed_sei_hdr;
2218 #if VA_CHECK_VERSION(0,39,1)
2219 /* region-of-interest params */
2220 num_roi = base_encoder->roi_regions ?
2221 g_list_length (base_encoder->roi_regions) : 0;
2223 /* ROI(Region of Interest) params */
2224 VAEncMiscParameterBufferROI *roi_param;
2225 VAEncROI *region_roi;
2230 gst_vaapi_enc_misc_param_new (base_encoder, VAEncMiscParameterTypeROI,
2231 sizeof (VAEncMiscParameterBufferROI) + num_roi * sizeof (VAEncROI));
2233 roi_param = misc->data;
2234 roi_param->roi_flags.bits.roi_value_is_qp_delta = 1;
2235 roi_param->max_delta_qp = 10;
2236 roi_param->min_delta_qp = 10;
2238 ptr = (guchar *) misc->param + sizeof (VAEncMiscParameterBuffer) +
2239 sizeof (VAEncMiscParameterBufferROI);
2242 for (tmp = base_encoder->roi_regions; tmp; tmp = tmp->next) {
2243 GstVaapiROI *item = tmp->data;
2244 region_roi->roi_value = item->roi_value;
2245 region_roi->roi_rectangle.x = item->rect.x;
2246 region_roi->roi_rectangle.y = item->rect.y;
2247 region_roi->roi_rectangle.width = item->rect.width;
2248 region_roi->roi_rectangle.height = item->rect.height;
2252 roi_param->roi = ptr;
2253 roi_param->num_roi = num_roi;
2255 gst_vaapi_enc_picture_add_misc_param (picture, misc);
2256 gst_vaapi_codec_object_replace (&misc, NULL);
2260 if (!gst_vaapi_encoder_ensure_param_quality_level (base_encoder, picture))
2265 error_create_packed_sei_hdr:
2267 GST_ERROR ("failed to create packed SEI header");
2272 /* Generates and submits PPS header accordingly into the bitstream */
2274 ensure_picture (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture,
2275 GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface)
2277 GstVaapiCodedBuffer *const codedbuf =
2278 GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy);
2279 gboolean res = FALSE;
2281 res = fill_picture (encoder, picture, codedbuf, surface);
2286 if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
2287 (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2288 VA_ENC_PACKED_HEADER_PICTURE)
2289 && !add_packed_picture_header (encoder, picture)) {
2290 GST_ERROR ("set picture packed header failed");
2296 /* Generates slice headers */
2298 ensure_slices (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
2300 GstVaapiEncoderH264Ref *reflist_0[16];
2301 GstVaapiEncoderH264Ref *reflist_1[16];
2302 GstVaapiH264ViewRefPool *const ref_pool =
2303 &encoder->ref_pools[encoder->view_idx];
2304 guint reflist_0_count = 0, reflist_1_count = 0;
2308 if (picture->type != GST_VAAPI_PICTURE_TYPE_I &&
2309 !reference_list_init (encoder, picture,
2310 reflist_0, &reflist_0_count, reflist_1, &reflist_1_count)) {
2311 GST_ERROR ("reference list reorder failed");
2315 g_assert (reflist_0_count + reflist_1_count <= ref_pool->max_ref_frames);
2316 if (reflist_0_count > ref_pool->max_reflist0_count)
2317 reflist_0_count = ref_pool->max_reflist0_count;
2318 if (reflist_1_count > ref_pool->max_reflist1_count)
2319 reflist_1_count = ref_pool->max_reflist1_count;
2321 if (!add_slice_headers (encoder, picture,
2322 reflist_0, reflist_0_count, reflist_1, reflist_1_count))
2328 /* Normalizes bitrate (and CPB size) for HRD conformance */
2330 ensure_bitrate_hrd (GstVaapiEncoderH264 * encoder)
2332 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2333 guint bitrate, cpb_size;
2335 if (!base_encoder->bitrate) {
2336 encoder->bitrate_bits = 0;
2340 /* Round down bitrate. This is a hard limit mandated by the user */
2341 g_assert (SX_BITRATE >= 6);
2342 bitrate = (base_encoder->bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
2343 if (bitrate != encoder->bitrate_bits) {
2344 GST_DEBUG ("HRD bitrate: %u bits/sec", bitrate);
2345 encoder->bitrate_bits = bitrate;
2346 encoder->config_changed = TRUE;
2349 /* Round up CPB size. This is an HRD compliance detail */
2350 g_assert (SX_CPB_SIZE >= 4);
2351 cpb_size = gst_util_uint64_scale (bitrate, encoder->cpb_length, 1000) &
2352 ~((1U << SX_CPB_SIZE) - 1);
2353 if (cpb_size != encoder->cpb_length_bits) {
2354 GST_DEBUG ("HRD CPB size: %u bits", cpb_size);
2355 encoder->cpb_length_bits = cpb_size;
2356 encoder->config_changed = TRUE;
2360 /* Estimates a good enough bitrate if none was supplied */
2362 ensure_bitrate (GstVaapiEncoderH264 * encoder)
2364 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2366 /* Default compression: 48 bits per macroblock in "high-compression" mode */
2367 switch (GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
2368 case GST_VAAPI_RATECONTROL_CBR:
2369 case GST_VAAPI_RATECONTROL_VBR:
2370 case GST_VAAPI_RATECONTROL_VBR_CONSTRAINED:
2371 if (!base_encoder->bitrate) {
2372 /* According to the literature and testing, CABAC entropy coding
2373 mode could provide for +10% to +18% improvement in general,
2374 thus estimating +15% here ; and using adaptive 8x8 transforms
2375 in I-frames could bring up to +10% improvement. */
2376 guint bits_per_mb = 48;
2379 if (!encoder->use_cabac)
2380 bits_per_mb += (bits_per_mb * 15) / 100;
2381 if (!encoder->use_dct8x8)
2382 bits_per_mb += (bits_per_mb * 10) / 100;
2384 factor = encoder->mb_width * encoder->mb_height * bits_per_mb;
2385 base_encoder->bitrate =
2386 gst_util_uint64_scale (factor, GST_VAAPI_ENCODER_FPS_N (encoder),
2387 GST_VAAPI_ENCODER_FPS_D (encoder)) / 1000;
2388 GST_INFO ("target bitrate computed to %u kbps", base_encoder->bitrate);
2392 base_encoder->bitrate = 0;
2395 ensure_bitrate_hrd (encoder);
2398 /* Constructs profile and level information based on user-defined limits */
2399 static GstVaapiEncoderStatus
2400 ensure_profile_and_level (GstVaapiEncoderH264 * encoder)
2402 const GstVaapiProfile profile = encoder->profile;
2403 const GstVaapiLevelH264 level = encoder->level;
2405 if (!ensure_tuning (encoder))
2406 GST_WARNING ("Failed to set some of the tuning option as expected! ");
2408 if (!ensure_profile (encoder) || !ensure_profile_limits (encoder))
2409 return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2411 /* Check HW constraints */
2412 if (!ensure_hw_profile_limits (encoder))
2413 return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2414 if (encoder->profile_idc > encoder->hw_max_profile_idc)
2415 return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2417 /* Ensure bitrate if not set already and derive the right level to use */
2418 ensure_bitrate (encoder);
2419 if (!ensure_level (encoder))
2420 return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
2422 if (encoder->profile != profile || encoder->level != level) {
2423 GST_DEBUG ("selected %s profile at level %s",
2424 gst_vaapi_utils_h264_get_profile_string (encoder->profile),
2425 gst_vaapi_utils_h264_get_level_string (encoder->level));
2426 encoder->config_changed = TRUE;
2428 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2432 reset_properties (GstVaapiEncoderH264 * encoder)
2434 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2437 if (encoder->idr_period < base_encoder->keyframe_period)
2438 encoder->idr_period = base_encoder->keyframe_period;
2439 if (encoder->idr_period > MAX_IDR_PERIOD)
2440 encoder->idr_period = MAX_IDR_PERIOD;
2442 if (encoder->min_qp > encoder->init_qp ||
2443 (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP &&
2444 encoder->min_qp < encoder->init_qp))
2445 encoder->min_qp = encoder->init_qp;
2447 mb_size = encoder->mb_width * encoder->mb_height;
2448 g_assert (gst_vaapi_encoder_ensure_num_slices (base_encoder, encoder->profile,
2449 encoder->entrypoint, (mb_size + 1) / 2, &encoder->num_slices));
2451 if (encoder->num_bframes > (base_encoder->keyframe_period + 1) / 2)
2452 encoder->num_bframes = (base_encoder->keyframe_period + 1) / 2;
2454 /* Workaround : vaapi-intel-driver doesn't have support for
2455 * B-frame encode when utilizing low-power encode hardware block.
2456 * So Disabling b-frame encoding in low-pwer encode.
2458 * Fixme :We should query the VAConfigAttribEncMaxRefFrames
2459 * instead of blindly disabling b-frame support and set b/p frame count,
2460 * buffer pool size etc based on that.*/
2461 if ((encoder->num_bframes > 0)
2462 && (encoder->entrypoint == GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_LP)) {
2464 ("Disabling b-frame since the driver doesn't supporting it in low-power encode");
2465 encoder->num_bframes = 0;
2468 if (encoder->num_bframes > 0 && GST_VAAPI_ENCODER_FPS_N (encoder) > 0)
2469 encoder->cts_offset = gst_util_uint64_scale (GST_SECOND,
2470 GST_VAAPI_ENCODER_FPS_D (encoder), GST_VAAPI_ENCODER_FPS_N (encoder));
2472 encoder->cts_offset = 0;
2474 /* init max_frame_num, max_poc */
2475 encoder->log2_max_frame_num =
2476 h264_get_log2_max_frame_num (encoder->idr_period);
2477 g_assert (encoder->log2_max_frame_num >= 4);
2478 encoder->max_frame_num = (1 << encoder->log2_max_frame_num);
2479 encoder->log2_max_pic_order_cnt = encoder->log2_max_frame_num + 1;
2480 encoder->max_pic_order_cnt = (1 << encoder->log2_max_pic_order_cnt);
2481 encoder->idr_num = 0;
2483 for (i = 0; i < encoder->num_views; i++) {
2484 GstVaapiH264ViewRefPool *const ref_pool = &encoder->ref_pools[i];
2485 GstVaapiH264ViewReorderPool *const reorder_pool =
2486 &encoder->reorder_pools[i];
2488 ref_pool->max_reflist0_count = 1;
2489 ref_pool->max_reflist1_count = encoder->num_bframes > 0;
2490 ref_pool->max_ref_frames = ref_pool->max_reflist0_count
2491 + ref_pool->max_reflist1_count;
2493 reorder_pool->frame_index = 0;
2497 static GstVaapiEncoderStatus
2498 gst_vaapi_encoder_h264_encode (GstVaapiEncoder * base_encoder,
2499 GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf)
2501 GstVaapiEncoderH264 *const encoder =
2502 GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2503 GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2504 GstVaapiSurfaceProxy *reconstruct = NULL;
2506 reconstruct = gst_vaapi_encoder_create_surface (base_encoder);
2508 g_assert (GST_VAAPI_SURFACE_PROXY_SURFACE (reconstruct));
2510 if (!ensure_sequence (encoder, picture))
2512 if (!ensure_misc_params (encoder, picture))
2514 if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
2516 if (!ensure_slices (encoder, picture))
2518 if (!gst_vaapi_enc_picture_encode (picture))
2521 if (!reference_list_update (encoder, picture, reconstruct))
2524 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2530 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
2536 static GstVaapiEncoderStatus
2537 gst_vaapi_encoder_h264_flush (GstVaapiEncoder * base_encoder)
2539 GstVaapiEncoderH264 *const encoder =
2540 GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2541 GstVaapiH264ViewReorderPool *reorder_pool;
2542 GstVaapiEncPicture *pic;
2545 for (i = 0; i < encoder->num_views; i++) {
2546 reorder_pool = &encoder->reorder_pools[i];
2547 reorder_pool->frame_index = 0;
2548 reorder_pool->cur_frame_num = 0;
2549 reorder_pool->cur_present_index = 0;
2551 while (!g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2552 pic = (GstVaapiEncPicture *)
2553 g_queue_pop_head (&reorder_pool->reorder_frame_list);
2554 gst_vaapi_enc_picture_unref (pic);
2556 g_queue_clear (&reorder_pool->reorder_frame_list);
2559 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2562 /* Generate "codec-data" buffer */
2563 static GstVaapiEncoderStatus
2564 gst_vaapi_encoder_h264_get_codec_data (GstVaapiEncoder * base_encoder,
2565 GstBuffer ** out_buffer_ptr)
2567 GstVaapiEncoderH264 *const encoder =
2568 GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2569 const guint32 configuration_version = 0x01;
2570 const guint32 nal_length_size = 4;
2571 guint8 profile_idc, profile_comp, level_idc;
2572 GstMapInfo sps_info, pps_info;
2576 if (!encoder->sps_data || !encoder->pps_data)
2577 return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
2578 if (gst_buffer_get_size (encoder->sps_data) < 4)
2579 return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
2581 if (!gst_buffer_map (encoder->sps_data, &sps_info, GST_MAP_READ))
2582 goto error_map_sps_buffer;
2584 if (!gst_buffer_map (encoder->pps_data, &pps_info, GST_MAP_READ))
2585 goto error_map_pps_buffer;
2587 /* skip sps_data[0], which is the nal_unit_type */
2588 profile_idc = sps_info.data[1];
2589 profile_comp = sps_info.data[2];
2590 level_idc = sps_info.data[3];
2593 gst_bit_writer_init (&bs, (sps_info.size + pps_info.size + 64) * 8);
2594 WRITE_UINT32 (&bs, configuration_version, 8);
2595 WRITE_UINT32 (&bs, profile_idc, 8);
2596 WRITE_UINT32 (&bs, profile_comp, 8);
2597 WRITE_UINT32 (&bs, level_idc, 8);
2598 WRITE_UINT32 (&bs, 0x3f, 6); /* 111111 */
2599 WRITE_UINT32 (&bs, nal_length_size - 1, 2);
2600 WRITE_UINT32 (&bs, 0x07, 3); /* 111 */
2603 WRITE_UINT32 (&bs, 1, 5); /* SPS count = 1 */
2604 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
2605 /* Write Nal unit length and data of SPS */
2606 if (!gst_vaapi_utils_h26x_write_nal_unit (&bs, sps_info.data, sps_info.size))
2607 goto nal_to_byte_stream_error;
2610 WRITE_UINT32 (&bs, 1, 8); /* PPS count = 1 */
2611 /* Write Nal unit length and data of PPS */
2612 if (!gst_vaapi_utils_h26x_write_nal_unit (&bs, pps_info.data, pps_info.size))
2613 goto nal_to_byte_stream_error;
2615 gst_buffer_unmap (encoder->pps_data, &pps_info);
2616 gst_buffer_unmap (encoder->sps_data, &sps_info);
2618 buffer = gst_buffer_new_wrapped (GST_BIT_WRITER_DATA (&bs),
2619 GST_BIT_WRITER_BIT_SIZE (&bs) / 8);
2621 goto error_alloc_buffer;
2622 *out_buffer_ptr = buffer;
2624 gst_bit_writer_clear (&bs, FALSE);
2625 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2630 GST_ERROR ("failed to write codec-data");
2631 gst_buffer_unmap (encoder->sps_data, &sps_info);
2632 gst_buffer_unmap (encoder->pps_data, &pps_info);
2633 gst_bit_writer_clear (&bs, TRUE);
2634 return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
2636 nal_to_byte_stream_error:
2638 GST_ERROR ("failed to write nal unit");
2639 gst_buffer_unmap (encoder->sps_data, &sps_info);
2640 gst_buffer_unmap (encoder->pps_data, &pps_info);
2641 gst_bit_writer_clear (&bs, TRUE);
2642 return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
2644 error_map_sps_buffer:
2646 GST_ERROR ("failed to map SPS packed header");
2647 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2649 error_map_pps_buffer:
2651 GST_ERROR ("failed to map PPS packed header");
2652 gst_buffer_unmap (encoder->sps_data, &sps_info);
2653 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2657 GST_ERROR ("failed to allocate codec-data buffer");
2658 gst_bit_writer_clear (&bs, TRUE);
2659 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2663 static GstVaapiEncoderStatus
2664 gst_vaapi_encoder_h264_reordering (GstVaapiEncoder * base_encoder,
2665 GstVideoCodecFrame * frame, GstVaapiEncPicture ** output)
2667 GstVaapiEncoderH264 *const encoder =
2668 GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2669 GstVaapiH264ViewReorderPool *reorder_pool = NULL;
2670 GstVaapiEncPicture *picture;
2671 gboolean is_idr = FALSE;
2675 /* encoding views alternatively for MVC */
2676 if (encoder->is_mvc) {
2677 /* FIXME: Use first-in-bundle flag on buffers to reset view idx? */
2679 encoder->view_idx = frame->system_frame_number % encoder->num_views;
2681 encoder->view_idx = (encoder->view_idx + 1) % encoder->num_views;
2683 reorder_pool = &encoder->reorder_pools[encoder->view_idx];
2686 if (reorder_pool->reorder_state != GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES)
2687 return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
2689 /* reorder_state = GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES
2690 dump B frames from queue, sometime, there may also have P frame or I frame */
2691 g_assert (encoder->num_bframes > 0);
2692 g_return_val_if_fail (!g_queue_is_empty (&reorder_pool->reorder_frame_list),
2693 GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN);
2694 picture = g_queue_pop_head (&reorder_pool->reorder_frame_list);
2696 if (g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2697 reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES;
2702 /* new frame coming */
2703 picture = GST_VAAPI_ENC_PICTURE_NEW (H264, encoder, frame);
2705 GST_WARNING ("create H264 picture failed, frame timestamp:%"
2706 GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts));
2707 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2709 ++reorder_pool->cur_present_index;
2710 picture->poc = ((reorder_pool->cur_present_index * 2) %
2711 encoder->max_pic_order_cnt);
2713 is_idr = (reorder_pool->frame_index == 0 ||
2714 reorder_pool->frame_index >= encoder->idr_period);
2716 /* check key frames */
2717 if (is_idr || GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame) ||
2718 (reorder_pool->frame_index %
2719 GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder)) == 0) {
2720 ++reorder_pool->cur_frame_num;
2721 ++reorder_pool->frame_index;
2723 /* b frame enabled, check queue of reorder_frame_list */
2724 if (encoder->num_bframes
2725 && !g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2726 GstVaapiEncPicture *p_pic;
2728 p_pic = g_queue_pop_tail (&reorder_pool->reorder_frame_list);
2729 set_p_frame (p_pic, encoder);
2730 g_queue_foreach (&reorder_pool->reorder_frame_list,
2731 (GFunc) set_b_frame, encoder);
2732 ++reorder_pool->cur_frame_num;
2733 set_key_frame (picture, encoder, is_idr);
2734 g_queue_push_tail (&reorder_pool->reorder_frame_list, picture);
2736 reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES;
2737 } else { /* no b frames in queue */
2738 set_key_frame (picture, encoder, is_idr);
2739 g_assert (g_queue_is_empty (&reorder_pool->reorder_frame_list));
2740 if (encoder->num_bframes)
2741 reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES;
2746 /* new p/b frames coming */
2747 ++reorder_pool->frame_index;
2748 if (reorder_pool->reorder_state == GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES &&
2749 g_queue_get_length (&reorder_pool->reorder_frame_list) <
2750 encoder->num_bframes) {
2751 g_queue_push_tail (&reorder_pool->reorder_frame_list, picture);
2752 return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
2755 ++reorder_pool->cur_frame_num;
2756 set_p_frame (picture, encoder);
2758 if (reorder_pool->reorder_state == GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES) {
2759 g_queue_foreach (&reorder_pool->reorder_frame_list, (GFunc) set_b_frame,
2761 reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES;
2762 g_assert (!g_queue_is_empty (&reorder_pool->reorder_frame_list));
2767 frame = picture->frame;
2768 if (GST_CLOCK_TIME_IS_VALID (frame->pts))
2769 frame->pts += encoder->cts_offset;
2772 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2775 static GstVaapiEncoderStatus
2776 set_context_info (GstVaapiEncoder * base_encoder)
2778 GstVaapiEncoderH264 *const encoder =
2779 GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2780 GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
2781 const guint DEFAULT_SURFACES_COUNT = 3;
2783 /* Maximum sizes for common headers (in bits) */
2786 MAX_SPS_HDR_SIZE = 16473,
2787 MAX_VUI_PARAMS_SIZE = 210,
2788 MAX_HRD_PARAMS_SIZE = 4103,
2789 MAX_PPS_HDR_SIZE = 101,
2790 MAX_SLICE_HDR_SIZE = 397 + 2572 + 6670 + 2402,
2793 if (!ensure_hw_profile (encoder))
2794 return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2796 base_encoder->num_ref_frames =
2797 ((encoder->num_bframes ? 2 : 1) + DEFAULT_SURFACES_COUNT)
2798 * encoder->num_views;
2800 /* Only YUV 4:2:0 formats are supported for now. This means that we
2801 have a limit of 3200 bits per macroblock. */
2802 /* XXX: check profile and compute RawMbBits */
2803 base_encoder->codedbuf_size = (GST_ROUND_UP_16 (vip->width) *
2804 GST_ROUND_UP_16 (vip->height) / 256) * 400;
2806 /* Account for SPS header */
2807 /* XXX: exclude scaling lists, MVC/SVC extensions */
2808 base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
2809 MAX_VUI_PARAMS_SIZE + 2 * MAX_HRD_PARAMS_SIZE) / 8;
2811 /* Account for PPS header */
2812 /* XXX: exclude slice groups, scaling lists, MVC/SVC extensions */
2813 base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
2815 /* Account for slice header */
2816 base_encoder->codedbuf_size += encoder->num_slices * (4 +
2817 GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8);
2819 base_encoder->context_info.entrypoint = encoder->entrypoint;
2821 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2824 static GstVaapiEncoderStatus
2825 gst_vaapi_encoder_h264_reconfigure (GstVaapiEncoder * base_encoder)
2827 GstVaapiEncoderH264 *const encoder =
2828 GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2829 GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
2830 GstVaapiEncoderStatus status;
2831 guint mb_width, mb_height;
2833 mb_width = (GST_VAAPI_ENCODER_WIDTH (encoder) + 15) / 16;
2834 mb_height = (GST_VAAPI_ENCODER_HEIGHT (encoder) + 15) / 16;
2835 if (mb_width != encoder->mb_width || mb_height != encoder->mb_height) {
2836 GST_DEBUG ("resolution: %dx%d", GST_VAAPI_ENCODER_WIDTH (encoder),
2837 GST_VAAPI_ENCODER_HEIGHT (encoder));
2838 encoder->mb_width = mb_width;
2839 encoder->mb_height = mb_height;
2840 encoder->config_changed = TRUE;
2843 /* Take number of MVC views from input caps if provided */
2844 if (GST_VIDEO_INFO_MULTIVIEW_MODE (vip) ==
2845 GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME
2846 || GST_VIDEO_INFO_MULTIVIEW_MODE (vip) ==
2847 GST_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME)
2848 encoder->num_views = GST_VIDEO_INFO_VIEWS (vip);
2850 encoder->is_mvc = encoder->num_views > 1;
2852 status = ensure_profile_and_level (encoder);
2853 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
2856 reset_properties (encoder);
2857 ensure_control_rate_params (encoder);
2858 return set_context_info (base_encoder);
2862 gst_vaapi_encoder_h264_init (GstVaapiEncoder * base_encoder)
2864 GstVaapiEncoderH264 *const encoder =
2865 GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2868 /* Default encoding entrypoint */
2869 encoder->entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
2871 /* Multi-view coding information */
2872 encoder->is_mvc = FALSE;
2873 encoder->num_views = 1;
2874 encoder->view_idx = 0;
2875 memset (encoder->view_ids, 0, sizeof (encoder->view_ids));
2877 /* re-ordering list initialize */
2878 for (i = 0; i < MAX_NUM_VIEWS; i++) {
2879 GstVaapiH264ViewReorderPool *const reorder_pool =
2880 &encoder->reorder_pools[i];
2881 g_queue_init (&reorder_pool->reorder_frame_list);
2882 reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_NONE;
2883 reorder_pool->frame_index = 0;
2884 reorder_pool->cur_frame_num = 0;
2885 reorder_pool->cur_present_index = 0;
2888 /* reference list info initialize */
2889 for (i = 0; i < MAX_NUM_VIEWS; i++) {
2890 GstVaapiH264ViewRefPool *const ref_pool = &encoder->ref_pools[i];
2891 g_queue_init (&ref_pool->ref_list);
2892 ref_pool->max_ref_frames = 0;
2893 ref_pool->max_reflist0_count = 1;
2894 ref_pool->max_reflist1_count = 1;
2901 gst_vaapi_encoder_h264_finalize (GstVaapiEncoder * base_encoder)
2903 /*free private buffers */
2904 GstVaapiEncoderH264 *const encoder =
2905 GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2906 GstVaapiEncPicture *pic;
2907 GstVaapiEncoderH264Ref *ref;
2910 gst_buffer_replace (&encoder->sps_data, NULL);
2911 gst_buffer_replace (&encoder->subset_sps_data, NULL);
2912 gst_buffer_replace (&encoder->pps_data, NULL);
2914 /* reference list info de-init */
2915 for (i = 0; i < MAX_NUM_VIEWS; i++) {
2916 GstVaapiH264ViewRefPool *const ref_pool = &encoder->ref_pools[i];
2917 while (!g_queue_is_empty (&ref_pool->ref_list)) {
2918 ref = (GstVaapiEncoderH264Ref *) g_queue_pop_head (&ref_pool->ref_list);
2919 reference_pic_free (encoder, ref);
2921 g_queue_clear (&ref_pool->ref_list);
2924 /* re-ordering list initialize */
2925 for (i = 0; i < MAX_NUM_VIEWS; i++) {
2926 GstVaapiH264ViewReorderPool *const reorder_pool =
2927 &encoder->reorder_pools[i];
2928 while (!g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2929 pic = (GstVaapiEncPicture *)
2930 g_queue_pop_head (&reorder_pool->reorder_frame_list);
2931 gst_vaapi_enc_picture_unref (pic);
2933 g_queue_clear (&reorder_pool->reorder_frame_list);
2937 static GstVaapiEncoderStatus
2938 gst_vaapi_encoder_h264_set_property (GstVaapiEncoder * base_encoder,
2939 gint prop_id, const GValue * value)
2941 GstVaapiEncoderH264 *const encoder =
2942 GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2945 case GST_VAAPI_ENCODER_H264_PROP_MAX_BFRAMES:
2946 encoder->num_bframes = g_value_get_uint (value);
2948 case GST_VAAPI_ENCODER_H264_PROP_INIT_QP:
2949 encoder->init_qp = g_value_get_uint (value);
2951 case GST_VAAPI_ENCODER_H264_PROP_MIN_QP:
2952 encoder->min_qp = g_value_get_uint (value);
2954 case GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES:
2955 encoder->num_slices = g_value_get_uint (value);
2957 case GST_VAAPI_ENCODER_H264_PROP_CABAC:
2958 encoder->use_cabac = g_value_get_boolean (value);
2960 case GST_VAAPI_ENCODER_H264_PROP_DCT8X8:
2961 encoder->use_dct8x8 = g_value_get_boolean (value);
2963 case GST_VAAPI_ENCODER_H264_PROP_CPB_LENGTH:
2964 encoder->cpb_length = g_value_get_uint (value);
2966 case GST_VAAPI_ENCODER_H264_PROP_NUM_VIEWS:
2967 encoder->num_views = g_value_get_uint (value);
2969 case GST_VAAPI_ENCODER_H264_PROP_VIEW_IDS:{
2971 GValueArray *view_ids = g_value_get_boxed (value);
2973 if (view_ids == NULL) {
2974 for (i = 0; i < encoder->num_views; i++)
2975 encoder->view_ids[i] = i;
2977 g_assert (view_ids->n_values <= encoder->num_views);
2979 for (i = 0; i < encoder->num_views; i++) {
2980 GValue *val = g_value_array_get_nth (view_ids, i);
2981 encoder->view_ids[i] = g_value_get_uint (val);
2987 return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
2989 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2992 GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (H264);
2994 static inline const GstVaapiEncoderClass *
2995 gst_vaapi_encoder_h264_class (void)
2997 static const GstVaapiEncoderClass GstVaapiEncoderH264Class = {
2998 GST_VAAPI_ENCODER_CLASS_INIT (H264, h264),
2999 .set_property = gst_vaapi_encoder_h264_set_property,
3000 .get_codec_data = gst_vaapi_encoder_h264_get_codec_data
3002 return &GstVaapiEncoderH264Class;
3006 * gst_vaapi_encoder_h264_new:
3007 * @display: a #GstVaapiDisplay
3009 * Creates a new #GstVaapiEncoder for H.264 encoding. Note that the
3010 * only supported output stream format is "byte-stream" format.
3012 * Return value: the newly allocated #GstVaapiEncoder object
3015 gst_vaapi_encoder_h264_new (GstVaapiDisplay * display)
3017 return gst_vaapi_encoder_new (gst_vaapi_encoder_h264_class (), display);
3021 * gst_vaapi_encoder_h264_get_default_properties:
3023 * Determines the set of common and H.264 specific encoder properties.
3024 * The caller owns an extra reference to the resulting array of
3025 * #GstVaapiEncoderPropInfo elements, so it shall be released with
3026 * g_ptr_array_unref() after usage.
3028 * Return value: the set of encoder properties for #GstVaapiEncoderH264,
3029 * or %NULL if an error occurred.
3032 gst_vaapi_encoder_h264_get_default_properties (void)
3034 const GstVaapiEncoderClass *const klass = gst_vaapi_encoder_h264_class ();
3037 props = gst_vaapi_encoder_properties_get_default (klass);
3042 * GstVaapiEncoderH264:max-bframes:
3044 * The number of B-frames between I and P.
3046 GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3047 GST_VAAPI_ENCODER_H264_PROP_MAX_BFRAMES,
3048 g_param_spec_uint ("max-bframes",
3049 "Max B-Frames", "Number of B-frames between I and P", 0, 10, 0,
3050 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3053 * GstVaapiEncoderH264:init-qp:
3055 * The initial quantizer value.
3057 GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3058 GST_VAAPI_ENCODER_H264_PROP_INIT_QP,
3059 g_param_spec_uint ("init-qp",
3060 "Initial QP", "Initial quantizer value", 1, 51, 26,
3061 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3064 * GstVaapiEncoderH264:min-qp:
3066 * The minimum quantizer value.
3068 GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3069 GST_VAAPI_ENCODER_H264_PROP_MIN_QP,
3070 g_param_spec_uint ("min-qp",
3071 "Minimum QP", "Minimum quantizer value", 1, 51, 1,
3072 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3075 * GstVaapiEncoderH264:num-slices:
3077 * The number of slices per frame.
3079 GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3080 GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES,
3081 g_param_spec_uint ("num-slices",
3083 "Number of slices per frame",
3084 1, 200, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3087 * GstVaapiEncoderH264:cabac:
3089 * Enable CABAC entropy coding mode for improved compression ratio,
3090 * at the expense that the minimum target profile is Main. Default
3091 * is CAVLC entropy coding mode.
3093 GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3094 GST_VAAPI_ENCODER_H264_PROP_CABAC,
3095 g_param_spec_boolean ("cabac",
3097 "Enable CABAC entropy coding mode",
3098 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3101 * GstVaapiEncoderH264:dct8x8:
3103 * Enable adaptive use of 8x8 transforms in I-frames. This improves
3104 * the compression ratio by the minimum target profile is High.
3105 * Default is to use 4x4 DCT only.
3107 GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3108 GST_VAAPI_ENCODER_H264_PROP_DCT8X8,
3109 g_param_spec_boolean ("dct8x8",
3111 "Enable adaptive use of 8x8 transforms in I-frames",
3112 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3115 * GstVaapiEncoderH264:cpb-length:
3117 * The size of the CPB buffer in milliseconds.
3119 GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3120 GST_VAAPI_ENCODER_H264_PROP_CPB_LENGTH,
3121 g_param_spec_uint ("cpb-length",
3122 "CPB Length", "Length of the CPB buffer in milliseconds",
3123 1, 10000, DEFAULT_CPB_LENGTH,
3124 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3127 * GstVaapiEncoderH264:num-views:
3129 * The number of views for MVC encoding .
3131 GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3132 GST_VAAPI_ENCODER_H264_PROP_NUM_VIEWS,
3133 g_param_spec_uint ("num-views",
3135 "Number of Views for MVC encoding",
3136 1, MAX_NUM_VIEWS, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3138 * GstVaapiEncoderH264:view-ids:
3140 * The view ids for MVC encoding .
3142 GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3143 GST_VAAPI_ENCODER_H264_PROP_VIEW_IDS,
3144 g_param_spec_value_array ("view-ids",
3145 "View IDs", "Set of View Ids used for MVC encoding",
3146 g_param_spec_uint ("view-id-value", "View id value",
3147 "view id values used for mvc encoding", 0, MAX_VIEW_ID, 0,
3148 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
3149 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3155 * gst_vaapi_encoder_h264_set_max_profile:
3156 * @encoder: a #GstVaapiEncoderH264
3157 * @profile: an H.264 #GstVaapiProfile
3159 * Notifies the @encoder to use coding tools from the supplied
3162 * This means that if the minimal profile derived to
3163 * support the specified coding tools is greater than this @profile,
3164 * then an error is returned when the @encoder is configured.
3166 * Return value: %TRUE on success
3169 gst_vaapi_encoder_h264_set_max_profile (GstVaapiEncoderH264 * encoder,
3170 GstVaapiProfile profile)
3174 g_return_val_if_fail (encoder != NULL, FALSE);
3175 g_return_val_if_fail (profile != GST_VAAPI_PROFILE_UNKNOWN, FALSE);
3177 if (gst_vaapi_profile_get_codec (profile) != GST_VAAPI_CODEC_H264)
3180 profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
3184 encoder->max_profile_idc = profile_idc;
3189 * gst_vaapi_encoder_h264_get_profile_and_level:
3190 * @encoder: a #GstVaapiEncoderH264
3191 * @out_profile_ptr: return location for the #GstVaapiProfile
3192 * @out_level_ptr: return location for the #GstVaapiLevelH264
3194 * Queries the H.264 @encoder for the active profile and level. That
3195 * information is only constructed and valid after the encoder is
3196 * configured, i.e. after the gst_vaapi_encoder_set_codec_state()
3197 * function is called.
3199 * Return value: %TRUE on success
3202 gst_vaapi_encoder_h264_get_profile_and_level (GstVaapiEncoderH264 * encoder,
3203 GstVaapiProfile * out_profile_ptr, GstVaapiLevelH264 * out_level_ptr)
3205 g_return_val_if_fail (encoder != NULL, FALSE);
3207 if (!encoder->profile || !encoder->level)
3210 if (out_profile_ptr)
3211 *out_profile_ptr = encoder->profile;
3213 *out_level_ptr = encoder->level;