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