vah264enc: Enable parameters change while running.
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / va / gstvah264enc.c
1 /* GStreamer
2  *  Copyright (C) 2021 Intel Corporation
3  *     Author: He Junyan <junyan.he@intel.com>
4  *     Author: Víctor Jáquez <vjaquez@igalia.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 /**
23  * SECTION:element-vah264enc
24  * @title: vah264enc
25  * @short_description: A VA-API based H264 video encoder
26  *
27  * vah264enc encodes raw video VA surfaces into H.264 bitstreams using
28  * the installed and chosen [VA-API](https://01.org/linuxmedia/vaapi)
29  * driver.
30  *
31  * The raw video frames in main memory can be imported into VA surfaces.
32  *
33  * ## Example launch line
34  * ```
35  * gst-launch-1.0 videotestsrc num-buffers=60 ! timeoverlay ! vah264enc ! h264parse ! mp4mux ! filesink location=test.mp4
36  * ```
37  *
38  * Since: 1.22
39  *
40  */
41
42  /* @TODO:
43   * 1. Look ahead, which can optimize the slice type and QP.
44   * 2. Field encoding.
45   * 3. The stereo encoding such as the frame-packing or MVC.
46   * 4. Weight prediction of B frame.
47   * 5. latency calculation.
48   */
49
50 #ifdef HAVE_CONFIG_H
51 #include "config.h"
52 #endif
53
54 #include "gstvah264enc.h"
55
56 #include <gst/codecparsers/gsth264bitwriter.h>
57 #include <gst/va/gstva.h>
58 #include <gst/va/gstvavideoformat.h>
59 #include <gst/va/vasurfaceimage.h>
60 #include <gst/video/video.h>
61 #include <va/va_drmcommon.h>
62
63 #include "gstvabaseenc.h"
64 #include "gstvacaps.h"
65 #include "gstvadisplay_priv.h"
66 #include "gstvaencoder.h"
67 #include "gstvaprofile.h"
68 #include "vacompat.h"
69
70 GST_DEBUG_CATEGORY_STATIC (gst_va_h264enc_debug);
71 #define GST_CAT_DEFAULT gst_va_h264enc_debug
72
73 #define GST_VA_H264_ENC(obj)            ((GstVaH264Enc *) obj)
74 #define GST_VA_H264_ENC_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_FROM_INSTANCE (obj), GstVaH264EncClass))
75 #define GST_VA_H264_ENC_CLASS(klass)    ((GstVaH264EncClass *) klass)
76
77 typedef struct _GstVaH264Enc GstVaH264Enc;
78 typedef struct _GstVaH264EncClass GstVaH264EncClass;
79 typedef struct _GstVaH264EncFrame GstVaH264EncFrame;
80 typedef struct _GstVaH264LevelLimits GstVaH264LevelLimits;
81
82 enum
83 {
84   PROP_KEY_INT_MAX = 1,
85   PROP_BFRAMES,
86   PROP_IFRAMES,
87   PROP_NUM_REF_FRAMES,
88   PROP_B_PYRAMID,
89   PROP_NUM_SLICES,
90   PROP_MIN_QP,
91   PROP_MAX_QP,
92   PROP_QP_I,
93   PROP_QP_P,
94   PROP_QP_B,
95   PROP_DCT8X8,
96   PROP_CABAC,
97   PROP_TRELLIS,
98   PROP_MBBRC,
99   PROP_BITRATE,
100   PROP_TARGET_PERCENTAGE,
101   PROP_TARGET_USAGE,
102   PROP_RATE_CONTROL,
103   PROP_CPB_SIZE,
104   PROP_AUD,
105   PROP_CC,
106   N_PROPERTIES
107 };
108
109 static GParamSpec *properties[N_PROPERTIES];
110
111 static GstElementClass *parent_class = NULL;
112
113 /* Scale factor for bitrate (HRD bit_rate_scale: min = 6) */
114 #define SX_BITRATE 6
115 /* Scale factor for CPB size (HRD cpb_size_scale: min = 4) */
116 #define SX_CPB_SIZE 4
117 /* Maximum sizes for common headers (in bits) */
118 #define MAX_SPS_HDR_SIZE  16473
119 #define MAX_VUI_PARAMS_SIZE  210
120 #define MAX_HRD_PARAMS_SIZE  4103
121 #define MAX_PPS_HDR_SIZE  101
122 #define MAX_SLICE_HDR_SIZE  397 + 2572 + 6670 + 2402
123
124 #define MAX_GOP_SIZE  1024
125
126 /* *INDENT-OFF* */
127 struct _GstVaH264EncClass
128 {
129   GstVaBaseEncClass parent_class;
130
131   GType rate_control_type;
132   char rate_control_type_name[64];
133   GEnumValue rate_control[16];
134 };
135 /* *INDENT-ON* */
136
137 struct _GstVaH264Enc
138 {
139   /*< private > */
140   GstVaBaseEnc parent;
141
142   /* properties */
143   struct
144   {
145     /* kbps */
146     guint bitrate;
147     /* VA_RC_XXX */
148     guint32 rc_ctrl;
149     guint key_int_max;
150     guint32 num_ref_frames;
151     gboolean b_pyramid;
152     guint32 num_bframes;
153     guint32 num_iframes;
154     guint32 min_qp;
155     guint32 max_qp;
156     guint32 qp_i;
157     guint32 qp_p;
158     guint32 qp_b;
159     gboolean use_cabac;
160     gboolean use_dct8x8;
161     gboolean use_trellis;
162     gboolean aud;
163     gboolean cc;
164     guint32 mbbrc;
165     guint32 num_slices;
166     guint32 cpb_size;
167     guint32 target_percentage;
168     guint32 target_usage;
169   } prop;
170
171   /* H264 fields */
172   gint mb_width;
173   gint mb_height;
174   guint8 level_idc;
175   const gchar *level_str;
176   /* Minimum Compression Ratio (A.3.1) */
177   guint min_cr;
178   gboolean use_cabac;
179   gboolean use_dct8x8;
180   gboolean use_trellis;
181   gboolean aud;
182   gboolean cc;
183   guint32 num_slices;
184   guint32 packed_headers;
185
186   struct
187   {
188     /* frames between two IDR [idr, ...., idr) */
189     guint32 idr_period;
190     /* How may IDRs we have encoded */
191     guint32 total_idr_count;
192     /* frames between I/P and P frames [I, B, B, .., B, P) */
193     guint32 ip_period;
194     /* frames between I frames [I, B, B, .., B, P, ..., I), open GOP */
195     guint32 i_period;
196     /* B frames between I/P and P. */
197     guint32 num_bframes;
198     /* Use B pyramid structure in the GOP. */
199     gboolean b_pyramid;
200     /* Level 0 is the simple B not acting as ref. */
201     guint32 highest_pyramid_level;
202     /* If open GOP, I frames within a GOP. */
203     guint32 num_iframes;
204     /* A map of all frames types within a GOP. */
205     struct
206     {
207       guint8 slice_type;
208       gboolean is_ref;
209       guint8 pyramid_level;
210       /* Only for b pyramid */
211       gint left_ref_poc_diff;
212       gint right_ref_poc_diff;
213     } frame_types[MAX_GOP_SIZE];
214     /* current index in the frames types map. */
215     guint cur_frame_index;
216     /* Number of ref frames within current GOP. H264's frame num. */
217     gint cur_frame_num;
218     /* Max frame num within a GOP. */
219     guint32 max_frame_num;
220     guint32 log2_max_frame_num;
221     /* Max poc within a GOP. */
222     guint32 max_pic_order_cnt;
223     guint32 log2_max_pic_order_cnt;
224
225     /* Total ref frames of list0 and list1. */
226     guint32 num_ref_frames;
227     guint32 ref_num_list0;
228     guint32 ref_num_list1;
229
230     guint num_reorder_frames;
231   } gop;
232
233   struct
234   {
235     guint target_usage;
236     guint32 rc_ctrl_mode;
237
238     guint32 min_qp;
239     guint32 max_qp;
240     guint32 qp_i;
241     guint32 qp_p;
242     guint32 qp_b;
243     /* macroblock bitrate control */
244     guint32 mbbrc;
245     guint target_bitrate;
246     guint target_percentage;
247     guint max_bitrate;
248     /* bitrate (bits) */
249     guint max_bitrate_bits;
250     guint target_bitrate_bits;
251     /* length of CPB buffer */
252     guint cpb_size;
253     /* length of CPB buffer (bits) */
254     guint cpb_length_bits;
255   } rc;
256
257   GstH264SPS sequence_hdr;
258 };
259
260 struct _GstVaH264EncFrame
261 {
262   GstVaEncodePicture *picture;
263   GstH264SliceType type;
264   gboolean is_ref;
265   guint pyramid_level;
266   /* Only for b pyramid */
267   gint left_ref_poc_diff;
268   gint right_ref_poc_diff;
269
270   gint poc;
271   gint frame_num;
272   /* The pic_num will be marked as unused_for_reference, which is
273    * replaced by this frame. -1 if we do not need to care about it
274    * explicitly. */
275   gint unused_for_reference_pic_num;
276
277   /* The total frame count we handled. */
278   guint total_frame_count;
279
280   gboolean last_frame;
281 };
282
283 /**
284  * GstVaH264LevelLimits:
285  * @name: the level name
286  * @level_idc: the H.264 level_idc value
287  * @MaxMBPS: the maximum macroblock processing rate (MB/sec)
288  * @MaxFS: the maximum frame size (MBs)
289  * @MaxDpbMbs: the maxium decoded picture buffer size (MBs)
290  * @MaxBR: the maximum video bit rate (kbps)
291  * @MaxCPB: the maximum CPB size (kbits)
292  * @MinCR: the minimum Compression Ratio
293  *
294  * The data structure that describes the limits of an H.264 level.
295  */
296 struct _GstVaH264LevelLimits
297 {
298   const gchar *name;
299   guint8 level_idc;
300   guint32 MaxMBPS;
301   guint32 MaxFS;
302   guint32 MaxDpbMbs;
303   guint32 MaxBR;
304   guint32 MaxCPB;
305   guint32 MinCR;
306 };
307
308 /* Table A-1 - Level limits */
309 /* *INDENT-OFF* */
310 static const GstVaH264LevelLimits _va_h264_level_limits[] = {
311   /* level   idc   MaxMBPS   MaxFS   MaxDpbMbs  MaxBR   MaxCPB  MinCr */
312   {  "1",    10,   1485,     99,     396,       64,     175,    2 },
313   {  "1b",   11,   1485,     99,     396,       128,    350,    2 },
314   {  "1.1",  11,   3000,     396,    900,       192,    500,    2 },
315   {  "1.2",  12,   6000,     396,    2376,      384,    1000,   2 },
316   {  "1.3",  13,   11880,    396,    2376,      768,    2000,   2 },
317   {  "2",    20,   11880,    396,    2376,      2000,   2000,   2 },
318   {  "2.1",  21,   19800,    792,    4752,      4000,   4000,   2 },
319   {  "2.2",  22,   20250,    1620,   8100,      4000,   4000,   2 },
320   {  "3",    30,   40500,    1620,   8100,      10000,  10000,  2 },
321   {  "3.1",  31,   108000,   3600,   18000,     14000,  14000,  4 },
322   {  "3.2",  32,   216000,   5120,   20480,     20000,  20000,  4 },
323   {  "4",    40,   245760,   8192,   32768,     20000,  25000,  4 },
324   {  "4.1",  41,   245760,   8192,   32768,     50000,  62500,  2 },
325   {  "4.2",  42,   522240,   8704,   34816,     50000,  62500,  2 },
326   {  "5",    50,   589824,   22080,  110400,    135000, 135000, 2 },
327   {  "5.1",  51,   983040,   36864,  184320,    240000, 240000, 2 },
328   {  "5.2",  52,   2073600,  36864,  184320,    240000, 240000, 2 },
329   {  "6",    60,   4177920,  139264, 696320,    240000, 240000, 2 },
330   {  "6.1",  61,   8355840,  139264, 696320,    480000, 480000, 2 },
331   {  "6.2",  62,  16711680,  139264, 696320,    800000, 800000, 2 },
332 };
333 /* *INDENT-ON* */
334
335 #ifndef GST_DISABLE_GST_DEBUG
336 static const gchar *
337 _slice_type_name (GstH264SliceType type)
338 {
339   switch (type) {
340     case GST_H264_P_SLICE:
341       return "P";
342     case GST_H264_B_SLICE:
343       return "B";
344     case GST_H264_I_SLICE:
345       return "I";
346     default:
347       g_assert_not_reached ();
348   }
349
350   return NULL;
351 }
352
353 static const gchar *
354 _rate_control_get_name (guint32 rc_mode)
355 {
356   GParamSpecEnum *spec;
357   guint i;
358
359   if (!(properties[PROP_RATE_CONTROL]
360           && G_IS_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])))
361     return NULL;
362
363   spec = G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL]);
364   for (i = 0; i < spec->enum_class->n_values; i++) {
365     if (spec->enum_class->values[i].value == rc_mode)
366       return spec->enum_class->values[i].value_nick;
367   }
368
369   return NULL;
370 }
371 #endif
372
373 static GstVaH264EncFrame *
374 gst_va_enc_frame_new (void)
375 {
376   GstVaH264EncFrame *frame;
377
378   frame = g_slice_new (GstVaH264EncFrame);
379   frame->frame_num = 0;
380   frame->unused_for_reference_pic_num = -1;
381   frame->picture = NULL;
382   frame->total_frame_count = 0;
383   frame->last_frame = FALSE;
384
385   return frame;
386 }
387
388 static void
389 gst_va_enc_frame_free (gpointer pframe)
390 {
391   GstVaH264EncFrame *frame = pframe;
392   g_clear_pointer (&frame->picture, gst_va_encode_picture_free);
393   g_slice_free (GstVaH264EncFrame, frame);
394 }
395
396 static inline GstVaH264EncFrame *
397 _enc_frame (GstVideoCodecFrame * frame)
398 {
399   GstVaH264EncFrame *enc_frame = gst_video_codec_frame_get_user_data (frame);
400   g_assert (enc_frame);
401   return enc_frame;
402 }
403
404 /* Normalizes bitrate (and CPB size) for HRD conformance */
405 static void
406 _calculate_bitrate_hrd (GstVaH264Enc * self)
407 {
408   guint bitrate_bits, cpb_bits_size;
409
410   /* Round down bitrate. This is a hard limit mandated by the user */
411   g_assert (SX_BITRATE >= 6);
412   bitrate_bits = (self->rc.max_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
413   GST_DEBUG_OBJECT (self, "Max bitrate: %u bits/sec", bitrate_bits);
414   self->rc.max_bitrate_bits = bitrate_bits;
415
416   bitrate_bits = (self->rc.target_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
417   GST_DEBUG_OBJECT (self, "Target bitrate: %u bits/sec", bitrate_bits);
418   self->rc.target_bitrate_bits = bitrate_bits;
419
420   if (self->rc.cpb_size > 0 && self->rc.cpb_size < (self->rc.max_bitrate / 2)) {
421     GST_INFO_OBJECT (self, "Too small cpb_size: %d", self->rc.cpb_size);
422     self->rc.cpb_size = 0;
423   }
424
425   if (self->rc.cpb_size == 0) {
426     /* We cache 2 second coded data by default. */
427     self->rc.cpb_size = self->rc.max_bitrate * 2;
428     GST_INFO_OBJECT (self, "Adjust cpb_size to: %d", self->rc.cpb_size);
429   }
430
431   /* Round up CPB size. This is an HRD compliance detail */
432   g_assert (SX_CPB_SIZE >= 4);
433   cpb_bits_size = (self->rc.cpb_size * 1000) & ~((1U << SX_CPB_SIZE) - 1);
434
435   GST_DEBUG_OBJECT (self, "HRD CPB size: %u bits", cpb_bits_size);
436   self->rc.cpb_length_bits = cpb_bits_size;
437 }
438
439 #define update_property(type, obj, old_val, new_val, prop_id)           \
440   gst_va_base_enc_update_property_##type (obj, old_val, new_val, properties[prop_id])
441 #define update_property_uint(obj, old_val, new_val, prop_id)    \
442   update_property (uint, obj, old_val, new_val, prop_id)
443 #define update_property_bool(obj, old_val, new_val, prop_id)    \
444   update_property (bool, obj, old_val, new_val, prop_id)
445
446 /* Estimates a good enough bitrate if none was supplied */
447 static gboolean
448 _ensure_rate_control (GstVaH264Enc * self)
449 {
450   /* User can specify the properties of: "bitrate", "target-percentage",
451    * "max-qp", "min-qp", "qpi", "qpp", "qpb", "mbbrc", "cpb-size",
452    * "rate-control" and "target-usage" to control the RC behavior.
453    *
454    * "target-usage" is different from the others, it controls the encoding
455    * speed and quality, while the others control encoding bit rate and
456    * quality. The lower value has better quality(maybe bigger MV search
457    * range) but slower speed, the higher value has faster speed but lower
458    * quality.
459    *
460    * The possible composition to control the bit rate and quality:
461    *
462    * 1. CQP mode: "rate-control=cqp", then "qpi", "qpp" and "qpb"
463    *    specify the QP of I/P/B frames respectively(within the
464    *    "max-qp" and "min-qp" range). The QP will not change during
465    *    the whole stream. Other properties are ignored.
466    *
467    * 2. CBR mode: "rate-control=CBR", then the "bitrate" specify the
468    *    target bit rate and the "cpb-size" specifies the max coded
469    *    picture buffer size to avoid overflow. If the "bitrate" is not
470    *    set, it is calculated by the picture resolution and frame
471    *    rate. If "cpb-size" is not set, it is set to the size of
472    *    caching 2 second coded data. Encoder will try its best to make
473    *    the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
474    *    enable bit rate control in macro block level. Other paramters
475    *    are ignored.
476    *
477    * 3. VBR mode: "rate-control=VBR", then the "bitrate" specify the
478    *    target bit rate, "target-percentage" is used to calculate the
479    *    max bit rate of VBR mode by ("bitrate" * 100) /
480    *    "target-percentage". It is also used by driver to calculate
481    *    the min bit rate. The "cpb-size" specifies the max coded
482    *    picture buffer size to avoid overflow. If the "bitrate" is not
483    *    set, the target bit rate will be calculated by the picture
484    *    resolution and frame rate. Encoder will try its best to make
485    *    the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
486    *    enable bit rate control in macro block level. Other paramters
487    *    are ignored.
488    *
489    * 4. VCM mode: "rate-control=VCM", then the "bitrate" specify the
490    *    target bit rate, and encoder will try its best to make the QP
491    *    with in the ["max-qp", "min-qp"] range. Other paramters are
492    *    ignored.
493    */
494
495   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
496   guint bitrate;
497   guint32 rc_ctrl, rc_mode, quality_level;
498
499   quality_level = gst_va_encoder_get_quality_level (base->encoder,
500       base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
501   if (self->rc.target_usage > quality_level) {
502     GST_INFO_OBJECT (self, "User setting target-usage: %d is not supported, "
503         "fallback to %d", self->rc.target_usage, quality_level);
504     self->rc.target_usage = quality_level;
505
506     update_property_uint (base, &self->prop.target_usage, self->rc.target_usage,
507         PROP_TARGET_USAGE);
508   }
509
510   GST_OBJECT_LOCK (self);
511   rc_ctrl = self->prop.rc_ctrl;
512   GST_OBJECT_UNLOCK (self);
513
514   if (rc_ctrl != VA_RC_NONE) {
515     rc_mode = gst_va_encoder_get_rate_control_mode (base->encoder,
516         base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
517     if (!(rc_mode & rc_ctrl)) {
518       guint32 defval =
519           G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])->default_value;
520       GST_INFO_OBJECT (self, "The rate control mode %s is not supported, "
521           "fallback to %s mode", _rate_control_get_name (rc_ctrl),
522           _rate_control_get_name (defval));
523       self->rc.rc_ctrl_mode = defval;
524
525       update_property_uint (base, &self->prop.rc_ctrl, self->rc.rc_ctrl_mode,
526           PROP_RATE_CONTROL);
527     }
528   } else {
529     self->rc.rc_ctrl_mode = VA_RC_NONE;
530   }
531
532   if (self->rc.min_qp > self->rc.max_qp) {
533     GST_INFO_OBJECT (self, "The min_qp %d is bigger than the max_qp %d, "
534         "set it to the max_qp", self->rc.min_qp, self->rc.max_qp);
535     self->rc.min_qp = self->rc.max_qp;
536
537     update_property_uint (base, &self->prop.min_qp, self->rc.min_qp,
538         PROP_MIN_QP);
539   }
540
541   /* Make all the qp in the valid range */
542   if (self->rc.qp_i < self->rc.min_qp) {
543     if (self->rc.qp_i != 26)
544       GST_INFO_OBJECT (self, "The qp_i %d is smaller than the min_qp %d, "
545           "set it to the min_qp", self->rc.qp_i, self->rc.min_qp);
546     self->rc.qp_i = self->rc.min_qp;
547   }
548   if (self->rc.qp_i > self->rc.max_qp) {
549     if (self->rc.qp_i != 26)
550       GST_INFO_OBJECT (self, "The qp_i %d is bigger than the max_qp %d, "
551           "set it to the max_qp", self->rc.qp_i, self->rc.max_qp);
552     self->rc.qp_i = self->rc.max_qp;
553   }
554
555   if (self->rc.qp_p < self->rc.min_qp) {
556     if (self->rc.qp_p != 26)
557       GST_INFO_OBJECT (self, "The qp_p %d is smaller than the min_qp %d, "
558           "set it to the min_qp", self->rc.qp_p, self->rc.min_qp);
559     self->rc.qp_p = self->rc.min_qp;
560   }
561   if (self->rc.qp_p > self->rc.max_qp) {
562     if (self->rc.qp_p != 26)
563       GST_INFO_OBJECT (self, "The qp_p %d is bigger than the max_qp %d, "
564           "set it to the max_qp", self->rc.qp_p, self->rc.max_qp);
565     self->rc.qp_p = self->rc.max_qp;
566   }
567
568   if (self->rc.qp_b < self->rc.min_qp) {
569     if (self->rc.qp_b != 26)
570       GST_INFO_OBJECT (self, "The qp_b %d is smaller than the min_qp %d, "
571           "set it to the min_qp", self->rc.qp_b, self->rc.min_qp);
572     self->rc.qp_b = self->rc.min_qp;
573   }
574   if (self->rc.qp_b > self->rc.max_qp) {
575     if (self->rc.qp_b != 26)
576       GST_INFO_OBJECT (self, "The qp_b %d is bigger than the max_qp %d, "
577           "set it to the max_qp", self->rc.qp_b, self->rc.max_qp);
578     self->rc.qp_b = self->rc.max_qp;
579   }
580
581   GST_OBJECT_LOCK (self);
582   bitrate = self->prop.bitrate;
583   GST_OBJECT_UNLOCK (self);
584
585   /* Calculate a bitrate is not set. */
586   if ((self->rc.rc_ctrl_mode == VA_RC_CBR || self->rc.rc_ctrl_mode == VA_RC_VBR
587           || self->rc.rc_ctrl_mode == VA_RC_VCM) && bitrate == 0) {
588     /* Default compression: 48 bits per macroblock in "high-compression" mode */
589     guint bits_per_mb = 48;
590     guint64 factor;
591
592     /* According to the literature and testing, CABAC entropy coding
593      * mode could provide for +10% to +18% improvement in general,
594      * thus estimating +15% here ; and using adaptive 8x8 transforms
595      * in I-frames could bring up to +10% improvement. */
596     if (!self->use_cabac)
597       bits_per_mb += (bits_per_mb * 15) / 100;
598     if (!self->use_dct8x8)
599       bits_per_mb += (bits_per_mb * 10) / 100;
600
601     factor = (guint64) self->mb_width * self->mb_height * bits_per_mb;
602     bitrate = gst_util_uint64_scale (factor,
603         GST_VIDEO_INFO_FPS_N (&base->input_state->info),
604         GST_VIDEO_INFO_FPS_D (&base->input_state->info)) / 1000;
605     GST_INFO_OBJECT (self, "target bitrate computed to %u kbps", bitrate);
606   }
607
608   /* Adjust the setting based on RC mode. */
609   switch (self->rc.rc_ctrl_mode) {
610     case VA_RC_NONE:
611     case VA_RC_CQP:
612       self->rc.max_bitrate = 0;
613       self->rc.target_bitrate = 0;
614       self->rc.target_percentage = 0;
615       self->rc.cpb_size = 0;
616       break;
617     case VA_RC_CBR:
618       self->rc.max_bitrate = bitrate;
619       self->rc.target_bitrate = bitrate;
620       self->rc.target_percentage = 100;
621       self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
622       break;
623     case VA_RC_VBR:
624       g_assert (self->rc.target_percentage >= 10);
625       self->rc.max_bitrate = (guint) gst_util_uint64_scale_int (bitrate,
626           100, self->rc.target_percentage);
627       self->rc.target_bitrate = bitrate;
628       self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
629       break;
630     case VA_RC_VCM:
631       self->rc.max_bitrate = bitrate;
632       self->rc.target_bitrate = bitrate;
633       self->rc.target_percentage = 0;
634       self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
635       self->rc.cpb_size = 0;
636
637       if (self->gop.num_bframes > 0) {
638         GST_INFO_OBJECT (self, "VCM mode just support I/P mode, no B frame");
639         self->gop.num_bframes = 0;
640         self->gop.b_pyramid = FALSE;
641       }
642       break;
643     default:
644       GST_WARNING_OBJECT (self, "Unsupported rate control");
645       return FALSE;
646       break;
647   }
648
649   GST_DEBUG_OBJECT (self, "Max bitrate: %u bits/sec, "
650       "Target bitrate: %u bits/sec", self->rc.max_bitrate,
651       self->rc.target_bitrate);
652
653   if (self->rc.rc_ctrl_mode != VA_RC_NONE && self->rc.rc_ctrl_mode != VA_RC_CQP)
654     _calculate_bitrate_hrd (self);
655
656   /* update & notifications */
657   update_property_uint (base, &self->prop.bitrate, bitrate, PROP_BITRATE);
658   update_property_uint (base, &self->prop.cpb_size, self->rc.cpb_size,
659       PROP_CPB_SIZE);
660   update_property_uint (base, &self->prop.target_percentage,
661       self->rc.target_percentage, PROP_TARGET_PERCENTAGE);
662   update_property_uint (base, &self->prop.qp_i, self->rc.qp_i, PROP_QP_I);
663   update_property_uint (base, &self->prop.qp_p, self->rc.qp_p, PROP_QP_P);
664   update_property_uint (base, &self->prop.qp_b, self->rc.qp_b, PROP_QP_B);
665
666   return TRUE;
667 }
668
669 static guint
670 _get_h264_cpb_nal_factor (VAProfile profile)
671 {
672   guint f;
673
674   /* Table A-2 */
675   switch (profile) {
676     case VAProfileH264High:
677       f = 1500;
678       break;
679     case VAProfileH264ConstrainedBaseline:
680     case VAProfileH264Main:
681       f = 1200;
682       break;
683     case VAProfileH264MultiviewHigh:
684     case VAProfileH264StereoHigh:
685       f = 1500;                 /* H.10.2.1 (r) */
686       break;
687     default:
688       g_assert_not_reached ();
689       f = 1200;
690       break;
691   }
692   return f;
693 }
694
695 /* Derives the level from the currently set limits */
696 static gboolean
697 _calculate_level (GstVaH264Enc * self)
698 {
699   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
700   const guint cpb_factor = _get_h264_cpb_nal_factor (base->profile);
701   guint i, PicSizeMbs, MaxDpbMbs, MaxMBPS;
702
703   PicSizeMbs = self->mb_width * self->mb_height;
704   MaxDpbMbs = PicSizeMbs * (self->gop.num_ref_frames + 1);
705   MaxMBPS = gst_util_uint64_scale_int_ceil (PicSizeMbs,
706       GST_VIDEO_INFO_FPS_N (&base->input_state->info),
707       GST_VIDEO_INFO_FPS_D (&base->input_state->info));
708
709   for (i = 0; i < G_N_ELEMENTS (_va_h264_level_limits); i++) {
710     const GstVaH264LevelLimits *const limits = &_va_h264_level_limits[i];
711     if (PicSizeMbs <= limits->MaxFS && MaxDpbMbs <= limits->MaxDpbMbs
712         && MaxMBPS <= limits->MaxMBPS && (!self->rc.max_bitrate_bits
713             || self->rc.max_bitrate_bits <= (limits->MaxBR * 1000 * cpb_factor))
714         && (!self->rc.cpb_length_bits
715             || self->rc.cpb_length_bits <=
716             (limits->MaxCPB * 1000 * cpb_factor))) {
717
718       self->level_idc = _va_h264_level_limits[i].level_idc;
719       self->level_str = _va_h264_level_limits[i].name;
720       self->min_cr = _va_h264_level_limits[i].MinCR;
721
722       return TRUE;
723     }
724   }
725
726   GST_ERROR_OBJECT (self,
727       "failed to find a suitable level matching codec config");
728   return FALSE;
729 }
730
731 static void
732 _validate_parameters (GstVaH264Enc * self)
733 {
734   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
735   gint32 max_slices;
736
737   /* Ensure the num_slices provided by the user not exceed the limit
738    * of the number of slices permitted by the stream and by the
739    * hardware. */
740   g_assert (self->num_slices >= 1);
741   max_slices = gst_va_encoder_get_max_slice_num (base->encoder,
742       base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
743   if (self->num_slices > max_slices)
744     self->num_slices = max_slices;
745   /* The stream size limit. */
746   if (self->num_slices > ((self->mb_width * self->mb_height + 1) / 2))
747     self->num_slices = ((self->mb_width * self->mb_height + 1) / 2);
748
749   update_property_uint (base, &self->prop.num_slices,
750       self->num_slices, PROP_NUM_SLICES);
751
752   /* Ensure trellis. */
753   if (self->use_trellis &&
754       !gst_va_encoder_has_trellis (base->encoder, base->profile,
755           GST_VA_BASE_ENC_ENTRYPOINT (base))) {
756     GST_INFO_OBJECT (self, "The trellis is not supported");
757     self->use_trellis = FALSE;
758   }
759
760   update_property_bool (base, &self->prop.use_trellis, self->use_trellis,
761       PROP_TRELLIS);
762 }
763
764 /* Get log2_max_frame_num_minus4, log2_max_pic_order_cnt_lsb_minus4
765  * value, shall be in the range of 0 to 12, inclusive. */
766 static guint
767 _get_log2_max_num (guint num)
768 {
769   guint ret = 0;
770
771   while (num) {
772     ++ret;
773     num >>= 1;
774   }
775
776   /* shall be in the range of 0+4 to 12+4, inclusive. */
777   if (ret < 4) {
778     ret = 4;
779   } else if (ret > 16) {
780     ret = 16;
781   }
782   return ret;
783 }
784
785 static void
786 _print_gop_structure (GstVaH264Enc * self)
787 {
788 #ifndef GST_DISABLE_GST_DEBUG
789   GString *str;
790   gint i;
791
792   if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) < GST_LEVEL_INFO)
793     return;
794
795   str = g_string_new (NULL);
796
797   g_string_append_printf (str, "[ ");
798
799   for (i = 0; i < self->gop.idr_period; i++) {
800     if (i == 0) {
801       g_string_append_printf (str, "IDR");
802       continue;
803     } else {
804       g_string_append_printf (str, ", ");
805     }
806
807     g_string_append_printf (str, "%s",
808         _slice_type_name (self->gop.frame_types[i].slice_type));
809
810     if (self->gop.b_pyramid
811         && self->gop.frame_types[i].slice_type == GST_H264_B_SLICE) {
812       g_string_append_printf (str, "<L%d (%d, %d)>",
813           self->gop.frame_types[i].pyramid_level,
814           self->gop.frame_types[i].left_ref_poc_diff,
815           self->gop.frame_types[i].right_ref_poc_diff);
816     }
817
818     if (self->gop.frame_types[i].is_ref) {
819       g_string_append_printf (str, "(ref)");
820     }
821
822   }
823
824   g_string_append_printf (str, " ]");
825
826   GST_INFO_OBJECT (self, "GOP size: %d, forward reference %d, backward"
827       " reference %d, GOP structure: %s", self->gop.idr_period,
828       self->gop.ref_num_list0, self->gop.ref_num_list1, str->str);
829
830   g_string_free (str, TRUE);
831 #endif
832 }
833
834 struct PyramidInfo
835 {
836   guint level;
837   gint left_ref_poc_diff;
838   gint right_ref_poc_diff;
839 };
840
841 static void
842 _set_pyramid_info (struct PyramidInfo *info, guint len,
843     guint current_level, guint highest_level)
844 {
845   guint index;
846
847   g_assert (len >= 1);
848
849   if (current_level == highest_level || len == 1) {
850     for (index = 0; index < len; index++) {
851       info[index].level = current_level;
852       info[index].left_ref_poc_diff = (index + 1) * -2;
853       info[index].right_ref_poc_diff = (len - index) * 2;
854     }
855
856     return;
857   }
858
859   index = len / 2;
860   info[index].level = current_level;
861   info[index].left_ref_poc_diff = (index + 1) * -2;
862   info[index].right_ref_poc_diff = (len - index) * 2;
863
864   current_level++;
865
866   if (index > 0)
867     _set_pyramid_info (info, index, current_level, highest_level);
868
869   if (index + 1 < len)
870     _set_pyramid_info (&info[index + 1], len - (index + 1),
871         current_level, highest_level);
872 }
873
874 static void
875 _create_gop_frame_types (GstVaH264Enc * self)
876 {
877   guint i;
878   guint i_frames = self->gop.num_iframes;
879   struct PyramidInfo pyramid_info[31] = { 0, };
880
881   if (self->gop.highest_pyramid_level > 0) {
882     g_assert (self->gop.num_bframes > 0);
883     _set_pyramid_info (pyramid_info, self->gop.num_bframes,
884         0, self->gop.highest_pyramid_level);
885   }
886
887   g_assert (self->gop.idr_period <= MAX_GOP_SIZE);
888   for (i = 0; i < self->gop.idr_period; i++) {
889     if (i == 0) {
890       self->gop.frame_types[i].slice_type = GST_H264_I_SLICE;
891       self->gop.frame_types[i].is_ref = TRUE;
892       continue;
893     }
894
895     /* Intra only stream. */
896     if (self->gop.ip_period == 0) {
897       self->gop.frame_types[i].slice_type = GST_H264_I_SLICE;
898       self->gop.frame_types[i].is_ref = FALSE;
899       continue;
900     }
901
902     if (i % self->gop.ip_period) {
903       guint pyramid_index =
904           i % self->gop.ip_period - 1 /* The first P or IDR */ ;
905
906       self->gop.frame_types[i].slice_type = GST_H264_B_SLICE;
907       self->gop.frame_types[i].pyramid_level =
908           pyramid_info[pyramid_index].level;
909       self->gop.frame_types[i].is_ref =
910           (self->gop.frame_types[i].pyramid_level <
911           self->gop.highest_pyramid_level);
912       self->gop.frame_types[i].left_ref_poc_diff =
913           pyramid_info[pyramid_index].left_ref_poc_diff;
914       self->gop.frame_types[i].right_ref_poc_diff =
915           pyramid_info[pyramid_index].right_ref_poc_diff;
916       continue;
917     }
918
919     if (self->gop.i_period && i % self->gop.i_period == 0 && i_frames > 0) {
920       /* Replace P with I. */
921       self->gop.frame_types[i].slice_type = GST_H264_I_SLICE;
922       self->gop.frame_types[i].is_ref = TRUE;
923       i_frames--;
924       continue;
925     }
926
927     self->gop.frame_types[i].slice_type = GST_H264_P_SLICE;
928     self->gop.frame_types[i].is_ref = TRUE;
929   }
930
931   /* Force the last one to be a P */
932   if (self->gop.idr_period > 1 && self->gop.ip_period > 0) {
933     self->gop.frame_types[self->gop.idr_period - 1].slice_type =
934         GST_H264_P_SLICE;
935     self->gop.frame_types[self->gop.idr_period - 1].is_ref = TRUE;
936   }
937 }
938
939 /* Consider the idr_period, num_bframes, L0/L1 reference number.
940  * TODO: Load some preset fixed GOP structure.
941  * TODO: Skip this if in lookahead mode. */
942 static void
943 _generate_gop_structure (GstVaH264Enc * self)
944 {
945   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
946   guint32 list0, list1, gop_ref_num;
947   gint32 p_frames;
948
949   /* If not set, generate a idr every second */
950   if (self->gop.idr_period == 0) {
951     self->gop.idr_period = (GST_VIDEO_INFO_FPS_N (&base->input_state->info)
952         + GST_VIDEO_INFO_FPS_D (&base->input_state->info) - 1) /
953         GST_VIDEO_INFO_FPS_D (&base->input_state->info);
954   }
955
956   /* Do not use a too huge GOP size. */
957   if (self->gop.idr_period > 1024) {
958     self->gop.idr_period = 1024;
959     GST_INFO_OBJECT (self, "Lowering the GOP size to %d", self->gop.idr_period);
960   }
961
962   update_property_uint (base, &self->prop.key_int_max, self->gop.idr_period,
963       PROP_KEY_INT_MAX);
964
965   /* Prefer have more than 1 refs for the GOP which is not very small. */
966   if (self->gop.idr_period > 8) {
967     if (self->gop.num_bframes > (self->gop.idr_period - 1) / 2) {
968       self->gop.num_bframes = (self->gop.idr_period - 1) / 2;
969       GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
970           self->gop.num_bframes);
971     }
972   } else {
973     /* beign and end should be ref */
974     if (self->gop.num_bframes > self->gop.idr_period - 1 - 1) {
975       if (self->gop.idr_period > 1) {
976         self->gop.num_bframes = self->gop.idr_period - 1 - 1;
977       } else {
978         self->gop.num_bframes = 0;
979       }
980       GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
981           self->gop.num_bframes);
982     }
983   }
984
985   if (!gst_va_encoder_get_max_num_reference (base->encoder, base->profile,
986           GST_VA_BASE_ENC_ENTRYPOINT (base), &list0, &list1)) {
987     GST_INFO_OBJECT (self, "Failed to get the max num reference");
988     list0 = 1;
989     list1 = 0;
990   }
991
992   if (list0 > self->gop.num_ref_frames)
993     list0 = self->gop.num_ref_frames;
994   if (list1 > self->gop.num_ref_frames)
995     list1 = self->gop.num_ref_frames;
996
997   if (list0 == 0) {
998     GST_INFO_OBJECT (self,
999         "No reference support, fallback to intra only stream");
1000
1001     /* It does not make sense that if only the list1 exists. */
1002     self->gop.num_ref_frames = 0;
1003
1004     self->gop.ip_period = 0;
1005     self->gop.num_bframes = 0;
1006     self->gop.b_pyramid = FALSE;
1007     self->gop.highest_pyramid_level = 0;
1008     self->gop.num_iframes = self->gop.idr_period - 1 /* The idr */ ;
1009     self->gop.ref_num_list0 = 0;
1010     self->gop.ref_num_list1 = 0;
1011     goto create_poc;
1012   }
1013
1014   if (self->gop.num_ref_frames <= 1) {
1015     GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
1016         " no B frame allowed, fallback to I/P mode", self->gop.num_ref_frames);
1017     self->gop.num_bframes = 0;
1018     list1 = 0;
1019   }
1020
1021   /* b_pyramid needs at least 1 ref for B, besides the I/P */
1022   if (self->gop.b_pyramid && self->gop.num_ref_frames <= 2) {
1023     GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
1024         " not enough for b_pyramid", self->gop.num_ref_frames);
1025     self->gop.b_pyramid = FALSE;
1026   }
1027
1028   if (list1 == 0 && self->gop.num_bframes > 0) {
1029     GST_INFO_OBJECT (self,
1030         "No hw reference support for list 1, fallback to I/P mode");
1031     self->gop.num_bframes = 0;
1032     self->gop.b_pyramid = FALSE;
1033   }
1034
1035   /* I/P mode, no list1 needed. */
1036   if (self->gop.num_bframes == 0)
1037     list1 = 0;
1038
1039   /* Not enough B frame, no need for b_pyramid. */
1040   if (self->gop.num_bframes <= 1)
1041     self->gop.b_pyramid = FALSE;
1042
1043   /* b pyramid has only one backward ref. */
1044   if (self->gop.b_pyramid)
1045     list1 = 1;
1046
1047   if (self->gop.num_ref_frames > list0 + list1) {
1048     self->gop.num_ref_frames = list0 + list1;
1049     GST_INFO_OBJECT (self, "HW limits, lowering the number of reference"
1050         " frames to %d", self->gop.num_ref_frames);
1051   }
1052
1053   /* How many possible refs within a GOP. */
1054   gop_ref_num = (self->gop.idr_period + self->gop.num_bframes) /
1055       (self->gop.num_bframes + 1);
1056   /* The end ref */
1057   if (self->gop.num_bframes > 0
1058       /* frame_num % (self->gop.num_bframes + 1) happens to be the end P */
1059       && (self->gop.idr_period % (self->gop.num_bframes + 1) != 1))
1060     gop_ref_num++;
1061
1062   /* Adjust reference num based on B frames and B pyramid. */
1063   if (self->gop.num_bframes == 0) {
1064     self->gop.b_pyramid = FALSE;
1065     self->gop.ref_num_list0 = self->gop.num_ref_frames;
1066     self->gop.ref_num_list1 = 0;
1067   } else if (self->gop.b_pyramid) {
1068     guint b_frames = self->gop.num_bframes;
1069     guint b_refs;
1070
1071     /* b pyramid has only one backward ref. */
1072     g_assert (list1 == 1);
1073     self->gop.ref_num_list1 = list1;
1074     self->gop.ref_num_list0 =
1075         self->gop.num_ref_frames - self->gop.ref_num_list1;
1076
1077     b_frames = b_frames / 2;
1078     b_refs = 0;
1079     while (b_frames) {
1080       /* At least 1 B ref for each level, plus begin and end 2 P/I */
1081       b_refs += 1;
1082       if (b_refs + 2 > self->gop.num_ref_frames)
1083         break;
1084
1085       self->gop.highest_pyramid_level++;
1086       b_frames = b_frames / 2;
1087     }
1088
1089     GST_INFO_OBJECT (self, "pyramid level is %d",
1090         self->gop.highest_pyramid_level);
1091   } else {
1092     /* We prefer list0. Backward refs have more latency. */
1093     self->gop.ref_num_list1 = 1;
1094     self->gop.ref_num_list0 =
1095         self->gop.num_ref_frames - self->gop.ref_num_list1;
1096     /* Balance the forward and backward refs, but not cause a big latency. */
1097     while ((self->gop.num_bframes * self->gop.ref_num_list1 <= 16)
1098         && (self->gop.ref_num_list1 <= gop_ref_num)
1099         && (self->gop.ref_num_list1 < list1)
1100         && (self->gop.ref_num_list0 / self->gop.ref_num_list1 > 4)) {
1101       self->gop.ref_num_list0--;
1102       self->gop.ref_num_list1++;
1103     }
1104
1105     if (self->gop.ref_num_list0 > list0)
1106       self->gop.ref_num_list0 = list0;
1107   }
1108
1109   /* It's OK, keep slots for GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME frame. */
1110   if (self->gop.ref_num_list0 > gop_ref_num)
1111     GST_DEBUG_OBJECT (self, "num_ref_frames %d is bigger than gop_ref_num %d",
1112         self->gop.ref_num_list0, gop_ref_num);
1113
1114   /* Include the ref picture itself. */
1115   self->gop.ip_period = 1 + self->gop.num_bframes;
1116
1117   p_frames = gop_ref_num - 1 /* IDR */ ;
1118   if (p_frames < 0)
1119     p_frames = 0;
1120   if (self->gop.num_iframes > p_frames) {
1121     self->gop.num_iframes = p_frames;
1122     GST_INFO_OBJECT (self, "Too many I frames insertion, lowering it to %d",
1123         self->gop.num_iframes);
1124   }
1125
1126   if (self->gop.num_iframes > 0) {
1127     guint total_i_frames = self->gop.num_iframes + 1 /* IDR */ ;
1128     self->gop.i_period =
1129         (gop_ref_num / total_i_frames) * (self->gop.num_bframes + 1);
1130   }
1131
1132 create_poc:
1133   /* init max_frame_num, max_poc */
1134   self->gop.log2_max_frame_num = _get_log2_max_num (self->gop.idr_period);
1135   self->gop.max_frame_num = (1 << self->gop.log2_max_frame_num);
1136   self->gop.log2_max_pic_order_cnt = self->gop.log2_max_frame_num + 1;
1137   self->gop.max_pic_order_cnt = (1 << self->gop.log2_max_pic_order_cnt);
1138   self->gop.num_reorder_frames = self->gop.b_pyramid ?
1139       self->gop.highest_pyramid_level * 2 + 1 /* the last P frame. */ :
1140       self->gop.ref_num_list1;
1141   /* Should not exceed the max ref num. */
1142   self->gop.num_reorder_frames =
1143       MIN (self->gop.num_reorder_frames, self->gop.num_ref_frames);
1144   self->gop.num_reorder_frames = MIN (self->gop.num_reorder_frames, 16);
1145
1146   _create_gop_frame_types (self);
1147   _print_gop_structure (self);
1148
1149   /* updates & notifications */
1150   update_property_uint (base, &self->prop.num_ref_frames,
1151       self->gop.num_ref_frames, PROP_NUM_REF_FRAMES);
1152   update_property_uint (base, &self->prop.num_iframes, self->gop.num_iframes,
1153       PROP_IFRAMES);
1154 }
1155
1156 static void
1157 _calculate_coded_size (GstVaH264Enc * self)
1158 {
1159   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1160   guint codedbuf_size = 0;
1161
1162   if (base->profile == VAProfileH264High
1163       || base->profile == VAProfileH264MultiviewHigh
1164       || base->profile == VAProfileH264StereoHigh) {
1165     /* The number of bits of macroblock_layer( ) data for any macroblock
1166        is not greater than 128 + RawMbBits */
1167     guint RawMbBits = 0;
1168     guint BitDepthY = 8;
1169     guint BitDepthC = 8;
1170     guint MbWidthC = 8;
1171     guint MbHeightC = 8;
1172
1173     switch (base->rt_format) {
1174       case VA_RT_FORMAT_YUV420:
1175         BitDepthY = 8;
1176         BitDepthC = 8;
1177         MbWidthC = 8;
1178         MbHeightC = 8;
1179         break;
1180       case VA_RT_FORMAT_YUV422:
1181         BitDepthY = 8;
1182         BitDepthC = 8;
1183         MbWidthC = 8;
1184         MbHeightC = 16;
1185         break;
1186       case VA_RT_FORMAT_YUV444:
1187         BitDepthY = 8;
1188         BitDepthC = 8;
1189         MbWidthC = 16;
1190         MbHeightC = 16;
1191         break;
1192       case VA_RT_FORMAT_YUV400:
1193         BitDepthY = 8;
1194         BitDepthC = 0;
1195         MbWidthC = 0;
1196         MbHeightC = 0;
1197         break;
1198       case VA_RT_FORMAT_YUV420_10:
1199         BitDepthY = 10;
1200         BitDepthC = 10;
1201         MbWidthC = 8;
1202         MbHeightC = 8;
1203       case VA_RT_FORMAT_YUV422_10:
1204         BitDepthY = 10;
1205         BitDepthC = 10;
1206         MbWidthC = 8;
1207         MbHeightC = 16;
1208       case VA_RT_FORMAT_YUV444_10:
1209         BitDepthY = 10;
1210         BitDepthC = 10;
1211         MbWidthC = 16;
1212         MbHeightC = 16;
1213         break;
1214       default:
1215         g_assert_not_reached ();
1216         break;
1217     }
1218
1219     /* The variable RawMbBits is derived as
1220      * RawMbBits = 256 * BitDepthY + 2 * MbWidthC * MbHeightC * BitDepthC */
1221     RawMbBits = 256 * BitDepthY + 2 * MbWidthC * MbHeightC * BitDepthC;
1222     codedbuf_size = (self->mb_width * self->mb_height) * (128 + RawMbBits) / 8;
1223   } else {
1224     /* The number of bits of macroblock_layer( ) data for any macroblock
1225      * is not greater than 3200 */
1226     codedbuf_size = (self->mb_width * self->mb_height) * (3200 / 8);
1227   }
1228
1229   /* Account for SPS header */
1230   /* XXX: exclude scaling lists, MVC/SVC extensions */
1231   codedbuf_size += 4 /* start code */  + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
1232       MAX_VUI_PARAMS_SIZE + 2 * MAX_HRD_PARAMS_SIZE) / 8;
1233
1234   /* Account for PPS header */
1235   /* XXX: exclude slice groups, scaling lists, MVC/SVC extensions */
1236   codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
1237
1238   /* Account for slice header */
1239   codedbuf_size +=
1240       self->num_slices * (4 + GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8);
1241
1242   /* Add 5% for safety */
1243   base->codedbuf_size = (guint) ((gfloat) codedbuf_size * 1.05);
1244
1245   GST_DEBUG_OBJECT (self, "Calculate codedbuf size: %u", base->codedbuf_size);
1246 }
1247
1248 static guint
1249 _get_rtformat (GstVaH264Enc * self, GstVideoFormat format)
1250 {
1251   guint chroma;
1252
1253   chroma = gst_va_chroma_from_video_format (format);
1254
1255   /* Check whether the rtformat is supported. */
1256   if (chroma != VA_RT_FORMAT_YUV420) {
1257     GST_ERROR_OBJECT (self, "Unsupported chroma for video format: %s",
1258         gst_video_format_to_string (format));
1259     return 0;
1260   }
1261
1262   return chroma;
1263 }
1264
1265 static gboolean
1266 _init_packed_headers (GstVaH264Enc * self)
1267 {
1268   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1269   guint32 packed_headers;
1270   guint32 desired_packed_headers = VA_ENC_PACKED_HEADER_SEQUENCE        /* SPS */
1271       | VA_ENC_PACKED_HEADER_PICTURE    /* PPS */
1272       | VA_ENC_PACKED_HEADER_SLICE      /* Slice headers */
1273       | VA_ENC_PACKED_HEADER_RAW_DATA;  /* SEI, AUD, etc. */
1274
1275   self->packed_headers = 0;
1276
1277   if (!gst_va_encoder_get_packed_headers (base->encoder, base->profile,
1278           GST_VA_BASE_ENC_ENTRYPOINT (base), &packed_headers))
1279     return FALSE;
1280
1281   if (desired_packed_headers & ~packed_headers) {
1282     GST_INFO_OBJECT (self, "Driver does not support some wanted packed headers "
1283         "(wanted %#x, found %#x)", desired_packed_headers, packed_headers);
1284   }
1285
1286   self->packed_headers = desired_packed_headers & packed_headers;
1287
1288   return TRUE;
1289 }
1290
1291
1292 static gboolean
1293 _decide_profile (GstVaH264Enc * self, VAProfile * _profile, guint * _rt_format)
1294 {
1295   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1296   gboolean ret = FALSE;
1297   GstVideoFormat in_format;
1298   VAProfile profile;
1299   guint rt_format;
1300   GstCaps *allowed_caps = NULL;
1301   guint num_structures, i;
1302   GstStructure *structure;
1303   const GValue *v_profile;
1304   GPtrArray *candidates = NULL;
1305   gchar *profile_name;
1306
1307   candidates = g_ptr_array_new_with_free_func (g_free);
1308
1309   /* First, check whether the downstream requires a specified profile. */
1310   allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (base));
1311   if (!allowed_caps)
1312     allowed_caps = gst_pad_query_caps (GST_VIDEO_ENCODER_SRC_PAD (base), NULL);
1313
1314   if (allowed_caps && !gst_caps_is_empty (allowed_caps)) {
1315     num_structures = gst_caps_get_size (allowed_caps);
1316     for (i = 0; i < num_structures; i++) {
1317       structure = gst_caps_get_structure (allowed_caps, i);
1318       v_profile = gst_structure_get_value (structure, "profile");
1319       if (!v_profile)
1320         continue;
1321
1322       if (G_VALUE_HOLDS_STRING (v_profile)) {
1323         profile_name = g_strdup (g_value_get_string (v_profile));
1324         g_ptr_array_add (candidates, profile_name);
1325       } else if (GST_VALUE_HOLDS_LIST (v_profile)) {
1326         guint j;
1327
1328         for (j = 0; j < gst_value_list_get_size (v_profile); j++) {
1329           const GValue *p = gst_value_list_get_value (v_profile, j);
1330           if (!p)
1331             continue;
1332
1333           profile_name = g_strdup (g_value_get_string (p));
1334           g_ptr_array_add (candidates, profile_name);
1335         }
1336       }
1337     }
1338   }
1339
1340   if (candidates->len == 0) {
1341     GST_ERROR_OBJECT (self, "No available profile in caps");
1342     ret = FALSE;
1343     goto out;
1344   }
1345
1346   in_format = GST_VIDEO_INFO_FORMAT (&base->input_state->info);
1347   rt_format = _get_rtformat (self, in_format);
1348   if (!rt_format) {
1349     GST_ERROR_OBJECT (self, "unsupported video format %s",
1350         gst_video_format_to_string (in_format));
1351     ret = FALSE;
1352     goto out;
1353   }
1354
1355   /* Find the suitable profile by features and check the HW
1356    * support. */
1357   ret = FALSE;
1358   for (i = 0; i < candidates->len; i++) {
1359     profile_name = g_ptr_array_index (candidates, i);
1360
1361     /* dct8x8 require at least high profile. */
1362     if (self->use_dct8x8) {
1363       if (!g_strstr_len (profile_name, -1, "high"))
1364         continue;
1365     }
1366
1367     /* cabac require at least main profile. */
1368     if (self->use_cabac) {
1369       if (!g_strstr_len (profile_name, -1, "main")
1370           && !g_strstr_len (profile_name, -1, "high"))
1371         continue;
1372     }
1373
1374     /* baseline only support I/P mode. */
1375     if (self->gop.num_bframes > 0) {
1376       if (g_strstr_len (profile_name, -1, "baseline"))
1377         continue;
1378     }
1379
1380     profile = gst_va_profile_from_name (H264, profile_name);
1381     if (profile == VAProfileNone)
1382       continue;
1383
1384     if (!gst_va_encoder_has_profile (base->encoder, profile))
1385       continue;
1386
1387     if ((rt_format & gst_va_encoder_get_rtformat (base->encoder,
1388                 profile, GST_VA_BASE_ENC_ENTRYPOINT (base))) == 0)
1389       continue;
1390
1391     *_profile = profile;
1392     *_rt_format = rt_format;
1393     ret = TRUE;
1394     goto out;
1395   }
1396
1397   /* Just use the first HW available profile and disable features if
1398    * needed. */
1399   profile_name = NULL;
1400   for (i = 0; i < candidates->len; i++) {
1401     profile_name = g_ptr_array_index (candidates, i);
1402     profile = gst_va_profile_from_name (H264, profile_name);
1403     if (profile == VAProfileNone)
1404       continue;
1405
1406     if (!gst_va_encoder_has_profile (base->encoder, profile))
1407       continue;
1408
1409     if ((rt_format & gst_va_encoder_get_rtformat (base->encoder,
1410                 profile, GST_VA_BASE_ENC_ENTRYPOINT (base))) == 0)
1411       continue;
1412
1413     *_profile = profile;
1414     *_rt_format = rt_format;
1415     ret = TRUE;
1416   }
1417
1418   if (ret == FALSE)
1419     goto out;
1420
1421   if (self->use_dct8x8 && !g_strstr_len (profile_name, -1, "high")) {
1422     GST_INFO_OBJECT (self, "Disable dct8x8, profile %s does not support it",
1423         gst_va_profile_name (profile));
1424     self->use_dct8x8 = FALSE;
1425     update_property_bool (base, &self->prop.use_dct8x8, self->use_dct8x8,
1426         PROP_DCT8X8);
1427   }
1428
1429   if (self->use_cabac && (!g_strstr_len (profile_name, -1, "main")
1430           && !g_strstr_len (profile_name, -1, "high"))) {
1431     GST_INFO_OBJECT (self, "Disable cabac, profile %s does not support it",
1432         gst_va_profile_name (profile));
1433     self->use_cabac = FALSE;
1434     update_property_bool (base, &self->prop.use_cabac, self->use_cabac,
1435         PROP_CABAC);
1436   }
1437
1438   if (self->gop.num_bframes > 0 && g_strstr_len (profile_name, -1, "baseline")) {
1439     GST_INFO_OBJECT (self, "No B frames, profile %s does not support it",
1440         gst_va_profile_name (profile));
1441     self->gop.num_bframes = 0;
1442     self->gop.b_pyramid = 0;
1443   }
1444
1445 out:
1446   g_clear_pointer (&candidates, g_ptr_array_unref);
1447   g_clear_pointer (&allowed_caps, gst_caps_unref);
1448
1449   if (ret) {
1450     GST_INFO_OBJECT (self, "Select the profile %s",
1451         gst_va_profile_name (profile));
1452   } else {
1453     GST_ERROR_OBJECT (self, "Failed to find an available profile");
1454   }
1455
1456   return ret;
1457 }
1458
1459 /* Clear all the info of last reconfig and set the fields based on
1460  * property. The reconfig may change these fields because of the
1461  * profile/level and HW limitation. */
1462 static void
1463 gst_va_h264_enc_reset_state (GstVaBaseEnc * base)
1464 {
1465   GstVaH264Enc *self = GST_VA_H264_ENC (base);
1466
1467   GST_VA_BASE_ENC_CLASS (parent_class)->reset_state (base);
1468
1469   GST_OBJECT_LOCK (self);
1470   self->use_cabac = self->prop.use_cabac;
1471   self->use_dct8x8 = self->prop.use_dct8x8;
1472   self->use_trellis = self->prop.use_trellis;
1473   self->aud = self->prop.aud;
1474   self->cc = self->prop.cc;
1475   self->num_slices = self->prop.num_slices;
1476
1477   self->gop.idr_period = self->prop.key_int_max;
1478   self->gop.num_bframes = self->prop.num_bframes;
1479   self->gop.b_pyramid = self->prop.b_pyramid;
1480   self->gop.num_iframes = self->prop.num_iframes;
1481   self->gop.num_ref_frames = self->prop.num_ref_frames;
1482
1483   self->rc.rc_ctrl_mode = self->prop.rc_ctrl;
1484   self->rc.min_qp = self->prop.min_qp;
1485   self->rc.max_qp = self->prop.max_qp;
1486   self->rc.qp_i = self->prop.qp_i;
1487   self->rc.qp_p = self->prop.qp_p;
1488   self->rc.qp_b = self->prop.qp_b;
1489   self->rc.mbbrc = self->prop.mbbrc;
1490
1491   self->rc.target_percentage = self->prop.target_percentage;
1492   self->rc.target_usage = self->prop.target_usage;
1493   self->rc.cpb_size = self->prop.cpb_size;
1494   GST_OBJECT_UNLOCK (self);
1495
1496   self->level_idc = 0;
1497   self->level_str = NULL;
1498   self->mb_width = 0;
1499   self->mb_height = 0;
1500
1501   self->gop.i_period = 0;
1502   self->gop.total_idr_count = 0;
1503   self->gop.ip_period = 0;
1504   self->gop.highest_pyramid_level = 0;
1505   memset (self->gop.frame_types, 0, sizeof (self->gop.frame_types));
1506   self->gop.cur_frame_index = 0;
1507   self->gop.cur_frame_num = 0;
1508   self->gop.max_frame_num = 0;
1509   self->gop.log2_max_frame_num = 0;
1510   self->gop.max_pic_order_cnt = 0;
1511   self->gop.log2_max_pic_order_cnt = 0;
1512   self->gop.ref_num_list0 = 0;
1513   self->gop.ref_num_list1 = 0;
1514   self->gop.num_reorder_frames = 0;
1515
1516   self->rc.max_bitrate = 0;
1517   self->rc.target_bitrate = 0;
1518   self->rc.max_bitrate_bits = 0;
1519   self->rc.target_bitrate_bits = 0;
1520   self->rc.cpb_length_bits = 0;
1521
1522   memset (&self->sequence_hdr, 0, sizeof (GstH264SPS));
1523 }
1524
1525 static gboolean
1526 gst_va_h264_enc_reconfig (GstVaBaseEnc * base)
1527 {
1528   GstVideoEncoder *venc = GST_VIDEO_ENCODER (base);
1529   GstVaH264Enc *self = GST_VA_H264_ENC (base);
1530   GstCaps *out_caps, *reconf_caps = NULL;
1531   GstVideoCodecState *output_state = NULL;
1532   GstVideoFormat format, reconf_format = GST_VIDEO_FORMAT_UNKNOWN;
1533   VAProfile profile = VAProfileNone;
1534   gboolean do_renegotiation = TRUE, do_reopen, need_negotiation;
1535   guint max_ref_frames, max_surfaces = 0, rt_format = 0, codedbuf_size;
1536   gint width, height;
1537
1538   width = GST_VIDEO_INFO_WIDTH (&base->input_state->info);
1539   height = GST_VIDEO_INFO_HEIGHT (&base->input_state->info);
1540   format = GST_VIDEO_INFO_FORMAT (&base->input_state->info);
1541   codedbuf_size = base->codedbuf_size;
1542
1543   need_negotiation =
1544       !gst_va_encoder_get_reconstruct_pool_config (base->encoder, &reconf_caps,
1545       &max_surfaces);
1546   if (!need_negotiation && reconf_caps) {
1547     GstVideoInfo vi;
1548     if (!gst_video_info_from_caps (&vi, reconf_caps))
1549       return FALSE;
1550     reconf_format = GST_VIDEO_INFO_FORMAT (&vi);
1551   }
1552
1553   if (!_decide_profile (self, &profile, &rt_format))
1554     return FALSE;
1555
1556   /* first check */
1557   do_reopen = !(base->profile == profile && base->rt_format == rt_format
1558       && format == reconf_format && width == base->width
1559       && height == base->height && self->prop.rc_ctrl == self->rc.rc_ctrl_mode);
1560
1561   if (do_reopen && gst_va_encoder_is_open (base->encoder))
1562     gst_va_encoder_close (base->encoder);
1563
1564   gst_va_base_enc_reset_state (base);
1565
1566   base->profile = profile;
1567   base->rt_format = rt_format;
1568   base->width = width;
1569   base->height = height;
1570
1571   self->mb_width = GST_ROUND_UP_16 (base->width) / 16;
1572   self->mb_height = GST_ROUND_UP_16 (base->height) / 16;
1573
1574   /* Frame rate is needed for rate control and PTS setting. */
1575   if (GST_VIDEO_INFO_FPS_N (&base->input_state->info) == 0
1576       || GST_VIDEO_INFO_FPS_D (&base->input_state->info) == 0) {
1577     GST_INFO_OBJECT (self, "Unknown framerate, just set to 30 fps");
1578     GST_VIDEO_INFO_FPS_N (&base->input_state->info) = 30;
1579     GST_VIDEO_INFO_FPS_D (&base->input_state->info) = 1;
1580   }
1581   base->frame_duration = gst_util_uint64_scale (GST_SECOND,
1582       GST_VIDEO_INFO_FPS_D (&base->input_state->info),
1583       GST_VIDEO_INFO_FPS_N (&base->input_state->info));
1584
1585   GST_DEBUG_OBJECT (self, "resolution:%dx%d, MB size: %dx%d,"
1586       " frame duration is %" GST_TIME_FORMAT,
1587       base->width, base->height, self->mb_width, self->mb_height,
1588       GST_TIME_ARGS (base->frame_duration));
1589
1590   _validate_parameters (self);
1591
1592   if (!_ensure_rate_control (self))
1593     return FALSE;
1594
1595   if (!_calculate_level (self))
1596     return FALSE;
1597
1598   _generate_gop_structure (self);
1599
1600   _calculate_coded_size (self);
1601
1602   /* updates & notifications */
1603   /* num_bframes are modified several times before */
1604   update_property_uint (base, &self->prop.num_bframes, self->gop.num_bframes,
1605       PROP_BFRAMES);
1606   update_property_bool (base, &self->prop.b_pyramid, self->gop.b_pyramid,
1607       PROP_B_PYRAMID);
1608
1609   if (!_init_packed_headers (self))
1610     return FALSE;
1611
1612   self->aud = self->aud && self->packed_headers & VA_ENC_PACKED_HEADER_RAW_DATA;
1613   update_property_bool (base, &self->prop.aud, self->aud, PROP_AUD);
1614
1615   self->cc = self->cc && self->packed_headers & VA_ENC_PACKED_HEADER_RAW_DATA;
1616   update_property_bool (base, &self->prop.cc, self->cc, PROP_CC);
1617
1618   max_ref_frames = self->gop.num_ref_frames + 3 /* scratch frames */ ;
1619
1620   /* second check after calculations */
1621   do_reopen |=
1622       !(max_ref_frames == max_surfaces && codedbuf_size == base->codedbuf_size);
1623   if (do_reopen && gst_va_encoder_is_open (base->encoder))
1624     gst_va_encoder_close (base->encoder);
1625
1626   if (!gst_va_encoder_is_open (base->encoder)
1627       && !gst_va_encoder_open (base->encoder, base->profile,
1628           format, base->rt_format, base->width, base->height,
1629           base->codedbuf_size, max_ref_frames, self->rc.rc_ctrl_mode,
1630           self->packed_headers)) {
1631     GST_ERROR_OBJECT (self, "Failed to open the VA encoder.");
1632     return FALSE;
1633   }
1634
1635   /* Add some tags */
1636   gst_va_base_enc_add_codec_tag (base, "H264");
1637
1638   out_caps = gst_va_profile_caps (base->profile);
1639   g_assert (out_caps);
1640   out_caps = gst_caps_fixate (out_caps);
1641
1642   if (self->level_str)
1643     gst_caps_set_simple (out_caps, "level", G_TYPE_STRING, self->level_str,
1644         NULL);
1645
1646   gst_caps_set_simple (out_caps, "width", G_TYPE_INT, base->width,
1647       "height", G_TYPE_INT, base->height, "alignment", G_TYPE_STRING, "au",
1648       "stream-format", G_TYPE_STRING, "byte-stream", NULL);
1649
1650   if (!need_negotiation) {
1651     output_state = gst_video_encoder_get_output_state (venc);
1652     do_renegotiation = TRUE;
1653     if (output_state) {
1654       do_renegotiation = !gst_caps_is_subset (output_state->caps, out_caps);
1655       gst_video_codec_state_unref (output_state);
1656     }
1657     if (!do_renegotiation) {
1658       gst_caps_unref (out_caps);
1659       return TRUE;
1660     }
1661   }
1662
1663   GST_DEBUG_OBJECT (self, "output caps is %" GST_PTR_FORMAT, out_caps);
1664
1665   output_state =
1666       gst_video_encoder_set_output_state (venc, out_caps, base->input_state);
1667   gst_video_codec_state_unref (output_state);
1668
1669   if (!gst_video_encoder_negotiate (venc)) {
1670     GST_ERROR_OBJECT (self, "Failed to negotiate with the downstream");
1671     return FALSE;
1672   }
1673
1674   return TRUE;
1675 }
1676
1677 static gboolean
1678 _push_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame * gst_frame,
1679     gboolean last)
1680 {
1681   GstVaH264Enc *self = GST_VA_H264_ENC (base);
1682   GstVaH264EncFrame *frame;
1683
1684   g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
1685       FALSE);
1686
1687   if (gst_frame) {
1688     /* Begin a new GOP, should have a empty reorder_list. */
1689     if (self->gop.cur_frame_index == self->gop.idr_period) {
1690       g_assert (g_queue_is_empty (&base->reorder_list));
1691       self->gop.cur_frame_index = 0;
1692       self->gop.cur_frame_num = 0;
1693     }
1694
1695     frame = _enc_frame (gst_frame);
1696     frame->poc =
1697         ((self->gop.cur_frame_index * 2) % self->gop.max_pic_order_cnt);
1698
1699     /* TODO: move most this logic onto vabaseenc class  */
1700     if (self->gop.cur_frame_index == 0) {
1701       g_assert (frame->poc == 0);
1702       GST_LOG_OBJECT (self, "system_frame_number: %d, an IDR frame, starts"
1703           " a new GOP", gst_frame->system_frame_number);
1704
1705       g_queue_clear_full (&base->ref_list,
1706           (GDestroyNotify) gst_video_codec_frame_unref);
1707
1708       GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (gst_frame);
1709     }
1710
1711     frame->type = self->gop.frame_types[self->gop.cur_frame_index].slice_type;
1712     frame->is_ref = self->gop.frame_types[self->gop.cur_frame_index].is_ref;
1713     frame->pyramid_level =
1714         self->gop.frame_types[self->gop.cur_frame_index].pyramid_level;
1715     frame->left_ref_poc_diff =
1716         self->gop.frame_types[self->gop.cur_frame_index].left_ref_poc_diff;
1717     frame->right_ref_poc_diff =
1718         self->gop.frame_types[self->gop.cur_frame_index].right_ref_poc_diff;
1719
1720     if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (gst_frame)) {
1721       GST_DEBUG_OBJECT (self, "system_frame_number: %d, a force key frame,"
1722           " promote its type from %s to %s", gst_frame->system_frame_number,
1723           _slice_type_name (frame->type), _slice_type_name (GST_H264_I_SLICE));
1724       frame->type = GST_H264_I_SLICE;
1725       frame->is_ref = TRUE;
1726     }
1727
1728     GST_LOG_OBJECT (self, "Push frame, system_frame_number: %d, poc %d, "
1729         "frame type %s", gst_frame->system_frame_number, frame->poc,
1730         _slice_type_name (frame->type));
1731
1732     self->gop.cur_frame_index++;
1733     g_queue_push_tail (&base->reorder_list,
1734         gst_video_codec_frame_ref (gst_frame));
1735   }
1736
1737   /* ensure the last one a non-B and end the GOP. */
1738   if (last && self->gop.cur_frame_index < self->gop.idr_period) {
1739     GstVideoCodecFrame *last_frame;
1740
1741     /* Ensure next push will start a new GOP. */
1742     self->gop.cur_frame_index = self->gop.idr_period;
1743
1744     if (!g_queue_is_empty (&base->reorder_list)) {
1745       last_frame = g_queue_peek_tail (&base->reorder_list);
1746       frame = _enc_frame (last_frame);
1747       if (frame->type == GST_H264_B_SLICE) {
1748         frame->type = GST_H264_P_SLICE;
1749         frame->is_ref = TRUE;
1750       }
1751     }
1752   }
1753
1754   return TRUE;
1755 }
1756
1757 struct RefFramesCount
1758 {
1759   gint poc;
1760   guint num;
1761 };
1762
1763 static void
1764 _count_backward_ref_num (gpointer data, gpointer user_data)
1765 {
1766   GstVaH264EncFrame *frame = _enc_frame (data);
1767   struct RefFramesCount *count = (struct RefFramesCount *) user_data;
1768
1769   g_assert (frame->poc != count->poc);
1770   if (frame->poc > count->poc)
1771     count->num++;
1772 }
1773
1774 static GstVideoCodecFrame *
1775 _pop_pyramid_b_frame (GstVaH264Enc * self)
1776 {
1777   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1778   guint i;
1779   gint index = -1;
1780   GstVaH264EncFrame *b_vaframe;
1781   GstVideoCodecFrame *b_frame;
1782   struct RefFramesCount count;
1783
1784   g_assert (self->gop.ref_num_list1 == 1);
1785
1786   b_frame = NULL;
1787   b_vaframe = NULL;
1788
1789   /* Find the lowest level with smallest poc. */
1790   for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
1791     GstVaH264EncFrame *vaf;
1792     GstVideoCodecFrame *f;
1793
1794     f = g_queue_peek_nth (&base->reorder_list, i);
1795
1796     if (!b_frame) {
1797       b_frame = f;
1798       b_vaframe = _enc_frame (b_frame);
1799       index = i;
1800       continue;
1801     }
1802
1803     vaf = _enc_frame (f);
1804     if (b_vaframe->pyramid_level < vaf->pyramid_level) {
1805       b_frame = f;
1806       b_vaframe = vaf;
1807       index = i;
1808       continue;
1809     }
1810
1811     if (b_vaframe->poc > vaf->poc) {
1812       b_frame = f;
1813       b_vaframe = vaf;
1814       index = i;
1815     }
1816   }
1817
1818 again:
1819   /* Check whether its refs are already poped. */
1820   g_assert (b_vaframe->left_ref_poc_diff != 0);
1821   g_assert (b_vaframe->right_ref_poc_diff != 0);
1822   for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
1823     GstVaH264EncFrame *vaf;
1824     GstVideoCodecFrame *f;
1825
1826     f = g_queue_peek_nth (&base->reorder_list, i);
1827
1828     if (f == b_frame)
1829       continue;
1830
1831     vaf = _enc_frame (f);
1832     if (vaf->poc == b_vaframe->poc + b_vaframe->left_ref_poc_diff
1833         || vaf->poc == b_vaframe->poc + b_vaframe->right_ref_poc_diff) {
1834       b_frame = f;
1835       b_vaframe = vaf;
1836       index = i;
1837       goto again;
1838     }
1839   }
1840
1841   /* Ensure we already have enough backward refs */
1842   count.num = 0;
1843   count.poc = b_vaframe->poc;
1844   g_queue_foreach (&base->ref_list, (GFunc) _count_backward_ref_num, &count);
1845   if (count.num >= self->gop.ref_num_list1) {
1846     GstVideoCodecFrame *f;
1847
1848     /* it will unref at pop_frame */
1849     f = g_queue_pop_nth (&base->reorder_list, index);
1850     g_assert (f == b_frame);
1851   } else {
1852     b_frame = NULL;
1853   }
1854
1855   return b_frame;
1856 }
1857
1858 static gboolean
1859 _pop_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame ** out_frame)
1860 {
1861   GstVaH264Enc *self = GST_VA_H264_ENC (base);
1862   GstVaH264EncFrame *vaframe;
1863   GstVideoCodecFrame *frame;
1864   struct RefFramesCount count;
1865
1866   g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
1867       FALSE);
1868
1869   *out_frame = NULL;
1870
1871   if (g_queue_is_empty (&base->reorder_list))
1872     return TRUE;
1873
1874   /* Return the last pushed non-B immediately. */
1875   frame = g_queue_peek_tail (&base->reorder_list);
1876   vaframe = _enc_frame (frame);
1877   if (vaframe->type != GST_H264_B_SLICE) {
1878     frame = g_queue_pop_tail (&base->reorder_list);
1879     goto get_one;
1880   }
1881
1882   if (self->gop.b_pyramid) {
1883     frame = _pop_pyramid_b_frame (self);
1884     if (frame == NULL)
1885       return TRUE;
1886     goto get_one;
1887   }
1888
1889   g_assert (self->gop.ref_num_list1 > 0);
1890
1891   /* If GOP end, pop anyway. */
1892   if (self->gop.cur_frame_index == self->gop.idr_period) {
1893     frame = g_queue_pop_head (&base->reorder_list);
1894     goto get_one;
1895   }
1896
1897   /* Ensure we already have enough backward refs */
1898   frame = g_queue_peek_head (&base->reorder_list);
1899   vaframe = _enc_frame (frame);
1900   count.num = 0;
1901   count.poc = vaframe->poc;
1902   g_queue_foreach (&base->ref_list, _count_backward_ref_num, &count);
1903   if (count.num >= self->gop.ref_num_list1) {
1904     frame = g_queue_pop_head (&base->reorder_list);
1905     goto get_one;
1906   }
1907
1908   return TRUE;
1909
1910 get_one:
1911   g_assert (self->gop.cur_frame_num < self->gop.max_frame_num);
1912
1913   vaframe = _enc_frame (frame);
1914   vaframe->frame_num = self->gop.cur_frame_num;
1915
1916   /* Add the frame number for ref frames. */
1917   if (vaframe->is_ref)
1918     self->gop.cur_frame_num++;
1919
1920   if (vaframe->frame_num == 0)
1921     self->gop.total_idr_count++;
1922
1923   if (self->gop.b_pyramid && vaframe->type == GST_H264_B_SLICE) {
1924     GST_LOG_OBJECT (self, "pop a pyramid B frame with system_frame_number:"
1925         " %d, poc: %d, frame num: %d, is_ref: %s, level %d",
1926         frame->system_frame_number, vaframe->poc, vaframe->frame_num,
1927         vaframe->is_ref ? "true" : "false", vaframe->pyramid_level);
1928   } else {
1929     GST_LOG_OBJECT (self, "pop a frame with system_frame_number: %d,"
1930         " frame type: %s, poc: %d, frame num: %d, is_ref: %s",
1931         frame->system_frame_number, _slice_type_name (vaframe->type),
1932         vaframe->poc, vaframe->frame_num, vaframe->is_ref ? "true" : "false");
1933   }
1934
1935   /* unref frame popped from queue or pyramid b_frame */
1936   gst_video_codec_frame_unref (frame);
1937   *out_frame = frame;
1938   return TRUE;
1939 }
1940
1941 static gboolean
1942 gst_va_h264_enc_reorder_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame,
1943     gboolean bump_all, GstVideoCodecFrame ** out_frame)
1944 {
1945   if (!_push_one_frame (base, frame, bump_all)) {
1946     GST_ERROR_OBJECT (base, "Failed to push the input frame"
1947         " system_frame_number: %d into the reorder list",
1948         frame->system_frame_number);
1949
1950     *out_frame = NULL;
1951     return FALSE;
1952   }
1953
1954   if (!_pop_one_frame (base, out_frame)) {
1955     GST_ERROR_OBJECT (base, "Failed to pop the frame from the reorder list");
1956     *out_frame = NULL;
1957     return FALSE;
1958   }
1959
1960   return TRUE;
1961 }
1962
1963 static inline gboolean
1964 _fill_sps (GstVaH264Enc * self, VAEncSequenceParameterBufferH264 * seq_param)
1965 {
1966   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1967   GstH264Profile profile;
1968   guint32 constraint_set0_flag, constraint_set1_flag;
1969   guint32 constraint_set2_flag, constraint_set3_flag;
1970   guint32 max_dec_frame_buffering;
1971
1972   /* let max_num_ref_frames <= MaxDpbFrames. */
1973   max_dec_frame_buffering =
1974       MIN (self->gop.num_ref_frames + 1 /* Last frame before bump */ ,
1975       16 /* DPB_MAX_SIZE */ );
1976
1977   constraint_set0_flag = 0;
1978   constraint_set1_flag = 0;
1979   constraint_set2_flag = 0;
1980   constraint_set3_flag = 0;
1981
1982   switch (base->profile) {
1983     case VAProfileH264ConstrainedBaseline:
1984       profile = GST_H264_PROFILE_BASELINE;
1985       /* A.2.1 (baseline profile constraints) */
1986       constraint_set0_flag = 1;
1987       constraint_set1_flag = 1;
1988       break;
1989     case VAProfileH264Main:
1990       profile = GST_H264_PROFILE_MAIN;
1991       /* A.2.2 (main profile constraints) */
1992       constraint_set1_flag = 1;
1993       break;
1994     case VAProfileH264High:
1995     case VAProfileH264MultiviewHigh:
1996     case VAProfileH264StereoHigh:
1997       profile = GST_H264_PROFILE_HIGH;
1998       break;
1999     default:
2000       return FALSE;
2001   }
2002
2003   /* seq_scaling_matrix_present_flag not supported now */
2004   g_assert (seq_param->seq_fields.bits.seq_scaling_matrix_present_flag == 0);
2005   /* pic_order_cnt_type only support 0 now */
2006   g_assert (seq_param->seq_fields.bits.pic_order_cnt_type == 0);
2007   /* only progressive frames encoding is supported now */
2008   g_assert (seq_param->seq_fields.bits.frame_mbs_only_flag);
2009
2010   /* *INDENT-OFF* */
2011   GST_DEBUG_OBJECT (self, "filling SPS");
2012   self->sequence_hdr = (GstH264SPS) {
2013     .id = 0,
2014     .profile_idc = profile,
2015     .constraint_set0_flag = constraint_set0_flag,
2016     .constraint_set1_flag = constraint_set1_flag,
2017     .constraint_set2_flag = constraint_set2_flag,
2018     .constraint_set3_flag = constraint_set3_flag,
2019     .level_idc = self->level_idc,
2020
2021     .chroma_format_idc = seq_param->seq_fields.bits.chroma_format_idc,
2022     .bit_depth_luma_minus8 = seq_param->bit_depth_luma_minus8,
2023     .bit_depth_chroma_minus8 = seq_param->bit_depth_chroma_minus8,
2024
2025     .log2_max_frame_num_minus4 =
2026         seq_param->seq_fields.bits.log2_max_frame_num_minus4,
2027     .pic_order_cnt_type = seq_param->seq_fields.bits.pic_order_cnt_type,
2028     .log2_max_pic_order_cnt_lsb_minus4 =
2029         seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4,
2030
2031     .num_ref_frames = seq_param->max_num_ref_frames,
2032     .gaps_in_frame_num_value_allowed_flag = 0,
2033     .pic_width_in_mbs_minus1 = seq_param->picture_width_in_mbs - 1,
2034     .pic_height_in_map_units_minus1 =
2035         (seq_param->seq_fields.bits.frame_mbs_only_flag ?
2036             seq_param->picture_height_in_mbs - 1 :
2037             seq_param->picture_height_in_mbs / 2 - 1),
2038     .frame_mbs_only_flag = seq_param->seq_fields.bits.frame_mbs_only_flag,
2039     .mb_adaptive_frame_field_flag = 0,
2040     .direct_8x8_inference_flag =
2041         seq_param->seq_fields.bits.direct_8x8_inference_flag,
2042     .frame_cropping_flag = seq_param->frame_cropping_flag,
2043     .frame_crop_left_offset = seq_param->frame_crop_left_offset,
2044     .frame_crop_right_offset = seq_param->frame_crop_right_offset,
2045     .frame_crop_top_offset = seq_param->frame_crop_top_offset,
2046     .frame_crop_bottom_offset = seq_param->frame_crop_bottom_offset,
2047
2048     .vui_parameters_present_flag = seq_param->vui_parameters_present_flag,
2049     .vui_parameters = {
2050       .aspect_ratio_info_present_flag =
2051           seq_param->vui_fields.bits.aspect_ratio_info_present_flag,
2052       .aspect_ratio_idc = seq_param->aspect_ratio_idc,
2053       .sar_width = seq_param->sar_width,
2054       .sar_height = seq_param->sar_height,
2055       .overscan_info_present_flag = 0,
2056       .overscan_appropriate_flag = 0,
2057       .chroma_loc_info_present_flag = 0,
2058       .timing_info_present_flag =
2059           seq_param->vui_fields.bits.timing_info_present_flag,
2060       .num_units_in_tick = seq_param->num_units_in_tick,
2061       .time_scale = seq_param->time_scale,
2062       .fixed_frame_rate_flag = seq_param->vui_fields.bits.fixed_frame_rate_flag,
2063
2064       /* We do not write hrd and no need for buffering period SEI. */
2065       .nal_hrd_parameters_present_flag = 0,
2066       .vcl_hrd_parameters_present_flag = 0,
2067
2068       .low_delay_hrd_flag = seq_param->vui_fields.bits.low_delay_hrd_flag,
2069       .pic_struct_present_flag = 1,
2070       .bitstream_restriction_flag =
2071           seq_param->vui_fields.bits.bitstream_restriction_flag,
2072       .motion_vectors_over_pic_boundaries_flag =
2073           seq_param->vui_fields.bits.motion_vectors_over_pic_boundaries_flag,
2074       .max_bytes_per_pic_denom = 2,
2075       .max_bits_per_mb_denom = 1,
2076       .log2_max_mv_length_horizontal =
2077           seq_param->vui_fields.bits.log2_max_mv_length_horizontal,
2078       .log2_max_mv_length_vertical =
2079           seq_param->vui_fields.bits.log2_max_mv_length_vertical,
2080       .num_reorder_frames = self->gop.num_reorder_frames,
2081       .max_dec_frame_buffering = max_dec_frame_buffering,
2082     },
2083   };
2084   /* *INDENT-ON* */
2085
2086   return TRUE;
2087 }
2088
2089 static gboolean
2090 _add_sequence_header (GstVaH264Enc * self, GstVaH264EncFrame * frame)
2091 {
2092   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2093   guint size;
2094 #define SPS_SIZE 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE + MAX_VUI_PARAMS_SIZE + \
2095     2 * MAX_HRD_PARAMS_SIZE) / 8
2096   guint8 packed_sps[SPS_SIZE] = { 0, };
2097 #undef SPS_SIZE
2098
2099   size = sizeof (packed_sps);
2100   if (gst_h264_bit_writer_sps (&self->sequence_hdr, TRUE, packed_sps,
2101           &size) != GST_H264_BIT_WRITER_OK) {
2102     GST_ERROR_OBJECT (self, "Failed to generate the sequence header");
2103     return FALSE;
2104   }
2105
2106   if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2107           VAEncPackedHeaderSequence, packed_sps, size * 8, FALSE)) {
2108     GST_ERROR_OBJECT (self, "Failed to add the packed sequence header");
2109     return FALSE;
2110   }
2111
2112   return TRUE;
2113 }
2114
2115 static inline void
2116 _fill_sequence_param (GstVaH264Enc * self,
2117     VAEncSequenceParameterBufferH264 * sequence)
2118 {
2119   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2120   gboolean direct_8x8_inference_flag = TRUE;
2121
2122   g_assert (self->gop.log2_max_frame_num >= 4);
2123   g_assert (self->gop.log2_max_pic_order_cnt >= 4);
2124
2125   /* A.2.3 Extended profile:
2126    * Sequence parameter sets shall have direct_8x8_inference_flag
2127    * equal to 1.
2128    *
2129    * A.3.3 Profile-specific level limits:
2130    * direct_8x8_inference_flag is not relevant to the Baseline,
2131    * Constrained Baseline, Constrained High, High 10 Intra, High 4:2:2
2132    * Intra, High 4:4:4 Intra, and CAVLC 4:4:4 Intra profiles as these
2133    * profiles do not allow B slice types, and
2134    * direct_8x8_inference_flag is equal to 1 for all levels of the
2135    * Extended profile. Table A-4.  We only have constrained baseline
2136    * here. */
2137   if (base->profile == VAProfileH264ConstrainedBaseline)
2138     direct_8x8_inference_flag = FALSE;
2139
2140   /* *INDENT-OFF* */
2141   *sequence = (VAEncSequenceParameterBufferH264) {
2142     .seq_parameter_set_id = 0,
2143     .level_idc = self->level_idc,
2144     .intra_period =
2145         self->gop.i_period > 0 ? self->gop.i_period : self->gop.idr_period,
2146     .intra_idr_period = self->gop.idr_period,
2147     .ip_period = self->gop.ip_period,
2148     .bits_per_second = self->rc.target_bitrate_bits,
2149     .max_num_ref_frames = self->gop.num_ref_frames,
2150     .picture_width_in_mbs = self->mb_width,
2151     .picture_height_in_mbs = self->mb_height,
2152
2153     .seq_fields.bits = {
2154       /* Only support 4:2:0 now. */
2155       .chroma_format_idc = 1,
2156       .frame_mbs_only_flag = 1,
2157       .mb_adaptive_frame_field_flag = FALSE,
2158       .seq_scaling_matrix_present_flag = FALSE,
2159       .direct_8x8_inference_flag = direct_8x8_inference_flag,
2160       .log2_max_frame_num_minus4 = self->gop.log2_max_frame_num - 4,
2161       .pic_order_cnt_type = 0,
2162       .log2_max_pic_order_cnt_lsb_minus4 = self->gop.log2_max_pic_order_cnt - 4,
2163     },
2164     .bit_depth_luma_minus8 = 0,
2165     .bit_depth_chroma_minus8 = 0,
2166
2167     .vui_parameters_present_flag = TRUE,
2168     .vui_fields.bits = {
2169       .aspect_ratio_info_present_flag = TRUE,
2170       .timing_info_present_flag = TRUE,
2171       .bitstream_restriction_flag = TRUE,
2172       .log2_max_mv_length_horizontal = 15,
2173       .log2_max_mv_length_vertical = 15,
2174       .fixed_frame_rate_flag = 1,
2175       .low_delay_hrd_flag = 0,
2176       .motion_vectors_over_pic_boundaries_flag = TRUE,
2177     },
2178     .aspect_ratio_idc = 0xff,
2179     /* FIXME: what if no framerate info is provided */
2180     .sar_width = GST_VIDEO_INFO_PAR_N (&base->input_state->info),
2181     .sar_height = GST_VIDEO_INFO_PAR_D (&base->input_state->info),
2182     .num_units_in_tick = GST_VIDEO_INFO_FPS_D (&base->input_state->info),
2183     .time_scale = GST_VIDEO_INFO_FPS_N (&base->input_state->info) * 2,
2184   };
2185   /* *INDENT-ON* */
2186
2187   /* frame_cropping_flag */
2188   if (base->width & 15 || base->height & 15) {
2189     static const guint SubWidthC[] = { 1, 2, 2, 1 };
2190     static const guint SubHeightC[] = { 1, 2, 1, 1 };
2191     const guint CropUnitX =
2192         SubWidthC[sequence->seq_fields.bits.chroma_format_idc];
2193     const guint CropUnitY =
2194         SubHeightC[sequence->seq_fields.bits.chroma_format_idc] *
2195         (2 - sequence->seq_fields.bits.frame_mbs_only_flag);
2196
2197     sequence->frame_cropping_flag = 1;
2198     sequence->frame_crop_left_offset = 0;
2199     sequence->frame_crop_right_offset = (16 * self->mb_width -
2200         base->width) / CropUnitX;
2201     sequence->frame_crop_top_offset = 0;
2202     sequence->frame_crop_bottom_offset = (16 * self->mb_height -
2203         base->height) / CropUnitY;
2204   }
2205 }
2206
2207 static gboolean
2208 _add_sequence_parameter (GstVaH264Enc * self, GstVaEncodePicture * picture,
2209     VAEncSequenceParameterBufferH264 * sequence)
2210 {
2211   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2212
2213   if (!gst_va_encoder_add_param (base->encoder, picture,
2214           VAEncSequenceParameterBufferType, sequence, sizeof (*sequence))) {
2215     GST_ERROR_OBJECT (self, "Failed to create the sequence parameter");
2216     return FALSE;
2217   }
2218
2219   return TRUE;
2220 }
2221
2222 static inline gboolean
2223 _fill_picture_parameter (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2224     VAEncPictureParameterBufferH264 * pic_param)
2225 {
2226   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2227   guint i;
2228
2229   /* *INDENT-OFF* */
2230   *pic_param = (VAEncPictureParameterBufferH264) {
2231     .CurrPic = {
2232       .picture_id =
2233           gst_va_encode_picture_get_reconstruct_surface (frame->picture),
2234       .TopFieldOrderCnt = frame->poc,
2235     },
2236     .coded_buf = frame->picture->coded_buffer,
2237     /* Only support one sps and pps now. */
2238     .pic_parameter_set_id = 0,
2239     .seq_parameter_set_id = 0,
2240     /* means last encoding picture, EOS nal added. */
2241     .last_picture = frame->last_frame,
2242     .frame_num = frame->frame_num,
2243
2244     .pic_init_qp = self->rc.qp_i,
2245     /* Use slice's these fields to control ref num. */
2246     .num_ref_idx_l0_active_minus1 = 0,
2247     .num_ref_idx_l1_active_minus1 = 0,
2248     .chroma_qp_index_offset = 0,
2249     .second_chroma_qp_index_offset = 0,
2250     /* picture fields */
2251     .pic_fields.bits.idr_pic_flag = (frame->frame_num == 0),
2252     .pic_fields.bits.reference_pic_flag = frame->is_ref,
2253     .pic_fields.bits.entropy_coding_mode_flag = self->use_cabac,
2254     .pic_fields.bits.weighted_pred_flag = 0,
2255     .pic_fields.bits.weighted_bipred_idc = 0,
2256     .pic_fields.bits.constrained_intra_pred_flag = 0,
2257     .pic_fields.bits.transform_8x8_mode_flag = self->use_dct8x8,
2258     /* enable debloking */
2259     .pic_fields.bits.deblocking_filter_control_present_flag = 1,
2260     .pic_fields.bits.redundant_pic_cnt_present_flag = 0,
2261     /* bottom_field_pic_order_in_frame_present_flag */
2262     .pic_fields.bits.pic_order_present_flag = 0,
2263     .pic_fields.bits.pic_scaling_matrix_present_flag = 0,
2264   };
2265   /* *INDENT-ON* */
2266
2267   /* Non I frame, construct reference list. */
2268   i = 0;
2269   if (frame->type != GST_H264_I_SLICE) {
2270     GstVaH264EncFrame *f;
2271
2272     if (g_queue_is_empty (&base->ref_list)) {
2273       GST_ERROR_OBJECT (self, "No reference found for frame type %s",
2274           _slice_type_name (frame->type));
2275       return FALSE;
2276     }
2277
2278     g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
2279
2280     /* ref frames in queue are already sorted by frame_num. */
2281     for (; i < g_queue_get_length (&base->ref_list); i++) {
2282       f = _enc_frame (g_queue_peek_nth (&base->ref_list, i));
2283
2284       pic_param->ReferenceFrames[i].picture_id =
2285           gst_va_encode_picture_get_reconstruct_surface (f->picture);
2286       pic_param->ReferenceFrames[i].TopFieldOrderCnt = f->poc;
2287       pic_param->ReferenceFrames[i].flags =
2288           VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2289       pic_param->ReferenceFrames[i].frame_idx = f->frame_num;
2290     }
2291   }
2292   for (; i < 16; ++i)
2293     pic_param->ReferenceFrames[i].picture_id = VA_INVALID_ID;
2294
2295   return TRUE;
2296 };
2297
2298 static gboolean
2299 _add_picture_parameter (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2300     VAEncPictureParameterBufferH264 * pic_param)
2301 {
2302   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2303
2304   if (!gst_va_encoder_add_param (base->encoder, frame->picture,
2305           VAEncPictureParameterBufferType, pic_param,
2306           sizeof (VAEncPictureParameterBufferH264))) {
2307     GST_ERROR_OBJECT (self, "Failed to create the picture parameter");
2308     return FALSE;
2309   }
2310
2311   return TRUE;
2312 }
2313
2314 static void
2315 _fill_pps (VAEncPictureParameterBufferH264 * pic_param, GstH264SPS * sps,
2316     GstH264PPS * pps)
2317 {
2318   /* *INDENT-OFF* */
2319   *pps = (GstH264PPS) {
2320     .id = 0,
2321     .sequence = sps,
2322     .entropy_coding_mode_flag =
2323         pic_param->pic_fields.bits.entropy_coding_mode_flag,
2324     .pic_order_present_flag =
2325         pic_param->pic_fields.bits.pic_order_present_flag,
2326     .num_slice_groups_minus1 = 0,
2327
2328     .num_ref_idx_l0_active_minus1 = pic_param->num_ref_idx_l0_active_minus1,
2329     .num_ref_idx_l1_active_minus1 = pic_param->num_ref_idx_l1_active_minus1,
2330
2331     .weighted_pred_flag = pic_param->pic_fields.bits.weighted_pred_flag,
2332     .weighted_bipred_idc = pic_param->pic_fields.bits.weighted_bipred_idc,
2333     .pic_init_qp_minus26 = pic_param->pic_init_qp - 26,
2334     .pic_init_qs_minus26 = 0,
2335     .chroma_qp_index_offset = pic_param->chroma_qp_index_offset,
2336     .deblocking_filter_control_present_flag =
2337         pic_param->pic_fields.bits.deblocking_filter_control_present_flag,
2338     .constrained_intra_pred_flag =
2339         pic_param->pic_fields.bits.constrained_intra_pred_flag,
2340     .redundant_pic_cnt_present_flag =
2341         pic_param->pic_fields.bits.redundant_pic_cnt_present_flag,
2342     .transform_8x8_mode_flag =
2343         pic_param->pic_fields.bits.transform_8x8_mode_flag,
2344     /* unsupport scaling lists */
2345     .pic_scaling_matrix_present_flag = 0,
2346     .second_chroma_qp_index_offset = pic_param->second_chroma_qp_index_offset,
2347   };
2348   /* *INDENT-ON* */
2349 }
2350
2351 static gboolean
2352 _add_picture_header (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2353     GstH264PPS * pps)
2354 {
2355   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2356 #define PPS_SIZE 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8
2357   guint8 packed_pps[PPS_SIZE] = { 0, };
2358 #undef PPS_SIZE
2359   guint size;
2360
2361   size = sizeof (packed_pps);
2362   if (gst_h264_bit_writer_pps (pps, TRUE, packed_pps,
2363           &size) != GST_H264_BIT_WRITER_OK) {
2364     GST_ERROR_OBJECT (self, "Failed to generate the picture header");
2365     return FALSE;
2366   }
2367
2368   if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2369           VAEncPackedHeaderPicture, packed_pps, size * 8, FALSE)) {
2370     GST_ERROR_OBJECT (self, "Failed to add the packed picture header");
2371     return FALSE;
2372   }
2373
2374   return TRUE;
2375 }
2376
2377 static gboolean
2378 _add_one_slice (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2379     gint start_mb, gint mb_size,
2380     VAEncSliceParameterBufferH264 * slice,
2381     GstVaH264EncFrame * list0[16], guint list0_num,
2382     GstVaH264EncFrame * list1[16], guint list1_num)
2383 {
2384   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2385   int8_t slice_qp_delta = 0;
2386   gint i;
2387
2388   /* *INDENT-OFF* */
2389   if (self->rc.rc_ctrl_mode == VA_RC_CQP) {
2390     if (frame->type == GST_H264_P_SLICE) {
2391       slice_qp_delta = self->rc.qp_p - self->rc.qp_i;
2392     } else if (frame->type == GST_H264_B_SLICE) {
2393       slice_qp_delta = (int8_t) (self->rc.qp_b - self->rc.qp_i);
2394     }
2395     g_assert (slice_qp_delta <= 51 && slice_qp_delta >= -51);
2396   }
2397
2398   *slice = (VAEncSliceParameterBufferH264) {
2399     .macroblock_address = start_mb,
2400     .num_macroblocks = mb_size,
2401     .macroblock_info = VA_INVALID_ID,
2402     .slice_type = (uint8_t) frame->type,
2403     /* Only one parameter set supported now. */
2404     .pic_parameter_set_id = 0,
2405     .idr_pic_id = self->gop.total_idr_count,
2406     .pic_order_cnt_lsb = frame->poc,
2407     /* Not support top/bottom. */
2408     .delta_pic_order_cnt_bottom = 0,
2409     .delta_pic_order_cnt[0] = 0,
2410     .delta_pic_order_cnt[1] = 0,
2411
2412     .direct_spatial_mv_pred_flag = TRUE,
2413     /* .num_ref_idx_active_override_flag = , */
2414     /* .num_ref_idx_l0_active_minus1 = , */
2415     /* .num_ref_idx_l1_active_minus1 = , */
2416     /* Set the reference list later. */
2417
2418     .luma_log2_weight_denom = 0,
2419     .chroma_log2_weight_denom = 0,
2420     .luma_weight_l0_flag = 0,
2421     .chroma_weight_l0_flag = 0,
2422     .luma_weight_l1_flag = 0,
2423     .chroma_weight_l1_flag = 0,
2424
2425     .cabac_init_idc = 0,
2426     /* Just use picture default setting. */
2427     .slice_qp_delta = slice_qp_delta,
2428
2429     .disable_deblocking_filter_idc = 0,
2430     .slice_alpha_c0_offset_div2 = 2,
2431     .slice_beta_offset_div2 = 2,
2432   };
2433   /* *INDENT-ON* */
2434
2435   if (frame->type == GST_H264_B_SLICE || frame->type == GST_H264_P_SLICE) {
2436     slice->num_ref_idx_active_override_flag = (list0_num > 0 || list1_num > 0);
2437     slice->num_ref_idx_l0_active_minus1 = list0_num > 0 ? list0_num - 1 : 0;
2438     if (frame->type == GST_H264_B_SLICE)
2439       slice->num_ref_idx_l1_active_minus1 = list1_num > 0 ? list1_num - 1 : 0;
2440   }
2441
2442   i = 0;
2443   if (frame->type != GST_H264_I_SLICE) {
2444     for (; i < list0_num; i++) {
2445       slice->RefPicList0[i].picture_id =
2446           gst_va_encode_picture_get_reconstruct_surface (list0[i]->picture);
2447       slice->RefPicList0[i].TopFieldOrderCnt = list0[i]->poc;
2448       slice->RefPicList0[i].flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2449       slice->RefPicList0[i].frame_idx = list0[i]->frame_num;
2450     }
2451   }
2452   for (; i < G_N_ELEMENTS (slice->RefPicList0); ++i) {
2453     slice->RefPicList0[i].picture_id = VA_INVALID_SURFACE;
2454     slice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID;
2455   }
2456
2457   i = 0;
2458   if (frame->type == GST_H264_B_SLICE) {
2459     for (; i < list1_num; i++) {
2460       slice->RefPicList1[i].picture_id =
2461           gst_va_encode_picture_get_reconstruct_surface (list1[i]->picture);
2462       slice->RefPicList1[i].TopFieldOrderCnt = list1[i]->poc;
2463       slice->RefPicList1[i].flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2464       slice->RefPicList1[i].frame_idx = list1[i]->frame_num;
2465     }
2466   }
2467   for (; i < G_N_ELEMENTS (slice->RefPicList1); ++i) {
2468     slice->RefPicList1[i].picture_id = VA_INVALID_SURFACE;
2469     slice->RefPicList1[i].flags = VA_PICTURE_H264_INVALID;
2470   }
2471
2472   if (!gst_va_encoder_add_param (base->encoder, frame->picture,
2473           VAEncSliceParameterBufferType, slice,
2474           sizeof (VAEncSliceParameterBufferH264))) {
2475     GST_ERROR_OBJECT (self, "Failed to create the slice parameter");
2476     return FALSE;
2477   }
2478
2479   return TRUE;
2480 }
2481
2482 static gint
2483 _poc_asc_compare (const GstVaH264EncFrame ** a, const GstVaH264EncFrame ** b)
2484 {
2485   return (*a)->poc - (*b)->poc;
2486 }
2487
2488 static gint
2489 _poc_des_compare (const GstVaH264EncFrame ** a, const GstVaH264EncFrame ** b)
2490 {
2491   return (*b)->poc - (*a)->poc;
2492 }
2493
2494 static gint
2495 _frame_num_asc_compare (const GstVaH264EncFrame ** a,
2496     const GstVaH264EncFrame ** b)
2497 {
2498   return (*a)->frame_num - (*b)->frame_num;
2499 }
2500
2501 static gint
2502 _frame_num_des_compare (const GstVaH264EncFrame ** a,
2503     const GstVaH264EncFrame ** b)
2504 {
2505   return (*b)->frame_num - (*a)->frame_num;
2506 }
2507
2508 /* If all the pic_num in the same order, OK. */
2509 static gboolean
2510 _ref_list_need_reorder (GstVaH264EncFrame * list[16], guint list_num,
2511     gboolean is_asc)
2512 {
2513   guint i;
2514   gint pic_num_diff;
2515
2516   if (list_num <= 1)
2517     return FALSE;
2518
2519   for (i = 1; i < list_num; i++) {
2520     pic_num_diff = list[i]->frame_num - list[i - 1]->frame_num;
2521     g_assert (pic_num_diff != 0);
2522
2523     if (pic_num_diff > 0 && !is_asc)
2524       return TRUE;
2525
2526     if (pic_num_diff < 0 && is_asc)
2527       return TRUE;
2528   }
2529
2530   return FALSE;
2531 }
2532
2533 static void
2534 _insert_ref_pic_list_modification (GstH264SliceHdr * slice_hdr,
2535     GstVaH264EncFrame * list[16], guint list_num, gboolean is_asc)
2536 {
2537   GstVaH264EncFrame *list_by_pic_num[16] = { };
2538   guint modification_num, i;
2539   GstH264RefPicListModification *ref_pic_list_modification = NULL;
2540   gint pic_num_diff, pic_num_lx_pred;
2541
2542   memcpy (list_by_pic_num, list, sizeof (GstVaH264EncFrame *) * list_num);
2543
2544   if (is_asc) {
2545     g_qsort_with_data (list_by_pic_num, list_num, sizeof (gpointer),
2546         (GCompareDataFunc) _frame_num_asc_compare, NULL);
2547   } else {
2548     g_qsort_with_data (list_by_pic_num, list_num, sizeof (gpointer),
2549         (GCompareDataFunc) _frame_num_des_compare, NULL);
2550   }
2551
2552   modification_num = 0;
2553   for (i = 0; i < list_num; i++) {
2554     if (list_by_pic_num[i]->poc != list[i]->poc)
2555       modification_num = i + 1;
2556   }
2557   g_assert (modification_num > 0);
2558
2559   if (is_asc) {
2560     slice_hdr->ref_pic_list_modification_flag_l1 = 1;
2561     slice_hdr->n_ref_pic_list_modification_l1 =
2562         modification_num + 1 /* The end operation. */ ;
2563     ref_pic_list_modification = slice_hdr->ref_pic_list_modification_l1;
2564   } else {
2565     slice_hdr->ref_pic_list_modification_flag_l0 = 1;
2566     slice_hdr->n_ref_pic_list_modification_l0 =
2567         modification_num + 1 /* The end operation. */ ;
2568     ref_pic_list_modification = slice_hdr->ref_pic_list_modification_l0;
2569   }
2570
2571   pic_num_lx_pred = slice_hdr->frame_num;
2572   for (i = 0; i < modification_num; i++) {
2573     pic_num_diff = list[i]->frame_num - pic_num_lx_pred;
2574     /* For the nex loop. */
2575     pic_num_lx_pred = list[i]->frame_num;
2576
2577     g_assert (pic_num_diff != 0);
2578
2579     if (pic_num_diff > 0) {
2580       ref_pic_list_modification->modification_of_pic_nums_idc = 1;
2581       ref_pic_list_modification->value.abs_diff_pic_num_minus1 =
2582           pic_num_diff - 1;
2583     } else {
2584       ref_pic_list_modification->modification_of_pic_nums_idc = 0;
2585       ref_pic_list_modification->value.abs_diff_pic_num_minus1 =
2586           (-pic_num_diff) - 1;
2587     }
2588
2589     ref_pic_list_modification++;
2590   }
2591
2592   ref_pic_list_modification->modification_of_pic_nums_idc = 3;
2593 }
2594
2595 static void
2596 _insert_ref_pic_marking_for_unused_frame (GstH264SliceHdr * slice_hdr,
2597     gint cur_frame_num, gint unused_frame_num)
2598 {
2599   GstH264RefPicMarking *refpicmarking;
2600
2601   slice_hdr->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag = 1;
2602   slice_hdr->dec_ref_pic_marking.n_ref_pic_marking = 2;
2603
2604   refpicmarking = &slice_hdr->dec_ref_pic_marking.ref_pic_marking[0];
2605
2606   refpicmarking->memory_management_control_operation = 1;
2607   refpicmarking->difference_of_pic_nums_minus1 =
2608       cur_frame_num - unused_frame_num - 1;
2609
2610   refpicmarking = &slice_hdr->dec_ref_pic_marking.ref_pic_marking[1];
2611   refpicmarking->memory_management_control_operation = 0;
2612 }
2613
2614 static gboolean
2615 _add_slice_header (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2616     GstH264PPS * pps, VAEncSliceParameterBufferH264 * slice,
2617     GstVaH264EncFrame * list0[16], guint list0_num,
2618     GstVaH264EncFrame * list1[16], guint list1_num)
2619 {
2620   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2621   GstH264SliceHdr slice_hdr;
2622   guint size, trail_bits;
2623   GstH264NalUnitType nal_type = GST_H264_NAL_SLICE;
2624 #define SLICE_HDR_SIZE 4 + GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8
2625   guint8 packed_slice_hdr[SLICE_HDR_SIZE] = { 0, };
2626 #undef SLICE_HDR_SIZE
2627
2628   if (frame->frame_num == 0)
2629     nal_type = GST_H264_NAL_SLICE_IDR;
2630
2631   /* *INDENT-OFF* */
2632   slice_hdr = (GstH264SliceHdr) {
2633     .first_mb_in_slice = slice->macroblock_address,
2634     .type = slice->slice_type,
2635     .pps = pps,
2636     .frame_num = frame->frame_num,
2637     /* interlaced not supported now. */
2638     .field_pic_flag = 0,
2639     .bottom_field_flag = 0,
2640     .idr_pic_id = (frame->frame_num == 0 ? slice->idr_pic_id : 0),
2641     /* only pic_order_cnt_type 1 is supported now. */
2642     .pic_order_cnt_lsb = slice->pic_order_cnt_lsb,
2643     .delta_pic_order_cnt_bottom = slice->delta_pic_order_cnt_bottom,
2644      /* Only for B frame. */
2645     .direct_spatial_mv_pred_flag =
2646         (frame->type == GST_H264_B_SLICE ?
2647          slice->direct_spatial_mv_pred_flag : 0),
2648
2649     .num_ref_idx_active_override_flag = slice->num_ref_idx_active_override_flag,
2650     .num_ref_idx_l0_active_minus1 = slice->num_ref_idx_l0_active_minus1,
2651     .num_ref_idx_l1_active_minus1 = slice->num_ref_idx_l1_active_minus1,
2652     /* Calculate it later. */
2653     .ref_pic_list_modification_flag_l0 = 0,
2654     .ref_pic_list_modification_flag_l1 = 0,
2655     /* We have weighted_pred_flag and weighted_bipred_idc 0 here, no
2656      * need weight_table. */
2657
2658     .dec_ref_pic_marking = {
2659       .no_output_of_prior_pics_flag = 0,
2660       .long_term_reference_flag = 0,
2661       /* If not sliding_window, we set it later. */
2662       .adaptive_ref_pic_marking_mode_flag = 0,
2663     },
2664
2665     .cabac_init_idc = slice->cabac_init_idc,
2666     .slice_qp_delta = slice->slice_qp_delta,
2667
2668     .disable_deblocking_filter_idc = slice->disable_deblocking_filter_idc,
2669     .slice_alpha_c0_offset_div2 = slice->slice_alpha_c0_offset_div2,
2670     .slice_beta_offset_div2 = slice->slice_beta_offset_div2,
2671   };
2672   /* *INDENT-ON* */
2673
2674   /* Reorder the ref lists if needed. */
2675   if (list0_num > 1) {
2676     /* list0 is in poc descend order now. */
2677     if (_ref_list_need_reorder (list0, list0_num, FALSE))
2678       _insert_ref_pic_list_modification (&slice_hdr, list0, list0_num, FALSE);
2679   }
2680
2681   if (list0_num > 1) {
2682     /* list0 is in poc ascend order now. */
2683     if (_ref_list_need_reorder (list1, list1_num, TRUE)) {
2684       _insert_ref_pic_list_modification (&slice_hdr, list1, list1_num, TRUE);
2685     }
2686   }
2687
2688   /* Mark the unused reference explicitly which this frame replaces. */
2689   if (frame->unused_for_reference_pic_num >= 0) {
2690     g_assert (frame->is_ref);
2691     _insert_ref_pic_marking_for_unused_frame (&slice_hdr, frame->frame_num,
2692         frame->unused_for_reference_pic_num);
2693   }
2694
2695   size = sizeof (packed_slice_hdr);
2696   trail_bits = 0;
2697   if (gst_h264_bit_writer_slice_hdr (&slice_hdr, TRUE, nal_type, frame->is_ref,
2698           packed_slice_hdr, &size, &trail_bits) != GST_H264_BIT_WRITER_OK) {
2699     GST_ERROR_OBJECT (self, "Failed to generate the slice header");
2700     return FALSE;
2701   }
2702
2703   if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2704           VAEncPackedHeaderSlice, packed_slice_hdr, size * 8 + trail_bits,
2705           FALSE)) {
2706     GST_ERROR_OBJECT (self, "Failed to add the packed slice header");
2707     return FALSE;
2708   }
2709
2710   return TRUE;
2711 }
2712
2713 static gboolean
2714 _add_aud (GstVaH264Enc * self, GstVaH264EncFrame * frame)
2715 {
2716   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2717   guint8 aud_data[8] = { };
2718   guint size;
2719   guint8 primary_pic_type = 0;
2720
2721   switch (frame->type) {
2722     case GST_H264_I_SLICE:
2723       primary_pic_type = 0;
2724       break;
2725     case GST_H264_P_SLICE:
2726       primary_pic_type = 1;
2727       break;
2728     case GST_H264_B_SLICE:
2729       primary_pic_type = 2;
2730       break;
2731     default:
2732       g_assert_not_reached ();
2733       break;
2734   }
2735
2736   size = sizeof (aud_data);
2737   if (gst_h264_bit_writer_aud (primary_pic_type, TRUE, aud_data,
2738           &size) != GST_H264_BIT_WRITER_OK) {
2739     GST_ERROR_OBJECT (self, "Failed to generate the AUD");
2740     return FALSE;
2741   }
2742
2743   if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2744           VAEncPackedHeaderRawData, aud_data, size * 8, FALSE)) {
2745     GST_ERROR_OBJECT (self, "Failed to add the AUD");
2746     return FALSE;
2747   }
2748
2749   return TRUE;
2750 }
2751
2752 static void
2753 _create_sei_cc_message (GstVideoCaptionMeta * cc_meta,
2754     GstH264SEIMessage * sei_msg)
2755 {
2756   guint8 *data;
2757   GstH264RegisteredUserData *user_data;
2758
2759   sei_msg->payloadType = GST_H264_SEI_REGISTERED_USER_DATA;
2760
2761   user_data = &sei_msg->payload.registered_user_data;
2762
2763   user_data->country_code = 181;
2764   user_data->size = 10 + cc_meta->size;
2765
2766   data = g_malloc (user_data->size);
2767
2768   /* 16-bits itu_t_t35_provider_code */
2769   data[0] = 0;
2770   data[1] = 49;
2771   /* 32-bits ATSC_user_identifier */
2772   data[2] = 'G';
2773   data[3] = 'A';
2774   data[4] = '9';
2775   data[5] = '4';
2776   /* 8-bits ATSC1_data_user_data_type_code */
2777   data[6] = 3;
2778   /* 8-bits:
2779    * 1 bit process_em_data_flag (0)
2780    * 1 bit process_cc_data_flag (1)
2781    * 1 bit additional_data_flag (0)
2782    * 5-bits cc_count
2783    */
2784   data[7] = ((cc_meta->size / 3) & 0x1f) | 0x40;
2785   /* 8 bits em_data, unused */
2786   data[8] = 255;
2787
2788   memcpy (data + 9, cc_meta->data, cc_meta->size);
2789
2790   /* 8 marker bits */
2791   data[user_data->size - 1] = 255;
2792
2793   user_data->data = data;
2794 }
2795
2796 static gboolean
2797 _create_sei_cc_data (GPtrArray * cc_list, guint8 * sei_data, guint * data_size)
2798 {
2799   GArray *msg_list = NULL;
2800   GstH264BitWriterResult ret;
2801   gint i;
2802
2803   msg_list = g_array_new (TRUE, TRUE, sizeof (GstH264SEIMessage));
2804   g_array_set_clear_func (msg_list, (GDestroyNotify) gst_h264_sei_clear);
2805   g_array_set_size (msg_list, cc_list->len);
2806
2807   for (i = 0; i < cc_list->len; i++) {
2808     GstH264SEIMessage *msg = &g_array_index (msg_list, GstH264SEIMessage, i);
2809     _create_sei_cc_message (g_ptr_array_index (cc_list, i), msg);
2810   }
2811
2812   ret = gst_h264_bit_writer_sei (msg_list, TRUE, sei_data, data_size);
2813
2814   g_array_unref (msg_list);
2815
2816   return (ret == GST_H264_BIT_WRITER_OK);
2817 }
2818
2819 static void
2820 _add_sei_cc (GstVaH264Enc * self, GstVideoCodecFrame * gst_frame)
2821 {
2822   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2823   GstVaH264EncFrame *frame;
2824   GPtrArray *cc_list = NULL;
2825   GstVideoCaptionMeta *cc_meta;
2826   gpointer iter = NULL;
2827   guint8 *packed_sei = NULL;
2828   guint sei_size = 0;
2829
2830   frame = _enc_frame (gst_frame);
2831
2832   /* SEI header size */
2833   sei_size = 6;
2834   while ((cc_meta = (GstVideoCaptionMeta *)
2835           gst_buffer_iterate_meta_filtered (gst_frame->input_buffer, &iter,
2836               GST_VIDEO_CAPTION_META_API_TYPE))) {
2837     if (cc_meta->caption_type != GST_VIDEO_CAPTION_TYPE_CEA708_RAW)
2838       continue;
2839
2840     if (!cc_list)
2841       cc_list = g_ptr_array_new ();
2842
2843     g_ptr_array_add (cc_list, cc_meta);
2844     /* Add enough SEI message size for bitwriter. */
2845     sei_size += cc_meta->size + 50;
2846   }
2847
2848   if (!cc_list)
2849     goto out;
2850
2851   packed_sei = g_malloc0 (sei_size);
2852
2853   if (!_create_sei_cc_data (cc_list, packed_sei, &sei_size)) {
2854     GST_WARNING_OBJECT (self, "Failed to write the SEI CC data");
2855     goto out;
2856   }
2857
2858   if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2859           VAEncPackedHeaderRawData, packed_sei, sei_size * 8, FALSE)) {
2860     GST_WARNING_OBJECT (self, "Failed to add SEI CC data");
2861     goto out;
2862   }
2863
2864 out:
2865   g_clear_pointer (&cc_list, g_ptr_array_unref);
2866   if (packed_sei)
2867     g_free (packed_sei);
2868 }
2869
2870 static gboolean
2871 _encode_one_frame (GstVaH264Enc * self, GstVideoCodecFrame * gst_frame)
2872 {
2873   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2874   VAEncPictureParameterBufferH264 pic_param;
2875   GstH264PPS pps;
2876   GstVaH264EncFrame *list0[16] = { NULL, };
2877   guint list0_num = 0;
2878   GstVaH264EncFrame *list1[16] = { NULL, };
2879   guint list1_num = 0;
2880   guint slice_of_mbs, slice_mod_mbs, slice_start_mb, slice_mbs;
2881   gint i;
2882   GstVaH264EncFrame *frame;
2883
2884   g_return_val_if_fail (gst_frame, FALSE);
2885
2886   frame = _enc_frame (gst_frame);
2887
2888   if (self->aud && !_add_aud (self, frame))
2889     return FALSE;
2890
2891   /* Repeat the SPS for IDR. */
2892   if (frame->poc == 0) {
2893     VAEncSequenceParameterBufferH264 sequence;
2894
2895     if (!gst_va_base_enc_add_rate_control_parameter (base, frame->picture,
2896             self->rc.rc_ctrl_mode, self->rc.max_bitrate_bits,
2897             self->rc.target_percentage, self->rc.qp_i, self->rc.min_qp,
2898             self->rc.max_qp, self->rc.mbbrc))
2899       return FALSE;
2900
2901     if (!gst_va_base_enc_add_quality_level_parameter (base, frame->picture,
2902             self->rc.target_usage))
2903       return FALSE;
2904
2905     if (!gst_va_base_enc_add_frame_rate_parameter (base, frame->picture))
2906       return FALSE;
2907
2908     if (!gst_va_base_enc_add_hrd_parameter (base, frame->picture,
2909             self->rc.rc_ctrl_mode, self->rc.cpb_length_bits))
2910       return FALSE;
2911
2912     if (!gst_va_base_enc_add_trellis_parameter (base, frame->picture,
2913             self->use_trellis))
2914       return FALSE;
2915
2916     _fill_sequence_param (self, &sequence);
2917     if (!_fill_sps (self, &sequence))
2918       return FALSE;
2919
2920     if (!_add_sequence_parameter (self, frame->picture, &sequence))
2921       return FALSE;
2922
2923     if ((self->packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE)
2924         && !_add_sequence_header (self, frame))
2925       return FALSE;
2926   }
2927
2928   /* Non I frame, construct reference list. */
2929   if (frame->type != GST_H264_I_SLICE) {
2930     GstVaH264EncFrame *vaf;
2931     GstVideoCodecFrame *f;
2932
2933     for (i = g_queue_get_length (&base->ref_list) - 1; i >= 0; i--) {
2934       f = g_queue_peek_nth (&base->ref_list, i);
2935       vaf = _enc_frame (f);
2936       if (vaf->poc > frame->poc)
2937         continue;
2938
2939       list0[list0_num] = vaf;
2940       list0_num++;
2941     }
2942
2943     /* reorder to select the most nearest forward frames. */
2944     g_qsort_with_data (list0, list0_num, sizeof (gpointer),
2945         (GCompareDataFunc) _poc_des_compare, NULL);
2946
2947     if (list0_num > self->gop.ref_num_list0)
2948       list0_num = self->gop.ref_num_list0;
2949   }
2950
2951   if (frame->type == GST_H264_B_SLICE) {
2952     GstVaH264EncFrame *vaf;
2953     GstVideoCodecFrame *f;
2954
2955     for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
2956       f = g_queue_peek_nth (&base->ref_list, i);
2957       vaf = _enc_frame (f);
2958       if (vaf->poc < frame->poc)
2959         continue;
2960
2961       list1[list1_num] = vaf;
2962       list1_num++;
2963     }
2964
2965     /* reorder to select the most nearest backward frames. */
2966     g_qsort_with_data (list1, list1_num, sizeof (gpointer),
2967         (GCompareDataFunc) _poc_asc_compare, NULL);
2968
2969     if (list1_num > self->gop.ref_num_list1)
2970       list1_num = self->gop.ref_num_list1;
2971   }
2972
2973   g_assert (list0_num + list1_num <= self->gop.num_ref_frames);
2974
2975   if (!_fill_picture_parameter (self, frame, &pic_param))
2976     return FALSE;
2977   if (!_add_picture_parameter (self, frame, &pic_param))
2978     return FALSE;
2979   _fill_pps (&pic_param, &self->sequence_hdr, &pps);
2980
2981   if ((self->packed_headers & VA_ENC_PACKED_HEADER_PICTURE)
2982       && frame->type == GST_H264_I_SLICE
2983       && !_add_picture_header (self, frame, &pps))
2984     return FALSE;
2985
2986   if (self->cc) {
2987     /* CC errors are not fatal */
2988     _add_sei_cc (self, gst_frame);
2989   }
2990
2991   slice_of_mbs = self->mb_width * self->mb_height / self->num_slices;
2992   slice_mod_mbs = self->mb_width * self->mb_height % self->num_slices;
2993   slice_start_mb = 0;
2994   slice_mbs = 0;
2995   for (i = 0; i < self->num_slices; i++) {
2996     VAEncSliceParameterBufferH264 slice;
2997
2998     slice_mbs = slice_of_mbs;
2999     /* divide the remainder to each equally */
3000     if (slice_mod_mbs) {
3001       slice_mbs++;
3002       slice_mod_mbs--;
3003     }
3004
3005     if (!_add_one_slice (self, frame, slice_start_mb, slice_mbs, &slice,
3006             list0, list0_num, list1, list1_num))
3007       return FALSE;
3008
3009     if ((self->packed_headers & VA_ENC_PACKED_HEADER_SLICE) &&
3010         (!_add_slice_header (self, frame, &pps, &slice, list0, list0_num,
3011                 list1, list1_num)))
3012       return FALSE;
3013
3014     slice_start_mb += slice_mbs;
3015   }
3016
3017   if (!gst_va_encoder_encode (base->encoder, frame->picture)) {
3018     GST_ERROR_OBJECT (self, "Encode frame error");
3019     return FALSE;
3020   }
3021
3022   return TRUE;
3023 }
3024
3025 static gboolean
3026 gst_va_h264_enc_flush (GstVideoEncoder * venc)
3027 {
3028   GstVaH264Enc *self = GST_VA_H264_ENC (venc);
3029
3030   /* begin from an IDR after flush. */
3031   self->gop.cur_frame_index = 0;
3032   self->gop.cur_frame_num = 0;
3033
3034   return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (venc);
3035 }
3036
3037 static void
3038 gst_va_h264_enc_prepare_output (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
3039 {
3040   GstVaH264Enc *self = GST_VA_H264_ENC (base);
3041   GstVaH264EncFrame *frame_enc;
3042
3043   frame_enc = _enc_frame (frame);
3044
3045   frame->pts =
3046       base->start_pts + base->frame_duration * frame_enc->total_frame_count;
3047   /* The PTS should always be later than the DTS. */
3048   frame->dts = base->start_pts + base->frame_duration *
3049       ((gint64) base->output_frame_count -
3050       (gint64) self->gop.num_reorder_frames);
3051   base->output_frame_count++;
3052   frame->duration = base->frame_duration;
3053 }
3054
3055 static gint
3056 _sort_by_frame_num (gconstpointer a, gconstpointer b, gpointer user_data)
3057 {
3058   GstVaH264EncFrame *frame1 = _enc_frame ((GstVideoCodecFrame *) a);
3059   GstVaH264EncFrame *frame2 = _enc_frame ((GstVideoCodecFrame *) b);
3060
3061   g_assert (frame1->frame_num != frame2->frame_num);
3062
3063   return frame1->frame_num - frame2->frame_num;
3064 }
3065
3066 static GstVideoCodecFrame *
3067 _find_unused_reference_frame (GstVaH264Enc * self, GstVaH264EncFrame * frame)
3068 {
3069   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3070   GstVaH264EncFrame *b_vaframe;
3071   GstVideoCodecFrame *b_frame;
3072   guint i;
3073
3074   /* We still have more space. */
3075   if (g_queue_get_length (&base->ref_list) < self->gop.num_ref_frames)
3076     return NULL;
3077
3078   /* Not b_pyramid, sliding window is enough. */
3079   if (!self->gop.b_pyramid)
3080     return g_queue_peek_head (&base->ref_list);
3081
3082   /* I/P frame, just using sliding window. */
3083   if (frame->type != GST_H264_B_SLICE)
3084     return g_queue_peek_head (&base->ref_list);
3085
3086   /* Choose the B frame with lowest POC. */
3087   b_frame = NULL;
3088   b_vaframe = NULL;
3089   for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
3090     GstVaH264EncFrame *vaf;
3091     GstVideoCodecFrame *f;
3092
3093     f = g_queue_peek_nth (&base->ref_list, i);
3094     vaf = _enc_frame (f);
3095     if (vaf->type != GST_H264_B_SLICE)
3096       continue;
3097
3098     if (!b_frame) {
3099       b_frame = f;
3100       b_vaframe = _enc_frame (b_frame);
3101       continue;
3102     }
3103
3104     b_vaframe = _enc_frame (b_frame);
3105     g_assert (vaf->poc != b_vaframe->poc);
3106     if (vaf->poc < b_vaframe->poc) {
3107       b_frame = f;
3108       b_vaframe = _enc_frame (b_frame);
3109     }
3110   }
3111
3112   /* No B frame as ref. */
3113   if (!b_frame)
3114     return g_queue_peek_head (&base->ref_list);
3115
3116   if (b_frame != g_queue_peek_head (&base->ref_list)) {
3117     b_vaframe = _enc_frame (b_frame);
3118     frame->unused_for_reference_pic_num = b_vaframe->frame_num;
3119     GST_LOG_OBJECT (self, "The frame with POC: %d, pic_num %d will be"
3120         " replaced by the frame with POC: %d, pic_num %d explicitly by"
3121         " using memory_management_control_operation=1",
3122         b_vaframe->poc, b_vaframe->frame_num, frame->poc, frame->frame_num);
3123   }
3124
3125   return b_frame;
3126 }
3127
3128 static GstFlowReturn
3129 gst_va_h264_enc_encode_frame (GstVaBaseEnc * base,
3130     GstVideoCodecFrame * gst_frame, gboolean is_last)
3131 {
3132   GstVaH264Enc *self = GST_VA_H264_ENC (base);
3133   GstVaH264EncFrame *frame;
3134   GstVideoCodecFrame *unused_ref = NULL;
3135
3136   frame = _enc_frame (gst_frame);
3137   frame->last_frame = is_last;
3138
3139   g_assert (frame->picture == NULL);
3140   frame->picture = gst_va_encode_picture_new (base->encoder,
3141       gst_frame->input_buffer);
3142
3143   if (!frame->picture) {
3144     GST_ERROR_OBJECT (self, "Failed to create the encode picture");
3145     return GST_FLOW_ERROR;
3146   }
3147
3148   if (frame->is_ref)
3149     unused_ref = _find_unused_reference_frame (self, frame);
3150
3151   if (!_encode_one_frame (self, gst_frame)) {
3152     GST_ERROR_OBJECT (self, "Failed to encode the frame");
3153     return GST_FLOW_ERROR;
3154   }
3155
3156   g_queue_push_tail (&base->output_list, gst_video_codec_frame_ref (gst_frame));
3157
3158   if (frame->is_ref) {
3159     if (unused_ref) {
3160       if (!g_queue_remove (&base->ref_list, unused_ref))
3161         g_assert_not_reached ();
3162
3163       gst_video_codec_frame_unref (unused_ref);
3164     }
3165
3166     /* Add it into the reference list. */
3167     g_queue_push_tail (&base->ref_list, gst_video_codec_frame_ref (gst_frame));
3168     g_queue_sort (&base->ref_list, _sort_by_frame_num, NULL);
3169
3170     g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
3171   }
3172
3173   return GST_FLOW_OK;
3174 }
3175
3176 static gboolean
3177 gst_va_h264_enc_new_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
3178 {
3179   GstVaH264EncFrame *frame_in;
3180
3181   frame_in = gst_va_enc_frame_new ();
3182   frame_in->total_frame_count = base->input_frame_count++;
3183   gst_video_codec_frame_set_user_data (frame, frame_in, gst_va_enc_frame_free);
3184
3185   return TRUE;
3186 }
3187
3188 /* *INDENT-OFF* */
3189 static const gchar *sink_caps_str =
3190     GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VA,
3191         "{ NV12 }") " ;"
3192     GST_VIDEO_CAPS_MAKE ("{ NV12 }");
3193 /* *INDENT-ON* */
3194
3195 static const gchar *src_caps_str = "video/x-h264";
3196
3197 static gpointer
3198 _register_debug_category (gpointer data)
3199 {
3200   GST_DEBUG_CATEGORY_INIT (gst_va_h264enc_debug, "vah264enc", 0,
3201       "VA h264 encoder");
3202
3203   return NULL;
3204 }
3205
3206 static void
3207 gst_va_h264_enc_init (GTypeInstance * instance, gpointer g_class)
3208 {
3209   GstVaH264Enc *self = GST_VA_H264_ENC (instance);
3210
3211   /* default values */
3212   self->prop.key_int_max = 0;
3213   self->prop.num_bframes = 0;
3214   self->prop.num_iframes = 0;
3215   self->prop.num_ref_frames = 3;
3216   self->prop.b_pyramid = FALSE;
3217   self->prop.num_slices = 1;
3218   self->prop.min_qp = 1;
3219   self->prop.max_qp = 51;
3220   self->prop.qp_i = 26;
3221   self->prop.qp_p = 26;
3222   self->prop.qp_b = 26;
3223   self->prop.use_dct8x8 = TRUE;
3224   self->prop.use_cabac = TRUE;
3225   self->prop.use_trellis = FALSE;
3226   self->prop.aud = FALSE;
3227   self->prop.cc = TRUE;
3228   self->prop.mbbrc = 0;
3229   self->prop.bitrate = 0;
3230   self->prop.target_percentage = 66;
3231   self->prop.target_usage = 4;
3232   if (properties[PROP_RATE_CONTROL]) {
3233     self->prop.rc_ctrl =
3234         G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])->default_value;
3235   } else {
3236     self->prop.rc_ctrl = VA_RC_NONE;
3237   }
3238   self->prop.cpb_size = 0;
3239 }
3240
3241 static void
3242 gst_va_h264_enc_set_property (GObject * object, guint prop_id,
3243     const GValue * value, GParamSpec * pspec)
3244 {
3245   GstVaH264Enc *self = GST_VA_H264_ENC (object);
3246   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3247
3248   GST_OBJECT_LOCK (self);
3249
3250   switch (prop_id) {
3251     case PROP_KEY_INT_MAX:
3252       self->prop.key_int_max = g_value_get_uint (value);
3253       break;
3254     case PROP_BFRAMES:
3255       self->prop.num_bframes = g_value_get_uint (value);
3256       break;
3257     case PROP_IFRAMES:
3258       self->prop.num_iframes = g_value_get_uint (value);
3259       break;
3260     case PROP_NUM_REF_FRAMES:
3261       self->prop.num_ref_frames = g_value_get_uint (value);
3262       break;
3263     case PROP_B_PYRAMID:
3264       self->prop.b_pyramid = g_value_get_boolean (value);
3265       break;
3266     case PROP_NUM_SLICES:
3267       self->prop.num_slices = g_value_get_uint (value);
3268       break;
3269     case PROP_MIN_QP:
3270       self->prop.min_qp = g_value_get_uint (value);
3271       break;
3272     case PROP_MAX_QP:
3273       self->prop.max_qp = g_value_get_uint (value);
3274       break;
3275     case PROP_QP_I:
3276       self->prop.qp_i = g_value_get_uint (value);
3277       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3278       break;
3279     case PROP_QP_P:
3280       self->prop.qp_p = g_value_get_uint (value);
3281       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3282       break;
3283     case PROP_QP_B:
3284       self->prop.qp_b = g_value_get_uint (value);
3285       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3286       break;
3287     case PROP_DCT8X8:
3288       self->prop.use_dct8x8 = g_value_get_boolean (value);
3289       break;
3290     case PROP_CABAC:
3291       self->prop.use_cabac = g_value_get_boolean (value);
3292       break;
3293     case PROP_TRELLIS:
3294       self->prop.use_trellis = g_value_get_boolean (value);
3295       break;
3296     case PROP_AUD:
3297       self->prop.aud = g_value_get_boolean (value);
3298       break;
3299     case PROP_CC:
3300       self->prop.cc = g_value_get_boolean (value);
3301       break;
3302     case PROP_MBBRC:{
3303       /* Macroblock-level rate control.
3304        * 0: use default,
3305        * 1: always enable,
3306        * 2: always disable,
3307        * other: reserved. */
3308       switch (g_value_get_enum (value)) {
3309         case GST_VA_FEATURE_DISABLED:
3310           self->prop.mbbrc = 2;
3311           break;
3312         case GST_VA_FEATURE_ENABLED:
3313           self->prop.mbbrc = 1;
3314           break;
3315         case GST_VA_FEATURE_AUTO:
3316           self->prop.mbbrc = 0;
3317           break;
3318       }
3319       break;
3320     }
3321     case PROP_BITRATE:
3322       self->prop.bitrate = g_value_get_uint (value);
3323       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3324       break;
3325     case PROP_TARGET_PERCENTAGE:
3326       self->prop.target_percentage = g_value_get_uint (value);
3327       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3328       break;
3329     case PROP_TARGET_USAGE:
3330       self->prop.target_usage = g_value_get_uint (value);
3331       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3332       break;
3333     case PROP_RATE_CONTROL:
3334       self->prop.rc_ctrl = g_value_get_enum (value);
3335       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3336       break;
3337     case PROP_CPB_SIZE:
3338       self->prop.cpb_size = g_value_get_uint (value);
3339       break;
3340     default:
3341       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3342   }
3343
3344   GST_OBJECT_UNLOCK (self);
3345
3346 #ifndef GST_DISABLE_GST_DEBUG
3347   if (!g_atomic_int_get (&GST_VA_BASE_ENC (self)->reconf)
3348       && base->encoder && gst_va_encoder_is_open (base->encoder)) {
3349     GST_WARNING_OBJECT (self, "Property `%s` change ignored while processing.",
3350         pspec->name);
3351   }
3352 #endif
3353
3354 }
3355
3356 static void
3357 gst_va_h264_enc_get_property (GObject * object, guint prop_id,
3358     GValue * value, GParamSpec * pspec)
3359 {
3360   GstVaH264Enc *const self = GST_VA_H264_ENC (object);
3361
3362   GST_OBJECT_LOCK (self);
3363
3364   switch (prop_id) {
3365     case PROP_KEY_INT_MAX:
3366       g_value_set_uint (value, self->prop.key_int_max);
3367       break;
3368     case PROP_BFRAMES:
3369       g_value_set_uint (value, self->prop.num_bframes);
3370       break;
3371     case PROP_IFRAMES:
3372       g_value_set_uint (value, self->prop.num_iframes);
3373       break;
3374     case PROP_NUM_REF_FRAMES:
3375       g_value_set_uint (value, self->prop.num_ref_frames);
3376       break;
3377     case PROP_B_PYRAMID:
3378       g_value_set_boolean (value, self->prop.b_pyramid);
3379       break;
3380     case PROP_NUM_SLICES:
3381       g_value_set_uint (value, self->prop.num_slices);
3382       break;
3383     case PROP_MIN_QP:
3384       g_value_set_uint (value, self->prop.min_qp);
3385       break;
3386     case PROP_MAX_QP:
3387       g_value_set_uint (value, self->prop.max_qp);
3388       break;
3389     case PROP_QP_I:
3390       g_value_set_uint (value, self->prop.qp_i);
3391       break;
3392     case PROP_QP_P:
3393       g_value_set_uint (value, self->prop.qp_p);
3394       break;
3395     case PROP_QP_B:
3396       g_value_set_uint (value, self->prop.qp_b);
3397       break;
3398     case PROP_DCT8X8:
3399       g_value_set_boolean (value, self->prop.use_dct8x8);
3400       break;
3401     case PROP_CABAC:
3402       g_value_set_boolean (value, self->prop.use_cabac);
3403       break;
3404     case PROP_TRELLIS:
3405       g_value_set_boolean (value, self->prop.use_trellis);
3406       break;
3407     case PROP_AUD:
3408       g_value_set_boolean (value, self->prop.aud);
3409       break;
3410     case PROP_CC:
3411       g_value_set_boolean (value, self->prop.cc);
3412       break;
3413     case PROP_MBBRC:
3414       g_value_set_enum (value, self->prop.mbbrc);
3415       break;
3416     case PROP_BITRATE:
3417       g_value_set_uint (value, self->prop.bitrate);
3418       break;
3419     case PROP_TARGET_PERCENTAGE:
3420       g_value_set_uint (value, self->prop.target_percentage);
3421       break;
3422     case PROP_TARGET_USAGE:
3423       g_value_set_uint (value, self->prop.target_usage);
3424       break;
3425     case PROP_RATE_CONTROL:
3426       g_value_set_enum (value, self->prop.rc_ctrl);
3427       break;
3428     case PROP_CPB_SIZE:
3429       g_value_set_uint (value, self->prop.cpb_size);
3430       break;
3431     default:
3432       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3433   }
3434
3435   GST_OBJECT_UNLOCK (self);
3436 }
3437
3438 static void
3439 gst_va_h264_enc_class_init (gpointer g_klass, gpointer class_data)
3440 {
3441   GstCaps *src_doc_caps, *sink_doc_caps;
3442   GstPadTemplate *sink_pad_templ, *src_pad_templ;
3443   GObjectClass *object_class = G_OBJECT_CLASS (g_klass);
3444   GstElementClass *element_class = GST_ELEMENT_CLASS (g_klass);
3445   GstVideoEncoderClass *venc_class = GST_VIDEO_ENCODER_CLASS (g_klass);
3446   GstVaBaseEncClass *va_enc_class = GST_VA_BASE_ENC_CLASS (g_klass);
3447   GstVaH264EncClass *vah264enc_class = GST_VA_H264_ENC_CLASS (g_klass);
3448   GstVaDisplay *display;
3449   GstVaEncoder *encoder;
3450   struct CData *cdata = class_data;
3451   gchar *long_name;
3452   const gchar *name, *desc;
3453   gint n_props = N_PROPERTIES;
3454   GParamFlags param_flags =
3455       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT;
3456
3457   if (cdata->entrypoint == VAEntrypointEncSlice) {
3458     desc = "VA-API based H.264 video encoder";
3459     name = "VA-API H.264 Encoder";
3460   } else {
3461     desc = "VA-API based H.264 low power video encoder";
3462     name = "VA-API H.264 Low Power Encoder";
3463   }
3464
3465   if (cdata->description)
3466     long_name = g_strdup_printf ("%s in %s", name, cdata->description);
3467   else
3468     long_name = g_strdup (name);
3469
3470   gst_element_class_set_metadata (element_class, long_name,
3471       "Codec/Encoder/Video/Hardware", desc, "He Junyan <junyan.he@intel.com>");
3472
3473   sink_doc_caps = gst_caps_from_string (sink_caps_str);
3474   src_doc_caps = gst_caps_from_string (src_caps_str);
3475
3476   parent_class = g_type_class_peek_parent (g_klass);
3477
3478   va_enc_class->codec = H264;
3479   va_enc_class->entrypoint = cdata->entrypoint;
3480   va_enc_class->render_device_path = g_strdup (cdata->render_device_path);
3481
3482   sink_pad_templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
3483       cdata->sink_caps);
3484   gst_element_class_add_pad_template (element_class, sink_pad_templ);
3485
3486   gst_pad_template_set_documentation_caps (sink_pad_templ, sink_doc_caps);
3487   gst_caps_unref (sink_doc_caps);
3488
3489   src_pad_templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
3490       cdata->src_caps);
3491   gst_element_class_add_pad_template (element_class, src_pad_templ);
3492
3493   gst_pad_template_set_documentation_caps (src_pad_templ, src_doc_caps);
3494   gst_caps_unref (src_doc_caps);
3495
3496   object_class->set_property = gst_va_h264_enc_set_property;
3497   object_class->get_property = gst_va_h264_enc_get_property;
3498
3499   venc_class->flush = GST_DEBUG_FUNCPTR (gst_va_h264_enc_flush);
3500
3501   va_enc_class->reset_state = GST_DEBUG_FUNCPTR (gst_va_h264_enc_reset_state);
3502   va_enc_class->reconfig = GST_DEBUG_FUNCPTR (gst_va_h264_enc_reconfig);
3503   va_enc_class->new_frame = GST_DEBUG_FUNCPTR (gst_va_h264_enc_new_frame);
3504   va_enc_class->reorder_frame =
3505       GST_DEBUG_FUNCPTR (gst_va_h264_enc_reorder_frame);
3506   va_enc_class->encode_frame = GST_DEBUG_FUNCPTR (gst_va_h264_enc_encode_frame);
3507   va_enc_class->prepare_output =
3508       GST_DEBUG_FUNCPTR (gst_va_h264_enc_prepare_output);
3509
3510   {
3511     display =
3512         gst_va_display_drm_new_from_path (va_enc_class->render_device_path);
3513     encoder = gst_va_encoder_new (display, va_enc_class->codec,
3514         va_enc_class->entrypoint);
3515     if (gst_va_encoder_get_rate_control_enum (encoder,
3516             vah264enc_class->rate_control)) {
3517       g_snprintf (vah264enc_class->rate_control_type_name,
3518           G_N_ELEMENTS (vah264enc_class->rate_control_type_name) - 1,
3519           "GstVaEncoderRateControl_%" GST_FOURCC_FORMAT "%s_%s",
3520           GST_FOURCC_ARGS (va_enc_class->codec),
3521           (va_enc_class->entrypoint == VAEntrypointEncSliceLP) ? "_LP" : "",
3522           g_path_get_basename (va_enc_class->render_device_path));
3523       vah264enc_class->rate_control_type =
3524           g_enum_register_static (vah264enc_class->rate_control_type_name,
3525           vah264enc_class->rate_control);
3526       gst_type_mark_as_plugin_api (vah264enc_class->rate_control_type, 0);
3527     }
3528     gst_object_unref (encoder);
3529     gst_object_unref (display);
3530   }
3531
3532   g_free (long_name);
3533   g_free (cdata->description);
3534   g_free (cdata->render_device_path);
3535   gst_caps_unref (cdata->src_caps);
3536   gst_caps_unref (cdata->sink_caps);
3537   g_free (cdata);
3538
3539   /**
3540    * GstVaH264Enc:key-int-max:
3541    *
3542    * The maximal distance between two keyframes.
3543    */
3544   properties[PROP_KEY_INT_MAX] = g_param_spec_uint ("key-int-max",
3545       "Key frame maximal interval",
3546       "The maximal distance between two keyframes. It decides the size of GOP"
3547       " (0: auto-calculate)", 0, MAX_GOP_SIZE, 0, param_flags);
3548
3549   /**
3550    * GstVaH264Enc:b-frames:
3551    *
3552    * Number of B-frames between two reference frames.
3553    */
3554   properties[PROP_BFRAMES] = g_param_spec_uint ("b-frames", "B Frames",
3555       "Number of B frames between I and P reference frames", 0, 31, 0,
3556       param_flags);
3557
3558   /**
3559    * GstVaH264Enc:i-frames:
3560    *
3561    * Force the number of i-frames insertion within one GOP.
3562    */
3563   properties[PROP_IFRAMES] = g_param_spec_uint ("i-frames", "I Frames",
3564       "Force the number of I frames insertion within one GOP, not including the "
3565       "first IDR frame", 0, 1023, 0, param_flags);
3566
3567   /**
3568    * GstVaH264Enc:ref-frames:
3569    *
3570    * The number of reference frames.
3571    */
3572   properties[PROP_NUM_REF_FRAMES] = g_param_spec_uint ("ref-frames",
3573       "Number of Reference Frames",
3574       "Number of reference frames, including both the forward and the backward",
3575       0, 16, 3, param_flags);
3576
3577   /**
3578    * GstVaH264Enc:b-pyramid:
3579    *
3580    * Enable the b-pyramid reference structure in GOP.
3581    */
3582   properties[PROP_B_PYRAMID] = g_param_spec_boolean ("b-pyramid", "b pyramid",
3583       "Enable the b-pyramid reference structure in the GOP", FALSE,
3584       param_flags);
3585
3586   /**
3587    * GstVaH264Enc:num-slices:
3588    *
3589    * The number of slices per frame.
3590    */
3591   properties[PROP_NUM_SLICES] = g_param_spec_uint ("num-slices",
3592       "Number of Slices", "Number of slices per frame", 1, 200, 1, param_flags);
3593
3594   /**
3595    * GstVaH264Enc:max-qp:
3596    *
3597    * The maximum quantizer value.
3598    */
3599   properties[PROP_MAX_QP] = g_param_spec_uint ("max-qp", "Maximum QP",
3600       "Maximum quantizer value for each frame", 0, 51, 51, param_flags);
3601
3602   /**
3603    * GstVaH264Enc:min-qp:
3604    *
3605    * The minimum quantizer value.
3606    */
3607   properties[PROP_MIN_QP] = g_param_spec_uint ("min-qp", "Minimum QP",
3608       "Minimum quantizer value for each frame", 0, 51, 1, param_flags);
3609
3610   /**
3611    * GstVaH264Enc:qpi:
3612    *
3613    * The quantizer value for I frame.
3614    *
3615    * In CQP mode, it specifies the QP of I frame, in other mode, it specifies
3616    * the init QP of all frames.
3617    */
3618   properties[PROP_QP_I] = g_param_spec_uint ("qpi", "I Frame QP",
3619       "The quantizer value for I frame. In CQP mode, it specifies the QP of I "
3620       "frame, in other mode, it specifies the init QP of all frames", 0, 51, 26,
3621       param_flags | GST_PARAM_MUTABLE_PLAYING);
3622
3623   /**
3624    * GstVaH264Enc:qpp:
3625    *
3626    * The quantizer value for P frame. Available only in CQP mode.
3627    */
3628   properties[PROP_QP_P] = g_param_spec_uint ("qpp",
3629       "The quantizer value for P frame",
3630       "The quantizer value for P frame. Available only in CQP mode",
3631       0, 51, 26, param_flags | GST_PARAM_MUTABLE_PLAYING);
3632
3633   /**
3634    * GstVaH264Enc:qpb:
3635    *
3636    * The quantizer value for B frame. Available only in CQP mode.
3637    */
3638   properties[PROP_QP_B] = g_param_spec_uint ("qpb",
3639       "The quantizer value for B frame",
3640       "The quantizer value for B frame. Available only in CQP mode",
3641       0, 51, 26, param_flags | GST_PARAM_MUTABLE_PLAYING);
3642
3643   /**
3644    * GstVaH264Enc:dct8x8:
3645    *
3646    * Enable adaptive use of 8x8 transforms in I-frames. This improves
3647    * the compression ratio but requires high profile at least.
3648    */
3649   properties[PROP_DCT8X8] = g_param_spec_boolean ("dct8x8", "Enable 8x8 DCT",
3650       "Enable adaptive use of 8x8 transforms in I-frames", TRUE, param_flags);
3651
3652   /**
3653    * GstVaH264Enc:cabac:
3654    *
3655    * It enables CABAC entropy coding mode to improve compression ratio,
3656    * but requires main profile at least.
3657    */
3658   properties[PROP_CABAC] = g_param_spec_boolean ("cabac", "Enable CABAC",
3659       "Enable CABAC entropy coding mode", TRUE, param_flags);
3660
3661   /**
3662    * GstVaH264Enc:trellis:
3663    *
3664    * It enable the trellis quantization method. Trellis is an improved
3665    * quantization algorithm.
3666    */
3667   properties[PROP_TRELLIS] = g_param_spec_boolean ("trellis", "Enable trellis",
3668       "Enable the trellis quantization method", FALSE, param_flags);
3669
3670   /**
3671    * GstVaH264Enc:aud:
3672    *
3673    * Insert the AU (Access Unit) delimeter for each frame.
3674    */
3675   properties[PROP_AUD] = g_param_spec_boolean ("aud", "Insert AUD",
3676       "Insert AU (Access Unit) delimeter for each frame", FALSE, param_flags);
3677
3678   /**
3679    * GstVaH264Enc:cc-insert:
3680    *
3681    * Closed Caption Insert mode. Only CEA-708 RAW format is supported for now.
3682    */
3683   properties[PROP_CC] = g_param_spec_boolean ("cc-insert",
3684       "Insert Closed Captions",
3685       "Insert CEA-708 Closed Captions",
3686       TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3687
3688   /**
3689    * GstVaH264Enc:mbbrc:
3690    *
3691    * Macroblock level bitrate control. Not available in CQP mode.
3692    */
3693   properties[PROP_MBBRC] = g_param_spec_enum ("mbbrc",
3694       "Macroblock level Bitrate Control",
3695       "Macroblock level Bitrate Control. Not available in CQP mode",
3696       GST_TYPE_VA_FEATURE, GST_VA_FEATURE_AUTO, param_flags);
3697
3698   /**
3699    * GstVaH264Enc:bitrate:
3700    *
3701    * The desired target bitrate, expressed in kbps. Not available in CQP mode.
3702    *
3703    * * **CBR**: This applies equally to the minimum, maximum and target bitrate.
3704    * * **VBR**: This applies to the target bitrate. The driver will use the
3705    *   "target-percentage" together to calculate the minimum and maximum
3706    *   bitrate.
3707    * * **VCM**: This applies to the target bitrate. The minimum and maximum
3708    *   bitrate are not needed.
3709    */
3710   properties[PROP_BITRATE] = g_param_spec_uint ("bitrate", "Bitrate (kbps)",
3711       "The desired bitrate expressed in kbps (0: auto-calculate)",
3712       0, 2000 * 1024, 0, param_flags | GST_PARAM_MUTABLE_PLAYING);
3713
3714   /**
3715    * GstVaH264Enc:target-percentage:
3716    *
3717    * The target percentage of the max bitrate, and expressed in uint, equal to
3718    * "target percentage" * 100. Available only when rate-control is VBR.
3719    *
3720    * "target percentage" = "target bitrate" * 100 /  "max bitrate"
3721    *
3722    * The driver uses it to calculate the minimum and maximum bitrate.
3723    */
3724   properties[PROP_TARGET_PERCENTAGE] = g_param_spec_uint ("target-percentage",
3725       "target bitrate percentage",
3726       "The percentage for 'target bitrate'/'maximum bitrate' (Only in VBR)",
3727       50, 100, 66, param_flags | GST_PARAM_MUTABLE_PLAYING);
3728
3729   /**
3730    * GstVaH264Enc:target-usage:
3731    *
3732    * The target usage of the encoder.
3733    *
3734    * It controls and balances the encoding speed and the encoding quality. The
3735    * lower value has better quality but slower speed, the higher value has
3736    * faster speed but lower quality.
3737    */
3738   properties[PROP_TARGET_USAGE] = g_param_spec_uint ("target-usage",
3739       "target usage",
3740       "The target usage to control and balance the encoding speed/quality",
3741       1, 7, 4, param_flags | GST_PARAM_MUTABLE_PLAYING);
3742
3743   /**
3744    * GstVaH264Enc:cpb-size:
3745    *
3746    * The desired max CPB size in Kb (0: auto-calculate).
3747    */
3748   properties[PROP_CPB_SIZE] = g_param_spec_uint ("cpb-size",
3749       "max CPB size in Kb",
3750       "The desired max CPB size in Kb (0: auto-calculate)", 0, 2000 * 1024, 0,
3751       param_flags | GST_PARAM_MUTABLE_PLAYING);
3752
3753   if (vah264enc_class->rate_control_type > 0) {
3754     properties[PROP_RATE_CONTROL] = g_param_spec_enum ("rate-control",
3755         "rate control mode", "The desired rate control mode for the encoder",
3756         vah264enc_class->rate_control_type,
3757         vah264enc_class->rate_control[0].value,
3758         GST_PARAM_CONDITIONALLY_AVAILABLE | GST_PARAM_MUTABLE_PLAYING
3759         | param_flags);
3760   } else {
3761     n_props--;
3762     properties[PROP_RATE_CONTROL] = NULL;
3763   }
3764
3765   g_object_class_install_properties (object_class, n_props, properties);
3766 }
3767
3768 static GstCaps *
3769 _complete_src_caps (GstCaps * srccaps)
3770 {
3771   GstCaps *caps = gst_caps_copy (srccaps);
3772
3773   gst_caps_set_simple (caps, "alignment", G_TYPE_STRING, "au", "stream-format",
3774       G_TYPE_STRING, "byte-stream", NULL);
3775
3776   return caps;
3777 }
3778
3779 /* bug in mesa gallium which adds P010_10LE. Admit only 420 chroma formats */
3780 static GstCaps *
3781 _fix_sink_caps (GstVaDisplay * display, GstCaps * sinkcaps)
3782 {
3783   GstCaps *caps;
3784   guint i, j;
3785
3786   if (!GST_VA_DISPLAY_IS_IMPLEMENTATION (display, MESA_GALLIUM))
3787     return gst_caps_ref (sinkcaps);
3788
3789   caps = gst_caps_copy (sinkcaps);
3790   for (i = 0; i < gst_caps_get_size (caps); i++) {
3791     GstStructure *st = gst_caps_get_structure (caps, i);
3792     const GValue *formats = gst_structure_get_value (st, "format");
3793     GArray *fmts;
3794     guint num;
3795
3796     /* let's accept it as is */
3797     if (G_VALUE_HOLDS_STRING (formats))
3798       continue;
3799
3800     g_assert (GST_VALUE_HOLDS_LIST (formats));
3801
3802     num = gst_value_list_get_size (formats);
3803     fmts = g_array_sized_new (FALSE, FALSE, sizeof (GstVideoFormat), num);
3804     for (j = 0; j < num; j++) {
3805       const gchar *format =
3806           g_value_get_string (gst_value_list_get_value (formats, j));
3807       GstVideoFormat f = gst_video_format_from_string (format);
3808       if (f != GST_VIDEO_FORMAT_UNKNOWN
3809           && gst_va_chroma_from_video_format (f) == VA_RT_FORMAT_YUV420)
3810         g_array_append_val (fmts, f);
3811     }
3812
3813     if (fmts->len == 0) {
3814       GST_ERROR ("No valid formats in sink caps template.");
3815       g_array_unref (fmts);
3816       return caps;
3817     }
3818
3819     if (fmts->len == 1) {
3820       GValue v = G_VALUE_INIT;
3821
3822       /* let's accept it as is */
3823       g_value_init (&v, G_TYPE_STRING);
3824       g_value_set_string (&v,
3825           gst_video_format_to_string (g_array_index (fmts, GstVideoFormat, 0)));
3826       gst_structure_set_value (st, "format", &v);
3827       g_value_unset (&v);
3828     } else {
3829       GValue val = G_VALUE_INIT;
3830       gst_value_array_init (&val, fmts->len);
3831
3832       for (j = 0; j < fmts->len; j++) {
3833         GValue v = G_VALUE_INIT;
3834
3835         g_value_init (&v, G_TYPE_STRING);
3836         g_value_set_string (&v,
3837             gst_video_format_to_string (g_array_index (fmts, GstVideoFormat,
3838                     j)));
3839         gst_value_array_append_value (&val, &v);
3840         g_value_unset (&v);
3841       }
3842
3843       gst_structure_set_value (st, "format", &val);
3844       g_value_unset (&val);
3845     }
3846
3847     g_array_unref (fmts);
3848   }
3849
3850   return caps;
3851 }
3852
3853 gboolean
3854 gst_va_h264_enc_register (GstPlugin * plugin, GstVaDevice * device,
3855     GstCaps * sink_caps, GstCaps * src_caps, guint rank,
3856     VAEntrypoint entrypoint)
3857 {
3858   static GOnce debug_once = G_ONCE_INIT;
3859   GType type;
3860   GTypeInfo type_info = {
3861     .class_size = sizeof (GstVaH264EncClass),
3862     .class_init = gst_va_h264_enc_class_init,
3863     .instance_size = sizeof (GstVaH264Enc),
3864     .instance_init = gst_va_h264_enc_init,
3865   };
3866   struct CData *cdata;
3867   gboolean ret;
3868   gchar *type_name, *feature_name;
3869
3870   g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE);
3871   g_return_val_if_fail (GST_IS_VA_DEVICE (device), FALSE);
3872   g_return_val_if_fail (GST_IS_CAPS (sink_caps), FALSE);
3873   g_return_val_if_fail (GST_IS_CAPS (src_caps), FALSE);
3874   g_return_val_if_fail (entrypoint == VAEntrypointEncSlice ||
3875       entrypoint == VAEntrypointEncSliceLP, FALSE);
3876
3877   cdata = g_new (struct CData, 1);
3878   cdata->entrypoint = entrypoint;
3879   cdata->description = NULL;
3880   cdata->render_device_path = g_strdup (device->render_device_path);
3881   cdata->sink_caps = _fix_sink_caps (device->display, sink_caps);
3882   cdata->src_caps = _complete_src_caps (src_caps);
3883
3884   /* class data will be leaked if the element never gets instantiated */
3885   GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
3886       GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
3887   GST_MINI_OBJECT_FLAG_SET (cdata->src_caps,
3888       GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
3889
3890   type_info.class_data = cdata;
3891   if (entrypoint == VAEntrypointEncSlice) {
3892     type_name = g_strdup ("GstVaH264Enc");
3893     feature_name = g_strdup ("vah264enc");
3894   } else {
3895     type_name = g_strdup ("GstVaH264LPEnc");
3896     feature_name = g_strdup ("vah264lpenc");
3897   }
3898
3899   /* The first encoder to be registered should use a constant name,
3900    * like vah264enc, for any additional encoders, we create unique
3901    * names, using inserting the render device name. */
3902   if (g_type_from_name (type_name)) {
3903     gchar *basename = g_path_get_basename (device->render_device_path);
3904     g_free (type_name);
3905     g_free (feature_name);
3906     if (entrypoint == VAEntrypointEncSlice) {
3907       type_name = g_strdup_printf ("GstVa%sH264Enc", basename);
3908       feature_name = g_strdup_printf ("va%sh264enc", basename);
3909     } else {
3910       type_name = g_strdup_printf ("GstVa%sH264LPEnc", basename);
3911       feature_name = g_strdup_printf ("va%sh264lpenc", basename);
3912     }
3913     cdata->description = basename;
3914     /* lower rank for non-first device */
3915     if (rank > 0)
3916       rank--;
3917   }
3918
3919   g_once (&debug_once, _register_debug_category, NULL);
3920   type = g_type_register_static (GST_TYPE_VA_BASE_ENC,
3921       type_name, &type_info, 0);
3922   ret = gst_element_register (plugin, feature_name, rank, type);
3923
3924   g_free (type_name);
3925   g_free (feature_name);
3926
3927   return ret;
3928 }