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