b93bafeacdf33e62db351a16de1840ae51958afb
[platform/upstream/gstreamer.git] / gst-libs / gst / vaapi / gstvaapiencoder_h264.c
1 /*
2  *  gstvaapiencoder_h264.c - H.264 encoder
3  *
4  *  Copyright (C) 2012-2014 Intel Corporation
5  *    Author: Wind Yuan <feng.yuan@intel.com>
6  *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
7  *
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.
12  *
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.
17  *
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
22  */
23
24 /* GValueArray has deprecated without providing an alternative in glib >= 2.32
25  * See https://bugzilla.gnome.org/show_bug.cgi?id=667228
26  */
27 #define GLIB_DISABLE_DEPRECATION_WARNINGS
28
29 #include "sysdeps.h"
30 #include <va/va.h>
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"
42
43 #define DEBUG 1
44 #include "gstvaapidebug.h"
45
46
47 /* Define the maximum number of views supported */
48 #define MAX_NUM_VIEWS 10
49
50 /* Define the maximum value for view-id */
51 #define MAX_VIEW_ID 1023
52
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))
59
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))
65
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)
73
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
78
79 /* only for internal usage, values won't be equal to actual payload type */
80 typedef enum
81 {
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;
86
87 typedef struct
88 {
89   GstVaapiSurfaceProxy *pic;
90   guint poc;
91   guint frame_num;
92 } GstVaapiEncoderH264Ref;
93
94 typedef enum
95 {
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;
100
101 typedef struct _GstVaapiH264ViewRefPool
102 {
103   GQueue ref_list;
104   guint max_ref_frames;
105   guint max_reflist0_count;
106   guint max_reflist1_count;
107 } GstVaapiH264ViewRefPool;
108
109 typedef struct _GstVaapiH264ViewReorderPool
110 {
111   GQueue reorder_frame_list;
112   guint reorder_state;
113   guint frame_index;
114   guint frame_count;            /* monotonically increasing with in every idr period */
115   guint cur_frame_num;
116   guint cur_present_index;
117 } GstVaapiH264ViewReorderPool;
118
119 static inline gboolean
120 _poc_greater_than (guint poc1, guint poc2, guint max_poc)
121 {
122   return (((poc1 - poc2) & (max_poc - 1)) < max_poc / 2);
123 }
124
125 /* Get slice_type value for H.264 specification */
126 static guint8
127 h264_get_slice_type (GstVaapiPictureType type)
128 {
129   switch (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;
136     default:
137       break;
138   }
139   return -1;
140 }
141
142 /* Get log2_max_frame_num value for H.264 specification */
143 static guint
144 h264_get_log2_max_frame_num (guint num)
145 {
146   guint ret = 0;
147
148   while (num) {
149     ++ret;
150     num >>= 1;
151   }
152   if (ret <= 4)
153     ret = 4;
154   else if (ret > 10)
155     ret = 10;
156   /* must be greater than 4 */
157   return ret;
158 }
159
160 /* Determines the cpbBrNalFactor based on the supplied profile */
161 static guint
162 h264_get_cpb_nal_factor (GstVaapiProfile profile)
163 {
164   guint f;
165
166   /* Table A-2 */
167   switch (profile) {
168     case GST_VAAPI_PROFILE_H264_HIGH:
169       f = 1500;
170       break;
171     case GST_VAAPI_PROFILE_H264_HIGH10:
172       f = 3600;
173       break;
174     case GST_VAAPI_PROFILE_H264_HIGH_422:
175     case GST_VAAPI_PROFILE_H264_HIGH_444:
176       f = 4800;
177       break;
178     case GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH:
179     case GST_VAAPI_PROFILE_H264_STEREO_HIGH:
180       f = 1500;                 /* H.10.2.1 (r) */
181       break;
182     default:
183       f = 1200;
184       break;
185   }
186   return f;
187 }
188
189 /* Write the NAL unit header */
190 static gboolean
191 bs_write_nal_header (GstBitWriter * bs, guint32 nal_ref_idc,
192     guint32 nal_unit_type)
193 {
194   WRITE_UINT32 (bs, 0, 1);
195   WRITE_UINT32 (bs, nal_ref_idc, 2);
196   WRITE_UINT32 (bs, nal_unit_type, 5);
197   return TRUE;
198
199   /* ERRORS */
200 bs_error:
201   {
202     GST_WARNING ("failed to write NAL unit header");
203     return FALSE;
204   }
205 }
206
207 /* Write the MVC NAL unit header extension */
208 static gboolean
209 bs_write_nal_header_mvc_extension (GstBitWriter * bs,
210     GstVaapiEncPicture * picture, guint32 view_id)
211 {
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;
218
219   if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
220     non_idr_flag = 0;
221
222   if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
223     anchor_pic_flag = 1;
224   /* svc_extension_flag == 0 for mvc stream */
225   WRITE_UINT32 (bs, svc_extension_flag, 1);
226
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);
234
235   return TRUE;
236
237   /* ERRORS */
238 bs_error:
239   {
240     GST_WARNING ("failed to write NAL unit header");
241     return FALSE;
242   }
243 }
244
245 /* Write the NAL unit trailing bits */
246 static gboolean
247 bs_write_trailing_bits (GstBitWriter * bs)
248 {
249   if (!gst_bit_writer_put_bits_uint32 (bs, 1, 1))
250     goto bs_error;
251   gst_bit_writer_align_bytes_unchecked (bs, 0);
252   return TRUE;
253
254   /* ERRORS */
255 bs_error:
256   {
257     GST_WARNING ("failed to write NAL unit trailing bits");
258     return FALSE;
259   }
260 }
261
262 /* Write an SPS NAL unit */
263 static gboolean
264 bs_write_sps_data (GstBitWriter * bs,
265     const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
266     const VAEncMiscParameterHRD * hrd_params)
267 {
268   guint8 profile_idc;
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;
273
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;
281   guint32 i = 0;
282
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;
292
293   /* profile_idc */
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);
305   /* level_idc */
306   WRITE_UINT32 (bs, seq_param->level_idc, 8);
307   /* seq_parameter_set_id */
308   WRITE_UE (bs, seq_param->seq_parameter_set_id);
309
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);
318     }
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);
325
326     /* seq_scaling_matrix_present_flag  */
327     g_assert (seq_param->seq_fields.bits.seq_scaling_matrix_present_flag == 0);
328     WRITE_UINT32 (bs,
329         seq_param->seq_fields.bits.seq_scaling_matrix_present_flag, 1);
330
331 #if 0
332     if (seq_param->seq_fields.bits.seq_scaling_matrix_present_flag) {
333       for (i = 0;
334           i < (seq_param->seq_fields.bits.chroma_format_idc != 3 ? 8 : 12);
335           i++) {
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) {
339           g_assert (0);
340           /* FIXME, need write scaling list if seq_scaling_matrix_present_flag ==1 */
341         }
342       }
343     }
344 #endif
345   }
346
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);
351
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");
357     WRITE_UINT32 (bs,
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]);
364     }
365   }
366
367   /* num_ref_frames */
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);
371
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);
378
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);
382   }
383
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);
388
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);
398   }
399
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 */
404     WRITE_UINT32 (bs,
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);
411       }
412     }
413
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);
420
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 */
427     }
428
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) {
433       /* hrd_parameters */
434       /* cpb_cnt_minus1 */
435       WRITE_UE (bs, 0);
436       WRITE_UINT32 (bs, SX_BITRATE - 6, 4);     /* bit_rate_scale */
437       WRITE_UINT32 (bs, SX_CPB_SIZE - 4, 4);    /* cpb_size_scale */
438
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);
444         /* cbr_flag[0] */
445         WRITE_UINT32 (bs, 1, 1);
446       }
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);
455     }
456
457     /* vcl_hrd_parameters_present_flag */
458     WRITE_UINT32 (bs, 0, 1);
459
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);
464     }
465     /* pic_struct_present_flag */
466     WRITE_UINT32 (bs, 1, 1);
467     /* bs_restriction_flag */
468     WRITE_UINT32 (bs, 0, 1);
469   }
470   return TRUE;
471
472   /* ERRORS */
473 bs_error:
474   {
475     GST_WARNING ("failed to write SPS NAL unit");
476     return FALSE;
477   }
478 }
479
480 static gboolean
481 bs_write_sps (GstBitWriter * bs,
482     const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
483     const VAEncMiscParameterHRD * hrd_params)
484 {
485   if (!bs_write_sps_data (bs, seq_param, profile, hrd_params))
486     return FALSE;
487
488   /* rbsp_trailing_bits */
489   bs_write_trailing_bits (bs);
490
491   return FALSE;
492 }
493
494 static gboolean
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)
499 {
500   guint32 i, j, k;
501
502   if (!bs_write_sps_data (bs, seq_param, profile, hrd_params))
503     return FALSE;
504
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;
508
509     num_views_minus1 = num_views - 1;
510     g_assert (num_views_minus1 < 1024);
511
512     /* bit equal to one */
513     WRITE_UINT32 (bs, 1, 1);
514
515     WRITE_UE (bs, num_views_minus1);
516
517     for (i = 0; i <= num_views_minus1; i++)
518       WRITE_UE (bs, view_ids[i]);
519
520     for (i = 1; i <= num_views_minus1; i++) {
521       guint32 num_anchor_refs_l0 = 0;
522       guint32 num_anchor_refs_l1 = 0;
523
524       WRITE_UE (bs, num_anchor_refs_l0);
525       for (j = 0; j < num_anchor_refs_l0; j++)
526         WRITE_UE (bs, 0);
527
528       WRITE_UE (bs, num_anchor_refs_l1);
529       for (j = 0; j < num_anchor_refs_l1; j++)
530         WRITE_UE (bs, 0);
531     }
532
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;
536
537       WRITE_UE (bs, num_non_anchor_refs_l0);
538       for (j = 0; j < num_non_anchor_refs_l0; j++)
539         WRITE_UE (bs, 0);
540
541       WRITE_UE (bs, num_non_anchor_refs_l1);
542       for (j = 0; j < num_non_anchor_refs_l1; j++)
543         WRITE_UE (bs, 0);
544     }
545
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);
550
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);
554
555       WRITE_UINT32 (bs, seq_param->level_idc, 8);
556       WRITE_UE (bs, num_applicable_ops_minus1);
557
558       for (j = 0; j <= num_applicable_ops_minus1; j++) {
559         guint8 temporal_id = 0;
560         guint16 num_target_views_minus1 = 1;
561
562         WRITE_UINT32 (bs, temporal_id, 3);
563         WRITE_UE (bs, num_target_views_minus1);
564
565         for (k = 0; k <= num_target_views_minus1; k++)
566           WRITE_UE (bs, k);
567
568         WRITE_UE (bs, num_views_minus1);
569       }
570     }
571
572     /* mvc_vui_parameters_present_flag */
573     WRITE_UINT32 (bs, 0, 1);
574   }
575
576   /* additional_extension2_flag */
577   WRITE_UINT32 (bs, 0, 1);
578
579   /* rbsp_trailing_bits */
580   bs_write_trailing_bits (bs);
581   return TRUE;
582
583   /* ERRORS */
584 bs_error:
585   {
586     GST_WARNING ("failed to write subset SPS NAL unit");
587     return FALSE;
588   }
589   return FALSE;
590 }
591
592 /* Write a PPS NAL unit */
593 static gboolean
594 bs_write_pps (GstBitWriter * bs,
595     const VAEncPictureParameterBufferH264 * pic_param, GstVaapiProfile profile)
596 {
597   guint32 num_slice_groups_minus1 = 0;
598   guint32 pic_init_qs_minus26 = 0;
599   guint32 redundant_pic_cnt_present_flag = 0;
600
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);
609   /* slice_groups-1 */
610   WRITE_UE (bs, num_slice_groups_minus1);
611
612   if (num_slice_groups_minus1 > 0) {
613      /*FIXME*/ g_assert (0 && "unsupported arbitrary slice ordering (ASO)");
614   }
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);
625
626   WRITE_UINT32 (bs,
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);
630
631   /* more_rbsp_data */
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);
636     WRITE_UINT32 (bs,
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");
640       /* FIXME */
641       /*
642          for (i = 0; i <
643          (6+(-( (chroma_format_idc ! = 3) ? 2 : 6) * -pic_param->pic_fields.bits.transform_8x8_mode_flag));
644          i++) {
645          gst_bit_writer_put_bits_uint8(bs, pic_param->pic_fields.bits.pic_scaling_list_present_flag, 1);
646          }
647        */
648     }
649     WRITE_SE (bs, pic_param->second_chroma_qp_index_offset);
650   }
651
652   /* rbsp_trailing_bits */
653   bs_write_trailing_bits (bs);
654   return TRUE;
655
656   /* ERRORS */
657 bs_error:
658   {
659     GST_WARNING ("failed to write PPS NAL unit");
660     return FALSE;
661   }
662 }
663
664 /* ------------------------------------------------------------------------- */
665 /* --- H.264 Encoder                                                     --- */
666 /* ------------------------------------------------------------------------- */
667
668 #define GST_VAAPI_ENCODER_H264_CAST(encoder) \
669     ((GstVaapiEncoderH264 *)(encoder))
670
671 struct _GstVaapiEncoderH264
672 {
673   GstVaapiEncoder parent_instance;
674
675   GstVaapiProfile profile;
676   GstVaapiLevelH264 level;
677   GstVaapiEntrypoint entrypoint;
678   guint8 profile_idc;
679   guint8 max_profile_idc;
680   guint8 hw_max_profile_idc;
681   guint8 level_idc;
682   guint32 idr_period;
683   guint32 init_qp;
684   guint32 min_qp;
685   guint32 num_slices;
686   guint32 num_bframes;
687   guint32 mb_width;
688   guint32 mb_height;
689   gboolean use_cabac;
690   gboolean use_dct8x8;
691   GstClockTime cts_offset;
692   gboolean config_changed;
693
694   /* frame, poc */
695   guint32 max_frame_num;
696   guint32 log2_max_frame_num;
697   guint32 max_pic_order_cnt;
698   guint32 log2_max_pic_order_cnt;
699   guint32 idr_num;
700   guint8 pic_order_cnt_type;
701   guint8 delta_pic_order_always_zero_flag;
702
703   GstBuffer *sps_data;
704   GstBuffer *subset_sps_data;
705   GstBuffer *pps_data;
706
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)
710
711   /* MVC */
712   gboolean is_mvc;
713   guint32 view_idx;             /* View Order Index (VOIdx) */
714   guint32 num_views;
715   guint16 view_ids[MAX_NUM_VIEWS];
716   GstVaapiH264ViewRefPool ref_pools[MAX_NUM_VIEWS];
717   GstVaapiH264ViewReorderPool reorder_pools[MAX_NUM_VIEWS];
718 };
719
720 /* Write a SEI buffering period payload */
721 static gboolean
722 bs_write_sei_buf_period (GstBitWriter * bs,
723     GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
724 {
725   guint initial_cpb_removal_delay = 0;
726   guint initial_cpb_removal_delay_offset = 0;
727   guint8 initial_cpb_removal_delay_length = 24;
728
729   /* sequence_parameter_set_id */
730   WRITE_UE (bs, encoder->view_idx);
731   /* NalHrdBpPresentFlag == TRUE */
732   /* cpb_cnt_minus1 == 0 */
733
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;
737
738   /* initial_cpb_remvoal_dealy */
739   WRITE_UINT32 (bs, initial_cpb_removal_delay,
740       initial_cpb_removal_delay_length);
741
742   /* initial_cpb_removal_delay_offset */
743   WRITE_UINT32 (bs, initial_cpb_removal_delay_offset,
744       initial_cpb_removal_delay_length);
745
746   /* VclHrdBpPresentFlag == FALSE */
747   return TRUE;
748
749   /* ERRORS */
750 bs_error:
751   {
752     GST_WARNING ("failed to write Buffering Period SEI message");
753     return FALSE;
754   }
755 }
756
757 /* Write a SEI picture timing payload */
758 static gboolean
759 bs_write_sei_pic_timing (GstBitWriter * bs,
760     GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
761 {
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;
769
770   reorder_pool = &encoder->reorder_pools[encoder->view_idx];
771   if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
772     reorder_pool->frame_count = 0;
773   else
774     reorder_pool->frame_count++;
775
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);
784
785   if (picture->type == GST_VAAPI_PICTURE_TYPE_B)
786     dpb_output_delay = 0;
787   else
788     dpb_output_delay = picture->poc - reorder_pool->frame_count * 2;
789
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);
793
794   /* pic_struct_present_flag == 1 */
795   /* pic_struct */
796   WRITE_UINT32 (bs, pic_struct, 4);
797   /* clock_timestamp_flag */
798   WRITE_UINT32 (bs, clock_timestamp_flag, 1);
799
800   return TRUE;
801
802   /* ERRORS */
803 bs_error:
804   {
805     GST_WARNING ("failed to write Picture Timing SEI message");
806     return FALSE;
807   }
808 }
809
810 /* Write a Slice NAL unit */
811 static gboolean
812 bs_write_slice (GstBitWriter * bs,
813     const VAEncSliceParameterBufferH264 * slice_param,
814     GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
815 {
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;
823
824   /* first_mb_in_slice */
825   WRITE_UE (bs, slice_param->macroblock_address);
826   /* slice_type */
827   WRITE_UE (bs, slice_param->slice_type);
828   /* pic_parameter_set_id */
829   WRITE_UE (bs, slice_param->pic_parameter_set_id);
830   /* frame_num */
831   WRITE_UINT32 (bs, picture->frame_num, encoder->log2_max_frame_num);
832
833   /* XXX: only frames (i.e. non-interlaced) are supported for now */
834   /* frame_mbs_only_flag == 0 */
835
836   /* idr_pic_id */
837   if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
838     WRITE_UE (bs, slice_param->idr_pic_id);
839
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]);
852   }
853   /* redundant_pic_cnt_present_flag is FALSE, no redundant coded pictures */
854
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);
858
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);
866     }
867   }
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);
873
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() */
881   }
882
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);
890     } else {
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);
894     }
895   }
896
897   /* cabac_init_idc */
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);
901   /*slice_qp_delta */
902   WRITE_SE (bs, slice_param->slice_qp_delta);
903
904   /* XXX: only supporting I, P and B type slices */
905   /* no sp_for_switch_flag and no slice_qs_delta */
906
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);
913     }
914   }
915
916   /* XXX: unsupported arbitrary slice ordering (ASO) */
917   /* num_slic_groups_minus1 should be zero */
918   return TRUE;
919
920   /* ERRORS */
921 bs_error:
922   {
923     GST_WARNING ("failed to write Slice NAL unit");
924     return FALSE;
925   }
926 }
927
928 static inline void
929 _check_sps_pps_status (GstVaapiEncoderH264 * encoder,
930     const guint8 * nal, guint32 size)
931 {
932   guint8 nal_type;
933   G_GNUC_UNUSED gsize ret;      /* FIXME */
934   gboolean has_subset_sps;
935
936   g_assert (size);
937
938   has_subset_sps = !encoder->is_mvc || (encoder->subset_sps_data != NULL);
939   if (encoder->sps_data && encoder->pps_data && has_subset_sps)
940     return;
941
942   nal_type = nal[0] & 0x1F;
943   switch (nal_type) {
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);
948       break;
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);
953       break;
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);
958       break;
959     default:
960       break;
961   }
962 }
963
964 /* Determines the largest supported profile by the underlying hardware */
965 static gboolean
966 ensure_hw_profile_limits (GstVaapiEncoderH264 * encoder)
967 {
968   GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
969   GArray *profiles;
970   guint i, profile_idc, max_profile_idc;
971
972   if (encoder->hw_max_profile_idc)
973     return TRUE;
974
975   profiles = gst_vaapi_display_get_encode_profiles (display);
976   if (!profiles)
977     return FALSE;
978
979   max_profile_idc = 0;
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);
984     if (!profile_idc)
985       continue;
986     if (max_profile_idc < profile_idc)
987       max_profile_idc = profile_idc;
988   }
989   g_array_unref (profiles);
990
991   encoder->hw_max_profile_idc = max_profile_idc;
992   return TRUE;
993 }
994
995 /* Derives the profile supported by the underlying hardware */
996 static gboolean
997 ensure_hw_profile (GstVaapiEncoderH264 * encoder)
998 {
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;
1003
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;
1009       // fall-through
1010     case GST_VAAPI_PROFILE_H264_MAIN:
1011       profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_HIGH;
1012       break;
1013     default:
1014       break;
1015   }
1016
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];
1021       break;
1022     }
1023   }
1024   if (profile == GST_VAAPI_PROFILE_UNKNOWN)
1025     goto error_unsupported_profile;
1026
1027   GST_VAAPI_ENCODER_CAST (encoder)->profile = profile;
1028   return TRUE;
1029
1030   /* ERRORS */
1031 error_unsupported_profile:
1032   {
1033     GST_ERROR ("unsupported HW profile %s",
1034         gst_vaapi_profile_get_name (encoder->profile));
1035     return FALSE;
1036   }
1037 }
1038
1039 /* Check target decoder constraints */
1040 static gboolean
1041 ensure_profile_limits (GstVaapiEncoderH264 * encoder)
1042 {
1043   GstVaapiProfile profile;
1044
1045   if (!encoder->max_profile_idc
1046       || encoder->profile_idc == encoder->max_profile_idc)
1047     return TRUE;
1048
1049   /* Give an error if the given parameters are invalid for requested
1050    * profile rather than lowering profile.
1051    */
1052   if (encoder->profile_idc > encoder->max_profile_idc) {
1053     GST_WARNING ("Invalid parameter for maximum profile");
1054     return FALSE;
1055   }
1056
1057   profile = GST_VAAPI_PROFILE_UNKNOWN;
1058
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;
1064
1065     if (encoder->max_profile_idc > GST_H264_PROFILE_MAIN)
1066       profile = GST_VAAPI_PROFILE_H264_HIGH;
1067
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;
1073     }
1074   }
1075
1076   if (profile) {
1077     encoder->profile = profile;
1078     encoder->profile_idc = encoder->max_profile_idc;
1079   }
1080   return TRUE;
1081 }
1082
1083 /* Derives the minimum profile from the active coding tools */
1084 static gboolean
1085 ensure_profile (GstVaapiEncoderH264 * encoder)
1086 {
1087   GstVaapiProfile profile;
1088
1089   /* Always start from "constrained-baseline" profile for maximum
1090      compatibility */
1091   profile = GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
1092
1093   /* Main profile coding tools */
1094   if (encoder->num_bframes > 0 || encoder->use_cabac)
1095     profile = GST_VAAPI_PROFILE_H264_MAIN;
1096
1097   /* High profile coding tools */
1098   if (encoder->use_dct8x8)
1099     profile = GST_VAAPI_PROFILE_H264_HIGH;
1100
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;
1106
1107   encoder->profile = profile;
1108   encoder->profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
1109   return TRUE;
1110 }
1111
1112 /* Derives the level from the currently set limits */
1113 static gboolean
1114 ensure_level (GstVaapiEncoderH264 * encoder)
1115 {
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;
1119
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));
1124
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)))
1134       break;
1135   }
1136   if (i == num_limits)
1137     goto error_unsupported_level;
1138
1139   encoder->level = limits_table[i].level;
1140   encoder->level_idc = limits_table[i].level_idc;
1141   return TRUE;
1142
1143   /* ERRORS */
1144 error_unsupported_level:
1145   {
1146     GST_ERROR ("failed to find a suitable level matching codec config");
1147     return FALSE;
1148   }
1149 }
1150
1151 /* Enable "high-compression" tuning options */
1152 static gboolean
1153 ensure_tuning_high_compression (GstVaapiEncoderH264 * encoder)
1154 {
1155   guint8 profile_idc;
1156
1157   if (!ensure_hw_profile_limits (encoder))
1158     return FALSE;
1159
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;
1163
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;
1170   }
1171
1172   /* Tuning options to enable High profile */
1173   if (profile_idc >= GST_H264_PROFILE_HIGH) {
1174     encoder->use_dct8x8 = TRUE;
1175   }
1176   return TRUE;
1177 }
1178
1179 /* Ensure tuning options */
1180 static gboolean
1181 ensure_tuning (GstVaapiEncoderH264 * encoder)
1182 {
1183   gboolean success;
1184
1185   switch (GST_VAAPI_ENCODER_TUNE (encoder)) {
1186     case GST_VAAPI_ENCODER_TUNE_HIGH_COMPRESSION:
1187       success = ensure_tuning_high_compression (encoder);
1188       break;
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;
1195       success = TRUE;
1196       break;
1197     default:
1198       success = TRUE;
1199       break;
1200   }
1201   return success;
1202 }
1203
1204 /* Handle new GOP starts */
1205 static void
1206 reset_gop_start (GstVaapiEncoderH264 * encoder)
1207 {
1208   GstVaapiH264ViewReorderPool *const reorder_pool =
1209       &encoder->reorder_pools[encoder->view_idx];
1210
1211   reorder_pool->frame_index = 1;
1212   reorder_pool->cur_frame_num = 0;
1213   reorder_pool->cur_present_index = 0;
1214   ++encoder->idr_num;
1215 }
1216
1217 /* Marks the supplied picture as a B-frame */
1218 static void
1219 set_b_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1220 {
1221   GstVaapiH264ViewReorderPool *const reorder_pool =
1222       &encoder->reorder_pools[encoder->view_idx];
1223
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);
1228 }
1229
1230 /* Marks the supplied picture as a P-frame */
1231 static void
1232 set_p_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1233 {
1234   GstVaapiH264ViewReorderPool *const reorder_pool =
1235       &encoder->reorder_pools[encoder->view_idx];
1236
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);
1240 }
1241
1242 /* Marks the supplied picture as an I-frame */
1243 static void
1244 set_i_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1245 {
1246   GstVaapiH264ViewReorderPool *const reorder_pool =
1247       &encoder->reorder_pools[encoder->view_idx];
1248
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);
1252
1253   g_assert (pic->frame);
1254   GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1255 }
1256
1257 /* Marks the supplied picture as an IDR frame */
1258 static void
1259 set_idr_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1260 {
1261   g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1262   pic->type = GST_VAAPI_PICTURE_TYPE_I;
1263   pic->frame_num = 0;
1264   pic->poc = 0;
1265   GST_VAAPI_ENC_PICTURE_FLAG_SET (pic, GST_VAAPI_ENC_PICTURE_FLAG_IDR);
1266
1267   g_assert (pic->frame);
1268   GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1269 }
1270
1271 /* Marks the supplied picture a a key-frame */
1272 static void
1273 set_key_frame (GstVaapiEncPicture * picture,
1274     GstVaapiEncoderH264 * encoder, gboolean is_idr)
1275 {
1276   if (is_idr) {
1277     reset_gop_start (encoder);
1278     set_idr_frame (picture, encoder);
1279   } else
1280     set_i_frame (picture, encoder);
1281 }
1282
1283 /* Fills in VA HRD parameters */
1284 static void
1285 fill_hrd_params (GstVaapiEncoderH264 * encoder, VAEncMiscParameterHRD * hrd)
1286 {
1287   if (encoder->bitrate_bits > 0) {
1288     hrd->buffer_size = encoder->cpb_length_bits;
1289     hrd->initial_buffer_fullness = hrd->buffer_size / 2;
1290   } else {
1291     hrd->buffer_size = 0;
1292     hrd->initial_buffer_fullness = 0;
1293   }
1294 }
1295
1296 /* Adds the supplied sequence header (SPS) to the list of packed
1297    headers to pass down as-is to the encoder */
1298 static gboolean
1299 add_packed_sequence_header (GstVaapiEncoderH264 * encoder,
1300     GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1301 {
1302   GstVaapiEncPackedHeader *packed_seq;
1303   GstBitWriter bs;
1304   VAEncPackedHeaderParameterBuffer packed_seq_param = { 0 };
1305   const VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1306   GstVaapiProfile profile = encoder->profile;
1307
1308   VAEncMiscParameterHRD hrd_params;
1309   guint32 data_bit_size;
1310   guint8 *data;
1311
1312   fill_hrd_params (encoder, &hrd_params);
1313
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);
1317
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;
1324
1325   bs_write_sps (&bs, seq_param, profile, &hrd_params);
1326
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);
1330
1331   packed_seq_param.type = VAEncPackedHeaderSequence;
1332   packed_seq_param.bit_length = data_bit_size;
1333   packed_seq_param.has_emulation_bytes = 0;
1334
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);
1339
1340   gst_vaapi_enc_picture_add_packed_header (picture, packed_seq);
1341   gst_vaapi_codec_object_replace (&packed_seq, NULL);
1342
1343   /* store sps data */
1344   _check_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1345   gst_bit_writer_clear (&bs, TRUE);
1346   return TRUE;
1347
1348   /* ERRORS */
1349 bs_error:
1350   {
1351     GST_WARNING ("failed to write SPS NAL unit");
1352     gst_bit_writer_clear (&bs, TRUE);
1353     return FALSE;
1354   }
1355 }
1356
1357 static gboolean
1358 add_packed_sequence_header_mvc (GstVaapiEncoderH264 * encoder,
1359     GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1360 {
1361   GstVaapiEncPackedHeader *packed_seq;
1362   GstBitWriter bs;
1363   VAEncPackedHeaderParameterBuffer packed_header_param_buffer = { 0 };
1364   const VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1365   VAEncMiscParameterHRD hrd_params;
1366   guint32 data_bit_size;
1367   guint8 *data;
1368
1369   fill_hrd_params (encoder, &hrd_params);
1370
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);
1375
1376   bs_write_subset_sps (&bs, seq_param, encoder->profile, encoder->num_views,
1377       encoder->view_ids, &hrd_params);
1378
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);
1382
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;
1386
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);
1391
1392   gst_vaapi_enc_picture_add_packed_header (picture, packed_seq);
1393   gst_vaapi_mini_object_replace ((GstVaapiMiniObject **) & packed_seq, NULL);
1394
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);
1398   return TRUE;
1399
1400   /* ERRORS */
1401 bs_error:
1402   {
1403     GST_WARNING ("failed to write SPS NAL unit");
1404     gst_bit_writer_clear (&bs, TRUE);
1405     return FALSE;
1406   }
1407 }
1408
1409 /* Adds the supplied picture header (PPS) to the list of packed
1410    headers to pass down as-is to the encoder */
1411 static gboolean
1412 add_packed_picture_header (GstVaapiEncoderH264 * encoder,
1413     GstVaapiEncPicture * picture)
1414 {
1415   GstVaapiEncPackedHeader *packed_pic;
1416   GstBitWriter bs;
1417   VAEncPackedHeaderParameterBuffer packed_pic_param = { 0 };
1418   const VAEncPictureParameterBufferH264 *const pic_param = picture->param;
1419   guint32 data_bit_size;
1420   guint8 *data;
1421
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);
1429
1430   packed_pic_param.type = VAEncPackedHeaderPicture;
1431   packed_pic_param.bit_length = data_bit_size;
1432   packed_pic_param.has_emulation_bytes = 0;
1433
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);
1438
1439   gst_vaapi_enc_picture_add_packed_header (picture, packed_pic);
1440   gst_vaapi_codec_object_replace (&packed_pic, NULL);
1441
1442   /* store pps data */
1443   _check_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1444   gst_bit_writer_clear (&bs, TRUE);
1445   return TRUE;
1446
1447   /* ERRORS */
1448 bs_error:
1449   {
1450     GST_WARNING ("failed to write PPS NAL unit");
1451     gst_bit_writer_clear (&bs, TRUE);
1452     return FALSE;
1453   }
1454 }
1455
1456 static gboolean
1457 add_packed_sei_header (GstVaapiEncoderH264 * encoder,
1458     GstVaapiEncPicture * picture, GstVaapiH264SeiPayloadType payloadtype)
1459 {
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;
1467
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);
1471
1472   need_buf_period = GST_VAAPI_H264_SEI_BUF_PERIOD & payloadtype;
1473   need_pic_timing = GST_VAAPI_H264_SEI_PIC_TIMING & payloadtype;
1474
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);
1483   }
1484
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);
1494   }
1495
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);
1499
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);
1505   }
1506
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);
1512   }
1513
1514   /* rbsp_trailing_bits */
1515   bs_write_trailing_bits (&bs);
1516
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);
1520
1521   packed_sei_param.type = VAEncPackedHeaderH264_SEI;
1522   packed_sei_param.bit_length = data_bit_size;
1523   packed_sei_param.has_emulation_bytes = 0;
1524
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);
1529
1530   gst_vaapi_enc_picture_add_packed_header (picture, packed_sei);
1531   gst_vaapi_codec_object_replace (&packed_sei, NULL);
1532
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);
1536   return TRUE;
1537
1538   /* ERRORS */
1539 bs_error:
1540   {
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);
1545     return FALSE;
1546   }
1547 }
1548
1549 static gboolean
1550 get_nal_hdr_attributes (GstVaapiEncPicture * picture,
1551     guint8 * nal_ref_idc, guint8 * nal_unit_type)
1552 {
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;
1558       else
1559         *nal_unit_type = GST_H264_NAL_SLICE;
1560       break;
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;
1564       break;
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;
1568       break;
1569     default:
1570       return FALSE;
1571   }
1572   return TRUE;
1573 }
1574
1575 /* Adds the supplied prefix nal header to the list of packed
1576    headers to pass down as-is to the encoder */
1577 static gboolean
1578 add_packed_prefix_nal_header (GstVaapiEncoderH264 * encoder,
1579     GstVaapiEncPicture * picture, GstVaapiEncSlice * slice)
1580 {
1581   GstVaapiEncPackedHeader *packed_prefix_nal;
1582   GstBitWriter bs;
1583   VAEncPackedHeaderParameterBuffer packed_prefix_nal_param = { 0 };
1584   guint32 data_bit_size;
1585   guint8 *data;
1586   guint8 nal_ref_idc, nal_unit_type;
1587
1588   gst_bit_writer_init (&bs, 128 * 8);
1589   WRITE_UINT32 (&bs, 0x00000001, 32);   /* start code */
1590
1591   if (!get_nal_hdr_attributes (picture, &nal_ref_idc, &nal_unit_type))
1592     goto bs_error;
1593   nal_unit_type = GST_H264_NAL_PREFIX_UNIT;
1594
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);
1600
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;
1604
1605   packed_prefix_nal =
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);
1610
1611   gst_vaapi_enc_slice_add_packed_header (slice, packed_prefix_nal);
1612   gst_vaapi_codec_object_replace (&packed_prefix_nal, NULL);
1613
1614   gst_bit_writer_clear (&bs, TRUE);
1615
1616   return TRUE;
1617
1618   /* ERRORS */
1619 bs_error:
1620   {
1621     GST_WARNING ("failed to write Prefix NAL unit header");
1622     gst_bit_writer_clear (&bs, TRUE);
1623     return FALSE;
1624   }
1625 }
1626
1627 /* Adds the supplied slice header to the list of packed
1628    headers to pass down as-is to the encoder */
1629 static gboolean
1630 add_packed_slice_header (GstVaapiEncoderH264 * encoder,
1631     GstVaapiEncPicture * picture, GstVaapiEncSlice * slice)
1632 {
1633   GstVaapiEncPackedHeader *packed_slice;
1634   GstBitWriter bs;
1635   VAEncPackedHeaderParameterBuffer packed_slice_param = { 0 };
1636   const VAEncSliceParameterBufferH264 *const slice_param = slice->param;
1637   guint32 data_bit_size;
1638   guint8 *data;
1639   guint8 nal_ref_idc, nal_unit_type;
1640
1641   gst_bit_writer_init (&bs, 128 * 8);
1642   WRITE_UINT32 (&bs, 0x00000001, 32);   /* start code */
1643
1644   if (!get_nal_hdr_attributes (picture, &nal_ref_idc, &nal_unit_type))
1645     goto bs_error;
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]);
1651   } else
1652     bs_write_nal_header (&bs, nal_ref_idc, nal_unit_type);
1653
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);
1657
1658   packed_slice_param.type = VAEncPackedHeaderSlice;
1659   packed_slice_param.bit_length = data_bit_size;
1660   packed_slice_param.has_emulation_bytes = 0;
1661
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);
1666
1667   gst_vaapi_enc_slice_add_packed_header (slice, packed_slice);
1668   gst_vaapi_codec_object_replace (&packed_slice, NULL);
1669
1670   gst_bit_writer_clear (&bs, TRUE);
1671   return TRUE;
1672
1673   /* ERRORS */
1674 bs_error:
1675   {
1676     GST_WARNING ("failed to write Slice NAL unit header");
1677     gst_bit_writer_clear (&bs, TRUE);
1678     return FALSE;
1679   }
1680 }
1681
1682 /* Reference picture management */
1683 static void
1684 reference_pic_free (GstVaapiEncoderH264 * encoder, GstVaapiEncoderH264Ref * ref)
1685 {
1686   if (!ref)
1687     return;
1688   if (ref->pic)
1689     gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), ref->pic);
1690   g_slice_free (GstVaapiEncoderH264Ref, ref);
1691 }
1692
1693 static inline GstVaapiEncoderH264Ref *
1694 reference_pic_create (GstVaapiEncoderH264 * encoder,
1695     GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1696 {
1697   GstVaapiEncoderH264Ref *const ref = g_slice_new0 (GstVaapiEncoderH264Ref);
1698
1699   ref->pic = surface;
1700   ref->frame_num = picture->frame_num;
1701   ref->poc = picture->poc;
1702   return ref;
1703 }
1704
1705 static gboolean
1706 reference_list_update (GstVaapiEncoderH264 * encoder,
1707     GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1708 {
1709   GstVaapiEncoderH264Ref *ref;
1710   GstVaapiH264ViewRefPool *const ref_pool =
1711       &encoder->ref_pools[encoder->view_idx];
1712
1713   if (GST_VAAPI_PICTURE_TYPE_B == picture->type) {
1714     gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), surface);
1715     return TRUE;
1716   }
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));
1723   }
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);
1728   return TRUE;
1729 }
1730
1731 static gboolean
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)
1737 {
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;
1742   guint count;
1743
1744   *reflist_0_count = 0;
1745   *reflist_1_count = 0;
1746   if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
1747     return TRUE;
1748
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);
1756       break;
1757     }
1758   }
1759
1760   /* order reflist_0 */
1761   g_assert (list_0_start);
1762   iter = list_0_start;
1763   count = 0;
1764   for (; iter; iter = g_list_previous (iter)) {
1765     reflist_0[count] = (GstVaapiEncoderH264Ref *) iter->data;
1766     ++count;
1767   }
1768   *reflist_0_count = count;
1769
1770   if (picture->type != GST_VAAPI_PICTURE_TYPE_B)
1771     return TRUE;
1772
1773   /* order reflist_1 */
1774   count = 0;
1775   iter = list_1_start;
1776   for (; iter; iter = g_list_next (iter)) {
1777     reflist_1[count] = (GstVaapiEncoderH264Ref *) iter->data;
1778     ++count;
1779   }
1780   *reflist_1_count = count;
1781   return TRUE;
1782 }
1783
1784 /* Fills in VA sequence parameter buffer */
1785 static gboolean
1786 fill_sequence (GstVaapiEncoderH264 * encoder, GstVaapiEncSequence * sequence)
1787 {
1788   VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1789   GstVaapiH264ViewRefPool *const ref_pool =
1790       &encoder->ref_pools[encoder->view_idx];
1791
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;
1801
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;
1805
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 =
1819       0;
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;
1823
1824   seq_param->bit_depth_luma_minus8 = 0;
1825   seq_param->bit_depth_chroma_minus8 = 0;
1826
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));
1836   }
1837
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);
1848
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;
1858   }
1859
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);
1869     }
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;
1877     }
1878   }
1879   return TRUE;
1880 }
1881
1882 /* Fills in VA picture parameter buffer */
1883 static gboolean
1884 fill_picture (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture,
1885     GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface)
1886 {
1887   VAEncPictureParameterBufferH264 *const pic_param = picture->param;
1888   GstVaapiH264ViewRefPool *const ref_pool =
1889       &encoder->ref_pools[encoder->view_idx];
1890   GstVaapiEncoderH264Ref *ref_pic;
1891   GList *reflist;
1892   guint i;
1893
1894   memset (pic_param, 0, sizeof (VAEncPictureParameterBufferH264));
1895
1896   /* reference list,  */
1897   pic_param->CurrPic.picture_id = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface);
1898   pic_param->CurrPic.TopFieldOrderCnt = picture->poc;
1899   i = 0;
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);
1906
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;
1913       ++i;
1914     }
1915     g_assert (i <= 16 && i <= ref_pool->max_ref_frames);
1916   }
1917   for (; i < 16; ++i) {
1918     pic_param->ReferenceFrames[i].picture_id = VA_INVALID_ID;
1919   }
1920   pic_param->coded_buf = GST_VAAPI_OBJECT_ID (codedbuf);
1921
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;
1933
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;
1951
1952   return TRUE;
1953 }
1954
1955 /* Adds slice headers to picture */
1956 static gboolean
1957 add_slice_headers (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture,
1958     GstVaapiEncoderH264Ref ** reflist_0, guint reflist_0_count,
1959     GstVaapiEncoderH264Ref ** reflist_1, guint reflist_1_count)
1960 {
1961   VAEncSliceParameterBufferH264 *slice_param;
1962   GstVaapiEncSlice *slice;
1963   guint slice_of_mbs, slice_mod_mbs, cur_slice_mbs;
1964   guint mb_size;
1965   guint last_mb_index;
1966   guint i_slice, i_ref;
1967
1968   g_assert (picture);
1969
1970   mb_size = encoder->mb_width * encoder->mb_height;
1971
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;
1975   last_mb_index = 0;
1976   for (i_slice = 0; i_slice < encoder->num_slices; ++i_slice) {
1977     cur_slice_mbs = slice_of_mbs;
1978     if (slice_mod_mbs) {
1979       ++cur_slice_mbs;
1980       --slice_mod_mbs;
1981     }
1982     slice = GST_VAAPI_ENC_SLICE_NEW (H264, encoder);
1983     g_assert (slice && slice->param_id != VA_INVALID_ID);
1984     slice_param = slice->param;
1985
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;
1995
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));
2000
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;
2007     else
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;
2011     else
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);
2015
2016     i_ref = 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;
2026       }
2027       g_assert (i_ref == 1);
2028     }
2029     for (; i_ref < G_N_ELEMENTS (slice_param->RefPicList0); ++i_ref) {
2030       slice_param->RefPicList0[i_ref].picture_id = VA_INVALID_SURFACE;
2031     }
2032
2033     i_ref = 0;
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;
2044       }
2045       g_assert (i_ref == 1);
2046     }
2047     for (; i_ref < G_N_ELEMENTS (slice_param->RefPicList1); ++i_ref) {
2048       slice_param->RefPicList1[i_ref].picture_id = VA_INVALID_SURFACE;
2049     }
2050
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));
2074
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;
2082
2083     /* set calculation for next slice */
2084     last_mb_index += cur_slice_mbs;
2085
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;
2096
2097     gst_vaapi_enc_picture_add_slice (picture, slice);
2098     gst_vaapi_codec_object_replace (&slice, NULL);
2099   }
2100   g_assert (last_mb_index == mb_size);
2101   return TRUE;
2102
2103 error_create_packed_slice_hdr:
2104   {
2105     GST_ERROR ("failed to create packed slice header buffer");
2106     gst_vaapi_codec_object_replace (&slice, NULL);
2107     return FALSE;
2108   }
2109 error_create_packed_prefix_nal_hdr:
2110   {
2111     GST_ERROR ("failed to create packed prefix nal header buffer");
2112     gst_vaapi_codec_object_replace (&slice, NULL);
2113     return FALSE;
2114   }
2115 }
2116
2117 /* Generates and submits SPS header accordingly into the bitstream */
2118 static gboolean
2119 ensure_sequence (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
2120 {
2121   GstVaapiEncSequence *sequence = NULL;
2122
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)
2125     return TRUE;
2126
2127   sequence = GST_VAAPI_ENC_SEQUENCE_NEW (H264, encoder);
2128   if (!sequence || !fill_sequence (encoder, sequence))
2129     goto error_create_seq_param;
2130
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;
2137   } else {
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;
2142   }
2143
2144   if (sequence) {
2145     gst_vaapi_enc_picture_set_sequence (picture, sequence);
2146     gst_vaapi_codec_object_replace (&sequence, NULL);
2147   }
2148
2149   if (!encoder->is_mvc || encoder->view_idx > 0)
2150     encoder->config_changed = FALSE;
2151   return TRUE;
2152
2153   /* ERRORS */
2154 error_create_seq_param:
2155   {
2156     GST_ERROR ("failed to create sequence parameter buffer (SPS)");
2157     gst_vaapi_codec_object_replace (&sequence, NULL);
2158     return FALSE;
2159   }
2160 error_create_packed_seq_hdr:
2161   {
2162     GST_ERROR ("failed to create packed sequence header buffer");
2163     gst_vaapi_codec_object_replace (&sequence, NULL);
2164     return FALSE;
2165   }
2166 }
2167
2168 static gboolean
2169 ensure_control_rate_params (GstVaapiEncoderH264 * encoder)
2170 {
2171   if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP)
2172     return TRUE;
2173
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;
2180
2181   /* HRD params */
2182   fill_hrd_params (encoder, &GST_VAAPI_ENCODER_VA_HRD (encoder));
2183
2184   return TRUE;
2185 }
2186
2187 /* Generates additional control parameters */
2188 static gboolean
2189 ensure_misc_params (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
2190 {
2191   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2192 #if VA_CHECK_VERSION(0,39,1)
2193   GstVaapiEncMiscParam *misc;
2194   guint num_roi;
2195 #endif
2196
2197   if (!gst_vaapi_encoder_ensure_param_control_rate (base_encoder, picture))
2198     return FALSE;
2199
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;
2209
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;
2216     }
2217   }
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;
2222   if (num_roi > 0) {
2223     /* ROI(Region of Interest) params */
2224     VAEncMiscParameterBufferROI *roi_param;
2225     VAEncROI *region_roi;
2226     gpointer ptr;
2227     GList *tmp;
2228
2229     misc =
2230         gst_vaapi_enc_misc_param_new (base_encoder, VAEncMiscParameterTypeROI,
2231         sizeof (VAEncMiscParameterBufferROI) + num_roi * sizeof (VAEncROI));
2232
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;
2237
2238     ptr = (guchar *) misc->param + sizeof (VAEncMiscParameterBuffer) +
2239         sizeof (VAEncMiscParameterBufferROI);
2240     region_roi = ptr;
2241
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;
2249       region_roi++;
2250     }
2251
2252     roi_param->roi = ptr;
2253     roi_param->num_roi = num_roi;
2254
2255     gst_vaapi_enc_picture_add_misc_param (picture, misc);
2256     gst_vaapi_codec_object_replace (&misc, NULL);
2257   }
2258 #endif
2259
2260   if (!gst_vaapi_encoder_ensure_param_quality_level (base_encoder, picture))
2261     return FALSE;
2262
2263   return TRUE;
2264
2265 error_create_packed_sei_hdr:
2266   {
2267     GST_ERROR ("failed to create packed SEI header");
2268     return FALSE;
2269   }
2270 }
2271
2272 /* Generates and submits PPS header accordingly into the bitstream */
2273 static gboolean
2274 ensure_picture (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture,
2275     GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface)
2276 {
2277   GstVaapiCodedBuffer *const codedbuf =
2278       GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy);
2279   gboolean res = FALSE;
2280
2281   res = fill_picture (encoder, picture, codedbuf, surface);
2282
2283   if (!res)
2284     return FALSE;
2285
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");
2291     return FALSE;
2292   }
2293   return TRUE;
2294 }
2295
2296 /* Generates slice headers */
2297 static gboolean
2298 ensure_slices (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
2299 {
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;
2305
2306   g_assert (picture);
2307
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");
2312     return FALSE;
2313   }
2314
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;
2320
2321   if (!add_slice_headers (encoder, picture,
2322           reflist_0, reflist_0_count, reflist_1, reflist_1_count))
2323     return FALSE;
2324
2325   return TRUE;
2326 }
2327
2328 /* Normalizes bitrate (and CPB size) for HRD conformance */
2329 static void
2330 ensure_bitrate_hrd (GstVaapiEncoderH264 * encoder)
2331 {
2332   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2333   guint bitrate, cpb_size;
2334
2335   if (!base_encoder->bitrate) {
2336     encoder->bitrate_bits = 0;
2337     return;
2338   }
2339
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;
2347   }
2348
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;
2357   }
2358 }
2359
2360 /* Estimates a good enough bitrate if none was supplied */
2361 static void
2362 ensure_bitrate (GstVaapiEncoderH264 * encoder)
2363 {
2364   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2365
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;
2377         guint64 factor;
2378
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;
2383
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);
2389       }
2390       break;
2391     default:
2392       base_encoder->bitrate = 0;
2393       break;
2394   }
2395   ensure_bitrate_hrd (encoder);
2396 }
2397
2398 /* Constructs profile and level information based on user-defined limits */
2399 static GstVaapiEncoderStatus
2400 ensure_profile_and_level (GstVaapiEncoderH264 * encoder)
2401 {
2402   const GstVaapiProfile profile = encoder->profile;
2403   const GstVaapiLevelH264 level = encoder->level;
2404
2405   if (!ensure_tuning (encoder))
2406     GST_WARNING ("Failed to set some of the tuning option as expected! ");
2407
2408   if (!ensure_profile (encoder) || !ensure_profile_limits (encoder))
2409     return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2410
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;
2416
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;
2421
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;
2427   }
2428   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2429 }
2430
2431 static void
2432 reset_properties (GstVaapiEncoderH264 * encoder)
2433 {
2434   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2435   guint mb_size, i;
2436
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;
2441
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;
2446
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));
2450
2451   if (encoder->num_bframes > (base_encoder->keyframe_period + 1) / 2)
2452     encoder->num_bframes = (base_encoder->keyframe_period + 1) / 2;
2453
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.
2457    *
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)) {
2463     GST_WARNING
2464         ("Disabling b-frame since the driver doesn't supporting it in low-power encode");
2465     encoder->num_bframes = 0;
2466   }
2467
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));
2471   else
2472     encoder->cts_offset = 0;
2473
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;
2482
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];
2487
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;
2492
2493     reorder_pool->frame_index = 0;
2494   }
2495 }
2496
2497 static GstVaapiEncoderStatus
2498 gst_vaapi_encoder_h264_encode (GstVaapiEncoder * base_encoder,
2499     GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf)
2500 {
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;
2505
2506   reconstruct = gst_vaapi_encoder_create_surface (base_encoder);
2507
2508   g_assert (GST_VAAPI_SURFACE_PROXY_SURFACE (reconstruct));
2509
2510   if (!ensure_sequence (encoder, picture))
2511     goto error;
2512   if (!ensure_misc_params (encoder, picture))
2513     goto error;
2514   if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
2515     goto error;
2516   if (!ensure_slices (encoder, picture))
2517     goto error;
2518   if (!gst_vaapi_enc_picture_encode (picture))
2519     goto error;
2520
2521   if (!reference_list_update (encoder, picture, reconstruct))
2522     goto error;
2523
2524   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2525
2526   /* ERRORS */
2527 error:
2528   {
2529     if (reconstruct)
2530       gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
2531           reconstruct);
2532     return ret;
2533   }
2534 }
2535
2536 static GstVaapiEncoderStatus
2537 gst_vaapi_encoder_h264_flush (GstVaapiEncoder * base_encoder)
2538 {
2539   GstVaapiEncoderH264 *const encoder =
2540       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2541   GstVaapiH264ViewReorderPool *reorder_pool;
2542   GstVaapiEncPicture *pic;
2543   guint i;
2544
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;
2550
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);
2555     }
2556     g_queue_clear (&reorder_pool->reorder_frame_list);
2557   }
2558
2559   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2560 }
2561
2562 /* Generate "codec-data" buffer */
2563 static GstVaapiEncoderStatus
2564 gst_vaapi_encoder_h264_get_codec_data (GstVaapiEncoder * base_encoder,
2565     GstBuffer ** out_buffer_ptr)
2566 {
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;
2573   GstBitWriter bs;
2574   GstBuffer *buffer;
2575
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;
2580
2581   if (!gst_buffer_map (encoder->sps_data, &sps_info, GST_MAP_READ))
2582     goto error_map_sps_buffer;
2583
2584   if (!gst_buffer_map (encoder->pps_data, &pps_info, GST_MAP_READ))
2585     goto error_map_pps_buffer;
2586
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];
2591
2592   /* Header */
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 */
2601
2602   /* Write SPS */
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;
2608
2609   /* Write PPS */
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;
2614
2615   gst_buffer_unmap (encoder->pps_data, &pps_info);
2616   gst_buffer_unmap (encoder->sps_data, &sps_info);
2617
2618   buffer = gst_buffer_new_wrapped (GST_BIT_WRITER_DATA (&bs),
2619       GST_BIT_WRITER_BIT_SIZE (&bs) / 8);
2620   if (!buffer)
2621     goto error_alloc_buffer;
2622   *out_buffer_ptr = buffer;
2623
2624   gst_bit_writer_clear (&bs, FALSE);
2625   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2626
2627   /* ERRORS */
2628 bs_error:
2629   {
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;
2635   }
2636 nal_to_byte_stream_error:
2637   {
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;
2643   }
2644 error_map_sps_buffer:
2645   {
2646     GST_ERROR ("failed to map SPS packed header");
2647     return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2648   }
2649 error_map_pps_buffer:
2650   {
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;
2654   }
2655 error_alloc_buffer:
2656   {
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;
2660   }
2661 }
2662
2663 static GstVaapiEncoderStatus
2664 gst_vaapi_encoder_h264_reordering (GstVaapiEncoder * base_encoder,
2665     GstVideoCodecFrame * frame, GstVaapiEncPicture ** output)
2666 {
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;
2672
2673   *output = NULL;
2674
2675   /* encoding views alternatively for MVC */
2676   if (encoder->is_mvc) {
2677     /* FIXME: Use first-in-bundle flag on buffers to reset view idx? */
2678     if (frame)
2679       encoder->view_idx = frame->system_frame_number % encoder->num_views;
2680     else
2681       encoder->view_idx = (encoder->view_idx + 1) % encoder->num_views;
2682   }
2683   reorder_pool = &encoder->reorder_pools[encoder->view_idx];
2684
2685   if (!frame) {
2686     if (reorder_pool->reorder_state != GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES)
2687       return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
2688
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);
2695     g_assert (picture);
2696     if (g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2697       reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES;
2698     }
2699     goto end;
2700   }
2701
2702   /* new frame coming */
2703   picture = GST_VAAPI_ENC_PICTURE_NEW (H264, encoder, frame);
2704   if (!picture) {
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;
2708   }
2709   ++reorder_pool->cur_present_index;
2710   picture->poc = ((reorder_pool->cur_present_index * 2) %
2711       encoder->max_pic_order_cnt);
2712
2713   is_idr = (reorder_pool->frame_index == 0 ||
2714       reorder_pool->frame_index >= encoder->idr_period);
2715
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;
2722
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;
2727
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);
2735       picture = p_pic;
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;
2742     }
2743     goto end;
2744   }
2745
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;
2753   }
2754
2755   ++reorder_pool->cur_frame_num;
2756   set_p_frame (picture, encoder);
2757
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,
2760         encoder);
2761     reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES;
2762     g_assert (!g_queue_is_empty (&reorder_pool->reorder_frame_list));
2763   }
2764
2765 end:
2766   g_assert (picture);
2767   frame = picture->frame;
2768   if (GST_CLOCK_TIME_IS_VALID (frame->pts))
2769     frame->pts += encoder->cts_offset;
2770   *output = picture;
2771
2772   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2773 }
2774
2775 static GstVaapiEncoderStatus
2776 set_context_info (GstVaapiEncoder * base_encoder)
2777 {
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;
2782
2783   /* Maximum sizes for common headers (in bits) */
2784   enum
2785   {
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,
2791   };
2792
2793   if (!ensure_hw_profile (encoder))
2794     return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2795
2796   base_encoder->num_ref_frames =
2797       ((encoder->num_bframes ? 2 : 1) + DEFAULT_SURFACES_COUNT)
2798       * encoder->num_views;
2799
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;
2805
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;
2810
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;
2814
2815   /* Account for slice header */
2816   base_encoder->codedbuf_size += encoder->num_slices * (4 +
2817       GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8);
2818
2819   base_encoder->context_info.entrypoint = encoder->entrypoint;
2820
2821   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2822 }
2823
2824 static GstVaapiEncoderStatus
2825 gst_vaapi_encoder_h264_reconfigure (GstVaapiEncoder * base_encoder)
2826 {
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;
2832
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;
2841   }
2842
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);
2849
2850   encoder->is_mvc = encoder->num_views > 1;
2851
2852   status = ensure_profile_and_level (encoder);
2853   if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
2854     return status;
2855
2856   reset_properties (encoder);
2857   ensure_control_rate_params (encoder);
2858   return set_context_info (base_encoder);
2859 }
2860
2861 static gboolean
2862 gst_vaapi_encoder_h264_init (GstVaapiEncoder * base_encoder)
2863 {
2864   GstVaapiEncoderH264 *const encoder =
2865       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2866   guint32 i;
2867
2868   /* Default encoding entrypoint */
2869   encoder->entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
2870
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));
2876
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;
2886   }
2887
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;
2895   }
2896
2897   return TRUE;
2898 }
2899
2900 static void
2901 gst_vaapi_encoder_h264_finalize (GstVaapiEncoder * base_encoder)
2902 {
2903   /*free private buffers */
2904   GstVaapiEncoderH264 *const encoder =
2905       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2906   GstVaapiEncPicture *pic;
2907   GstVaapiEncoderH264Ref *ref;
2908   guint32 i;
2909
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);
2913
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);
2920     }
2921     g_queue_clear (&ref_pool->ref_list);
2922   }
2923
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);
2932     }
2933     g_queue_clear (&reorder_pool->reorder_frame_list);
2934   }
2935 }
2936
2937 static GstVaapiEncoderStatus
2938 gst_vaapi_encoder_h264_set_property (GstVaapiEncoder * base_encoder,
2939     gint prop_id, const GValue * value)
2940 {
2941   GstVaapiEncoderH264 *const encoder =
2942       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2943
2944   switch (prop_id) {
2945     case GST_VAAPI_ENCODER_H264_PROP_MAX_BFRAMES:
2946       encoder->num_bframes = g_value_get_uint (value);
2947       break;
2948     case GST_VAAPI_ENCODER_H264_PROP_INIT_QP:
2949       encoder->init_qp = g_value_get_uint (value);
2950       break;
2951     case GST_VAAPI_ENCODER_H264_PROP_MIN_QP:
2952       encoder->min_qp = g_value_get_uint (value);
2953       break;
2954     case GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES:
2955       encoder->num_slices = g_value_get_uint (value);
2956       break;
2957     case GST_VAAPI_ENCODER_H264_PROP_CABAC:
2958       encoder->use_cabac = g_value_get_boolean (value);
2959       break;
2960     case GST_VAAPI_ENCODER_H264_PROP_DCT8X8:
2961       encoder->use_dct8x8 = g_value_get_boolean (value);
2962       break;
2963     case GST_VAAPI_ENCODER_H264_PROP_CPB_LENGTH:
2964       encoder->cpb_length = g_value_get_uint (value);
2965       break;
2966     case GST_VAAPI_ENCODER_H264_PROP_NUM_VIEWS:
2967       encoder->num_views = g_value_get_uint (value);
2968       break;
2969     case GST_VAAPI_ENCODER_H264_PROP_VIEW_IDS:{
2970       guint i;
2971       GValueArray *view_ids = g_value_get_boxed (value);
2972
2973       if (view_ids == NULL) {
2974         for (i = 0; i < encoder->num_views; i++)
2975           encoder->view_ids[i] = i;
2976       } else {
2977         g_assert (view_ids->n_values <= encoder->num_views);
2978
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);
2982         }
2983       }
2984       break;
2985     }
2986     default:
2987       return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
2988   }
2989   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2990 }
2991
2992 GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (H264);
2993
2994 static inline const GstVaapiEncoderClass *
2995 gst_vaapi_encoder_h264_class (void)
2996 {
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
3001   };
3002   return &GstVaapiEncoderH264Class;
3003 }
3004
3005 /**
3006  * gst_vaapi_encoder_h264_new:
3007  * @display: a #GstVaapiDisplay
3008  *
3009  * Creates a new #GstVaapiEncoder for H.264 encoding. Note that the
3010  * only supported output stream format is "byte-stream" format.
3011  *
3012  * Return value: the newly allocated #GstVaapiEncoder object
3013  */
3014 GstVaapiEncoder *
3015 gst_vaapi_encoder_h264_new (GstVaapiDisplay * display)
3016 {
3017   return gst_vaapi_encoder_new (gst_vaapi_encoder_h264_class (), display);
3018 }
3019
3020 /**
3021  * gst_vaapi_encoder_h264_get_default_properties:
3022  *
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.
3027  *
3028  * Return value: the set of encoder properties for #GstVaapiEncoderH264,
3029  *   or %NULL if an error occurred.
3030  */
3031 GPtrArray *
3032 gst_vaapi_encoder_h264_get_default_properties (void)
3033 {
3034   const GstVaapiEncoderClass *const klass = gst_vaapi_encoder_h264_class ();
3035   GPtrArray *props;
3036
3037   props = gst_vaapi_encoder_properties_get_default (klass);
3038   if (!props)
3039     return NULL;
3040
3041   /**
3042    * GstVaapiEncoderH264:max-bframes:
3043    *
3044    * The number of B-frames between I and P.
3045    */
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));
3051
3052   /**
3053    * GstVaapiEncoderH264:init-qp:
3054    *
3055    * The initial quantizer value.
3056    */
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));
3062
3063   /**
3064    * GstVaapiEncoderH264:min-qp:
3065    *
3066    * The minimum quantizer value.
3067    */
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));
3073
3074   /**
3075    * GstVaapiEncoderH264:num-slices:
3076    *
3077    * The number of slices per frame.
3078    */
3079   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3080       GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES,
3081       g_param_spec_uint ("num-slices",
3082           "Number of Slices",
3083           "Number of slices per frame",
3084           1, 200, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3085
3086   /**
3087    * GstVaapiEncoderH264:cabac:
3088    *
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.
3092    */
3093   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3094       GST_VAAPI_ENCODER_H264_PROP_CABAC,
3095       g_param_spec_boolean ("cabac",
3096           "Enable CABAC",
3097           "Enable CABAC entropy coding mode",
3098           FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3099
3100   /**
3101    * GstVaapiEncoderH264:dct8x8:
3102    *
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.
3106    */
3107   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3108       GST_VAAPI_ENCODER_H264_PROP_DCT8X8,
3109       g_param_spec_boolean ("dct8x8",
3110           "Enable 8x8 DCT",
3111           "Enable adaptive use of 8x8 transforms in I-frames",
3112           FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3113
3114   /**
3115    * GstVaapiEncoderH264:cpb-length:
3116    *
3117    * The size of the CPB buffer in milliseconds.
3118    */
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));
3125
3126   /**
3127    * GstVaapiEncoderH264:num-views:
3128    *
3129    * The number of views for MVC encoding .
3130    */
3131   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
3132       GST_VAAPI_ENCODER_H264_PROP_NUM_VIEWS,
3133       g_param_spec_uint ("num-views",
3134           "Number of Views",
3135           "Number of Views for MVC encoding",
3136           1, MAX_NUM_VIEWS, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3137   /**
3138    * GstVaapiEncoderH264:view-ids:
3139    *
3140    * The view ids for MVC encoding .
3141    */
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));
3150
3151   return props;
3152 }
3153
3154 /**
3155  * gst_vaapi_encoder_h264_set_max_profile:
3156  * @encoder: a #GstVaapiEncoderH264
3157  * @profile: an H.264 #GstVaapiProfile
3158  *
3159  * Notifies the @encoder to use coding tools from the supplied
3160  * @profile at most.
3161  *
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.
3165  *
3166  * Return value: %TRUE on success
3167  */
3168 gboolean
3169 gst_vaapi_encoder_h264_set_max_profile (GstVaapiEncoderH264 * encoder,
3170     GstVaapiProfile profile)
3171 {
3172   guint8 profile_idc;
3173
3174   g_return_val_if_fail (encoder != NULL, FALSE);
3175   g_return_val_if_fail (profile != GST_VAAPI_PROFILE_UNKNOWN, FALSE);
3176
3177   if (gst_vaapi_profile_get_codec (profile) != GST_VAAPI_CODEC_H264)
3178     return FALSE;
3179
3180   profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
3181   if (!profile_idc)
3182     return FALSE;
3183
3184   encoder->max_profile_idc = profile_idc;
3185   return TRUE;
3186 }
3187
3188 /**
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
3193  *
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.
3198  *
3199  * Return value: %TRUE on success
3200  */
3201 gboolean
3202 gst_vaapi_encoder_h264_get_profile_and_level (GstVaapiEncoderH264 * encoder,
3203     GstVaapiProfile * out_profile_ptr, GstVaapiLevelH264 * out_level_ptr)
3204 {
3205   g_return_val_if_fail (encoder != NULL, FALSE);
3206
3207   if (!encoder->profile || !encoder->level)
3208     return FALSE;
3209
3210   if (out_profile_ptr)
3211     *out_profile_ptr = encoder->profile;
3212   if (out_level_ptr)
3213     *out_level_ptr = encoder->level;
3214   return TRUE;
3215 }