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