encoder: h264: fix pixel-aspect-ratio in encoded stream.
[platform/upstream/gstreamer-vaapi.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 #include "sysdeps.h"
25 #include <va/va.h>
26 #include <va/va_enc_h264.h>
27 #include <gst/base/gstbitwriter.h>
28 #include <gst/codecparsers/gsth264parser.h>
29 #include "gstvaapicompat.h"
30 #include "gstvaapiencoder_priv.h"
31 #include "gstvaapiencoder_h264.h"
32 #include "gstvaapiutils_h264.h"
33 #include "gstvaapiutils_h264_priv.h"
34 #include "gstvaapicodedbufferproxy_priv.h"
35 #include "gstvaapisurface.h"
36
37 #define DEBUG 1
38 #include "gstvaapidebug.h"
39
40 /* Define the maximum number of views supported */
41 #define MAX_NUM_VIEWS 2
42
43 /* Define the maximum IDR period */
44 #define MAX_IDR_PERIOD 512
45
46 /* Default CPB length (in milliseconds) */
47 #define DEFAULT_CPB_LENGTH 1500
48
49 /* Scale factor for CPB size (HRD cpb_size_scale: min = 4) */
50 #define SX_CPB_SIZE 4
51
52 /* Scale factor for bitrate (HRD bit_rate_scale: min = 6) */
53 #define SX_BITRATE 6
54
55 /* Define default rate control mode ("constant-qp") */
56 #define DEFAULT_RATECONTROL GST_VAAPI_RATECONTROL_CQP
57
58 /* Supported set of VA rate controls, within this implementation */
59 #define SUPPORTED_RATECONTROLS                          \
60   (GST_VAAPI_RATECONTROL_MASK (CQP)  |                  \
61    GST_VAAPI_RATECONTROL_MASK (CBR)  |                  \
62    GST_VAAPI_RATECONTROL_MASK (VBR)  |                  \
63    GST_VAAPI_RATECONTROL_MASK (VBR_CONSTRAINED))
64
65 /* Supported set of tuning options, within this implementation */
66 #define SUPPORTED_TUNE_OPTIONS                          \
67   (GST_VAAPI_ENCODER_TUNE_MASK (NONE) |                 \
68    GST_VAAPI_ENCODER_TUNE_MASK (HIGH_COMPRESSION))
69
70 /* Supported set of VA packed headers, within this implementation */
71 #define SUPPORTED_PACKED_HEADERS                \
72   (VA_ENC_PACKED_HEADER_SEQUENCE |              \
73    VA_ENC_PACKED_HEADER_PICTURE  |              \
74    VA_ENC_PACKED_HEADER_SLICE    |              \
75    VA_ENC_PACKED_HEADER_RAW_DATA)
76
77 #define GST_H264_NAL_REF_IDC_NONE        0
78 #define GST_H264_NAL_REF_IDC_LOW         1
79 #define GST_H264_NAL_REF_IDC_MEDIUM      2
80 #define GST_H264_NAL_REF_IDC_HIGH        3
81
82 typedef struct
83 {
84   GstVaapiSurfaceProxy *pic;
85   guint poc;
86   guint frame_num;
87 } GstVaapiEncoderH264Ref;
88
89 typedef enum
90 {
91   GST_VAAPI_ENC_H264_REORD_NONE = 0,
92   GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES = 1,
93   GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES = 2
94 } GstVaapiEncH264ReorderState;
95
96 typedef struct _GstVaapiH264ViewRefPool
97 {
98   GQueue ref_list;
99   guint max_ref_frames;
100   guint max_reflist0_count;
101   guint max_reflist1_count;
102 } GstVaapiH264ViewRefPool;
103
104 typedef struct _GstVaapiH264ViewReorderPool
105 {
106   GQueue reorder_frame_list;
107   guint reorder_state;
108   guint frame_index;
109   guint cur_frame_num;
110   guint cur_present_index;
111 } GstVaapiH264ViewReorderPool;
112
113 static inline gboolean
114 _poc_greater_than (guint poc1, guint poc2, guint max_poc)
115 {
116   return (((poc1 - poc2) & (max_poc - 1)) < max_poc / 2);
117 }
118
119 /* Get slice_type value for H.264 specification */
120 static guint8
121 h264_get_slice_type (GstVaapiPictureType type)
122 {
123   switch (type) {
124     case GST_VAAPI_PICTURE_TYPE_I:
125       return GST_H264_I_SLICE;
126     case GST_VAAPI_PICTURE_TYPE_P:
127       return GST_H264_P_SLICE;
128     case GST_VAAPI_PICTURE_TYPE_B:
129       return GST_H264_B_SLICE;
130     default:
131       break;
132   }
133   return -1;
134 }
135
136 /* Get log2_max_frame_num value for H.264 specification */
137 static guint
138 h264_get_log2_max_frame_num (guint num)
139 {
140   guint ret = 0;
141
142   while (num) {
143     ++ret;
144     num >>= 1;
145   }
146   if (ret <= 4)
147     ret = 4;
148   else if (ret > 10)
149     ret = 10;
150   /* must be greater than 4 */
151   return ret;
152 }
153
154 /* Determines the cpbBrNalFactor based on the supplied profile */
155 static guint
156 h264_get_cpb_nal_factor (GstVaapiProfile profile)
157 {
158   guint f;
159
160   /* Table A-2 */
161   switch (profile) {
162     case GST_VAAPI_PROFILE_H264_HIGH:
163       f = 1500;
164       break;
165     case GST_VAAPI_PROFILE_H264_HIGH10:
166       f = 3600;
167       break;
168     case GST_VAAPI_PROFILE_H264_HIGH_422:
169     case GST_VAAPI_PROFILE_H264_HIGH_444:
170       f = 4800;
171       break;
172     case GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH:
173     case GST_VAAPI_PROFILE_H264_STEREO_HIGH:
174       f = 1500;                 /* H.10.2.1 (r) */
175       break;
176     default:
177       f = 1200;
178       break;
179   }
180   return f;
181 }
182
183 /* ------------------------------------------------------------------------- */
184 /* --- H.264 Bitstream Writer                                            --- */
185 /* ------------------------------------------------------------------------- */
186
187 #define WRITE_UINT32(bs, val, nbits) do {                       \
188     if (!gst_bit_writer_put_bits_uint32 (bs, val, nbits)) {     \
189       GST_WARNING ("failed to write uint32, nbits: %d", nbits); \
190       goto bs_error;                                            \
191     }                                                           \
192   } while (0)
193
194 #define WRITE_UE(bs, val) do {                  \
195     if (!bs_write_ue (bs, val)) {               \
196       GST_WARNING ("failed to write ue(v)");    \
197       goto bs_error;                            \
198     }                                           \
199   } while (0)
200
201 #define WRITE_SE(bs, val) do {                  \
202     if (!bs_write_se (bs, val)) {               \
203       GST_WARNING ("failed to write se(v)");    \
204       goto bs_error;                            \
205     }                                           \
206   } while (0)
207
208 /* Write an unsigned integer Exp-Golomb-coded syntax element. i.e. ue(v) */
209 static gboolean
210 bs_write_ue (GstBitWriter * bs, guint32 value)
211 {
212   guint32 size_in_bits = 0;
213   guint32 tmp_value = ++value;
214
215   while (tmp_value) {
216     ++size_in_bits;
217     tmp_value >>= 1;
218   }
219   if (size_in_bits > 1
220       && !gst_bit_writer_put_bits_uint32 (bs, 0, size_in_bits - 1))
221     return FALSE;
222   if (!gst_bit_writer_put_bits_uint32 (bs, value, size_in_bits))
223     return FALSE;
224   return TRUE;
225 }
226
227 /* Write a signed integer Exp-Golomb-coded syntax element. i.e. se(v) */
228 static gboolean
229 bs_write_se (GstBitWriter * bs, gint32 value)
230 {
231   guint32 new_val;
232
233   if (value <= 0)
234     new_val = -(value << 1);
235   else
236     new_val = (value << 1) - 1;
237
238   if (!bs_write_ue (bs, new_val))
239     return FALSE;
240   return TRUE;
241 }
242
243 /* Write the NAL unit header */
244 static gboolean
245 bs_write_nal_header (GstBitWriter * bs, guint32 nal_ref_idc,
246     guint32 nal_unit_type)
247 {
248   WRITE_UINT32 (bs, 0, 1);
249   WRITE_UINT32 (bs, nal_ref_idc, 2);
250   WRITE_UINT32 (bs, nal_unit_type, 5);
251   return TRUE;
252
253   /* ERRORS */
254 bs_error:
255   {
256     GST_WARNING ("failed to write NAL unit header");
257     return FALSE;
258   }
259 }
260
261 /* Write the MVC NAL unit header extension */
262 static gboolean
263 bs_write_nal_header_mvc_extension (GstBitWriter * bs,
264     GstVaapiEncPicture * picture, guint32 view_id)
265 {
266   guint32 svc_extension_flag = 0;
267   guint32 non_idr_flag = 1;
268   guint32 priority_id = 0;
269   guint32 temporal_id = 0;
270   guint32 anchor_pic_flag = 0;
271   guint32 inter_view_flag = 0;
272
273   if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
274     non_idr_flag = 0;
275
276   if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
277     anchor_pic_flag = 1;
278   /* svc_extension_flag == 0 for mvc stream */
279   WRITE_UINT32 (bs, svc_extension_flag, 1);
280
281   WRITE_UINT32 (bs, non_idr_flag, 1);
282   WRITE_UINT32 (bs, priority_id, 6);
283   WRITE_UINT32 (bs, view_id, 10);
284   WRITE_UINT32 (bs, temporal_id, 3);
285   WRITE_UINT32 (bs, anchor_pic_flag, 1);
286   WRITE_UINT32 (bs, inter_view_flag, 1);
287   WRITE_UINT32 (bs, 1, 1);
288
289   return TRUE;
290
291   /* ERRORS */
292 bs_error:
293   {
294     GST_WARNING ("failed to write NAL unit header");
295     return FALSE;
296   }
297 }
298
299 /* Write the NAL unit trailing bits */
300 static gboolean
301 bs_write_trailing_bits (GstBitWriter * bs)
302 {
303   if (!gst_bit_writer_put_bits_uint32 (bs, 1, 1))
304     goto bs_error;
305   gst_bit_writer_align_bytes_unchecked (bs, 0);
306   return TRUE;
307
308   /* ERRORS */
309 bs_error:
310   {
311     GST_WARNING ("failed to write NAL unit trailing bits");
312     return FALSE;
313   }
314 }
315
316 /* Write an SPS NAL unit */
317 static gboolean
318 bs_write_sps_data (GstBitWriter * bs,
319     const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
320     const VAEncMiscParameterHRD * hrd_params)
321 {
322   guint8 profile_idc;
323   guint32 constraint_set0_flag, constraint_set1_flag;
324   guint32 constraint_set2_flag, constraint_set3_flag;
325   guint32 gaps_in_frame_num_value_allowed_flag = 0;     // ??
326   gboolean nal_hrd_parameters_present_flag;
327
328   guint32 b_qpprime_y_zero_transform_bypass = 0;
329   guint32 residual_color_transform_flag = 0;
330   guint32 pic_height_in_map_units =
331       (seq_param->seq_fields.bits.frame_mbs_only_flag ?
332       seq_param->picture_height_in_mbs : seq_param->picture_height_in_mbs / 2);
333   guint32 mb_adaptive_frame_field =
334       !seq_param->seq_fields.bits.frame_mbs_only_flag;
335   guint32 i = 0;
336
337   profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
338   constraint_set0_flag =        /* A.2.1 (baseline profile constraints) */
339       profile == GST_VAAPI_PROFILE_H264_BASELINE ||
340       profile == GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
341   constraint_set1_flag =        /* A.2.2 (main profile constraints) */
342       profile == GST_VAAPI_PROFILE_H264_MAIN ||
343       profile == GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
344   constraint_set2_flag = 0;
345   constraint_set3_flag = 0;
346
347   /* profile_idc */
348   WRITE_UINT32 (bs, profile_idc, 8);
349   /* constraint_set0_flag */
350   WRITE_UINT32 (bs, constraint_set0_flag, 1);
351   /* constraint_set1_flag */
352   WRITE_UINT32 (bs, constraint_set1_flag, 1);
353   /* constraint_set2_flag */
354   WRITE_UINT32 (bs, constraint_set2_flag, 1);
355   /* constraint_set3_flag */
356   WRITE_UINT32 (bs, constraint_set3_flag, 1);
357   /* reserved_zero_4bits */
358   WRITE_UINT32 (bs, 0, 4);
359   /* level_idc */
360   WRITE_UINT32 (bs, seq_param->level_idc, 8);
361   /* seq_parameter_set_id */
362   WRITE_UE (bs, seq_param->seq_parameter_set_id);
363
364   if (profile == GST_VAAPI_PROFILE_H264_HIGH ||
365       profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH ||
366       profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH) {
367     /* for high profile */
368     /* chroma_format_idc  = 1, 4:2:0 */
369     WRITE_UE (bs, seq_param->seq_fields.bits.chroma_format_idc);
370     if (3 == seq_param->seq_fields.bits.chroma_format_idc) {
371       WRITE_UINT32 (bs, residual_color_transform_flag, 1);
372     }
373     /* bit_depth_luma_minus8 */
374     WRITE_UE (bs, seq_param->bit_depth_luma_minus8);
375     /* bit_depth_chroma_minus8 */
376     WRITE_UE (bs, seq_param->bit_depth_chroma_minus8);
377     /* b_qpprime_y_zero_transform_bypass */
378     WRITE_UINT32 (bs, b_qpprime_y_zero_transform_bypass, 1);
379
380     /* seq_scaling_matrix_present_flag  */
381     g_assert (seq_param->seq_fields.bits.seq_scaling_matrix_present_flag == 0);
382     WRITE_UINT32 (bs,
383         seq_param->seq_fields.bits.seq_scaling_matrix_present_flag, 1);
384
385 #if 0
386     if (seq_param->seq_fields.bits.seq_scaling_matrix_present_flag) {
387       for (i = 0;
388           i < (seq_param->seq_fields.bits.chroma_format_idc != 3 ? 8 : 12);
389           i++) {
390         gst_bit_writer_put_bits_uint8 (bs,
391             seq_param->seq_fields.bits.seq_scaling_list_present_flag, 1);
392         if (seq_param->seq_fields.bits.seq_scaling_list_present_flag) {
393           g_assert (0);
394           /* FIXME, need write scaling list if seq_scaling_matrix_present_flag ==1 */
395         }
396       }
397     }
398 #endif
399   }
400
401   /* log2_max_frame_num_minus4 */
402   WRITE_UE (bs, seq_param->seq_fields.bits.log2_max_frame_num_minus4);
403   /* pic_order_cnt_type */
404   WRITE_UE (bs, seq_param->seq_fields.bits.pic_order_cnt_type);
405
406   if (seq_param->seq_fields.bits.pic_order_cnt_type == 0) {
407     /* log2_max_pic_order_cnt_lsb_minus4 */
408     WRITE_UE (bs, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4);
409   } else if (seq_param->seq_fields.bits.pic_order_cnt_type == 1) {
410     g_assert (0 && "only POC type 0 is supported");
411     WRITE_UINT32 (bs,
412         seq_param->seq_fields.bits.delta_pic_order_always_zero_flag, 1);
413     WRITE_SE (bs, seq_param->offset_for_non_ref_pic);
414     WRITE_SE (bs, seq_param->offset_for_top_to_bottom_field);
415     WRITE_UE (bs, seq_param->num_ref_frames_in_pic_order_cnt_cycle);
416     for (i = 0; i < seq_param->num_ref_frames_in_pic_order_cnt_cycle; i++) {
417       WRITE_SE (bs, seq_param->offset_for_ref_frame[i]);
418     }
419   }
420
421   /* num_ref_frames */
422   WRITE_UE (bs, seq_param->max_num_ref_frames);
423   /* gaps_in_frame_num_value_allowed_flag */
424   WRITE_UINT32 (bs, gaps_in_frame_num_value_allowed_flag, 1);
425
426   /* pic_width_in_mbs_minus1 */
427   WRITE_UE (bs, seq_param->picture_width_in_mbs - 1);
428   /* pic_height_in_map_units_minus1 */
429   WRITE_UE (bs, pic_height_in_map_units - 1);
430   /* frame_mbs_only_flag */
431   WRITE_UINT32 (bs, seq_param->seq_fields.bits.frame_mbs_only_flag, 1);
432
433   if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {        //ONLY mbs
434     g_assert (0 && "only progressive frames encoding is supported");
435     WRITE_UINT32 (bs, mb_adaptive_frame_field, 1);
436   }
437
438   /* direct_8x8_inference_flag */
439   WRITE_UINT32 (bs, 0, 1);
440   /* frame_cropping_flag */
441   WRITE_UINT32 (bs, seq_param->frame_cropping_flag, 1);
442
443   if (seq_param->frame_cropping_flag) {
444     /* frame_crop_left_offset */
445     WRITE_UE (bs, seq_param->frame_crop_left_offset);
446     /* frame_crop_right_offset */
447     WRITE_UE (bs, seq_param->frame_crop_right_offset);
448     /* frame_crop_top_offset */
449     WRITE_UE (bs, seq_param->frame_crop_top_offset);
450     /* frame_crop_bottom_offset */
451     WRITE_UE (bs, seq_param->frame_crop_bottom_offset);
452   }
453
454   /* vui_parameters_present_flag */
455   WRITE_UINT32 (bs, seq_param->vui_parameters_present_flag, 1);
456   if (seq_param->vui_parameters_present_flag) {
457     /* aspect_ratio_info_present_flag */
458     WRITE_UINT32 (bs,
459         seq_param->vui_fields.bits.aspect_ratio_info_present_flag, 1);
460     if (seq_param->vui_fields.bits.aspect_ratio_info_present_flag) {
461       WRITE_UINT32 (bs, seq_param->aspect_ratio_idc, 8);
462       if (seq_param->aspect_ratio_idc == 0xFF) {
463         WRITE_UINT32 (bs, seq_param->sar_width, 16);
464         WRITE_UINT32 (bs, seq_param->sar_height, 16);
465       }
466     }
467
468     /* overscan_info_present_flag */
469     WRITE_UINT32 (bs, 0, 1);
470     /* video_signal_type_present_flag */
471     WRITE_UINT32 (bs, 0, 1);
472     /* chroma_loc_info_present_flag */
473     WRITE_UINT32 (bs, 0, 1);
474
475     /* timing_info_present_flag */
476     WRITE_UINT32 (bs, seq_param->vui_fields.bits.timing_info_present_flag, 1);
477     if (seq_param->vui_fields.bits.timing_info_present_flag) {
478       WRITE_UINT32 (bs, seq_param->num_units_in_tick, 32);
479       WRITE_UINT32 (bs, seq_param->time_scale, 32);
480       WRITE_UINT32 (bs, 1, 1);  /* fixed_frame_rate_flag */
481     }
482
483     /* nal_hrd_parameters_present_flag */
484     nal_hrd_parameters_present_flag = seq_param->bits_per_second > 0;
485     nal_hrd_parameters_present_flag = FALSE;    /* XXX: disabled for now */
486     WRITE_UINT32 (bs, nal_hrd_parameters_present_flag, 1);
487     if (nal_hrd_parameters_present_flag) {
488       /* hrd_parameters */
489       /* cpb_cnt_minus1 */
490       WRITE_UE (bs, 0);
491       WRITE_UINT32 (bs, SX_BITRATE - 6, 4);     /* bit_rate_scale */
492       WRITE_UINT32 (bs, SX_CPB_SIZE - 4, 4);    /* cpb_size_scale */
493
494       for (i = 0; i < 1; ++i) {
495         /* bit_rate_value_minus1[0] */
496         WRITE_UE (bs, (seq_param->bits_per_second >> SX_BITRATE) - 1);
497         /* cpb_size_value_minus1[0] */
498         WRITE_UE (bs, (hrd_params->buffer_size >> SX_CPB_SIZE) - 1);
499         /* cbr_flag[0] */
500         WRITE_UINT32 (bs, 1, 1);
501       }
502       /* initial_cpb_removal_delay_length_minus1 */
503       WRITE_UINT32 (bs, 23, 5);
504       /* cpb_removal_delay_length_minus1 */
505       WRITE_UINT32 (bs, 23, 5);
506       /* dpb_output_delay_length_minus1 */
507       WRITE_UINT32 (bs, 23, 5);
508       /* time_offset_length  */
509       WRITE_UINT32 (bs, 23, 5);
510     }
511
512     /* vcl_hrd_parameters_present_flag */
513     WRITE_UINT32 (bs, 0, 1);
514
515     if (nal_hrd_parameters_present_flag
516         || 0 /*vcl_hrd_parameters_present_flag */ ) {
517       /* low_delay_hrd_flag */
518       WRITE_UINT32 (bs, 0, 1);
519     }
520     /* pic_struct_present_flag */
521     WRITE_UINT32 (bs, 0, 1);
522     /* bs_restriction_flag */
523     WRITE_UINT32 (bs, 0, 1);
524   }
525   return TRUE;
526
527   /* ERRORS */
528 bs_error:
529   {
530     GST_WARNING ("failed to write SPS NAL unit");
531     return FALSE;
532   }
533 }
534
535 static gboolean
536 bs_write_sps (GstBitWriter * bs,
537     const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
538     const VAEncMiscParameterHRD * hrd_params)
539 {
540   if (!bs_write_sps_data (bs, seq_param, profile, hrd_params))
541     return FALSE;
542
543   /* rbsp_trailing_bits */
544   bs_write_trailing_bits (bs);
545
546   return FALSE;
547 }
548
549 static gboolean
550 bs_write_subset_sps (GstBitWriter * bs,
551     const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
552     guint num_views, const VAEncMiscParameterHRD * hrd_params)
553 {
554   guint32 i, j, k;
555
556   if (!bs_write_sps_data (bs, seq_param, profile, hrd_params))
557     return FALSE;
558
559   if (profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH ||
560       profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH) {
561     guint32 num_views_minus1, num_level_values_signalled_minus1;
562
563     num_views_minus1 = num_views - 1;
564     g_assert (num_views_minus1 < 1024);
565
566     /* bit equal to one */
567     WRITE_UINT32 (bs, 1, 1);
568
569     WRITE_UE (bs, num_views_minus1);
570
571     for (i = 0; i <= num_views_minus1; i++)
572       WRITE_UE (bs, i);
573
574     for (i = 1; i <= num_views_minus1; i++) {
575       guint32 num_anchor_refs_l0 = 0;
576       WRITE_UE (bs, num_anchor_refs_l0);
577       for (j = 0; j < num_anchor_refs_l0; j++)
578         WRITE_UE (bs, 0);
579
580       guint32 num_anchor_refs_l1 = 0;
581       WRITE_UE (bs, num_anchor_refs_l1);
582       for (j = 0; j < num_anchor_refs_l1; j++)
583         WRITE_UE (bs, 0);
584     }
585
586     for (i = 1; i <= num_views_minus1; i++) {
587       guint32 num_non_anchor_refs_l0 = 0;
588       WRITE_UE (bs, num_non_anchor_refs_l0);
589       for (j = 0; j < num_non_anchor_refs_l0; j++)
590         WRITE_UE (bs, 0);
591
592       guint32 num_non_anchor_refs_l1 = 0;
593       WRITE_UE (bs, num_non_anchor_refs_l1);
594       for (j = 0; j < num_non_anchor_refs_l1; j++)
595         WRITE_UE (bs, 0);
596     }
597
598     /* num level values signalled minus1 */
599     num_level_values_signalled_minus1 = 0;
600     g_assert (num_level_values_signalled_minus1 < 64);
601     WRITE_UE (bs, num_level_values_signalled_minus1);
602
603     for (i = 0; i <= num_level_values_signalled_minus1; i++) {
604       guint16 num_applicable_ops_minus1 = 0;
605       g_assert (num_applicable_ops_minus1 < 1024);
606
607       WRITE_UINT32 (bs, seq_param->level_idc, 8);
608       WRITE_UE (bs, num_applicable_ops_minus1);
609
610       for (j = 0; j <= num_applicable_ops_minus1; j++) {
611         guint8 temporal_id = 0;
612         guint16 num_target_views_minus1 = 1;
613
614         WRITE_UINT32 (bs, temporal_id, 3);
615         WRITE_UE (bs, num_target_views_minus1);
616
617         for (k = 0; k <= num_target_views_minus1; k++)
618           WRITE_UE (bs, k);
619
620         WRITE_UE (bs, num_views_minus1);
621       }
622     }
623
624     /* mvc_vui_parameters_present_flag */
625     WRITE_UINT32 (bs, 0, 1);
626   }
627
628   /* additional_extension2_flag */
629   WRITE_UINT32 (bs, 0, 1);
630
631   /* rbsp_trailing_bits */
632   bs_write_trailing_bits (bs);
633   return TRUE;
634
635   /* ERRORS */
636 bs_error:
637   {
638     GST_WARNING ("failed to write subset SPS NAL unit");
639     return FALSE;
640   }
641   return FALSE;
642 }
643
644 /* Write a PPS NAL unit */
645 static gboolean
646 bs_write_pps (GstBitWriter * bs,
647     const VAEncPictureParameterBufferH264 * pic_param, GstVaapiProfile profile)
648 {
649   guint32 num_slice_groups_minus1 = 0;
650   guint32 pic_init_qs_minus26 = 0;
651   guint32 redundant_pic_cnt_present_flag = 0;
652
653   /* pic_parameter_set_id */
654   WRITE_UE (bs, pic_param->pic_parameter_set_id);
655   /* seq_parameter_set_id */
656   WRITE_UE (bs, pic_param->seq_parameter_set_id);
657   /* entropy_coding_mode_flag */
658   WRITE_UINT32 (bs, pic_param->pic_fields.bits.entropy_coding_mode_flag, 1);
659   /* pic_order_present_flag */
660   WRITE_UINT32 (bs, pic_param->pic_fields.bits.pic_order_present_flag, 1);
661   /* slice_groups-1 */
662   WRITE_UE (bs, num_slice_groups_minus1);
663
664   if (num_slice_groups_minus1 > 0) {
665      /*FIXME*/ g_assert (0 && "unsupported arbitrary slice ordering (ASO)");
666   }
667   WRITE_UE (bs, pic_param->num_ref_idx_l0_active_minus1);
668   WRITE_UE (bs, pic_param->num_ref_idx_l1_active_minus1);
669   WRITE_UINT32 (bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);
670   WRITE_UINT32 (bs, pic_param->pic_fields.bits.weighted_bipred_idc, 2);
671   /* pic_init_qp_minus26 */
672   WRITE_SE (bs, pic_param->pic_init_qp - 26);
673   /* pic_init_qs_minus26 */
674   WRITE_SE (bs, pic_init_qs_minus26);
675   /* chroma_qp_index_offset */
676   WRITE_SE (bs, pic_param->chroma_qp_index_offset);
677
678   WRITE_UINT32 (bs,
679       pic_param->pic_fields.bits.deblocking_filter_control_present_flag, 1);
680   WRITE_UINT32 (bs, pic_param->pic_fields.bits.constrained_intra_pred_flag, 1);
681   WRITE_UINT32 (bs, redundant_pic_cnt_present_flag, 1);
682
683   /* more_rbsp_data */
684   if (profile == GST_VAAPI_PROFILE_H264_HIGH) {
685     WRITE_UINT32 (bs, pic_param->pic_fields.bits.transform_8x8_mode_flag, 1);
686     WRITE_UINT32 (bs,
687         pic_param->pic_fields.bits.pic_scaling_matrix_present_flag, 1);
688     if (pic_param->pic_fields.bits.pic_scaling_matrix_present_flag) {
689       g_assert (0 && "unsupported scaling lists");
690       /* FIXME */
691       /*
692          for (i = 0; i <
693          (6+(-( (chroma_format_idc ! = 3) ? 2 : 6) * -pic_param->pic_fields.bits.transform_8x8_mode_flag));
694          i++) {
695          gst_bit_writer_put_bits_uint8(bs, pic_param->pic_fields.bits.pic_scaling_list_present_flag, 1);
696          }
697        */
698     }
699     WRITE_SE (bs, pic_param->second_chroma_qp_index_offset);
700   }
701
702   /* rbsp_trailing_bits */
703   bs_write_trailing_bits (bs);
704   return TRUE;
705
706   /* ERRORS */
707 bs_error:
708   {
709     GST_WARNING ("failed to write PPS NAL unit");
710     return FALSE;
711   }
712 }
713
714 /* ------------------------------------------------------------------------- */
715 /* --- H.264 Encoder                                                     --- */
716 /* ------------------------------------------------------------------------- */
717
718 #define GST_VAAPI_ENCODER_H264_CAST(encoder) \
719     ((GstVaapiEncoderH264 *)(encoder))
720
721 struct _GstVaapiEncoderH264
722 {
723   GstVaapiEncoder parent_instance;
724
725   GstVaapiProfile profile;
726   GstVaapiLevelH264 level;
727   guint8 profile_idc;
728   guint8 max_profile_idc;
729   guint8 hw_max_profile_idc;
730   guint8 level_idc;
731   guint32 idr_period;
732   guint32 init_qp;
733   guint32 min_qp;
734   guint32 num_slices;
735   guint32 num_bframes;
736   guint32 mb_width;
737   guint32 mb_height;
738   gboolean use_cabac;
739   gboolean use_dct8x8;
740   GstClockTime cts_offset;
741   gboolean config_changed;
742
743   /* frame, poc */
744   guint32 max_frame_num;
745   guint32 log2_max_frame_num;
746   guint32 max_pic_order_cnt;
747   guint32 log2_max_pic_order_cnt;
748   guint32 idr_num;
749   guint8 pic_order_cnt_type;
750   guint8 delta_pic_order_always_zero_flag;
751
752   GstBuffer *sps_data;
753   GstBuffer *subset_sps_data;
754   GstBuffer *pps_data;
755
756   guint bitrate_bits;           // bitrate (bits)
757   guint cpb_length;             // length of CPB buffer (ms)
758   guint cpb_length_bits;        // length of CPB buffer (bits)
759
760   /* MVC */
761   gboolean is_mvc;
762   guint32 view_idx;
763   guint32 num_views;
764   GstVaapiH264ViewRefPool ref_pools[MAX_NUM_VIEWS];
765   GstVaapiH264ViewReorderPool reorder_pools[MAX_NUM_VIEWS];
766 };
767
768 /* Write a Slice NAL unit */
769 static gboolean
770 bs_write_slice (GstBitWriter * bs,
771     const VAEncSliceParameterBufferH264 * slice_param,
772     GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
773 {
774   const VAEncPictureParameterBufferH264 *const pic_param = picture->param;
775   guint32 field_pic_flag = 0;
776   guint32 ref_pic_list_modification_flag_l0 = 0;
777   guint32 ref_pic_list_modification_flag_l1 = 0;
778   guint32 no_output_of_prior_pics_flag = 0;
779   guint32 long_term_reference_flag = 0;
780   guint32 adaptive_ref_pic_marking_mode_flag = 0;
781
782   /* first_mb_in_slice */
783   WRITE_UE (bs, slice_param->macroblock_address);
784   /* slice_type */
785   WRITE_UE (bs, slice_param->slice_type);
786   /* pic_parameter_set_id */
787   WRITE_UE (bs, slice_param->pic_parameter_set_id);
788   /* frame_num */
789   WRITE_UINT32 (bs, picture->frame_num, encoder->log2_max_frame_num);
790
791   /* XXX: only frames (i.e. non-interlaced) are supported for now */
792   /* frame_mbs_only_flag == 0 */
793
794   /* idr_pic_id */
795   if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
796     WRITE_UE (bs, slice_param->idr_pic_id);
797
798   /* XXX: only POC type 0 is supported */
799   if (!encoder->pic_order_cnt_type) {
800     WRITE_UINT32 (bs, slice_param->pic_order_cnt_lsb,
801         encoder->log2_max_pic_order_cnt);
802     /* bottom_field_pic_order_in_frame_present_flag is FALSE */
803     if (pic_param->pic_fields.bits.pic_order_present_flag && !field_pic_flag)
804       WRITE_SE (bs, slice_param->delta_pic_order_cnt_bottom);
805   } else if (encoder->pic_order_cnt_type == 1 &&
806       !encoder->delta_pic_order_always_zero_flag) {
807     WRITE_SE (bs, slice_param->delta_pic_order_cnt[0]);
808     if (pic_param->pic_fields.bits.pic_order_present_flag && !field_pic_flag)
809       WRITE_SE (bs, slice_param->delta_pic_order_cnt[1]);
810   }
811   /* redundant_pic_cnt_present_flag is FALSE, no redundant coded pictures */
812
813   /* only works for B-frames */
814   if (slice_param->slice_type == 1)
815     WRITE_UINT32 (bs, slice_param->direct_spatial_mv_pred_flag, 1);
816
817   /* not supporting SP slices */
818   if (slice_param->slice_type == 0 || slice_param->slice_type == 1) {
819     WRITE_UINT32 (bs, slice_param->num_ref_idx_active_override_flag, 1);
820     if (slice_param->num_ref_idx_active_override_flag) {
821       WRITE_UE (bs, slice_param->num_ref_idx_l0_active_minus1);
822       if (slice_param->slice_type == 1)
823         WRITE_UE (bs, slice_param->num_ref_idx_l1_active_minus1);
824     }
825   }
826   /* XXX: not supporting custom reference picture list modifications */
827   if ((slice_param->slice_type != 2) && (slice_param->slice_type != 4))
828     WRITE_UINT32 (bs, ref_pic_list_modification_flag_l0, 1);
829   if (slice_param->slice_type == 1)
830     WRITE_UINT32 (bs, ref_pic_list_modification_flag_l1, 1);
831
832   /* we have: weighted_pred_flag == FALSE and */
833   /*        : weighted_bipred_idc == FALSE */
834   if ((pic_param->pic_fields.bits.weighted_pred_flag &&
835           (slice_param->slice_type == 0)) ||
836       ((pic_param->pic_fields.bits.weighted_bipred_idc == 1) &&
837           (slice_param->slice_type == 1))) {
838     /* XXXX: add pred_weight_table() */
839   }
840
841   /* dec_ref_pic_marking() */
842   if (slice_param->slice_type == 0 || slice_param->slice_type == 2) {
843     if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture)) {
844       /* no_output_of_prior_pics_flag = 0 */
845       WRITE_UINT32 (bs, no_output_of_prior_pics_flag, 1);
846       /* long_term_reference_flag = 0 */
847       WRITE_UINT32 (bs, long_term_reference_flag, 1);
848     } else {
849       /* only sliding_window reference picture marking mode is supported */
850       /* adpative_ref_pic_marking_mode_flag = 0 */
851       WRITE_UINT32 (bs, adaptive_ref_pic_marking_mode_flag, 1);
852     }
853   }
854
855   /* cabac_init_idc */
856   if (pic_param->pic_fields.bits.entropy_coding_mode_flag &&
857       slice_param->slice_type != 2)
858     WRITE_UE (bs, slice_param->cabac_init_idc);
859   /*slice_qp_delta */
860   WRITE_SE (bs, slice_param->slice_qp_delta);
861
862   /* XXX: only supporting I, P and B type slices */
863   /* no sp_for_switch_flag and no slice_qs_delta */
864
865   if (pic_param->pic_fields.bits.deblocking_filter_control_present_flag) {
866     /* disable_deblocking_filter_idc */
867     WRITE_UE (bs, slice_param->disable_deblocking_filter_idc);
868     if (slice_param->disable_deblocking_filter_idc != 1) {
869       WRITE_SE (bs, slice_param->slice_alpha_c0_offset_div2);
870       WRITE_SE (bs, slice_param->slice_beta_offset_div2);
871     }
872   }
873
874   /* XXX: unsupported arbitrary slice ordering (ASO) */
875   /* num_slic_groups_minus1 should be zero */
876   return TRUE;
877
878   /* ERRORS */
879 bs_error:
880   {
881     GST_WARNING ("failed to write Slice NAL unit");
882     return FALSE;
883   }
884 }
885
886 static inline void
887 _check_sps_pps_status (GstVaapiEncoderH264 * encoder,
888     const guint8 * nal, guint32 size)
889 {
890   guint8 nal_type;
891   gsize ret;
892   gboolean has_subset_sps;
893
894   g_assert (size);
895
896   has_subset_sps = !encoder->is_mvc || (encoder->subset_sps_data != NULL);
897   if (encoder->sps_data && encoder->pps_data && has_subset_sps)
898     return;
899
900   nal_type = nal[0] & 0x1F;
901   switch (nal_type) {
902     case GST_H264_NAL_SPS:
903       encoder->sps_data = gst_buffer_new_allocate (NULL, size, NULL);
904       ret = gst_buffer_fill (encoder->sps_data, 0, nal, size);
905       g_assert (ret == size);
906       break;
907     case GST_H264_NAL_SUBSET_SPS:
908       encoder->subset_sps_data = gst_buffer_new_allocate (NULL, size, NULL);
909       ret = gst_buffer_fill (encoder->subset_sps_data, 0, nal, size);
910       g_assert (ret == size);
911       break;
912     case GST_H264_NAL_PPS:
913       encoder->pps_data = gst_buffer_new_allocate (NULL, size, NULL);
914       ret = gst_buffer_fill (encoder->pps_data, 0, nal, size);
915       g_assert (ret == size);
916       break;
917     default:
918       break;
919   }
920 }
921
922 /* Determines the largest supported profile by the underlying hardware */
923 static gboolean
924 ensure_hw_profile_limits (GstVaapiEncoderH264 * encoder)
925 {
926   GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
927   GArray *profiles;
928   guint i, profile_idc, max_profile_idc;
929
930   if (encoder->hw_max_profile_idc)
931     return TRUE;
932
933   profiles = gst_vaapi_display_get_encode_profiles (display);
934   if (!profiles)
935     return FALSE;
936
937   max_profile_idc = 0;
938   for (i = 0; i < profiles->len; i++) {
939     const GstVaapiProfile profile =
940         g_array_index (profiles, GstVaapiProfile, i);
941     profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
942     if (!profile_idc)
943       continue;
944     if (max_profile_idc < profile_idc)
945       max_profile_idc = profile_idc;
946   }
947   g_array_unref (profiles);
948
949   encoder->hw_max_profile_idc = max_profile_idc;
950   return TRUE;
951 }
952
953 /* Derives the profile supported by the underlying hardware */
954 static gboolean
955 ensure_hw_profile (GstVaapiEncoderH264 * encoder)
956 {
957   GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
958   GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
959   GstVaapiProfile profile, profiles[4];
960   guint i, num_profiles = 0;
961
962   profiles[num_profiles++] = encoder->profile;
963   switch (encoder->profile) {
964     case GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE:
965       profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_BASELINE;
966       profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_MAIN;
967       // fall-through
968     case GST_VAAPI_PROFILE_H264_MAIN:
969       profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_HIGH;
970       break;
971     default:
972       break;
973   }
974
975   profile = GST_VAAPI_PROFILE_UNKNOWN;
976   for (i = 0; i < num_profiles; i++) {
977     if (gst_vaapi_display_has_encoder (display, profiles[i], entrypoint)) {
978       profile = profiles[i];
979       break;
980     }
981   }
982   if (profile == GST_VAAPI_PROFILE_UNKNOWN)
983     goto error_unsupported_profile;
984
985   GST_VAAPI_ENCODER_CAST (encoder)->profile = profile;
986   return TRUE;
987
988   /* ERRORS */
989 error_unsupported_profile:
990   {
991     GST_ERROR ("unsupported HW profile (0x%08x)", encoder->profile);
992     return FALSE;
993   }
994 }
995
996 /* Check target decoder constraints */
997 static gboolean
998 ensure_profile_limits (GstVaapiEncoderH264 * encoder)
999 {
1000   GstVaapiProfile profile;
1001
1002   if (!encoder->max_profile_idc
1003       || encoder->profile_idc <= encoder->max_profile_idc)
1004     return TRUE;
1005
1006   GST_WARNING ("lowering coding tools to meet target decoder constraints");
1007
1008   profile = GST_VAAPI_PROFILE_UNKNOWN;
1009
1010   /* Try Main profile coding tools */
1011   if (encoder->max_profile_idc < 100) {
1012     encoder->use_dct8x8 = FALSE;
1013     profile = GST_VAAPI_PROFILE_H264_MAIN;
1014   }
1015
1016   /* Try Constrained Baseline profile coding tools */
1017   if (encoder->max_profile_idc < 77) {
1018     encoder->num_bframes = 0;
1019     encoder->use_cabac = FALSE;
1020     profile = GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
1021   }
1022
1023   if (profile) {
1024     encoder->profile = profile;
1025     encoder->profile_idc = encoder->max_profile_idc;
1026   }
1027   return TRUE;
1028 }
1029
1030 /* Derives the minimum profile from the active coding tools */
1031 static gboolean
1032 ensure_profile (GstVaapiEncoderH264 * encoder)
1033 {
1034   GstVaapiProfile profile;
1035
1036   /* Always start from "constrained-baseline" profile for maximum
1037      compatibility */
1038   profile = GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
1039
1040   /* Main profile coding tools */
1041   if (encoder->num_bframes > 0 || encoder->use_cabac)
1042     profile = GST_VAAPI_PROFILE_H264_MAIN;
1043
1044   /* High profile coding tools */
1045   if (encoder->use_dct8x8)
1046     profile = GST_VAAPI_PROFILE_H264_HIGH;
1047
1048   /* MVC profiles coding tools */
1049   if (encoder->num_views == 2)
1050     profile = GST_VAAPI_PROFILE_H264_STEREO_HIGH;
1051   else if (encoder->num_views > 2)
1052     profile = GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH;
1053
1054   encoder->profile = profile;
1055   encoder->profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
1056   return TRUE;
1057 }
1058
1059 /* Derives the level from the currently set limits */
1060 static gboolean
1061 ensure_level (GstVaapiEncoderH264 * encoder)
1062 {
1063   const guint cpb_factor = h264_get_cpb_nal_factor (encoder->profile);
1064   const GstVaapiH264LevelLimits *limits_table;
1065   guint i, num_limits, PicSizeMbs, MaxDpbMbs, MaxMBPS;
1066
1067   PicSizeMbs = encoder->mb_width * encoder->mb_height;
1068   MaxDpbMbs = PicSizeMbs * ((encoder->num_bframes) ? 2 : 1);
1069   MaxMBPS = gst_util_uint64_scale_int_ceil (PicSizeMbs,
1070       GST_VAAPI_ENCODER_FPS_N (encoder), GST_VAAPI_ENCODER_FPS_D (encoder));
1071
1072   limits_table = gst_vaapi_utils_h264_get_level_limits_table (&num_limits);
1073   for (i = 0; i < num_limits; i++) {
1074     const GstVaapiH264LevelLimits *const limits = &limits_table[i];
1075     if (PicSizeMbs <= limits->MaxFS &&
1076         MaxDpbMbs <= limits->MaxDpbMbs &&
1077         MaxMBPS <= limits->MaxMBPS && (!encoder->bitrate_bits
1078             || encoder->bitrate_bits <= (limits->MaxBR * cpb_factor)) &&
1079         (!encoder->cpb_length_bits ||
1080             encoder->cpb_length_bits <= (limits->MaxCPB * cpb_factor)))
1081       break;
1082   }
1083   if (i == num_limits)
1084     goto error_unsupported_level;
1085
1086   encoder->level = limits_table[i].level;
1087   encoder->level_idc = limits_table[i].level_idc;
1088   return TRUE;
1089
1090   /* ERRORS */
1091 error_unsupported_level:
1092   {
1093     GST_ERROR ("failed to find a suitable level matching codec config");
1094     return FALSE;
1095   }
1096 }
1097
1098 /* Enable "high-compression" tuning options */
1099 static gboolean
1100 ensure_tuning_high_compression (GstVaapiEncoderH264 * encoder)
1101 {
1102   guint8 profile_idc;
1103
1104   if (!ensure_hw_profile_limits (encoder))
1105     return FALSE;
1106
1107   profile_idc = encoder->hw_max_profile_idc;
1108   if (encoder->max_profile_idc && encoder->max_profile_idc < profile_idc)
1109     profile_idc = encoder->max_profile_idc;
1110
1111   /* Tuning options to enable Main profile */
1112   if (profile_idc >= 77 && profile_idc != 88) {
1113     encoder->use_cabac = TRUE;
1114     if (!encoder->num_bframes)
1115       encoder->num_bframes = 1;
1116   }
1117
1118   /* Tuning options to enable High profile */
1119   if (profile_idc >= 100) {
1120     encoder->use_dct8x8 = TRUE;
1121   }
1122   return TRUE;
1123 }
1124
1125 /* Ensure tuning options */
1126 static gboolean
1127 ensure_tuning (GstVaapiEncoderH264 * encoder)
1128 {
1129   gboolean success;
1130
1131   switch (GST_VAAPI_ENCODER_TUNE (encoder)) {
1132     case GST_VAAPI_ENCODER_TUNE_HIGH_COMPRESSION:
1133       success = ensure_tuning_high_compression (encoder);
1134       break;
1135     default:
1136       success = TRUE;
1137       break;
1138   }
1139   return success;
1140 }
1141
1142 /* Handle new GOP starts */
1143 static void
1144 reset_gop_start (GstVaapiEncoderH264 * encoder)
1145 {
1146   GstVaapiH264ViewReorderPool *const reorder_pool =
1147       &encoder->reorder_pools[encoder->view_idx];
1148
1149   reorder_pool->frame_index = 1;
1150   reorder_pool->cur_frame_num = 0;
1151   reorder_pool->cur_present_index = 0;
1152   ++encoder->idr_num;
1153 }
1154
1155 /* Marks the supplied picture as a B-frame */
1156 static void
1157 set_b_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1158 {
1159   GstVaapiH264ViewReorderPool *const reorder_pool =
1160       &encoder->reorder_pools[encoder->view_idx];
1161
1162   g_assert (pic && encoder);
1163   g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1164   pic->type = GST_VAAPI_PICTURE_TYPE_B;
1165   pic->frame_num = (reorder_pool->cur_frame_num % encoder->max_frame_num);
1166 }
1167
1168 /* Marks the supplied picture as a P-frame */
1169 static void
1170 set_p_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1171 {
1172   GstVaapiH264ViewReorderPool *const reorder_pool =
1173       &encoder->reorder_pools[encoder->view_idx];
1174
1175   g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1176   pic->type = GST_VAAPI_PICTURE_TYPE_P;
1177   pic->frame_num = (reorder_pool->cur_frame_num % encoder->max_frame_num);
1178 }
1179
1180 /* Marks the supplied picture as an I-frame */
1181 static void
1182 set_i_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1183 {
1184   GstVaapiH264ViewReorderPool *const reorder_pool =
1185       &encoder->reorder_pools[encoder->view_idx];
1186
1187   g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1188   pic->type = GST_VAAPI_PICTURE_TYPE_I;
1189   pic->frame_num = (reorder_pool->cur_frame_num % encoder->max_frame_num);
1190
1191   g_assert (pic->frame);
1192   GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1193 }
1194
1195 /* Marks the supplied picture as an IDR frame */
1196 static void
1197 set_idr_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH264 * encoder)
1198 {
1199   g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1200   pic->type = GST_VAAPI_PICTURE_TYPE_I;
1201   pic->frame_num = 0;
1202   pic->poc = 0;
1203   GST_VAAPI_ENC_PICTURE_FLAG_SET (pic, GST_VAAPI_ENC_PICTURE_FLAG_IDR);
1204
1205   g_assert (pic->frame);
1206   GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1207 }
1208
1209 /* Marks the supplied picture a a key-frame */
1210 static void
1211 set_key_frame (GstVaapiEncPicture * picture,
1212     GstVaapiEncoderH264 * encoder, gboolean is_idr)
1213 {
1214   if (is_idr) {
1215     reset_gop_start (encoder);
1216     set_idr_frame (picture, encoder);
1217   } else
1218     set_i_frame (picture, encoder);
1219 }
1220
1221 /* Fills in VA HRD parameters */
1222 static void
1223 fill_hrd_params (GstVaapiEncoderH264 * encoder, VAEncMiscParameterHRD * hrd)
1224 {
1225   if (encoder->bitrate_bits > 0) {
1226     hrd->buffer_size = encoder->cpb_length_bits;
1227     hrd->initial_buffer_fullness = hrd->buffer_size / 2;
1228   } else {
1229     hrd->buffer_size = 0;
1230     hrd->initial_buffer_fullness = 0;
1231   }
1232 }
1233
1234 /* Adds the supplied sequence header (SPS) to the list of packed
1235    headers to pass down as-is to the encoder */
1236 static gboolean
1237 add_packed_sequence_header (GstVaapiEncoderH264 * encoder,
1238     GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1239 {
1240   GstVaapiEncPackedHeader *packed_seq;
1241   GstBitWriter bs;
1242   VAEncPackedHeaderParameterBuffer packed_seq_param = { 0 };
1243   const VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1244   GstVaapiProfile profile = encoder->profile;
1245
1246   VAEncMiscParameterHRD hrd_params;
1247   guint32 data_bit_size;
1248   guint8 *data;
1249
1250   fill_hrd_params (encoder, &hrd_params);
1251
1252   gst_bit_writer_init (&bs, 128 * 8);
1253   WRITE_UINT32 (&bs, 0x00000001, 32);   /* start code */
1254   bs_write_nal_header (&bs, GST_H264_NAL_REF_IDC_HIGH, GST_H264_NAL_SPS);
1255
1256   /* Set High profile for encoding the MVC base view. Otherwise, some
1257      traditional decoder cannot recognize MVC profile streams with
1258      only the base view in there */
1259   if (profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH ||
1260       profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH)
1261     profile = GST_VAAPI_PROFILE_H264_HIGH;
1262
1263   bs_write_sps (&bs, seq_param, profile, &hrd_params);
1264
1265   g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1266   data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1267   data = GST_BIT_WRITER_DATA (&bs);
1268
1269   packed_seq_param.type = VAEncPackedHeaderSequence;
1270   packed_seq_param.bit_length = data_bit_size;
1271   packed_seq_param.has_emulation_bytes = 0;
1272
1273   packed_seq = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1274       &packed_seq_param, sizeof (packed_seq_param),
1275       data, (data_bit_size + 7) / 8);
1276   g_assert (packed_seq);
1277
1278   gst_vaapi_enc_picture_add_packed_header (picture, packed_seq);
1279   gst_vaapi_codec_object_replace (&packed_seq, NULL);
1280
1281   /* store sps data */
1282   _check_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1283   gst_bit_writer_clear (&bs, TRUE);
1284   return TRUE;
1285
1286   /* ERRORS */
1287 bs_error:
1288   {
1289     GST_WARNING ("failed to write SPS NAL unit");
1290     gst_bit_writer_clear (&bs, TRUE);
1291     return FALSE;
1292   }
1293 }
1294
1295 static gboolean
1296 add_packed_sequence_header_mvc (GstVaapiEncoderH264 * encoder,
1297     GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1298 {
1299   GstVaapiEncPackedHeader *packed_seq;
1300   GstBitWriter bs;
1301   VAEncPackedHeaderParameterBuffer packed_header_param_buffer = { 0 };
1302   const VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1303   VAEncMiscParameterHRD hrd_params;
1304   guint32 data_bit_size;
1305   guint8 *data;
1306
1307   fill_hrd_params (encoder, &hrd_params);
1308
1309   /* non-base layer, pack one subset sps */
1310   gst_bit_writer_init (&bs, 128 * 8);
1311   WRITE_UINT32 (&bs, 0x00000001, 32);   /* start code */
1312   bs_write_nal_header (&bs, GST_H264_NAL_REF_IDC_HIGH, GST_H264_NAL_SUBSET_SPS);
1313
1314   bs_write_subset_sps (&bs, seq_param, encoder->profile, encoder->num_views,
1315       &hrd_params);
1316
1317   g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1318   data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1319   data = GST_BIT_WRITER_DATA (&bs);
1320
1321   packed_header_param_buffer.type = VAEncPackedHeaderSequence;
1322   packed_header_param_buffer.bit_length = data_bit_size;
1323   packed_header_param_buffer.has_emulation_bytes = 0;
1324
1325   packed_seq = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1326       &packed_header_param_buffer, sizeof (packed_header_param_buffer),
1327       data, (data_bit_size + 7) / 8);
1328   g_assert (packed_seq);
1329
1330   gst_vaapi_enc_picture_add_packed_header (picture, packed_seq);
1331   gst_vaapi_mini_object_replace ((GstVaapiMiniObject **) & packed_seq, NULL);
1332
1333   /* store subset sps data */
1334   _check_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1335   gst_bit_writer_clear (&bs, TRUE);
1336   return TRUE;
1337
1338   /* ERRORS */
1339 bs_error:
1340   {
1341     GST_WARNING ("failed to write SPS NAL unit");
1342     gst_bit_writer_clear (&bs, TRUE);
1343     return FALSE;
1344   }
1345 }
1346
1347 /* Adds the supplied picture header (PPS) to the list of packed
1348    headers to pass down as-is to the encoder */
1349 static gboolean
1350 add_packed_picture_header (GstVaapiEncoderH264 * encoder,
1351     GstVaapiEncPicture * picture)
1352 {
1353   GstVaapiEncPackedHeader *packed_pic;
1354   GstBitWriter bs;
1355   VAEncPackedHeaderParameterBuffer packed_pic_param = { 0 };
1356   const VAEncPictureParameterBufferH264 *const pic_param = picture->param;
1357   guint32 data_bit_size;
1358   guint8 *data;
1359
1360   gst_bit_writer_init (&bs, 128 * 8);
1361   WRITE_UINT32 (&bs, 0x00000001, 32);   /* start code */
1362   bs_write_nal_header (&bs, GST_H264_NAL_REF_IDC_HIGH, GST_H264_NAL_PPS);
1363   bs_write_pps (&bs, pic_param, encoder->profile);
1364   g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1365   data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1366   data = GST_BIT_WRITER_DATA (&bs);
1367
1368   packed_pic_param.type = VAEncPackedHeaderPicture;
1369   packed_pic_param.bit_length = data_bit_size;
1370   packed_pic_param.has_emulation_bytes = 0;
1371
1372   packed_pic = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1373       &packed_pic_param, sizeof (packed_pic_param),
1374       data, (data_bit_size + 7) / 8);
1375   g_assert (packed_pic);
1376
1377   gst_vaapi_enc_picture_add_packed_header (picture, packed_pic);
1378   gst_vaapi_codec_object_replace (&packed_pic, NULL);
1379
1380   /* store pps data */
1381   _check_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1382   gst_bit_writer_clear (&bs, TRUE);
1383   return TRUE;
1384
1385   /* ERRORS */
1386 bs_error:
1387   {
1388     GST_WARNING ("failed to write PPS NAL unit");
1389     gst_bit_writer_clear (&bs, TRUE);
1390     return FALSE;
1391   }
1392 }
1393
1394 static gboolean
1395 get_nal_hdr_attributes (GstVaapiEncPicture * picture,
1396     guint8 * nal_ref_idc, guint8 * nal_unit_type)
1397 {
1398   switch (picture->type) {
1399     case GST_VAAPI_PICTURE_TYPE_I:
1400       *nal_ref_idc = GST_H264_NAL_REF_IDC_HIGH;
1401       if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
1402         *nal_unit_type = GST_H264_NAL_SLICE_IDR;
1403       else
1404         *nal_unit_type = GST_H264_NAL_SLICE;
1405       break;
1406     case GST_VAAPI_PICTURE_TYPE_P:
1407       *nal_ref_idc = GST_H264_NAL_REF_IDC_MEDIUM;
1408       *nal_unit_type = GST_H264_NAL_SLICE;
1409       break;
1410     case GST_VAAPI_PICTURE_TYPE_B:
1411       *nal_ref_idc = GST_H264_NAL_REF_IDC_NONE;
1412       *nal_unit_type = GST_H264_NAL_SLICE;
1413       break;
1414     default:
1415       return FALSE;
1416   }
1417   return TRUE;
1418 }
1419
1420 /* Adds the supplied prefix nal header to the list of packed
1421    headers to pass down as-is to the encoder */
1422 static gboolean
1423 add_packed_prefix_nal_header (GstVaapiEncoderH264 * encoder,
1424     GstVaapiEncPicture * picture, GstVaapiEncSlice * slice)
1425 {
1426   GstVaapiEncPackedHeader *packed_prefix_nal;
1427   GstBitWriter bs;
1428   VAEncPackedHeaderParameterBuffer packed_prefix_nal_param = { 0 };
1429   guint32 data_bit_size;
1430   guint8 *data;
1431   guint8 nal_ref_idc, nal_unit_type;
1432
1433   gst_bit_writer_init (&bs, 128 * 8);
1434   WRITE_UINT32 (&bs, 0x00000001, 32);   /* start code */
1435
1436   if (!get_nal_hdr_attributes (picture, &nal_ref_idc, &nal_unit_type))
1437     goto bs_error;
1438   nal_unit_type = GST_H264_NAL_PREFIX_UNIT;
1439
1440   bs_write_nal_header (&bs, nal_ref_idc, nal_unit_type);
1441   bs_write_nal_header_mvc_extension (&bs, picture, encoder->view_idx);
1442   g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1443   data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1444   data = GST_BIT_WRITER_DATA (&bs);
1445
1446   packed_prefix_nal_param.type = VAEncPackedHeaderRawData;
1447   packed_prefix_nal_param.bit_length = data_bit_size;
1448   packed_prefix_nal_param.has_emulation_bytes = 0;
1449
1450   packed_prefix_nal =
1451       gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1452       &packed_prefix_nal_param, sizeof (packed_prefix_nal_param), data,
1453       (data_bit_size + 7) / 8);
1454   g_assert (packed_prefix_nal);
1455
1456   gst_vaapi_enc_slice_add_packed_header (slice, packed_prefix_nal);
1457   gst_vaapi_codec_object_replace (&packed_prefix_nal, NULL);
1458
1459   gst_bit_writer_clear (&bs, TRUE);
1460
1461   return TRUE;
1462
1463   /* ERRORS */
1464 bs_error:
1465   {
1466     GST_WARNING ("failed to write Prefix NAL unit header");
1467     gst_bit_writer_clear (&bs, TRUE);
1468     return FALSE;
1469   }
1470 }
1471
1472 /* Adds the supplied slice header to the list of packed
1473    headers to pass down as-is to the encoder */
1474 static gboolean
1475 add_packed_slice_header (GstVaapiEncoderH264 * encoder,
1476     GstVaapiEncPicture * picture, GstVaapiEncSlice * slice)
1477 {
1478   GstVaapiEncPackedHeader *packed_slice;
1479   GstBitWriter bs;
1480   VAEncPackedHeaderParameterBuffer packed_slice_param = { 0 };
1481   const VAEncSliceParameterBufferH264 *const slice_param = slice->param;
1482   guint32 data_bit_size;
1483   guint8 *data;
1484   guint8 nal_ref_idc, nal_unit_type;
1485
1486   gst_bit_writer_init (&bs, 128 * 8);
1487   WRITE_UINT32 (&bs, 0x00000001, 32);   /* start code */
1488
1489   if (!get_nal_hdr_attributes (picture, &nal_ref_idc, &nal_unit_type))
1490     goto bs_error;
1491   /* pack nal_unit_header_mvc_extension() for the non base view */
1492   if (encoder->is_mvc && encoder->view_idx) {
1493     bs_write_nal_header (&bs, nal_ref_idc, GST_H264_NAL_SLICE_EXT);
1494     bs_write_nal_header_mvc_extension (&bs, picture, encoder->view_idx);
1495   } else
1496     bs_write_nal_header (&bs, nal_ref_idc, nal_unit_type);
1497
1498   bs_write_slice (&bs, slice_param, encoder, picture);
1499   data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1500   data = GST_BIT_WRITER_DATA (&bs);
1501
1502   packed_slice_param.type = VAEncPackedHeaderSlice;
1503   packed_slice_param.bit_length = data_bit_size;
1504   packed_slice_param.has_emulation_bytes = 0;
1505
1506   packed_slice = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1507       &packed_slice_param, sizeof (packed_slice_param),
1508       data, (data_bit_size + 7) / 8);
1509   g_assert (packed_slice);
1510
1511   gst_vaapi_enc_slice_add_packed_header (slice, packed_slice);
1512   gst_vaapi_codec_object_replace (&packed_slice, NULL);
1513
1514   gst_bit_writer_clear (&bs, TRUE);
1515   return TRUE;
1516
1517   /* ERRORS */
1518 bs_error:
1519   {
1520     GST_WARNING ("failed to write Slice NAL unit header");
1521     gst_bit_writer_clear (&bs, TRUE);
1522     return FALSE;
1523   }
1524 }
1525
1526 /* Reference picture management */
1527 static void
1528 reference_pic_free (GstVaapiEncoderH264 * encoder, GstVaapiEncoderH264Ref * ref)
1529 {
1530   if (!ref)
1531     return;
1532   if (ref->pic)
1533     gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), ref->pic);
1534   g_slice_free (GstVaapiEncoderH264Ref, ref);
1535 }
1536
1537 static inline GstVaapiEncoderH264Ref *
1538 reference_pic_create (GstVaapiEncoderH264 * encoder,
1539     GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1540 {
1541   GstVaapiEncoderH264Ref *const ref = g_slice_new0 (GstVaapiEncoderH264Ref);
1542
1543   ref->pic = surface;
1544   ref->frame_num = picture->frame_num;
1545   ref->poc = picture->poc;
1546   return ref;
1547 }
1548
1549 static gboolean
1550 reference_list_update (GstVaapiEncoderH264 * encoder,
1551     GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1552 {
1553   GstVaapiEncoderH264Ref *ref;
1554   GstVaapiH264ViewRefPool *const ref_pool =
1555       &encoder->ref_pools[encoder->view_idx];
1556
1557   if (GST_VAAPI_PICTURE_TYPE_B == picture->type) {
1558     gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), surface);
1559     return TRUE;
1560   }
1561   if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture)) {
1562     while (!g_queue_is_empty (&ref_pool->ref_list))
1563       reference_pic_free (encoder, g_queue_pop_head (&ref_pool->ref_list));
1564   } else if (g_queue_get_length (&ref_pool->ref_list) >=
1565       ref_pool->max_ref_frames) {
1566     reference_pic_free (encoder, g_queue_pop_head (&ref_pool->ref_list));
1567   }
1568   ref = reference_pic_create (encoder, picture, surface);
1569   g_queue_push_tail (&ref_pool->ref_list, ref);
1570   g_assert (g_queue_get_length (&ref_pool->ref_list) <=
1571       ref_pool->max_ref_frames);
1572   return TRUE;
1573 }
1574
1575 static gboolean
1576 reference_list_init (GstVaapiEncoderH264 * encoder,
1577     GstVaapiEncPicture * picture,
1578     GstVaapiEncoderH264Ref ** reflist_0,
1579     guint * reflist_0_count,
1580     GstVaapiEncoderH264Ref ** reflist_1, guint * reflist_1_count)
1581 {
1582   GstVaapiEncoderH264Ref *tmp;
1583   GstVaapiH264ViewRefPool *const ref_pool =
1584       &encoder->ref_pools[encoder->view_idx];
1585   GList *iter, *list_0_start = NULL, *list_1_start = NULL;
1586   guint count;
1587
1588   *reflist_0_count = 0;
1589   *reflist_1_count = 0;
1590   if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
1591     return TRUE;
1592
1593   iter = g_queue_peek_tail_link (&ref_pool->ref_list);
1594   for (; iter; iter = g_list_previous (iter)) {
1595     tmp = (GstVaapiEncoderH264Ref *) iter->data;
1596     g_assert (tmp && tmp->poc != picture->poc);
1597     if (_poc_greater_than (picture->poc, tmp->poc, encoder->max_pic_order_cnt)) {
1598       list_0_start = iter;
1599       list_1_start = g_list_next (iter);
1600       break;
1601     }
1602   }
1603
1604   /* order reflist_0 */
1605   g_assert (list_0_start);
1606   iter = list_0_start;
1607   count = 0;
1608   for (; iter; iter = g_list_previous (iter)) {
1609     reflist_0[count] = (GstVaapiEncoderH264Ref *) iter->data;
1610     ++count;
1611   }
1612   *reflist_0_count = count;
1613
1614   if (picture->type != GST_VAAPI_PICTURE_TYPE_B)
1615     return TRUE;
1616
1617   /* order reflist_1 */
1618   count = 0;
1619   iter = list_1_start;
1620   for (; iter; iter = g_list_next (iter)) {
1621     reflist_1[count] = (GstVaapiEncoderH264Ref *) iter->data;
1622     ++count;
1623   }
1624   *reflist_1_count = count;
1625   return TRUE;
1626 }
1627
1628 /* Fills in VA sequence parameter buffer */
1629 static gboolean
1630 fill_sequence (GstVaapiEncoderH264 * encoder, GstVaapiEncSequence * sequence)
1631 {
1632   VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
1633   GstVaapiH264ViewRefPool *const ref_pool =
1634       &encoder->ref_pools[encoder->view_idx];
1635
1636   memset (seq_param, 0, sizeof (VAEncSequenceParameterBufferH264));
1637   seq_param->seq_parameter_set_id = encoder->view_idx;
1638   seq_param->level_idc = encoder->level_idc;
1639   seq_param->intra_period = GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder);
1640   seq_param->ip_period = 1 + encoder->num_bframes;
1641   seq_param->bits_per_second = encoder->bitrate_bits;
1642
1643   seq_param->max_num_ref_frames = ref_pool->max_ref_frames;
1644   seq_param->picture_width_in_mbs = encoder->mb_width;
1645   seq_param->picture_height_in_mbs = encoder->mb_height;
1646
1647   /*sequence field values */
1648   seq_param->seq_fields.value = 0;
1649   seq_param->seq_fields.bits.chroma_format_idc = 1;
1650   seq_param->seq_fields.bits.frame_mbs_only_flag = 1;
1651   seq_param->seq_fields.bits.mb_adaptive_frame_field_flag = FALSE;
1652   seq_param->seq_fields.bits.seq_scaling_matrix_present_flag = FALSE;
1653   /* direct_8x8_inference_flag default false */
1654   seq_param->seq_fields.bits.direct_8x8_inference_flag = FALSE;
1655   g_assert (encoder->log2_max_frame_num >= 4);
1656   seq_param->seq_fields.bits.log2_max_frame_num_minus4 =
1657       encoder->log2_max_frame_num - 4;
1658   /* picture order count */
1659   encoder->pic_order_cnt_type = seq_param->seq_fields.bits.pic_order_cnt_type =
1660       0;
1661   g_assert (encoder->log2_max_pic_order_cnt >= 4);
1662   seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 =
1663       encoder->log2_max_pic_order_cnt - 4;
1664
1665   seq_param->bit_depth_luma_minus8 = 0;
1666   seq_param->bit_depth_chroma_minus8 = 0;
1667
1668   /* not used if pic_order_cnt_type == 0 */
1669   if (seq_param->seq_fields.bits.pic_order_cnt_type == 1) {
1670     encoder->delta_pic_order_always_zero_flag =
1671         seq_param->seq_fields.bits.delta_pic_order_always_zero_flag = TRUE;
1672     seq_param->num_ref_frames_in_pic_order_cnt_cycle = 0;
1673     seq_param->offset_for_non_ref_pic = 0;
1674     seq_param->offset_for_top_to_bottom_field = 0;
1675     memset (seq_param->offset_for_ref_frame, 0,
1676         sizeof (seq_param->offset_for_ref_frame));
1677   }
1678
1679   /* frame_cropping_flag */
1680   if ((GST_VAAPI_ENCODER_WIDTH (encoder) & 15) ||
1681       (GST_VAAPI_ENCODER_HEIGHT (encoder) & 15)) {
1682     static const guint SubWidthC[] = { 1, 2, 2, 1 };
1683     static const guint SubHeightC[] = { 1, 2, 1, 1 };
1684     const guint CropUnitX =
1685         SubWidthC[seq_param->seq_fields.bits.chroma_format_idc];
1686     const guint CropUnitY =
1687         SubHeightC[seq_param->seq_fields.bits.chroma_format_idc] *
1688         (2 - seq_param->seq_fields.bits.frame_mbs_only_flag);
1689
1690     seq_param->frame_cropping_flag = 1;
1691     seq_param->frame_crop_left_offset = 0;
1692     seq_param->frame_crop_right_offset =
1693         (16 * encoder->mb_width -
1694         GST_VAAPI_ENCODER_WIDTH (encoder)) / CropUnitX;
1695     seq_param->frame_crop_top_offset = 0;
1696     seq_param->frame_crop_bottom_offset =
1697         (16 * encoder->mb_height -
1698         GST_VAAPI_ENCODER_HEIGHT (encoder)) / CropUnitY;
1699   }
1700
1701   /* VUI parameters are always set, at least for timing_info (framerate) */
1702   seq_param->vui_parameters_present_flag = TRUE;
1703   if (seq_param->vui_parameters_present_flag) {
1704     seq_param->vui_fields.bits.aspect_ratio_info_present_flag = TRUE;
1705     if (seq_param->vui_fields.bits.aspect_ratio_info_present_flag) {
1706       const GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
1707       seq_param->aspect_ratio_idc = 0xff;
1708       seq_param->sar_width = GST_VIDEO_INFO_PAR_N (vip);
1709       seq_param->sar_height = GST_VIDEO_INFO_PAR_D (vip);
1710     }
1711     seq_param->vui_fields.bits.bitstream_restriction_flag = FALSE;
1712     /* if vui_parameters_present_flag is TRUE and sps data belongs to
1713      * subset sps, timing_info_preset_flag should be zero (H.7.4.2.1.1) */
1714     seq_param->vui_fields.bits.timing_info_present_flag = !encoder->view_idx;
1715     if (seq_param->vui_fields.bits.timing_info_present_flag) {
1716       seq_param->num_units_in_tick = GST_VAAPI_ENCODER_FPS_D (encoder);
1717       seq_param->time_scale = GST_VAAPI_ENCODER_FPS_N (encoder) * 2;
1718     }
1719   }
1720   return TRUE;
1721 }
1722
1723 /* Fills in VA picture parameter buffer */
1724 static gboolean
1725 fill_picture (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture,
1726     GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface)
1727 {
1728   VAEncPictureParameterBufferH264 *const pic_param = picture->param;
1729   GstVaapiH264ViewRefPool *const ref_pool =
1730       &encoder->ref_pools[encoder->view_idx];
1731   GstVaapiEncoderH264Ref *ref_pic;
1732   GList *reflist;
1733   guint i;
1734
1735   memset (pic_param, 0, sizeof (VAEncPictureParameterBufferH264));
1736
1737   /* reference list,  */
1738   pic_param->CurrPic.picture_id = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface);
1739   pic_param->CurrPic.TopFieldOrderCnt = picture->poc;
1740   i = 0;
1741   if (picture->type != GST_VAAPI_PICTURE_TYPE_I) {
1742     for (reflist = g_queue_peek_head_link (&ref_pool->ref_list);
1743         reflist; reflist = g_list_next (reflist)) {
1744       ref_pic = reflist->data;
1745       g_assert (ref_pic && ref_pic->pic &&
1746           GST_VAAPI_SURFACE_PROXY_SURFACE_ID (ref_pic->pic) != VA_INVALID_ID);
1747
1748       pic_param->ReferenceFrames[i].picture_id =
1749           GST_VAAPI_SURFACE_PROXY_SURFACE_ID (ref_pic->pic);
1750       ++i;
1751     }
1752     g_assert (i <= 16 && i <= ref_pool->max_ref_frames);
1753   }
1754   for (; i < 16; ++i) {
1755     pic_param->ReferenceFrames[i].picture_id = VA_INVALID_ID;
1756   }
1757   pic_param->coded_buf = GST_VAAPI_OBJECT_ID (codedbuf);
1758
1759   pic_param->pic_parameter_set_id = encoder->view_idx;
1760   pic_param->seq_parameter_set_id = encoder->view_idx;
1761   pic_param->last_picture = 0;  /* means last encoding picture */
1762   pic_param->frame_num = picture->frame_num;
1763   pic_param->pic_init_qp = encoder->init_qp;
1764   pic_param->num_ref_idx_l0_active_minus1 =
1765       (ref_pool->max_reflist0_count ? (ref_pool->max_reflist0_count - 1) : 0);
1766   pic_param->num_ref_idx_l1_active_minus1 =
1767       (ref_pool->max_reflist1_count ? (ref_pool->max_reflist1_count - 1) : 0);
1768   pic_param->chroma_qp_index_offset = 0;
1769   pic_param->second_chroma_qp_index_offset = 0;
1770
1771   /* set picture fields */
1772   pic_param->pic_fields.value = 0;
1773   pic_param->pic_fields.bits.idr_pic_flag =
1774       GST_VAAPI_ENC_PICTURE_IS_IDR (picture);
1775   pic_param->pic_fields.bits.reference_pic_flag =
1776       (picture->type != GST_VAAPI_PICTURE_TYPE_B);
1777   pic_param->pic_fields.bits.entropy_coding_mode_flag = encoder->use_cabac;
1778   pic_param->pic_fields.bits.weighted_pred_flag = FALSE;
1779   pic_param->pic_fields.bits.weighted_bipred_idc = 0;
1780   pic_param->pic_fields.bits.constrained_intra_pred_flag = 0;
1781   pic_param->pic_fields.bits.transform_8x8_mode_flag = encoder->use_dct8x8;
1782   /* enable debloking */
1783   pic_param->pic_fields.bits.deblocking_filter_control_present_flag = TRUE;
1784   pic_param->pic_fields.bits.redundant_pic_cnt_present_flag = FALSE;
1785   /* bottom_field_pic_order_in_frame_present_flag */
1786   pic_param->pic_fields.bits.pic_order_present_flag = FALSE;
1787   pic_param->pic_fields.bits.pic_scaling_matrix_present_flag = FALSE;
1788
1789   return TRUE;
1790 }
1791
1792 /* Adds slice headers to picture */
1793 static gboolean
1794 add_slice_headers (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture,
1795     GstVaapiEncoderH264Ref ** reflist_0, guint reflist_0_count,
1796     GstVaapiEncoderH264Ref ** reflist_1, guint reflist_1_count)
1797 {
1798   VAEncSliceParameterBufferH264 *slice_param;
1799   GstVaapiEncSlice *slice;
1800   guint slice_of_mbs, slice_mod_mbs, cur_slice_mbs;
1801   guint mb_size;
1802   guint last_mb_index;
1803   guint i_slice, i_ref;
1804
1805   g_assert (picture);
1806
1807   mb_size = encoder->mb_width * encoder->mb_height;
1808
1809   g_assert (encoder->num_slices && encoder->num_slices < mb_size);
1810   slice_of_mbs = mb_size / encoder->num_slices;
1811   slice_mod_mbs = mb_size % encoder->num_slices;
1812   last_mb_index = 0;
1813   for (i_slice = 0; i_slice < encoder->num_slices; ++i_slice) {
1814     cur_slice_mbs = slice_of_mbs;
1815     if (slice_mod_mbs) {
1816       ++cur_slice_mbs;
1817       --slice_mod_mbs;
1818     }
1819     slice = GST_VAAPI_ENC_SLICE_NEW (H264, encoder);
1820     g_assert (slice && slice->param_id != VA_INVALID_ID);
1821     slice_param = slice->param;
1822
1823     memset (slice_param, 0, sizeof (VAEncSliceParameterBufferH264));
1824     slice_param->macroblock_address = last_mb_index;
1825     slice_param->num_macroblocks = cur_slice_mbs;
1826     slice_param->macroblock_info = VA_INVALID_ID;
1827     slice_param->slice_type = h264_get_slice_type (picture->type);
1828     g_assert (slice_param->slice_type != -1);
1829     slice_param->pic_parameter_set_id = encoder->view_idx;
1830     slice_param->idr_pic_id = encoder->idr_num;
1831     slice_param->pic_order_cnt_lsb = picture->poc;
1832
1833     /* not used if pic_order_cnt_type = 0 */
1834     slice_param->delta_pic_order_cnt_bottom = 0;
1835     memset (slice_param->delta_pic_order_cnt, 0,
1836         sizeof (slice_param->delta_pic_order_cnt));
1837
1838     /* only works for B frames */
1839     slice_param->direct_spatial_mv_pred_flag = FALSE;
1840     /* default equal to picture parameters */
1841     slice_param->num_ref_idx_active_override_flag = FALSE;
1842     if (picture->type != GST_VAAPI_PICTURE_TYPE_I && reflist_0_count > 0)
1843       slice_param->num_ref_idx_l0_active_minus1 = reflist_0_count - 1;
1844     else
1845       slice_param->num_ref_idx_l0_active_minus1 = 0;
1846     if (picture->type == GST_VAAPI_PICTURE_TYPE_B && reflist_1_count > 0)
1847       slice_param->num_ref_idx_l1_active_minus1 = reflist_1_count - 1;
1848     else
1849       slice_param->num_ref_idx_l1_active_minus1 = 0;
1850     g_assert (slice_param->num_ref_idx_l0_active_minus1 == 0);
1851     g_assert (slice_param->num_ref_idx_l1_active_minus1 == 0);
1852
1853     i_ref = 0;
1854     if (picture->type != GST_VAAPI_PICTURE_TYPE_I) {
1855       for (; i_ref < reflist_0_count; ++i_ref) {
1856         slice_param->RefPicList0[i_ref].picture_id =
1857             GST_VAAPI_SURFACE_PROXY_SURFACE_ID (reflist_0[i_ref]->pic);
1858       }
1859       g_assert (i_ref == 1);
1860     }
1861     for (; i_ref < G_N_ELEMENTS (slice_param->RefPicList0); ++i_ref) {
1862       slice_param->RefPicList0[i_ref].picture_id = VA_INVALID_SURFACE;
1863     }
1864
1865     i_ref = 0;
1866     if (picture->type == GST_VAAPI_PICTURE_TYPE_B) {
1867       for (; i_ref < reflist_1_count; ++i_ref) {
1868         slice_param->RefPicList1[i_ref].picture_id =
1869             GST_VAAPI_SURFACE_PROXY_SURFACE_ID (reflist_1[i_ref]->pic);
1870       }
1871       g_assert (i_ref == 1);
1872     }
1873     for (; i_ref < G_N_ELEMENTS (slice_param->RefPicList1); ++i_ref) {
1874       slice_param->RefPicList1[i_ref].picture_id = VA_INVALID_SURFACE;
1875     }
1876
1877     /* not used if  pic_param.pic_fields.bits.weighted_pred_flag == FALSE */
1878     slice_param->luma_log2_weight_denom = 0;
1879     slice_param->chroma_log2_weight_denom = 0;
1880     slice_param->luma_weight_l0_flag = FALSE;
1881     memset (slice_param->luma_weight_l0, 0,
1882         sizeof (slice_param->luma_weight_l0));
1883     memset (slice_param->luma_offset_l0, 0,
1884         sizeof (slice_param->luma_offset_l0));
1885     slice_param->chroma_weight_l0_flag = FALSE;
1886     memset (slice_param->chroma_weight_l0, 0,
1887         sizeof (slice_param->chroma_weight_l0));
1888     memset (slice_param->chroma_offset_l0, 0,
1889         sizeof (slice_param->chroma_offset_l0));
1890     slice_param->luma_weight_l1_flag = FALSE;
1891     memset (slice_param->luma_weight_l1, 0,
1892         sizeof (slice_param->luma_weight_l1));
1893     memset (slice_param->luma_offset_l1, 0,
1894         sizeof (slice_param->luma_offset_l1));
1895     slice_param->chroma_weight_l1_flag = FALSE;
1896     memset (slice_param->chroma_weight_l1, 0,
1897         sizeof (slice_param->chroma_weight_l1));
1898     memset (slice_param->chroma_offset_l1, 0,
1899         sizeof (slice_param->chroma_offset_l1));
1900
1901     slice_param->cabac_init_idc = 0;
1902     slice_param->slice_qp_delta = encoder->init_qp - encoder->min_qp;
1903     if (slice_param->slice_qp_delta > 4)
1904       slice_param->slice_qp_delta = 4;
1905     slice_param->disable_deblocking_filter_idc = 0;
1906     slice_param->slice_alpha_c0_offset_div2 = 2;
1907     slice_param->slice_beta_offset_div2 = 2;
1908
1909     /* set calculation for next slice */
1910     last_mb_index += cur_slice_mbs;
1911
1912     /* add packed Prefix NAL unit before each Coded slice NAL in base view */
1913     if (encoder->is_mvc && !encoder->view_idx &&
1914         (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
1915             VA_ENC_PACKED_HEADER_RAW_DATA)
1916         && !add_packed_prefix_nal_header (encoder, picture, slice))
1917       goto error_create_packed_prefix_nal_hdr;
1918     if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
1919             VA_ENC_PACKED_HEADER_SLICE)
1920         && !add_packed_slice_header (encoder, picture, slice))
1921       goto error_create_packed_slice_hdr;
1922
1923     gst_vaapi_enc_picture_add_slice (picture, slice);
1924     gst_vaapi_codec_object_replace (&slice, NULL);
1925   }
1926   g_assert (last_mb_index == mb_size);
1927   return TRUE;
1928
1929 error_create_packed_slice_hdr:
1930   {
1931     GST_ERROR ("failed to create packed slice header buffer");
1932     gst_vaapi_codec_object_replace (&slice, NULL);
1933     return FALSE;
1934   }
1935 error_create_packed_prefix_nal_hdr:
1936   {
1937     GST_ERROR ("failed to create packed prefix nal header buffer");
1938     gst_vaapi_codec_object_replace (&slice, NULL);
1939     return FALSE;
1940   }
1941 }
1942
1943 /* Generates and submits SPS header accordingly into the bitstream */
1944 static gboolean
1945 ensure_sequence (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
1946 {
1947   GstVaapiEncSequence *sequence = NULL;
1948
1949   /* submit an SPS header before every new I-frame, if codec config changed */
1950   if (!encoder->config_changed || picture->type != GST_VAAPI_PICTURE_TYPE_I)
1951     return TRUE;
1952
1953   sequence = GST_VAAPI_ENC_SEQUENCE_NEW (H264, encoder);
1954   if (!sequence || !fill_sequence (encoder, sequence))
1955     goto error_create_seq_param;
1956
1957   /* add subset sps for non-base view and sps for base view */
1958   if (encoder->is_mvc && encoder->view_idx) {
1959     if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) & VAEncPackedHeaderH264_SPS)
1960         && !add_packed_sequence_header_mvc (encoder, picture, sequence))
1961       goto error_create_packed_seq_hdr;
1962   } else {
1963     if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) & VAEncPackedHeaderH264_SPS)
1964         && !add_packed_sequence_header (encoder, picture, sequence))
1965       goto error_create_packed_seq_hdr;
1966   }
1967
1968   if (sequence) {
1969     gst_vaapi_enc_picture_set_sequence (picture, sequence);
1970     gst_vaapi_codec_object_replace (&sequence, NULL);
1971   }
1972
1973   if (!encoder->is_mvc || encoder->view_idx > 0)
1974     encoder->config_changed = FALSE;
1975   return TRUE;
1976
1977   /* ERRORS */
1978 error_create_seq_param:
1979   {
1980     GST_ERROR ("failed to create sequence parameter buffer (SPS)");
1981     gst_vaapi_codec_object_replace (&sequence, NULL);
1982     return FALSE;
1983   }
1984 error_create_packed_seq_hdr:
1985   {
1986     GST_ERROR ("failed to create packed sequence header buffer");
1987     gst_vaapi_codec_object_replace (&sequence, NULL);
1988     return FALSE;
1989   }
1990 }
1991
1992 /* Generates additional control parameters */
1993 static gboolean
1994 ensure_misc_params (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
1995 {
1996   GstVaapiEncMiscParam *misc = NULL;
1997   VAEncMiscParameterRateControl *rate_control;
1998
1999   /* HRD params */
2000   misc = GST_VAAPI_ENC_MISC_PARAM_NEW (HRD, encoder);
2001   g_assert (misc);
2002   if (!misc)
2003     return FALSE;
2004   fill_hrd_params (encoder, misc->data);
2005   gst_vaapi_enc_picture_add_misc_param (picture, misc);
2006   gst_vaapi_codec_object_replace (&misc, NULL);
2007
2008   /* RateControl params */
2009   if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CBR ||
2010       GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_VBR) {
2011     misc = GST_VAAPI_ENC_MISC_PARAM_NEW (RateControl, encoder);
2012     g_assert (misc);
2013     if (!misc)
2014       return FALSE;
2015     rate_control = misc->data;
2016     memset (rate_control, 0, sizeof (VAEncMiscParameterRateControl));
2017     rate_control->bits_per_second = encoder->bitrate_bits;
2018     rate_control->target_percentage = 70;
2019     rate_control->window_size = encoder->cpb_length;
2020     rate_control->initial_qp = encoder->init_qp;
2021     rate_control->min_qp = encoder->min_qp;
2022     rate_control->basic_unit_size = 0;
2023     gst_vaapi_enc_picture_add_misc_param (picture, misc);
2024     gst_vaapi_codec_object_replace (&misc, NULL);
2025   }
2026   return TRUE;
2027 }
2028
2029 /* Generates and submits PPS header accordingly into the bitstream */
2030 static gboolean
2031 ensure_picture (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture,
2032     GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface)
2033 {
2034   GstVaapiCodedBuffer *const codedbuf =
2035       GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy);
2036   gboolean res = FALSE;
2037
2038   res = fill_picture (encoder, picture, codedbuf, surface);
2039
2040   if (!res)
2041     return FALSE;
2042
2043   if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
2044       (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) & VAEncPackedHeaderH264_PPS)
2045       && !add_packed_picture_header (encoder, picture)) {
2046     GST_ERROR ("set picture packed header failed");
2047     return FALSE;
2048   }
2049   return TRUE;
2050 }
2051
2052 /* Generates slice headers */
2053 static gboolean
2054 ensure_slices (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
2055 {
2056   GstVaapiEncoderH264Ref *reflist_0[16];
2057   GstVaapiEncoderH264Ref *reflist_1[16];
2058   GstVaapiH264ViewRefPool *const ref_pool =
2059       &encoder->ref_pools[encoder->view_idx];
2060   guint reflist_0_count = 0, reflist_1_count = 0;
2061
2062   g_assert (picture);
2063
2064   if (picture->type != GST_VAAPI_PICTURE_TYPE_I &&
2065       !reference_list_init (encoder, picture,
2066           reflist_0, &reflist_0_count, reflist_1, &reflist_1_count)) {
2067     GST_ERROR ("reference list reorder failed");
2068     return FALSE;
2069   }
2070
2071   g_assert (reflist_0_count + reflist_1_count <= ref_pool->max_ref_frames);
2072   if (reflist_0_count > ref_pool->max_reflist0_count)
2073     reflist_0_count = ref_pool->max_reflist0_count;
2074   if (reflist_1_count > ref_pool->max_reflist1_count)
2075     reflist_1_count = ref_pool->max_reflist1_count;
2076
2077   if (!add_slice_headers (encoder, picture,
2078           reflist_0, reflist_0_count, reflist_1, reflist_1_count))
2079     return FALSE;
2080
2081   return TRUE;
2082 }
2083
2084 /* Normalizes bitrate (and CPB size) for HRD conformance */
2085 static void
2086 ensure_bitrate_hrd (GstVaapiEncoderH264 * encoder)
2087 {
2088   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2089   guint bitrate, cpb_size;
2090
2091   if (!base_encoder->bitrate) {
2092     encoder->bitrate_bits = 0;
2093     return;
2094   }
2095
2096   /* Round down bitrate. This is a hard limit mandated by the user */
2097   g_assert (SX_BITRATE >= 6);
2098   bitrate = (base_encoder->bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
2099   if (bitrate != encoder->bitrate_bits) {
2100     GST_DEBUG ("HRD bitrate: %u bits/sec", bitrate);
2101     encoder->bitrate_bits = bitrate;
2102     encoder->config_changed = TRUE;
2103   }
2104
2105   /* Round up CPB size. This is an HRD compliance detail */
2106   g_assert (SX_CPB_SIZE >= 4);
2107   cpb_size = gst_util_uint64_scale (bitrate, encoder->cpb_length, 1000) &
2108       ~((1U << SX_CPB_SIZE) - 1);
2109   if (cpb_size != encoder->cpb_length_bits) {
2110     GST_DEBUG ("HRD CPB size: %u bits", cpb_size);
2111     encoder->cpb_length_bits = cpb_size;
2112     encoder->config_changed = TRUE;
2113   }
2114 }
2115
2116 /* Estimates a good enough bitrate if none was supplied */
2117 static void
2118 ensure_bitrate (GstVaapiEncoderH264 * encoder)
2119 {
2120   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2121
2122   /* Default compression: 48 bits per macroblock in "high-compression" mode */
2123   switch (GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
2124     case GST_VAAPI_RATECONTROL_CBR:
2125     case GST_VAAPI_RATECONTROL_VBR:
2126     case GST_VAAPI_RATECONTROL_VBR_CONSTRAINED:
2127       if (!base_encoder->bitrate) {
2128         /* According to the literature and testing, CABAC entropy coding
2129            mode could provide for +10% to +18% improvement in general,
2130            thus estimating +15% here ; and using adaptive 8x8 transforms
2131            in I-frames could bring up to +10% improvement. */
2132         guint bits_per_mb = 48;
2133         if (!encoder->use_cabac)
2134           bits_per_mb += (bits_per_mb * 15) / 100;
2135         if (!encoder->use_dct8x8)
2136           bits_per_mb += (bits_per_mb * 10) / 100;
2137
2138         base_encoder->bitrate =
2139             encoder->mb_width * encoder->mb_height * bits_per_mb *
2140             GST_VAAPI_ENCODER_FPS_N (encoder) /
2141             GST_VAAPI_ENCODER_FPS_D (encoder) / 1000;
2142         GST_INFO ("target bitrate computed to %u kbps", base_encoder->bitrate);
2143       }
2144       break;
2145     default:
2146       base_encoder->bitrate = 0;
2147       break;
2148   }
2149   ensure_bitrate_hrd (encoder);
2150 }
2151
2152 /* Constructs profile and level information based on user-defined limits */
2153 static GstVaapiEncoderStatus
2154 ensure_profile_and_level (GstVaapiEncoderH264 * encoder)
2155 {
2156   const GstVaapiProfile profile = encoder->profile;
2157   const GstVaapiLevelH264 level = encoder->level;
2158
2159   ensure_tuning (encoder);
2160
2161   if (!ensure_profile (encoder) || !ensure_profile_limits (encoder))
2162     return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2163
2164   /* Check HW constraints */
2165   if (!ensure_hw_profile_limits (encoder))
2166     return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2167   if (encoder->profile_idc > encoder->hw_max_profile_idc)
2168     return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2169
2170   /* Ensure bitrate if not set already and derive the right level to use */
2171   ensure_bitrate (encoder);
2172   if (!ensure_level (encoder))
2173     return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
2174
2175   if (encoder->profile != profile || encoder->level != level) {
2176     GST_DEBUG ("selected %s profile at level %s",
2177         gst_vaapi_utils_h264_get_profile_string (encoder->profile),
2178         gst_vaapi_utils_h264_get_level_string (encoder->level));
2179     encoder->config_changed = TRUE;
2180   }
2181   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2182 }
2183
2184 static void
2185 reset_properties (GstVaapiEncoderH264 * encoder)
2186 {
2187   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2188   guint mb_size, i;
2189
2190   if (encoder->idr_period < base_encoder->keyframe_period)
2191     encoder->idr_period = base_encoder->keyframe_period;
2192   if (encoder->idr_period > MAX_IDR_PERIOD)
2193     encoder->idr_period = MAX_IDR_PERIOD;
2194
2195   if (encoder->min_qp > encoder->init_qp ||
2196       (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP &&
2197           encoder->min_qp < encoder->init_qp))
2198     encoder->min_qp = encoder->init_qp;
2199
2200   mb_size = encoder->mb_width * encoder->mb_height;
2201   if (encoder->num_slices > (mb_size + 1) / 2)
2202     encoder->num_slices = (mb_size + 1) / 2;
2203   g_assert (encoder->num_slices);
2204
2205   if (encoder->num_bframes > (base_encoder->keyframe_period + 1) / 2)
2206     encoder->num_bframes = (base_encoder->keyframe_period + 1) / 2;
2207
2208   if (encoder->num_bframes)
2209     encoder->cts_offset = GST_SECOND * GST_VAAPI_ENCODER_FPS_D (encoder) /
2210         GST_VAAPI_ENCODER_FPS_N (encoder);
2211   else
2212     encoder->cts_offset = 0;
2213
2214   /* init max_frame_num, max_poc */
2215   encoder->log2_max_frame_num =
2216       h264_get_log2_max_frame_num (encoder->idr_period);
2217   g_assert (encoder->log2_max_frame_num >= 4);
2218   encoder->max_frame_num = (1 << encoder->log2_max_frame_num);
2219   encoder->log2_max_pic_order_cnt = encoder->log2_max_frame_num + 1;
2220   encoder->max_pic_order_cnt = (1 << encoder->log2_max_pic_order_cnt);
2221   encoder->idr_num = 0;
2222
2223   encoder->is_mvc = encoder->num_views > 1;
2224   for (i = 0; i < encoder->num_views; i++) {
2225     GstVaapiH264ViewRefPool *const ref_pool = &encoder->ref_pools[i];
2226     ref_pool->max_reflist0_count = 1;
2227     ref_pool->max_reflist1_count = encoder->num_bframes > 0;
2228     ref_pool->max_ref_frames = ref_pool->max_reflist0_count
2229         + ref_pool->max_reflist1_count;
2230
2231     GstVaapiH264ViewReorderPool *const reorder_pool =
2232         &encoder->reorder_pools[i];
2233     reorder_pool->frame_index = 0;
2234   }
2235 }
2236
2237 static GstVaapiEncoderStatus
2238 gst_vaapi_encoder_h264_encode (GstVaapiEncoder * base_encoder,
2239     GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf)
2240 {
2241   GstVaapiEncoderH264 *const encoder =
2242       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2243   GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2244   GstVaapiSurfaceProxy *reconstruct = NULL;
2245
2246   reconstruct = gst_vaapi_encoder_create_surface (base_encoder);
2247
2248   g_assert (GST_VAAPI_SURFACE_PROXY_SURFACE (reconstruct));
2249
2250   if (!ensure_sequence (encoder, picture))
2251     goto error;
2252   if (!ensure_misc_params (encoder, picture))
2253     goto error;
2254   if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
2255     goto error;
2256   if (!ensure_slices (encoder, picture))
2257     goto error;
2258   if (!gst_vaapi_enc_picture_encode (picture))
2259     goto error;
2260
2261   if (!reference_list_update (encoder, picture, reconstruct))
2262     goto error;
2263
2264   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2265 error:
2266   if (reconstruct)
2267     gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
2268         reconstruct);
2269   return ret;
2270 }
2271
2272 static GstVaapiEncoderStatus
2273 gst_vaapi_encoder_h264_flush (GstVaapiEncoder * base_encoder)
2274 {
2275   GstVaapiEncoderH264 *const encoder =
2276       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2277   GstVaapiH264ViewReorderPool *reorder_pool;
2278   GstVaapiEncPicture *pic;
2279   guint i;
2280
2281   for (i = 0; i < encoder->num_views; i++) {
2282     reorder_pool = &encoder->reorder_pools[i];
2283     reorder_pool->frame_index = 0;
2284     reorder_pool->cur_frame_num = 0;
2285     reorder_pool->cur_present_index = 0;
2286
2287     while (!g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2288       pic = (GstVaapiEncPicture *)
2289           g_queue_pop_head (&reorder_pool->reorder_frame_list);
2290       gst_vaapi_enc_picture_unref (pic);
2291     }
2292     g_queue_clear (&reorder_pool->reorder_frame_list);
2293   }
2294
2295   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2296 }
2297
2298 /* Generate "codec-data" buffer */
2299 static GstVaapiEncoderStatus
2300 gst_vaapi_encoder_h264_get_codec_data (GstVaapiEncoder * base_encoder,
2301     GstBuffer ** out_buffer_ptr)
2302 {
2303   GstVaapiEncoderH264 *const encoder =
2304       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2305   const guint32 configuration_version = 0x01;
2306   const guint32 nal_length_size = 4;
2307   guint8 profile_idc, profile_comp, level_idc;
2308   GstMapInfo sps_info, pps_info;
2309   GstBitWriter bs;
2310   GstBuffer *buffer;
2311
2312   if (!encoder->sps_data || !encoder->pps_data)
2313     return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
2314   if (gst_buffer_get_size (encoder->sps_data) < 4)
2315     return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
2316
2317   if (!gst_buffer_map (encoder->sps_data, &sps_info, GST_MAP_READ))
2318     goto error_map_sps_buffer;
2319
2320   if (!gst_buffer_map (encoder->pps_data, &pps_info, GST_MAP_READ))
2321     goto error_map_pps_buffer;
2322
2323   /* skip sps_data[0], which is the nal_unit_type */
2324   profile_idc = sps_info.data[1];
2325   profile_comp = sps_info.data[2];
2326   level_idc = sps_info.data[3];
2327
2328   /* Header */
2329   gst_bit_writer_init (&bs, (sps_info.size + pps_info.size + 64) * 8);
2330   WRITE_UINT32 (&bs, configuration_version, 8);
2331   WRITE_UINT32 (&bs, profile_idc, 8);
2332   WRITE_UINT32 (&bs, profile_comp, 8);
2333   WRITE_UINT32 (&bs, level_idc, 8);
2334   WRITE_UINT32 (&bs, 0x3f, 6);  /* 111111 */
2335   WRITE_UINT32 (&bs, nal_length_size - 1, 2);
2336   WRITE_UINT32 (&bs, 0x07, 3);  /* 111 */
2337
2338   /* Write SPS */
2339   WRITE_UINT32 (&bs, 1, 5);     /* SPS count = 1 */
2340   g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
2341   WRITE_UINT32 (&bs, sps_info.size, 16);
2342   gst_bit_writer_put_bytes (&bs, sps_info.data, sps_info.size);
2343
2344   /* Write PPS */
2345   WRITE_UINT32 (&bs, 1, 8);     /* PPS count = 1 */
2346   WRITE_UINT32 (&bs, pps_info.size, 16);
2347   gst_bit_writer_put_bytes (&bs, pps_info.data, pps_info.size);
2348
2349   gst_buffer_unmap (encoder->pps_data, &pps_info);
2350   gst_buffer_unmap (encoder->sps_data, &sps_info);
2351
2352   buffer = gst_buffer_new_wrapped (GST_BIT_WRITER_DATA (&bs),
2353       GST_BIT_WRITER_BIT_SIZE (&bs) / 8);
2354   if (!buffer)
2355     goto error_alloc_buffer;
2356   *out_buffer_ptr = buffer;
2357
2358   gst_bit_writer_clear (&bs, FALSE);
2359   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2360
2361   /* ERRORS */
2362 bs_error:
2363   {
2364     GST_ERROR ("failed to write codec-data");
2365     gst_buffer_unmap (encoder->sps_data, &sps_info);
2366     gst_buffer_unmap (encoder->pps_data, &pps_info);
2367     gst_bit_writer_clear (&bs, TRUE);
2368     return FALSE;
2369   }
2370 error_map_sps_buffer:
2371   {
2372     GST_ERROR ("failed to map SPS packed header");
2373     return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2374   }
2375 error_map_pps_buffer:
2376   {
2377     GST_ERROR ("failed to map PPS packed header");
2378     gst_buffer_unmap (encoder->sps_data, &sps_info);
2379     return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2380   }
2381 error_alloc_buffer:
2382   {
2383     GST_ERROR ("failed to allocate codec-data buffer");
2384     gst_bit_writer_clear (&bs, TRUE);
2385     return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2386   }
2387 }
2388
2389 static GstVaapiEncoderStatus
2390 gst_vaapi_encoder_h264_reordering (GstVaapiEncoder * base_encoder,
2391     GstVideoCodecFrame * frame, GstVaapiEncPicture ** output)
2392 {
2393   GstVaapiEncoderH264 *const encoder =
2394       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2395   GstVaapiH264ViewReorderPool *reorder_pool = NULL;
2396   GstVaapiEncPicture *picture;
2397   gboolean is_idr = FALSE;
2398
2399   *output = NULL;
2400
2401   /* encoding views alternatively for MVC */
2402   if (encoder->is_mvc) {
2403     if (frame)
2404       encoder->view_idx = frame->system_frame_number % MAX_NUM_VIEWS;
2405     else
2406       encoder->view_idx = (encoder->view_idx + 1) % MAX_NUM_VIEWS;
2407   }
2408   reorder_pool = &encoder->reorder_pools[encoder->view_idx];
2409
2410   if (!frame) {
2411     if (reorder_pool->reorder_state != GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES)
2412       return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
2413
2414     /* reorder_state = GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES
2415        dump B frames from queue, sometime, there may also have P frame or I frame */
2416     g_assert (encoder->num_bframes > 0);
2417     g_return_val_if_fail (!g_queue_is_empty (&reorder_pool->reorder_frame_list),
2418         GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN);
2419     picture = g_queue_pop_head (&reorder_pool->reorder_frame_list);
2420     g_assert (picture);
2421     if (g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2422       reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES;
2423     }
2424     goto end;
2425   }
2426
2427   /* new frame coming */
2428   picture = GST_VAAPI_ENC_PICTURE_NEW (H264, encoder, frame);
2429   if (!picture) {
2430     GST_WARNING ("create H264 picture failed, frame timestamp:%"
2431         GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts));
2432     return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2433   }
2434   ++reorder_pool->cur_present_index;
2435   picture->poc = ((reorder_pool->cur_present_index * 2) %
2436       encoder->max_pic_order_cnt);
2437
2438   is_idr = (reorder_pool->frame_index == 0 ||
2439       reorder_pool->frame_index >= encoder->idr_period);
2440
2441   /* check key frames */
2442   if (is_idr || GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame) ||
2443       (reorder_pool->frame_index %
2444           GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder)) == 0) {
2445     ++reorder_pool->cur_frame_num;
2446     ++reorder_pool->frame_index;
2447
2448     /* b frame enabled,  check queue of reorder_frame_list */
2449     if (encoder->num_bframes
2450         && !g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2451       GstVaapiEncPicture *p_pic;
2452
2453       p_pic = g_queue_pop_tail (&reorder_pool->reorder_frame_list);
2454       set_p_frame (p_pic, encoder);
2455       g_queue_foreach (&reorder_pool->reorder_frame_list,
2456           (GFunc) set_b_frame, encoder);
2457       ++reorder_pool->cur_frame_num;
2458       set_key_frame (picture, encoder, is_idr);
2459       g_queue_push_tail (&reorder_pool->reorder_frame_list, picture);
2460       picture = p_pic;
2461       reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES;
2462     } else {                    /* no b frames in queue */
2463       set_key_frame (picture, encoder, is_idr);
2464       g_assert (g_queue_is_empty (&reorder_pool->reorder_frame_list));
2465       if (encoder->num_bframes)
2466         reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES;
2467     }
2468     goto end;
2469   }
2470
2471   /* new p/b frames coming */
2472   ++reorder_pool->frame_index;
2473   if (reorder_pool->reorder_state == GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES &&
2474       g_queue_get_length (&reorder_pool->reorder_frame_list) <
2475       encoder->num_bframes) {
2476     g_queue_push_tail (&reorder_pool->reorder_frame_list, picture);
2477     return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
2478   }
2479
2480   ++reorder_pool->cur_frame_num;
2481   set_p_frame (picture, encoder);
2482
2483   if (reorder_pool->reorder_state == GST_VAAPI_ENC_H264_REORD_WAIT_FRAMES) {
2484     g_queue_foreach (&reorder_pool->reorder_frame_list, (GFunc) set_b_frame,
2485         encoder);
2486     reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_DUMP_FRAMES;
2487     g_assert (!g_queue_is_empty (&reorder_pool->reorder_frame_list));
2488   }
2489
2490 end:
2491   g_assert (picture);
2492   frame = picture->frame;
2493   if (GST_CLOCK_TIME_IS_VALID (frame->pts))
2494     frame->pts += encoder->cts_offset;
2495   *output = picture;
2496
2497   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2498 }
2499
2500 static GstVaapiEncoderStatus
2501 set_context_info (GstVaapiEncoder * base_encoder)
2502 {
2503   GstVaapiEncoderH264 *const encoder =
2504       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2505   GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
2506   const guint DEFAULT_SURFACES_COUNT = 3;
2507
2508   /* Maximum sizes for common headers (in bits) */
2509   enum
2510   {
2511     MAX_SPS_HDR_SIZE = 16473,
2512     MAX_VUI_PARAMS_SIZE = 210,
2513     MAX_HRD_PARAMS_SIZE = 4103,
2514     MAX_PPS_HDR_SIZE = 101,
2515     MAX_SLICE_HDR_SIZE = 397 + 2572 + 6670 + 2402,
2516   };
2517
2518   if (!ensure_hw_profile (encoder))
2519     return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2520
2521   base_encoder->num_ref_frames =
2522       ((encoder->num_bframes ? 2 : 1) + DEFAULT_SURFACES_COUNT)
2523       * encoder->num_views;
2524
2525   /* Only YUV 4:2:0 formats are supported for now. This means that we
2526      have a limit of 3200 bits per macroblock. */
2527   /* XXX: check profile and compute RawMbBits */
2528   base_encoder->codedbuf_size = (GST_ROUND_UP_16 (vip->width) *
2529       GST_ROUND_UP_16 (vip->height) / 256) * 400;
2530
2531   /* Account for SPS header */
2532   /* XXX: exclude scaling lists, MVC/SVC extensions */
2533   base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
2534       MAX_VUI_PARAMS_SIZE + 2 * MAX_HRD_PARAMS_SIZE) / 8;
2535
2536   /* Account for PPS header */
2537   /* XXX: exclude slice groups, scaling lists, MVC/SVC extensions */
2538   base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
2539
2540   /* Account for slice header */
2541   base_encoder->codedbuf_size += encoder->num_slices * (4 +
2542       GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8);
2543
2544   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2545 }
2546
2547 static GstVaapiEncoderStatus
2548 gst_vaapi_encoder_h264_reconfigure (GstVaapiEncoder * base_encoder)
2549 {
2550   GstVaapiEncoderH264 *const encoder =
2551       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2552   GstVaapiEncoderStatus status;
2553   guint mb_width, mb_height;
2554
2555   mb_width = (GST_VAAPI_ENCODER_WIDTH (encoder) + 15) / 16;
2556   mb_height = (GST_VAAPI_ENCODER_HEIGHT (encoder) + 15) / 16;
2557   if (mb_width != encoder->mb_width || mb_height != encoder->mb_height) {
2558     GST_DEBUG ("resolution: %dx%d", GST_VAAPI_ENCODER_WIDTH (encoder),
2559         GST_VAAPI_ENCODER_HEIGHT (encoder));
2560     encoder->mb_width = mb_width;
2561     encoder->mb_height = mb_height;
2562     encoder->config_changed = TRUE;
2563   }
2564
2565   status = ensure_profile_and_level (encoder);
2566   if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
2567     return status;
2568
2569   reset_properties (encoder);
2570   return set_context_info (base_encoder);
2571 }
2572
2573 static gboolean
2574 gst_vaapi_encoder_h264_init (GstVaapiEncoder * base_encoder)
2575 {
2576   GstVaapiEncoderH264 *const encoder =
2577       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2578   guint32 i;
2579
2580   /* Multi-view coding information */
2581   encoder->is_mvc = FALSE;
2582   encoder->num_views = 1;
2583   encoder->view_idx = 0;
2584
2585   /* re-ordering  list initialize */
2586   for (i = 0; i < MAX_NUM_VIEWS; i++) {
2587     GstVaapiH264ViewReorderPool *const reorder_pool =
2588         &encoder->reorder_pools[i];
2589     g_queue_init (&reorder_pool->reorder_frame_list);
2590     reorder_pool->reorder_state = GST_VAAPI_ENC_H264_REORD_NONE;
2591     reorder_pool->frame_index = 0;
2592     reorder_pool->cur_frame_num = 0;
2593     reorder_pool->cur_present_index = 0;
2594   }
2595
2596   /* reference list info initialize */
2597   for (i = 0; i < MAX_NUM_VIEWS; i++) {
2598     GstVaapiH264ViewRefPool *const ref_pool = &encoder->ref_pools[i];
2599     g_queue_init (&ref_pool->ref_list);
2600     ref_pool->max_ref_frames = 0;
2601     ref_pool->max_reflist0_count = 1;
2602     ref_pool->max_reflist1_count = 1;
2603   }
2604
2605   return TRUE;
2606 }
2607
2608 static void
2609 gst_vaapi_encoder_h264_finalize (GstVaapiEncoder * base_encoder)
2610 {
2611   /*free private buffers */
2612   GstVaapiEncoderH264 *const encoder =
2613       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2614   GstVaapiEncPicture *pic;
2615   GstVaapiEncoderH264Ref *ref;
2616   guint32 i;
2617
2618   gst_buffer_replace (&encoder->sps_data, NULL);
2619   gst_buffer_replace (&encoder->subset_sps_data, NULL);
2620   gst_buffer_replace (&encoder->pps_data, NULL);
2621
2622   /* reference list info de-init */
2623   for (i = 0; i < MAX_NUM_VIEWS; i++) {
2624     GstVaapiH264ViewRefPool *const ref_pool = &encoder->ref_pools[i];
2625     while (!g_queue_is_empty (&ref_pool->ref_list)) {
2626       ref = (GstVaapiEncoderH264Ref *) g_queue_pop_head (&ref_pool->ref_list);
2627       reference_pic_free (encoder, ref);
2628     }
2629     g_queue_clear (&ref_pool->ref_list);
2630   }
2631
2632   /* re-ordering  list initialize */
2633   for (i = 0; i < MAX_NUM_VIEWS; i++) {
2634     GstVaapiH264ViewReorderPool *const reorder_pool =
2635         &encoder->reorder_pools[i];
2636     while (!g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2637       pic = (GstVaapiEncPicture *)
2638           g_queue_pop_head (&reorder_pool->reorder_frame_list);
2639       gst_vaapi_enc_picture_unref (pic);
2640     }
2641     g_queue_clear (&reorder_pool->reorder_frame_list);
2642   }
2643 }
2644
2645 static GstVaapiEncoderStatus
2646 gst_vaapi_encoder_h264_set_property (GstVaapiEncoder * base_encoder,
2647     gint prop_id, const GValue * value)
2648 {
2649   GstVaapiEncoderH264 *const encoder =
2650       GST_VAAPI_ENCODER_H264_CAST (base_encoder);
2651
2652   switch (prop_id) {
2653     case GST_VAAPI_ENCODER_H264_PROP_MAX_BFRAMES:
2654       encoder->num_bframes = g_value_get_uint (value);
2655       break;
2656     case GST_VAAPI_ENCODER_H264_PROP_INIT_QP:
2657       encoder->init_qp = g_value_get_uint (value);
2658       break;
2659     case GST_VAAPI_ENCODER_H264_PROP_MIN_QP:
2660       encoder->min_qp = g_value_get_uint (value);
2661       break;
2662     case GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES:
2663       encoder->num_slices = g_value_get_uint (value);
2664       break;
2665     case GST_VAAPI_ENCODER_H264_PROP_CABAC:
2666       encoder->use_cabac = g_value_get_boolean (value);
2667       break;
2668     case GST_VAAPI_ENCODER_H264_PROP_DCT8X8:
2669       encoder->use_dct8x8 = g_value_get_boolean (value);
2670       break;
2671     case GST_VAAPI_ENCODER_H264_PROP_CPB_LENGTH:
2672       encoder->cpb_length = g_value_get_uint (value);
2673       break;
2674     case GST_VAAPI_ENCODER_H264_PROP_NUM_VIEWS:
2675       encoder->num_views = g_value_get_uint (value);
2676       break;
2677     default:
2678       return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
2679   }
2680   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2681 }
2682
2683 GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (H264);
2684
2685 static inline const GstVaapiEncoderClass *
2686 gst_vaapi_encoder_h264_class (void)
2687 {
2688   static const GstVaapiEncoderClass GstVaapiEncoderH264Class = {
2689     GST_VAAPI_ENCODER_CLASS_INIT (H264, h264),
2690     .set_property = gst_vaapi_encoder_h264_set_property,
2691     .get_codec_data = gst_vaapi_encoder_h264_get_codec_data
2692   };
2693   return &GstVaapiEncoderH264Class;
2694 }
2695
2696 /**
2697  * gst_vaapi_encoder_h264_new:
2698  * @display: a #GstVaapiDisplay
2699  *
2700  * Creates a new #GstVaapiEncoder for H.264 encoding. Note that the
2701  * only supported output stream format is "byte-stream" format.
2702  *
2703  * Return value: the newly allocated #GstVaapiEncoder object
2704  */
2705 GstVaapiEncoder *
2706 gst_vaapi_encoder_h264_new (GstVaapiDisplay * display)
2707 {
2708   return gst_vaapi_encoder_new (gst_vaapi_encoder_h264_class (), display);
2709 }
2710
2711 /**
2712  * gst_vaapi_encoder_h264_get_default_properties:
2713  *
2714  * Determines the set of common and H.264 specific encoder properties.
2715  * The caller owns an extra reference to the resulting array of
2716  * #GstVaapiEncoderPropInfo elements, so it shall be released with
2717  * g_ptr_array_unref() after usage.
2718  *
2719  * Return value: the set of encoder properties for #GstVaapiEncoderH264,
2720  *   or %NULL if an error occurred.
2721  */
2722 GPtrArray *
2723 gst_vaapi_encoder_h264_get_default_properties (void)
2724 {
2725   const GstVaapiEncoderClass *const klass = gst_vaapi_encoder_h264_class ();
2726   GPtrArray *props;
2727
2728   props = gst_vaapi_encoder_properties_get_default (klass);
2729   if (!props)
2730     return NULL;
2731
2732   /**
2733    * GstVaapiEncoderH264:max-bframes:
2734    *
2735    * The number of B-frames between I and P.
2736    */
2737   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2738       GST_VAAPI_ENCODER_H264_PROP_MAX_BFRAMES,
2739       g_param_spec_uint ("max-bframes",
2740           "Max B-Frames", "Number of B-frames between I and P", 0, 10, 0,
2741           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2742
2743   /**
2744    * GstVaapiEncoderH264:init-qp:
2745    *
2746    * The initial quantizer value.
2747    */
2748   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2749       GST_VAAPI_ENCODER_H264_PROP_INIT_QP,
2750       g_param_spec_uint ("init-qp",
2751           "Initial QP", "Initial quantizer value", 1, 51, 26,
2752           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2753
2754   /**
2755    * GstVaapiEncoderH264:min-qp:
2756    *
2757    * The minimum quantizer value.
2758    */
2759   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2760       GST_VAAPI_ENCODER_H264_PROP_MIN_QP,
2761       g_param_spec_uint ("min-qp",
2762           "Minimum QP", "Minimum quantizer value", 1, 51, 1,
2763           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2764
2765   /**
2766    * GstVaapiEncoderH264:num-slices:
2767    *
2768    * The number of slices per frame.
2769    */
2770   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2771       GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES,
2772       g_param_spec_uint ("num-slices",
2773           "Number of Slices",
2774           "Number of slices per frame",
2775           1, 200, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2776
2777   /**
2778    * GstVaapiEncoderH264:cabac:
2779    *
2780    * Enable CABAC entropy coding mode for improved compression ratio,
2781    * at the expense that the minimum target profile is Main. Default
2782    * is CAVLC entropy coding mode.
2783    */
2784   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2785       GST_VAAPI_ENCODER_H264_PROP_CABAC,
2786       g_param_spec_boolean ("cabac",
2787           "Enable CABAC",
2788           "Enable CABAC entropy coding mode",
2789           FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2790
2791   /**
2792    * GstVaapiEncoderH264:dct8x8:
2793    *
2794    * Enable adaptive use of 8x8 transforms in I-frames. This improves
2795    * the compression ratio by the minimum target profile is High.
2796    * Default is to use 4x4 DCT only.
2797    */
2798   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2799       GST_VAAPI_ENCODER_H264_PROP_DCT8X8,
2800       g_param_spec_boolean ("dct8x8",
2801           "Enable 8x8 DCT",
2802           "Enable adaptive use of 8x8 transforms in I-frames",
2803           FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2804
2805   /**
2806    * GstVaapiEncoderH264:cpb-length:
2807    *
2808    * The size of the CPB buffer in milliseconds.
2809    */
2810   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2811       GST_VAAPI_ENCODER_H264_PROP_CPB_LENGTH,
2812       g_param_spec_uint ("cpb-length",
2813           "CPB Length", "Length of the CPB buffer in milliseconds",
2814           1, 10000, DEFAULT_CPB_LENGTH,
2815           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2816
2817   /**
2818    * GstVaapiEncoderH264:num-views:
2819    *
2820    * The number of views for MVC encoding .
2821    */
2822   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2823       GST_VAAPI_ENCODER_H264_PROP_NUM_VIEWS,
2824       g_param_spec_uint ("num-views",
2825           "Number of Views",
2826           "Number of Views for MVC encoding",
2827           1, MAX_NUM_VIEWS, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2828
2829   return props;
2830 }
2831
2832 /**
2833  * gst_vaapi_encoder_h264_set_max_profile:
2834  * @encoder: a #GstVaapiEncoderH264
2835  * @profile: an H.264 #GstVaapiProfile
2836  *
2837  * Notifies the @encoder to use coding tools from the supplied
2838  * @profile at most.
2839  *
2840  * This means that if the minimal profile derived to
2841  * support the specified coding tools is greater than this @profile,
2842  * then an error is returned when the @encoder is configured.
2843  *
2844  * Return value: %TRUE on success
2845  */
2846 gboolean
2847 gst_vaapi_encoder_h264_set_max_profile (GstVaapiEncoderH264 * encoder,
2848     GstVaapiProfile profile)
2849 {
2850   guint8 profile_idc;
2851
2852   g_return_val_if_fail (encoder != NULL, FALSE);
2853   g_return_val_if_fail (profile != GST_VAAPI_PROFILE_UNKNOWN, FALSE);
2854
2855   if (gst_vaapi_profile_get_codec (profile) != GST_VAAPI_CODEC_H264)
2856     return FALSE;
2857
2858   profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
2859   if (!profile_idc)
2860     return FALSE;
2861
2862   encoder->max_profile_idc = profile_idc;
2863   return TRUE;
2864 }
2865
2866 /**
2867  * gst_vaapi_encoder_h264_get_profile_and_level:
2868  * @encoder: a #GstVaapiEncoderH264
2869  * @out_profile_ptr: return location for the #GstVaapiProfile
2870  * @out_level_ptr: return location for the #GstVaapiLevelH264
2871  *
2872  * Queries the H.264 @encoder for the active profile and level. That
2873  * information is only constructed and valid after the encoder is
2874  * configured, i.e. after the gst_vaapi_encoder_set_codec_state()
2875  * function is called.
2876  *
2877  * Return value: %TRUE on success
2878  */
2879 gboolean
2880 gst_vaapi_encoder_h264_get_profile_and_level (GstVaapiEncoderH264 * encoder,
2881     GstVaapiProfile * out_profile_ptr, GstVaapiLevelH264 * out_level_ptr)
2882 {
2883   g_return_val_if_fail (encoder != NULL, FALSE);
2884
2885   if (!encoder->profile || !encoder->level)
2886     return FALSE;
2887
2888   if (out_profile_ptr)
2889     *out_profile_ptr = encoder->profile;
2890   if (out_level_ptr)
2891     *out_level_ptr = encoder->level;
2892   return TRUE;
2893 }