2 * Copyright (C) 2021 Intel Corporation
3 * Author: He Junyan <junyan.he@intel.com>
4 * Author: Víctor Jáquez <vjaquez@igalia.com>
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.
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.
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.
23 * SECTION:element-vah264enc
25 * @short_description: A VA-API based H264 video encoder
27 * vah264enc encodes raw video VA surfaces into H.264 bitstreams using
28 * the installed and chosen [VA-API](https://01.org/linuxmedia/vaapi)
31 * The raw video frames in main memory can be imported into VA surfaces.
33 * ## Example launch line
35 * gst-launch-1.0 videotestsrc num-buffers=60 ! timeoverlay ! vah264enc ! h264parse ! mp4mux ! filesink location=test.mp4
43 * 1. Look ahead, which can optimize the slice type and QP.
45 * 3. The stereo encoding such as the frame-packing or MVC.
46 * 4. Weight prediction of B frame.
47 * 5. latency calculation.
54 #include "gstvah264enc.h"
56 #include <gst/codecparsers/gsth264bitwriter.h>
57 #include <gst/va/gstva.h>
58 #include <gst/va/gstvavideoformat.h>
59 #include <gst/va/vasurfaceimage.h>
60 #include <gst/video/video.h>
61 #include <va/va_drmcommon.h>
63 #include "gstvabaseenc.h"
64 #include "gstvacaps.h"
65 #include "gstvadisplay_priv.h"
66 #include "gstvaencoder.h"
67 #include "gstvaprofile.h"
70 GST_DEBUG_CATEGORY_STATIC (gst_va_h264enc_debug);
71 #define GST_CAT_DEFAULT gst_va_h264enc_debug
73 #define GST_VA_H264_ENC(obj) ((GstVaH264Enc *) obj)
74 #define GST_VA_H264_ENC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_FROM_INSTANCE (obj), GstVaH264EncClass))
75 #define GST_VA_H264_ENC_CLASS(klass) ((GstVaH264EncClass *) klass)
77 typedef struct _GstVaH264Enc GstVaH264Enc;
78 typedef struct _GstVaH264EncClass GstVaH264EncClass;
79 typedef struct _GstVaH264EncFrame GstVaH264EncFrame;
80 typedef struct _GstVaH264LevelLimits GstVaH264LevelLimits;
100 PROP_TARGET_PERCENTAGE,
109 static GParamSpec *properties[N_PROPERTIES];
111 static GstElementClass *parent_class = NULL;
113 /* Scale factor for bitrate (HRD bit_rate_scale: min = 6) */
115 /* Scale factor for CPB size (HRD cpb_size_scale: min = 4) */
116 #define SX_CPB_SIZE 4
117 /* Maximum sizes for common headers (in bits) */
118 #define MAX_SPS_HDR_SIZE 16473
119 #define MAX_VUI_PARAMS_SIZE 210
120 #define MAX_HRD_PARAMS_SIZE 4103
121 #define MAX_PPS_HDR_SIZE 101
122 #define MAX_SLICE_HDR_SIZE 397 + 2572 + 6670 + 2402
124 #define MAX_GOP_SIZE 1024
127 struct _GstVaH264EncClass
129 GstVaBaseEncClass parent_class;
131 GType rate_control_type;
132 char rate_control_type_name[64];
133 GEnumValue rate_control[16];
150 guint32 num_ref_frames;
161 gboolean use_trellis;
167 guint32 target_percentage;
168 guint32 target_usage;
175 const gchar *level_str;
176 /* Minimum Compression Ratio (A.3.1) */
180 gboolean use_trellis;
184 guint32 packed_headers;
188 /* frames between two IDR [idr, ...., idr) */
190 /* How may IDRs we have encoded */
191 guint32 total_idr_count;
192 /* frames between I/P and P frames [I, B, B, .., B, P) */
194 /* frames between I frames [I, B, B, .., B, P, ..., I), open GOP */
196 /* B frames between I/P and P. */
198 /* Use B pyramid structure in the GOP. */
200 /* Level 0 is the simple B not acting as ref. */
201 guint32 highest_pyramid_level;
202 /* If open GOP, I frames within a GOP. */
204 /* A map of all frames types within a GOP. */
209 guint8 pyramid_level;
210 /* Only for b pyramid */
211 gint left_ref_poc_diff;
212 gint right_ref_poc_diff;
213 } frame_types[MAX_GOP_SIZE];
214 /* current index in the frames types map. */
215 guint cur_frame_index;
216 /* Number of ref frames within current GOP. H264's frame num. */
218 /* Max frame num within a GOP. */
219 guint32 max_frame_num;
220 guint32 log2_max_frame_num;
221 /* Max poc within a GOP. */
222 guint32 max_pic_order_cnt;
223 guint32 log2_max_pic_order_cnt;
225 /* Total ref frames of list0 and list1. */
226 guint32 num_ref_frames;
227 guint32 ref_num_list0;
228 guint32 ref_num_list1;
230 guint num_reorder_frames;
236 guint32 rc_ctrl_mode;
243 /* macroblock bitrate control */
245 guint target_bitrate;
246 guint target_percentage;
249 guint max_bitrate_bits;
250 guint target_bitrate_bits;
251 /* length of CPB buffer */
253 /* length of CPB buffer (bits) */
254 guint cpb_length_bits;
257 GstH264SPS sequence_hdr;
260 struct _GstVaH264EncFrame
262 GstVaEncodePicture *picture;
263 GstH264SliceType type;
266 /* Only for b pyramid */
267 gint left_ref_poc_diff;
268 gint right_ref_poc_diff;
272 /* The pic_num will be marked as unused_for_reference, which is
273 * replaced by this frame. -1 if we do not need to care about it
275 gint unused_for_reference_pic_num;
277 /* The total frame count we handled. */
278 guint total_frame_count;
284 * GstVaH264LevelLimits:
285 * @name: the level name
286 * @level_idc: the H.264 level_idc value
287 * @MaxMBPS: the maximum macroblock processing rate (MB/sec)
288 * @MaxFS: the maximum frame size (MBs)
289 * @MaxDpbMbs: the maxium decoded picture buffer size (MBs)
290 * @MaxBR: the maximum video bit rate (kbps)
291 * @MaxCPB: the maximum CPB size (kbits)
292 * @MinCR: the minimum Compression Ratio
294 * The data structure that describes the limits of an H.264 level.
296 struct _GstVaH264LevelLimits
308 /* Table A-1 - Level limits */
310 static const GstVaH264LevelLimits _va_h264_level_limits[] = {
311 /* level idc MaxMBPS MaxFS MaxDpbMbs MaxBR MaxCPB MinCr */
312 { "1", 10, 1485, 99, 396, 64, 175, 2 },
313 { "1b", 11, 1485, 99, 396, 128, 350, 2 },
314 { "1.1", 11, 3000, 396, 900, 192, 500, 2 },
315 { "1.2", 12, 6000, 396, 2376, 384, 1000, 2 },
316 { "1.3", 13, 11880, 396, 2376, 768, 2000, 2 },
317 { "2", 20, 11880, 396, 2376, 2000, 2000, 2 },
318 { "2.1", 21, 19800, 792, 4752, 4000, 4000, 2 },
319 { "2.2", 22, 20250, 1620, 8100, 4000, 4000, 2 },
320 { "3", 30, 40500, 1620, 8100, 10000, 10000, 2 },
321 { "3.1", 31, 108000, 3600, 18000, 14000, 14000, 4 },
322 { "3.2", 32, 216000, 5120, 20480, 20000, 20000, 4 },
323 { "4", 40, 245760, 8192, 32768, 20000, 25000, 4 },
324 { "4.1", 41, 245760, 8192, 32768, 50000, 62500, 2 },
325 { "4.2", 42, 522240, 8704, 34816, 50000, 62500, 2 },
326 { "5", 50, 589824, 22080, 110400, 135000, 135000, 2 },
327 { "5.1", 51, 983040, 36864, 184320, 240000, 240000, 2 },
328 { "5.2", 52, 2073600, 36864, 184320, 240000, 240000, 2 },
329 { "6", 60, 4177920, 139264, 696320, 240000, 240000, 2 },
330 { "6.1", 61, 8355840, 139264, 696320, 480000, 480000, 2 },
331 { "6.2", 62, 16711680, 139264, 696320, 800000, 800000, 2 },
335 #ifndef GST_DISABLE_GST_DEBUG
337 _slice_type_name (GstH264SliceType type)
340 case GST_H264_P_SLICE:
342 case GST_H264_B_SLICE:
344 case GST_H264_I_SLICE:
347 g_assert_not_reached ();
354 _rate_control_get_name (guint32 rc_mode)
356 GParamSpecEnum *spec;
359 if (!(properties[PROP_RATE_CONTROL]
360 && G_IS_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])))
363 spec = G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL]);
364 for (i = 0; i < spec->enum_class->n_values; i++) {
365 if (spec->enum_class->values[i].value == rc_mode)
366 return spec->enum_class->values[i].value_nick;
373 static GstVaH264EncFrame *
374 gst_va_enc_frame_new (void)
376 GstVaH264EncFrame *frame;
378 frame = g_slice_new (GstVaH264EncFrame);
379 frame->frame_num = 0;
380 frame->unused_for_reference_pic_num = -1;
381 frame->picture = NULL;
382 frame->total_frame_count = 0;
383 frame->last_frame = FALSE;
389 gst_va_enc_frame_free (gpointer pframe)
391 GstVaH264EncFrame *frame = pframe;
392 g_clear_pointer (&frame->picture, gst_va_encode_picture_free);
393 g_slice_free (GstVaH264EncFrame, frame);
396 static inline GstVaH264EncFrame *
397 _enc_frame (GstVideoCodecFrame * frame)
399 GstVaH264EncFrame *enc_frame = gst_video_codec_frame_get_user_data (frame);
400 g_assert (enc_frame);
404 /* Normalizes bitrate (and CPB size) for HRD conformance */
406 _calculate_bitrate_hrd (GstVaH264Enc * self)
408 guint bitrate_bits, cpb_bits_size;
410 /* Round down bitrate. This is a hard limit mandated by the user */
411 g_assert (SX_BITRATE >= 6);
412 bitrate_bits = (self->rc.max_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
413 GST_DEBUG_OBJECT (self, "Max bitrate: %u bits/sec", bitrate_bits);
414 self->rc.max_bitrate_bits = bitrate_bits;
416 bitrate_bits = (self->rc.target_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
417 GST_DEBUG_OBJECT (self, "Target bitrate: %u bits/sec", bitrate_bits);
418 self->rc.target_bitrate_bits = bitrate_bits;
420 if (self->rc.cpb_size > 0 && self->rc.cpb_size < (self->rc.max_bitrate / 2)) {
421 GST_INFO_OBJECT (self, "Too small cpb_size: %d", self->rc.cpb_size);
422 self->rc.cpb_size = 0;
425 if (self->rc.cpb_size == 0) {
426 /* We cache 2 second coded data by default. */
427 self->rc.cpb_size = self->rc.max_bitrate * 2;
428 GST_INFO_OBJECT (self, "Adjust cpb_size to: %d", self->rc.cpb_size);
431 /* Round up CPB size. This is an HRD compliance detail */
432 g_assert (SX_CPB_SIZE >= 4);
433 cpb_bits_size = (self->rc.cpb_size * 1000) & ~((1U << SX_CPB_SIZE) - 1);
435 GST_DEBUG_OBJECT (self, "HRD CPB size: %u bits", cpb_bits_size);
436 self->rc.cpb_length_bits = cpb_bits_size;
439 #define update_property(type, obj, old_val, new_val, prop_id) \
440 gst_va_base_enc_update_property_##type (obj, old_val, new_val, properties[prop_id])
441 #define update_property_uint(obj, old_val, new_val, prop_id) \
442 update_property (uint, obj, old_val, new_val, prop_id)
443 #define update_property_bool(obj, old_val, new_val, prop_id) \
444 update_property (bool, obj, old_val, new_val, prop_id)
446 /* Estimates a good enough bitrate if none was supplied */
448 _ensure_rate_control (GstVaH264Enc * self)
450 /* User can specify the properties of: "bitrate", "target-percentage",
451 * "max-qp", "min-qp", "qpi", "qpp", "qpb", "mbbrc", "cpb-size",
452 * "rate-control" and "target-usage" to control the RC behavior.
454 * "target-usage" is different from the others, it controls the encoding
455 * speed and quality, while the others control encoding bit rate and
456 * quality. The lower value has better quality(maybe bigger MV search
457 * range) but slower speed, the higher value has faster speed but lower
460 * The possible composition to control the bit rate and quality:
462 * 1. CQP mode: "rate-control=cqp", then "qpi", "qpp" and "qpb"
463 * specify the QP of I/P/B frames respectively(within the
464 * "max-qp" and "min-qp" range). The QP will not change during
465 * the whole stream. Other properties are ignored.
467 * 2. CBR mode: "rate-control=CBR", then the "bitrate" specify the
468 * target bit rate and the "cpb-size" specifies the max coded
469 * picture buffer size to avoid overflow. If the "bitrate" is not
470 * set, it is calculated by the picture resolution and frame
471 * rate. If "cpb-size" is not set, it is set to the size of
472 * caching 2 second coded data. Encoder will try its best to make
473 * the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
474 * enable bit rate control in macro block level. Other paramters
477 * 3. VBR mode: "rate-control=VBR", then the "bitrate" specify the
478 * target bit rate, "target-percentage" is used to calculate the
479 * max bit rate of VBR mode by ("bitrate" * 100) /
480 * "target-percentage". It is also used by driver to calculate
481 * the min bit rate. The "cpb-size" specifies the max coded
482 * picture buffer size to avoid overflow. If the "bitrate" is not
483 * set, the target bit rate will be calculated by the picture
484 * resolution and frame rate. Encoder will try its best to make
485 * the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
486 * enable bit rate control in macro block level. Other paramters
489 * 4. VCM mode: "rate-control=VCM", then the "bitrate" specify the
490 * target bit rate, and encoder will try its best to make the QP
491 * with in the ["max-qp", "min-qp"] range. Other paramters are
495 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
497 guint32 rc_ctrl, rc_mode, quality_level;
499 quality_level = gst_va_encoder_get_quality_level (base->encoder,
500 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
501 if (self->rc.target_usage > quality_level) {
502 GST_INFO_OBJECT (self, "User setting target-usage: %d is not supported, "
503 "fallback to %d", self->rc.target_usage, quality_level);
504 self->rc.target_usage = quality_level;
506 update_property_uint (base, &self->prop.target_usage, self->rc.target_usage,
510 GST_OBJECT_LOCK (self);
511 rc_ctrl = self->prop.rc_ctrl;
512 GST_OBJECT_UNLOCK (self);
514 if (rc_ctrl != VA_RC_NONE) {
515 rc_mode = gst_va_encoder_get_rate_control_mode (base->encoder,
516 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
517 if (!(rc_mode & rc_ctrl)) {
519 G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])->default_value;
520 GST_INFO_OBJECT (self, "The rate control mode %s is not supported, "
521 "fallback to %s mode", _rate_control_get_name (rc_ctrl),
522 _rate_control_get_name (defval));
523 self->rc.rc_ctrl_mode = defval;
525 update_property_uint (base, &self->prop.rc_ctrl, self->rc.rc_ctrl_mode,
529 self->rc.rc_ctrl_mode = VA_RC_NONE;
532 if (self->rc.min_qp > self->rc.max_qp) {
533 GST_INFO_OBJECT (self, "The min_qp %d is bigger than the max_qp %d, "
534 "set it to the max_qp", self->rc.min_qp, self->rc.max_qp);
535 self->rc.min_qp = self->rc.max_qp;
537 update_property_uint (base, &self->prop.min_qp, self->rc.min_qp,
541 /* Make all the qp in the valid range */
542 if (self->rc.qp_i < self->rc.min_qp) {
543 if (self->rc.qp_i != 26)
544 GST_INFO_OBJECT (self, "The qp_i %d is smaller than the min_qp %d, "
545 "set it to the min_qp", self->rc.qp_i, self->rc.min_qp);
546 self->rc.qp_i = self->rc.min_qp;
548 if (self->rc.qp_i > self->rc.max_qp) {
549 if (self->rc.qp_i != 26)
550 GST_INFO_OBJECT (self, "The qp_i %d is bigger than the max_qp %d, "
551 "set it to the max_qp", self->rc.qp_i, self->rc.max_qp);
552 self->rc.qp_i = self->rc.max_qp;
555 if (self->rc.qp_p < self->rc.min_qp) {
556 if (self->rc.qp_p != 26)
557 GST_INFO_OBJECT (self, "The qp_p %d is smaller than the min_qp %d, "
558 "set it to the min_qp", self->rc.qp_p, self->rc.min_qp);
559 self->rc.qp_p = self->rc.min_qp;
561 if (self->rc.qp_p > self->rc.max_qp) {
562 if (self->rc.qp_p != 26)
563 GST_INFO_OBJECT (self, "The qp_p %d is bigger than the max_qp %d, "
564 "set it to the max_qp", self->rc.qp_p, self->rc.max_qp);
565 self->rc.qp_p = self->rc.max_qp;
568 if (self->rc.qp_b < self->rc.min_qp) {
569 if (self->rc.qp_b != 26)
570 GST_INFO_OBJECT (self, "The qp_b %d is smaller than the min_qp %d, "
571 "set it to the min_qp", self->rc.qp_b, self->rc.min_qp);
572 self->rc.qp_b = self->rc.min_qp;
574 if (self->rc.qp_b > self->rc.max_qp) {
575 if (self->rc.qp_b != 26)
576 GST_INFO_OBJECT (self, "The qp_b %d is bigger than the max_qp %d, "
577 "set it to the max_qp", self->rc.qp_b, self->rc.max_qp);
578 self->rc.qp_b = self->rc.max_qp;
581 GST_OBJECT_LOCK (self);
582 bitrate = self->prop.bitrate;
583 GST_OBJECT_UNLOCK (self);
585 /* Calculate a bitrate is not set. */
586 if ((self->rc.rc_ctrl_mode == VA_RC_CBR || self->rc.rc_ctrl_mode == VA_RC_VBR
587 || self->rc.rc_ctrl_mode == VA_RC_VCM) && bitrate == 0) {
588 /* Default compression: 48 bits per macroblock in "high-compression" mode */
589 guint bits_per_mb = 48;
592 /* According to the literature and testing, CABAC entropy coding
593 * mode could provide for +10% to +18% improvement in general,
594 * thus estimating +15% here ; and using adaptive 8x8 transforms
595 * in I-frames could bring up to +10% improvement. */
596 if (!self->use_cabac)
597 bits_per_mb += (bits_per_mb * 15) / 100;
598 if (!self->use_dct8x8)
599 bits_per_mb += (bits_per_mb * 10) / 100;
601 factor = (guint64) self->mb_width * self->mb_height * bits_per_mb;
602 bitrate = gst_util_uint64_scale (factor,
603 GST_VIDEO_INFO_FPS_N (&base->input_state->info),
604 GST_VIDEO_INFO_FPS_D (&base->input_state->info)) / 1000;
605 GST_INFO_OBJECT (self, "target bitrate computed to %u kbps", bitrate);
608 /* Adjust the setting based on RC mode. */
609 switch (self->rc.rc_ctrl_mode) {
612 self->rc.max_bitrate = 0;
613 self->rc.target_bitrate = 0;
614 self->rc.target_percentage = 0;
615 self->rc.cpb_size = 0;
618 self->rc.max_bitrate = bitrate;
619 self->rc.target_bitrate = bitrate;
620 self->rc.target_percentage = 100;
621 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
624 g_assert (self->rc.target_percentage >= 10);
625 self->rc.max_bitrate = (guint) gst_util_uint64_scale_int (bitrate,
626 100, self->rc.target_percentage);
627 self->rc.target_bitrate = bitrate;
628 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
631 self->rc.max_bitrate = bitrate;
632 self->rc.target_bitrate = bitrate;
633 self->rc.target_percentage = 0;
634 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
635 self->rc.cpb_size = 0;
637 if (self->gop.num_bframes > 0) {
638 GST_INFO_OBJECT (self, "VCM mode just support I/P mode, no B frame");
639 self->gop.num_bframes = 0;
640 self->gop.b_pyramid = FALSE;
644 GST_WARNING_OBJECT (self, "Unsupported rate control");
649 GST_DEBUG_OBJECT (self, "Max bitrate: %u bits/sec, "
650 "Target bitrate: %u bits/sec", self->rc.max_bitrate,
651 self->rc.target_bitrate);
653 if (self->rc.rc_ctrl_mode != VA_RC_NONE && self->rc.rc_ctrl_mode != VA_RC_CQP)
654 _calculate_bitrate_hrd (self);
656 /* update & notifications */
657 update_property_uint (base, &self->prop.bitrate, bitrate, PROP_BITRATE);
658 update_property_uint (base, &self->prop.cpb_size, self->rc.cpb_size,
660 update_property_uint (base, &self->prop.target_percentage,
661 self->rc.target_percentage, PROP_TARGET_PERCENTAGE);
662 update_property_uint (base, &self->prop.qp_i, self->rc.qp_i, PROP_QP_I);
663 update_property_uint (base, &self->prop.qp_p, self->rc.qp_p, PROP_QP_P);
664 update_property_uint (base, &self->prop.qp_b, self->rc.qp_b, PROP_QP_B);
670 _get_h264_cpb_nal_factor (VAProfile profile)
676 case VAProfileH264High:
679 case VAProfileH264ConstrainedBaseline:
680 case VAProfileH264Main:
683 case VAProfileH264MultiviewHigh:
684 case VAProfileH264StereoHigh:
685 f = 1500; /* H.10.2.1 (r) */
688 g_assert_not_reached ();
695 /* Derives the level from the currently set limits */
697 _calculate_level (GstVaH264Enc * self)
699 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
700 const guint cpb_factor = _get_h264_cpb_nal_factor (base->profile);
701 guint i, PicSizeMbs, MaxDpbMbs, MaxMBPS;
703 PicSizeMbs = self->mb_width * self->mb_height;
704 MaxDpbMbs = PicSizeMbs * (self->gop.num_ref_frames + 1);
705 MaxMBPS = gst_util_uint64_scale_int_ceil (PicSizeMbs,
706 GST_VIDEO_INFO_FPS_N (&base->input_state->info),
707 GST_VIDEO_INFO_FPS_D (&base->input_state->info));
709 for (i = 0; i < G_N_ELEMENTS (_va_h264_level_limits); i++) {
710 const GstVaH264LevelLimits *const limits = &_va_h264_level_limits[i];
711 if (PicSizeMbs <= limits->MaxFS && MaxDpbMbs <= limits->MaxDpbMbs
712 && MaxMBPS <= limits->MaxMBPS && (!self->rc.max_bitrate_bits
713 || self->rc.max_bitrate_bits <= (limits->MaxBR * 1000 * cpb_factor))
714 && (!self->rc.cpb_length_bits
715 || self->rc.cpb_length_bits <=
716 (limits->MaxCPB * 1000 * cpb_factor))) {
718 self->level_idc = _va_h264_level_limits[i].level_idc;
719 self->level_str = _va_h264_level_limits[i].name;
720 self->min_cr = _va_h264_level_limits[i].MinCR;
726 GST_ERROR_OBJECT (self,
727 "failed to find a suitable level matching codec config");
732 _validate_parameters (GstVaH264Enc * self)
734 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
737 /* Ensure the num_slices provided by the user not exceed the limit
738 * of the number of slices permitted by the stream and by the
740 g_assert (self->num_slices >= 1);
741 max_slices = gst_va_encoder_get_max_slice_num (base->encoder,
742 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
743 if (self->num_slices > max_slices)
744 self->num_slices = max_slices;
745 /* The stream size limit. */
746 if (self->num_slices > ((self->mb_width * self->mb_height + 1) / 2))
747 self->num_slices = ((self->mb_width * self->mb_height + 1) / 2);
749 update_property_uint (base, &self->prop.num_slices,
750 self->num_slices, PROP_NUM_SLICES);
752 /* Ensure trellis. */
753 if (self->use_trellis &&
754 !gst_va_encoder_has_trellis (base->encoder, base->profile,
755 GST_VA_BASE_ENC_ENTRYPOINT (base))) {
756 GST_INFO_OBJECT (self, "The trellis is not supported");
757 self->use_trellis = FALSE;
760 update_property_bool (base, &self->prop.use_trellis, self->use_trellis,
764 /* Get log2_max_frame_num_minus4, log2_max_pic_order_cnt_lsb_minus4
765 * value, shall be in the range of 0 to 12, inclusive. */
767 _get_log2_max_num (guint num)
776 /* shall be in the range of 0+4 to 12+4, inclusive. */
779 } else if (ret > 16) {
786 _print_gop_structure (GstVaH264Enc * self)
788 #ifndef GST_DISABLE_GST_DEBUG
792 if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) < GST_LEVEL_INFO)
795 str = g_string_new (NULL);
797 g_string_append_printf (str, "[ ");
799 for (i = 0; i < self->gop.idr_period; i++) {
801 g_string_append_printf (str, "IDR");
804 g_string_append_printf (str, ", ");
807 g_string_append_printf (str, "%s",
808 _slice_type_name (self->gop.frame_types[i].slice_type));
810 if (self->gop.b_pyramid
811 && self->gop.frame_types[i].slice_type == GST_H264_B_SLICE) {
812 g_string_append_printf (str, "<L%d (%d, %d)>",
813 self->gop.frame_types[i].pyramid_level,
814 self->gop.frame_types[i].left_ref_poc_diff,
815 self->gop.frame_types[i].right_ref_poc_diff);
818 if (self->gop.frame_types[i].is_ref) {
819 g_string_append_printf (str, "(ref)");
824 g_string_append_printf (str, " ]");
826 GST_INFO_OBJECT (self, "GOP size: %d, forward reference %d, backward"
827 " reference %d, GOP structure: %s", self->gop.idr_period,
828 self->gop.ref_num_list0, self->gop.ref_num_list1, str->str);
830 g_string_free (str, TRUE);
837 gint left_ref_poc_diff;
838 gint right_ref_poc_diff;
842 _set_pyramid_info (struct PyramidInfo *info, guint len,
843 guint current_level, guint highest_level)
849 if (current_level == highest_level || len == 1) {
850 for (index = 0; index < len; index++) {
851 info[index].level = current_level;
852 info[index].left_ref_poc_diff = (index + 1) * -2;
853 info[index].right_ref_poc_diff = (len - index) * 2;
860 info[index].level = current_level;
861 info[index].left_ref_poc_diff = (index + 1) * -2;
862 info[index].right_ref_poc_diff = (len - index) * 2;
867 _set_pyramid_info (info, index, current_level, highest_level);
870 _set_pyramid_info (&info[index + 1], len - (index + 1),
871 current_level, highest_level);
875 _create_gop_frame_types (GstVaH264Enc * self)
878 guint i_frames = self->gop.num_iframes;
879 struct PyramidInfo pyramid_info[31] = { 0, };
881 if (self->gop.highest_pyramid_level > 0) {
882 g_assert (self->gop.num_bframes > 0);
883 _set_pyramid_info (pyramid_info, self->gop.num_bframes,
884 0, self->gop.highest_pyramid_level);
887 g_assert (self->gop.idr_period <= MAX_GOP_SIZE);
888 for (i = 0; i < self->gop.idr_period; i++) {
890 self->gop.frame_types[i].slice_type = GST_H264_I_SLICE;
891 self->gop.frame_types[i].is_ref = TRUE;
895 /* Intra only stream. */
896 if (self->gop.ip_period == 0) {
897 self->gop.frame_types[i].slice_type = GST_H264_I_SLICE;
898 self->gop.frame_types[i].is_ref = FALSE;
902 if (i % self->gop.ip_period) {
903 guint pyramid_index =
904 i % self->gop.ip_period - 1 /* The first P or IDR */ ;
906 self->gop.frame_types[i].slice_type = GST_H264_B_SLICE;
907 self->gop.frame_types[i].pyramid_level =
908 pyramid_info[pyramid_index].level;
909 self->gop.frame_types[i].is_ref =
910 (self->gop.frame_types[i].pyramid_level <
911 self->gop.highest_pyramid_level);
912 self->gop.frame_types[i].left_ref_poc_diff =
913 pyramid_info[pyramid_index].left_ref_poc_diff;
914 self->gop.frame_types[i].right_ref_poc_diff =
915 pyramid_info[pyramid_index].right_ref_poc_diff;
919 if (self->gop.i_period && i % self->gop.i_period == 0 && i_frames > 0) {
920 /* Replace P with I. */
921 self->gop.frame_types[i].slice_type = GST_H264_I_SLICE;
922 self->gop.frame_types[i].is_ref = TRUE;
927 self->gop.frame_types[i].slice_type = GST_H264_P_SLICE;
928 self->gop.frame_types[i].is_ref = TRUE;
931 /* Force the last one to be a P */
932 if (self->gop.idr_period > 1 && self->gop.ip_period > 0) {
933 self->gop.frame_types[self->gop.idr_period - 1].slice_type =
935 self->gop.frame_types[self->gop.idr_period - 1].is_ref = TRUE;
939 /* Consider the idr_period, num_bframes, L0/L1 reference number.
940 * TODO: Load some preset fixed GOP structure.
941 * TODO: Skip this if in lookahead mode. */
943 _generate_gop_structure (GstVaH264Enc * self)
945 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
946 guint32 list0, list1, gop_ref_num;
949 /* If not set, generate a idr every second */
950 if (self->gop.idr_period == 0) {
951 self->gop.idr_period = (GST_VIDEO_INFO_FPS_N (&base->input_state->info)
952 + GST_VIDEO_INFO_FPS_D (&base->input_state->info) - 1) /
953 GST_VIDEO_INFO_FPS_D (&base->input_state->info);
956 /* Do not use a too huge GOP size. */
957 if (self->gop.idr_period > 1024) {
958 self->gop.idr_period = 1024;
959 GST_INFO_OBJECT (self, "Lowering the GOP size to %d", self->gop.idr_period);
962 update_property_uint (base, &self->prop.key_int_max, self->gop.idr_period,
965 /* Prefer have more than 1 refs for the GOP which is not very small. */
966 if (self->gop.idr_period > 8) {
967 if (self->gop.num_bframes > (self->gop.idr_period - 1) / 2) {
968 self->gop.num_bframes = (self->gop.idr_period - 1) / 2;
969 GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
970 self->gop.num_bframes);
973 /* beign and end should be ref */
974 if (self->gop.num_bframes > self->gop.idr_period - 1 - 1) {
975 if (self->gop.idr_period > 1) {
976 self->gop.num_bframes = self->gop.idr_period - 1 - 1;
978 self->gop.num_bframes = 0;
980 GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
981 self->gop.num_bframes);
985 if (!gst_va_encoder_get_max_num_reference (base->encoder, base->profile,
986 GST_VA_BASE_ENC_ENTRYPOINT (base), &list0, &list1)) {
987 GST_INFO_OBJECT (self, "Failed to get the max num reference");
992 if (list0 > self->gop.num_ref_frames)
993 list0 = self->gop.num_ref_frames;
994 if (list1 > self->gop.num_ref_frames)
995 list1 = self->gop.num_ref_frames;
998 GST_INFO_OBJECT (self,
999 "No reference support, fallback to intra only stream");
1001 /* It does not make sense that if only the list1 exists. */
1002 self->gop.num_ref_frames = 0;
1004 self->gop.ip_period = 0;
1005 self->gop.num_bframes = 0;
1006 self->gop.b_pyramid = FALSE;
1007 self->gop.highest_pyramid_level = 0;
1008 self->gop.num_iframes = self->gop.idr_period - 1 /* The idr */ ;
1009 self->gop.ref_num_list0 = 0;
1010 self->gop.ref_num_list1 = 0;
1014 if (self->gop.num_ref_frames <= 1) {
1015 GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
1016 " no B frame allowed, fallback to I/P mode", self->gop.num_ref_frames);
1017 self->gop.num_bframes = 0;
1021 /* b_pyramid needs at least 1 ref for B, besides the I/P */
1022 if (self->gop.b_pyramid && self->gop.num_ref_frames <= 2) {
1023 GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
1024 " not enough for b_pyramid", self->gop.num_ref_frames);
1025 self->gop.b_pyramid = FALSE;
1028 if (list1 == 0 && self->gop.num_bframes > 0) {
1029 GST_INFO_OBJECT (self,
1030 "No hw reference support for list 1, fallback to I/P mode");
1031 self->gop.num_bframes = 0;
1032 self->gop.b_pyramid = FALSE;
1035 /* I/P mode, no list1 needed. */
1036 if (self->gop.num_bframes == 0)
1039 /* Not enough B frame, no need for b_pyramid. */
1040 if (self->gop.num_bframes <= 1)
1041 self->gop.b_pyramid = FALSE;
1043 /* b pyramid has only one backward ref. */
1044 if (self->gop.b_pyramid)
1047 if (self->gop.num_ref_frames > list0 + list1) {
1048 self->gop.num_ref_frames = list0 + list1;
1049 GST_INFO_OBJECT (self, "HW limits, lowering the number of reference"
1050 " frames to %d", self->gop.num_ref_frames);
1053 /* How many possible refs within a GOP. */
1054 gop_ref_num = (self->gop.idr_period + self->gop.num_bframes) /
1055 (self->gop.num_bframes + 1);
1057 if (self->gop.num_bframes > 0
1058 /* frame_num % (self->gop.num_bframes + 1) happens to be the end P */
1059 && (self->gop.idr_period % (self->gop.num_bframes + 1) != 1))
1062 /* Adjust reference num based on B frames and B pyramid. */
1063 if (self->gop.num_bframes == 0) {
1064 self->gop.b_pyramid = FALSE;
1065 self->gop.ref_num_list0 = self->gop.num_ref_frames;
1066 self->gop.ref_num_list1 = 0;
1067 } else if (self->gop.b_pyramid) {
1068 guint b_frames = self->gop.num_bframes;
1071 /* b pyramid has only one backward ref. */
1072 g_assert (list1 == 1);
1073 self->gop.ref_num_list1 = list1;
1074 self->gop.ref_num_list0 =
1075 self->gop.num_ref_frames - self->gop.ref_num_list1;
1077 b_frames = b_frames / 2;
1080 /* At least 1 B ref for each level, plus begin and end 2 P/I */
1082 if (b_refs + 2 > self->gop.num_ref_frames)
1085 self->gop.highest_pyramid_level++;
1086 b_frames = b_frames / 2;
1089 GST_INFO_OBJECT (self, "pyramid level is %d",
1090 self->gop.highest_pyramid_level);
1092 /* We prefer list0. Backward refs have more latency. */
1093 self->gop.ref_num_list1 = 1;
1094 self->gop.ref_num_list0 =
1095 self->gop.num_ref_frames - self->gop.ref_num_list1;
1096 /* Balance the forward and backward refs, but not cause a big latency. */
1097 while ((self->gop.num_bframes * self->gop.ref_num_list1 <= 16)
1098 && (self->gop.ref_num_list1 <= gop_ref_num)
1099 && (self->gop.ref_num_list1 < list1)
1100 && (self->gop.ref_num_list0 / self->gop.ref_num_list1 > 4)) {
1101 self->gop.ref_num_list0--;
1102 self->gop.ref_num_list1++;
1105 if (self->gop.ref_num_list0 > list0)
1106 self->gop.ref_num_list0 = list0;
1109 /* It's OK, keep slots for GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME frame. */
1110 if (self->gop.ref_num_list0 > gop_ref_num)
1111 GST_DEBUG_OBJECT (self, "num_ref_frames %d is bigger than gop_ref_num %d",
1112 self->gop.ref_num_list0, gop_ref_num);
1114 /* Include the ref picture itself. */
1115 self->gop.ip_period = 1 + self->gop.num_bframes;
1117 p_frames = gop_ref_num - 1 /* IDR */ ;
1120 if (self->gop.num_iframes > p_frames) {
1121 self->gop.num_iframes = p_frames;
1122 GST_INFO_OBJECT (self, "Too many I frames insertion, lowering it to %d",
1123 self->gop.num_iframes);
1126 if (self->gop.num_iframes > 0) {
1127 guint total_i_frames = self->gop.num_iframes + 1 /* IDR */ ;
1128 self->gop.i_period =
1129 (gop_ref_num / total_i_frames) * (self->gop.num_bframes + 1);
1133 /* init max_frame_num, max_poc */
1134 self->gop.log2_max_frame_num = _get_log2_max_num (self->gop.idr_period);
1135 self->gop.max_frame_num = (1 << self->gop.log2_max_frame_num);
1136 self->gop.log2_max_pic_order_cnt = self->gop.log2_max_frame_num + 1;
1137 self->gop.max_pic_order_cnt = (1 << self->gop.log2_max_pic_order_cnt);
1138 self->gop.num_reorder_frames = self->gop.b_pyramid ?
1139 self->gop.highest_pyramid_level * 2 + 1 /* the last P frame. */ :
1140 self->gop.ref_num_list1;
1141 /* Should not exceed the max ref num. */
1142 self->gop.num_reorder_frames =
1143 MIN (self->gop.num_reorder_frames, self->gop.num_ref_frames);
1144 self->gop.num_reorder_frames = MIN (self->gop.num_reorder_frames, 16);
1146 _create_gop_frame_types (self);
1147 _print_gop_structure (self);
1149 /* updates & notifications */
1150 update_property_uint (base, &self->prop.num_ref_frames,
1151 self->gop.num_ref_frames, PROP_NUM_REF_FRAMES);
1152 update_property_uint (base, &self->prop.num_iframes, self->gop.num_iframes,
1157 _calculate_coded_size (GstVaH264Enc * self)
1159 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1160 guint codedbuf_size = 0;
1162 if (base->profile == VAProfileH264High
1163 || base->profile == VAProfileH264MultiviewHigh
1164 || base->profile == VAProfileH264StereoHigh) {
1165 /* The number of bits of macroblock_layer( ) data for any macroblock
1166 is not greater than 128 + RawMbBits */
1167 guint RawMbBits = 0;
1168 guint BitDepthY = 8;
1169 guint BitDepthC = 8;
1171 guint MbHeightC = 8;
1173 switch (base->rt_format) {
1174 case VA_RT_FORMAT_YUV420:
1180 case VA_RT_FORMAT_YUV422:
1186 case VA_RT_FORMAT_YUV444:
1192 case VA_RT_FORMAT_YUV400:
1198 case VA_RT_FORMAT_YUV420_10:
1203 case VA_RT_FORMAT_YUV422_10:
1208 case VA_RT_FORMAT_YUV444_10:
1215 g_assert_not_reached ();
1219 /* The variable RawMbBits is derived as
1220 * RawMbBits = 256 * BitDepthY + 2 * MbWidthC * MbHeightC * BitDepthC */
1221 RawMbBits = 256 * BitDepthY + 2 * MbWidthC * MbHeightC * BitDepthC;
1222 codedbuf_size = (self->mb_width * self->mb_height) * (128 + RawMbBits) / 8;
1224 /* The number of bits of macroblock_layer( ) data for any macroblock
1225 * is not greater than 3200 */
1226 codedbuf_size = (self->mb_width * self->mb_height) * (3200 / 8);
1229 /* Account for SPS header */
1230 /* XXX: exclude scaling lists, MVC/SVC extensions */
1231 codedbuf_size += 4 /* start code */ + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
1232 MAX_VUI_PARAMS_SIZE + 2 * MAX_HRD_PARAMS_SIZE) / 8;
1234 /* Account for PPS header */
1235 /* XXX: exclude slice groups, scaling lists, MVC/SVC extensions */
1236 codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
1238 /* Account for slice header */
1240 self->num_slices * (4 + GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8);
1242 /* Add 5% for safety */
1243 base->codedbuf_size = (guint) ((gfloat) codedbuf_size * 1.05);
1245 GST_DEBUG_OBJECT (self, "Calculate codedbuf size: %u", base->codedbuf_size);
1249 _get_rtformat (GstVaH264Enc * self, GstVideoFormat format)
1253 chroma = gst_va_chroma_from_video_format (format);
1255 /* Check whether the rtformat is supported. */
1256 if (chroma != VA_RT_FORMAT_YUV420) {
1257 GST_ERROR_OBJECT (self, "Unsupported chroma for video format: %s",
1258 gst_video_format_to_string (format));
1266 _init_packed_headers (GstVaH264Enc * self)
1268 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1269 guint32 packed_headers;
1270 guint32 desired_packed_headers = VA_ENC_PACKED_HEADER_SEQUENCE /* SPS */
1271 | VA_ENC_PACKED_HEADER_PICTURE /* PPS */
1272 | VA_ENC_PACKED_HEADER_SLICE /* Slice headers */
1273 | VA_ENC_PACKED_HEADER_RAW_DATA; /* SEI, AUD, etc. */
1275 self->packed_headers = 0;
1277 if (!gst_va_encoder_get_packed_headers (base->encoder, base->profile,
1278 GST_VA_BASE_ENC_ENTRYPOINT (base), &packed_headers))
1281 if (desired_packed_headers & ~packed_headers) {
1282 GST_INFO_OBJECT (self, "Driver does not support some wanted packed headers "
1283 "(wanted %#x, found %#x)", desired_packed_headers, packed_headers);
1286 self->packed_headers = desired_packed_headers & packed_headers;
1293 _decide_profile (GstVaH264Enc * self, VAProfile * _profile, guint * _rt_format)
1295 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1296 gboolean ret = FALSE;
1297 GstVideoFormat in_format;
1300 GstCaps *allowed_caps = NULL;
1301 guint num_structures, i;
1302 GstStructure *structure;
1303 const GValue *v_profile;
1304 GPtrArray *candidates = NULL;
1305 gchar *profile_name;
1307 candidates = g_ptr_array_new_with_free_func (g_free);
1309 /* First, check whether the downstream requires a specified profile. */
1310 allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (base));
1312 allowed_caps = gst_pad_query_caps (GST_VIDEO_ENCODER_SRC_PAD (base), NULL);
1314 if (allowed_caps && !gst_caps_is_empty (allowed_caps)) {
1315 num_structures = gst_caps_get_size (allowed_caps);
1316 for (i = 0; i < num_structures; i++) {
1317 structure = gst_caps_get_structure (allowed_caps, i);
1318 v_profile = gst_structure_get_value (structure, "profile");
1322 if (G_VALUE_HOLDS_STRING (v_profile)) {
1323 profile_name = g_strdup (g_value_get_string (v_profile));
1324 g_ptr_array_add (candidates, profile_name);
1325 } else if (GST_VALUE_HOLDS_LIST (v_profile)) {
1328 for (j = 0; j < gst_value_list_get_size (v_profile); j++) {
1329 const GValue *p = gst_value_list_get_value (v_profile, j);
1333 profile_name = g_strdup (g_value_get_string (p));
1334 g_ptr_array_add (candidates, profile_name);
1340 if (candidates->len == 0) {
1341 GST_ERROR_OBJECT (self, "No available profile in caps");
1346 in_format = GST_VIDEO_INFO_FORMAT (&base->input_state->info);
1347 rt_format = _get_rtformat (self, in_format);
1349 GST_ERROR_OBJECT (self, "unsupported video format %s",
1350 gst_video_format_to_string (in_format));
1355 /* Find the suitable profile by features and check the HW
1358 for (i = 0; i < candidates->len; i++) {
1359 profile_name = g_ptr_array_index (candidates, i);
1361 /* dct8x8 require at least high profile. */
1362 if (self->use_dct8x8) {
1363 if (!g_strstr_len (profile_name, -1, "high"))
1367 /* cabac require at least main profile. */
1368 if (self->use_cabac) {
1369 if (!g_strstr_len (profile_name, -1, "main")
1370 && !g_strstr_len (profile_name, -1, "high"))
1374 /* baseline only support I/P mode. */
1375 if (self->gop.num_bframes > 0) {
1376 if (g_strstr_len (profile_name, -1, "baseline"))
1380 profile = gst_va_profile_from_name (H264, profile_name);
1381 if (profile == VAProfileNone)
1384 if (!gst_va_encoder_has_profile (base->encoder, profile))
1387 if ((rt_format & gst_va_encoder_get_rtformat (base->encoder,
1388 profile, GST_VA_BASE_ENC_ENTRYPOINT (base))) == 0)
1391 *_profile = profile;
1392 *_rt_format = rt_format;
1397 /* Just use the first HW available profile and disable features if
1399 profile_name = NULL;
1400 for (i = 0; i < candidates->len; i++) {
1401 profile_name = g_ptr_array_index (candidates, i);
1402 profile = gst_va_profile_from_name (H264, profile_name);
1403 if (profile == VAProfileNone)
1406 if (!gst_va_encoder_has_profile (base->encoder, profile))
1409 if ((rt_format & gst_va_encoder_get_rtformat (base->encoder,
1410 profile, GST_VA_BASE_ENC_ENTRYPOINT (base))) == 0)
1413 *_profile = profile;
1414 *_rt_format = rt_format;
1421 if (self->use_dct8x8 && !g_strstr_len (profile_name, -1, "high")) {
1422 GST_INFO_OBJECT (self, "Disable dct8x8, profile %s does not support it",
1423 gst_va_profile_name (profile));
1424 self->use_dct8x8 = FALSE;
1425 update_property_bool (base, &self->prop.use_dct8x8, self->use_dct8x8,
1429 if (self->use_cabac && (!g_strstr_len (profile_name, -1, "main")
1430 && !g_strstr_len (profile_name, -1, "high"))) {
1431 GST_INFO_OBJECT (self, "Disable cabac, profile %s does not support it",
1432 gst_va_profile_name (profile));
1433 self->use_cabac = FALSE;
1434 update_property_bool (base, &self->prop.use_cabac, self->use_cabac,
1438 if (self->gop.num_bframes > 0 && g_strstr_len (profile_name, -1, "baseline")) {
1439 GST_INFO_OBJECT (self, "No B frames, profile %s does not support it",
1440 gst_va_profile_name (profile));
1441 self->gop.num_bframes = 0;
1442 self->gop.b_pyramid = 0;
1446 g_clear_pointer (&candidates, g_ptr_array_unref);
1447 g_clear_pointer (&allowed_caps, gst_caps_unref);
1450 GST_INFO_OBJECT (self, "Select the profile %s",
1451 gst_va_profile_name (profile));
1453 GST_ERROR_OBJECT (self, "Failed to find an available profile");
1459 /* Clear all the info of last reconfig and set the fields based on
1460 * property. The reconfig may change these fields because of the
1461 * profile/level and HW limitation. */
1463 gst_va_h264_enc_reset_state (GstVaBaseEnc * base)
1465 GstVaH264Enc *self = GST_VA_H264_ENC (base);
1467 GST_VA_BASE_ENC_CLASS (parent_class)->reset_state (base);
1469 GST_OBJECT_LOCK (self);
1470 self->use_cabac = self->prop.use_cabac;
1471 self->use_dct8x8 = self->prop.use_dct8x8;
1472 self->use_trellis = self->prop.use_trellis;
1473 self->aud = self->prop.aud;
1474 self->cc = self->prop.cc;
1475 self->num_slices = self->prop.num_slices;
1477 self->gop.idr_period = self->prop.key_int_max;
1478 self->gop.num_bframes = self->prop.num_bframes;
1479 self->gop.b_pyramid = self->prop.b_pyramid;
1480 self->gop.num_iframes = self->prop.num_iframes;
1481 self->gop.num_ref_frames = self->prop.num_ref_frames;
1483 self->rc.rc_ctrl_mode = self->prop.rc_ctrl;
1484 self->rc.min_qp = self->prop.min_qp;
1485 self->rc.max_qp = self->prop.max_qp;
1486 self->rc.qp_i = self->prop.qp_i;
1487 self->rc.qp_p = self->prop.qp_p;
1488 self->rc.qp_b = self->prop.qp_b;
1489 self->rc.mbbrc = self->prop.mbbrc;
1491 self->rc.target_percentage = self->prop.target_percentage;
1492 self->rc.target_usage = self->prop.target_usage;
1493 self->rc.cpb_size = self->prop.cpb_size;
1494 GST_OBJECT_UNLOCK (self);
1496 self->level_idc = 0;
1497 self->level_str = NULL;
1499 self->mb_height = 0;
1501 self->gop.i_period = 0;
1502 self->gop.total_idr_count = 0;
1503 self->gop.ip_period = 0;
1504 self->gop.highest_pyramid_level = 0;
1505 memset (self->gop.frame_types, 0, sizeof (self->gop.frame_types));
1506 self->gop.cur_frame_index = 0;
1507 self->gop.cur_frame_num = 0;
1508 self->gop.max_frame_num = 0;
1509 self->gop.log2_max_frame_num = 0;
1510 self->gop.max_pic_order_cnt = 0;
1511 self->gop.log2_max_pic_order_cnt = 0;
1512 self->gop.ref_num_list0 = 0;
1513 self->gop.ref_num_list1 = 0;
1514 self->gop.num_reorder_frames = 0;
1516 self->rc.max_bitrate = 0;
1517 self->rc.target_bitrate = 0;
1518 self->rc.max_bitrate_bits = 0;
1519 self->rc.target_bitrate_bits = 0;
1520 self->rc.cpb_length_bits = 0;
1522 memset (&self->sequence_hdr, 0, sizeof (GstH264SPS));
1526 gst_va_h264_enc_reconfig (GstVaBaseEnc * base)
1528 GstVideoEncoder *venc = GST_VIDEO_ENCODER (base);
1529 GstVaH264Enc *self = GST_VA_H264_ENC (base);
1530 GstCaps *out_caps, *reconf_caps = NULL;
1531 GstVideoCodecState *output_state = NULL;
1532 GstVideoFormat format, reconf_format = GST_VIDEO_FORMAT_UNKNOWN;
1533 VAProfile profile = VAProfileNone;
1534 gboolean do_renegotiation = TRUE, do_reopen, need_negotiation;
1535 guint max_ref_frames, max_surfaces = 0, rt_format = 0, codedbuf_size;
1538 width = GST_VIDEO_INFO_WIDTH (&base->input_state->info);
1539 height = GST_VIDEO_INFO_HEIGHT (&base->input_state->info);
1540 format = GST_VIDEO_INFO_FORMAT (&base->input_state->info);
1541 codedbuf_size = base->codedbuf_size;
1544 !gst_va_encoder_get_reconstruct_pool_config (base->encoder, &reconf_caps,
1546 if (!need_negotiation && reconf_caps) {
1548 if (!gst_video_info_from_caps (&vi, reconf_caps))
1550 reconf_format = GST_VIDEO_INFO_FORMAT (&vi);
1553 if (!_decide_profile (self, &profile, &rt_format))
1557 do_reopen = !(base->profile == profile && base->rt_format == rt_format
1558 && format == reconf_format && width == base->width
1559 && height == base->height && self->prop.rc_ctrl == self->rc.rc_ctrl_mode);
1561 if (do_reopen && gst_va_encoder_is_open (base->encoder))
1562 gst_va_encoder_close (base->encoder);
1564 gst_va_base_enc_reset_state (base);
1566 base->profile = profile;
1567 base->rt_format = rt_format;
1568 base->width = width;
1569 base->height = height;
1571 self->mb_width = GST_ROUND_UP_16 (base->width) / 16;
1572 self->mb_height = GST_ROUND_UP_16 (base->height) / 16;
1574 /* Frame rate is needed for rate control and PTS setting. */
1575 if (GST_VIDEO_INFO_FPS_N (&base->input_state->info) == 0
1576 || GST_VIDEO_INFO_FPS_D (&base->input_state->info) == 0) {
1577 GST_INFO_OBJECT (self, "Unknown framerate, just set to 30 fps");
1578 GST_VIDEO_INFO_FPS_N (&base->input_state->info) = 30;
1579 GST_VIDEO_INFO_FPS_D (&base->input_state->info) = 1;
1581 base->frame_duration = gst_util_uint64_scale (GST_SECOND,
1582 GST_VIDEO_INFO_FPS_D (&base->input_state->info),
1583 GST_VIDEO_INFO_FPS_N (&base->input_state->info));
1585 GST_DEBUG_OBJECT (self, "resolution:%dx%d, MB size: %dx%d,"
1586 " frame duration is %" GST_TIME_FORMAT,
1587 base->width, base->height, self->mb_width, self->mb_height,
1588 GST_TIME_ARGS (base->frame_duration));
1590 _validate_parameters (self);
1592 if (!_ensure_rate_control (self))
1595 if (!_calculate_level (self))
1598 _generate_gop_structure (self);
1600 _calculate_coded_size (self);
1602 /* updates & notifications */
1603 /* num_bframes are modified several times before */
1604 update_property_uint (base, &self->prop.num_bframes, self->gop.num_bframes,
1606 update_property_bool (base, &self->prop.b_pyramid, self->gop.b_pyramid,
1609 if (!_init_packed_headers (self))
1612 self->aud = self->aud && self->packed_headers & VA_ENC_PACKED_HEADER_RAW_DATA;
1613 update_property_bool (base, &self->prop.aud, self->aud, PROP_AUD);
1615 self->cc = self->cc && self->packed_headers & VA_ENC_PACKED_HEADER_RAW_DATA;
1616 update_property_bool (base, &self->prop.cc, self->cc, PROP_CC);
1618 max_ref_frames = self->gop.num_ref_frames + 3 /* scratch frames */ ;
1620 /* second check after calculations */
1622 !(max_ref_frames == max_surfaces && codedbuf_size == base->codedbuf_size);
1623 if (do_reopen && gst_va_encoder_is_open (base->encoder))
1624 gst_va_encoder_close (base->encoder);
1626 if (!gst_va_encoder_is_open (base->encoder)
1627 && !gst_va_encoder_open (base->encoder, base->profile,
1628 format, base->rt_format, base->width, base->height,
1629 base->codedbuf_size, max_ref_frames, self->rc.rc_ctrl_mode,
1630 self->packed_headers)) {
1631 GST_ERROR_OBJECT (self, "Failed to open the VA encoder.");
1636 gst_va_base_enc_add_codec_tag (base, "H264");
1638 out_caps = gst_va_profile_caps (base->profile);
1639 g_assert (out_caps);
1640 out_caps = gst_caps_fixate (out_caps);
1642 if (self->level_str)
1643 gst_caps_set_simple (out_caps, "level", G_TYPE_STRING, self->level_str,
1646 gst_caps_set_simple (out_caps, "width", G_TYPE_INT, base->width,
1647 "height", G_TYPE_INT, base->height, "alignment", G_TYPE_STRING, "au",
1648 "stream-format", G_TYPE_STRING, "byte-stream", NULL);
1650 if (!need_negotiation) {
1651 output_state = gst_video_encoder_get_output_state (venc);
1652 do_renegotiation = TRUE;
1654 do_renegotiation = !gst_caps_is_subset (output_state->caps, out_caps);
1655 gst_video_codec_state_unref (output_state);
1657 if (!do_renegotiation) {
1658 gst_caps_unref (out_caps);
1663 GST_DEBUG_OBJECT (self, "output caps is %" GST_PTR_FORMAT, out_caps);
1666 gst_video_encoder_set_output_state (venc, out_caps, base->input_state);
1667 gst_video_codec_state_unref (output_state);
1669 if (!gst_video_encoder_negotiate (venc)) {
1670 GST_ERROR_OBJECT (self, "Failed to negotiate with the downstream");
1678 _push_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame * gst_frame,
1681 GstVaH264Enc *self = GST_VA_H264_ENC (base);
1682 GstVaH264EncFrame *frame;
1684 g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
1688 /* Begin a new GOP, should have a empty reorder_list. */
1689 if (self->gop.cur_frame_index == self->gop.idr_period) {
1690 g_assert (g_queue_is_empty (&base->reorder_list));
1691 self->gop.cur_frame_index = 0;
1692 self->gop.cur_frame_num = 0;
1695 frame = _enc_frame (gst_frame);
1697 ((self->gop.cur_frame_index * 2) % self->gop.max_pic_order_cnt);
1699 /* TODO: move most this logic onto vabaseenc class */
1700 if (self->gop.cur_frame_index == 0) {
1701 g_assert (frame->poc == 0);
1702 GST_LOG_OBJECT (self, "system_frame_number: %d, an IDR frame, starts"
1703 " a new GOP", gst_frame->system_frame_number);
1705 g_queue_clear_full (&base->ref_list,
1706 (GDestroyNotify) gst_video_codec_frame_unref);
1708 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (gst_frame);
1711 frame->type = self->gop.frame_types[self->gop.cur_frame_index].slice_type;
1712 frame->is_ref = self->gop.frame_types[self->gop.cur_frame_index].is_ref;
1713 frame->pyramid_level =
1714 self->gop.frame_types[self->gop.cur_frame_index].pyramid_level;
1715 frame->left_ref_poc_diff =
1716 self->gop.frame_types[self->gop.cur_frame_index].left_ref_poc_diff;
1717 frame->right_ref_poc_diff =
1718 self->gop.frame_types[self->gop.cur_frame_index].right_ref_poc_diff;
1720 if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (gst_frame)) {
1721 GST_DEBUG_OBJECT (self, "system_frame_number: %d, a force key frame,"
1722 " promote its type from %s to %s", gst_frame->system_frame_number,
1723 _slice_type_name (frame->type), _slice_type_name (GST_H264_I_SLICE));
1724 frame->type = GST_H264_I_SLICE;
1725 frame->is_ref = TRUE;
1728 GST_LOG_OBJECT (self, "Push frame, system_frame_number: %d, poc %d, "
1729 "frame type %s", gst_frame->system_frame_number, frame->poc,
1730 _slice_type_name (frame->type));
1732 self->gop.cur_frame_index++;
1733 g_queue_push_tail (&base->reorder_list,
1734 gst_video_codec_frame_ref (gst_frame));
1737 /* ensure the last one a non-B and end the GOP. */
1738 if (last && self->gop.cur_frame_index < self->gop.idr_period) {
1739 GstVideoCodecFrame *last_frame;
1741 /* Ensure next push will start a new GOP. */
1742 self->gop.cur_frame_index = self->gop.idr_period;
1744 if (!g_queue_is_empty (&base->reorder_list)) {
1745 last_frame = g_queue_peek_tail (&base->reorder_list);
1746 frame = _enc_frame (last_frame);
1747 if (frame->type == GST_H264_B_SLICE) {
1748 frame->type = GST_H264_P_SLICE;
1749 frame->is_ref = TRUE;
1757 struct RefFramesCount
1764 _count_backward_ref_num (gpointer data, gpointer user_data)
1766 GstVaH264EncFrame *frame = _enc_frame (data);
1767 struct RefFramesCount *count = (struct RefFramesCount *) user_data;
1769 g_assert (frame->poc != count->poc);
1770 if (frame->poc > count->poc)
1774 static GstVideoCodecFrame *
1775 _pop_pyramid_b_frame (GstVaH264Enc * self)
1777 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1780 GstVaH264EncFrame *b_vaframe;
1781 GstVideoCodecFrame *b_frame;
1782 struct RefFramesCount count;
1784 g_assert (self->gop.ref_num_list1 == 1);
1789 /* Find the lowest level with smallest poc. */
1790 for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
1791 GstVaH264EncFrame *vaf;
1792 GstVideoCodecFrame *f;
1794 f = g_queue_peek_nth (&base->reorder_list, i);
1798 b_vaframe = _enc_frame (b_frame);
1803 vaf = _enc_frame (f);
1804 if (b_vaframe->pyramid_level < vaf->pyramid_level) {
1811 if (b_vaframe->poc > vaf->poc) {
1819 /* Check whether its refs are already poped. */
1820 g_assert (b_vaframe->left_ref_poc_diff != 0);
1821 g_assert (b_vaframe->right_ref_poc_diff != 0);
1822 for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
1823 GstVaH264EncFrame *vaf;
1824 GstVideoCodecFrame *f;
1826 f = g_queue_peek_nth (&base->reorder_list, i);
1831 vaf = _enc_frame (f);
1832 if (vaf->poc == b_vaframe->poc + b_vaframe->left_ref_poc_diff
1833 || vaf->poc == b_vaframe->poc + b_vaframe->right_ref_poc_diff) {
1841 /* Ensure we already have enough backward refs */
1843 count.poc = b_vaframe->poc;
1844 g_queue_foreach (&base->ref_list, (GFunc) _count_backward_ref_num, &count);
1845 if (count.num >= self->gop.ref_num_list1) {
1846 GstVideoCodecFrame *f;
1848 /* it will unref at pop_frame */
1849 f = g_queue_pop_nth (&base->reorder_list, index);
1850 g_assert (f == b_frame);
1859 _pop_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame ** out_frame)
1861 GstVaH264Enc *self = GST_VA_H264_ENC (base);
1862 GstVaH264EncFrame *vaframe;
1863 GstVideoCodecFrame *frame;
1864 struct RefFramesCount count;
1866 g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
1871 if (g_queue_is_empty (&base->reorder_list))
1874 /* Return the last pushed non-B immediately. */
1875 frame = g_queue_peek_tail (&base->reorder_list);
1876 vaframe = _enc_frame (frame);
1877 if (vaframe->type != GST_H264_B_SLICE) {
1878 frame = g_queue_pop_tail (&base->reorder_list);
1882 if (self->gop.b_pyramid) {
1883 frame = _pop_pyramid_b_frame (self);
1889 g_assert (self->gop.ref_num_list1 > 0);
1891 /* If GOP end, pop anyway. */
1892 if (self->gop.cur_frame_index == self->gop.idr_period) {
1893 frame = g_queue_pop_head (&base->reorder_list);
1897 /* Ensure we already have enough backward refs */
1898 frame = g_queue_peek_head (&base->reorder_list);
1899 vaframe = _enc_frame (frame);
1901 count.poc = vaframe->poc;
1902 g_queue_foreach (&base->ref_list, _count_backward_ref_num, &count);
1903 if (count.num >= self->gop.ref_num_list1) {
1904 frame = g_queue_pop_head (&base->reorder_list);
1911 g_assert (self->gop.cur_frame_num < self->gop.max_frame_num);
1913 vaframe = _enc_frame (frame);
1914 vaframe->frame_num = self->gop.cur_frame_num;
1916 /* Add the frame number for ref frames. */
1917 if (vaframe->is_ref)
1918 self->gop.cur_frame_num++;
1920 if (vaframe->frame_num == 0)
1921 self->gop.total_idr_count++;
1923 if (self->gop.b_pyramid && vaframe->type == GST_H264_B_SLICE) {
1924 GST_LOG_OBJECT (self, "pop a pyramid B frame with system_frame_number:"
1925 " %d, poc: %d, frame num: %d, is_ref: %s, level %d",
1926 frame->system_frame_number, vaframe->poc, vaframe->frame_num,
1927 vaframe->is_ref ? "true" : "false", vaframe->pyramid_level);
1929 GST_LOG_OBJECT (self, "pop a frame with system_frame_number: %d,"
1930 " frame type: %s, poc: %d, frame num: %d, is_ref: %s",
1931 frame->system_frame_number, _slice_type_name (vaframe->type),
1932 vaframe->poc, vaframe->frame_num, vaframe->is_ref ? "true" : "false");
1935 /* unref frame popped from queue or pyramid b_frame */
1936 gst_video_codec_frame_unref (frame);
1942 gst_va_h264_enc_reorder_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame,
1943 gboolean bump_all, GstVideoCodecFrame ** out_frame)
1945 if (!_push_one_frame (base, frame, bump_all)) {
1946 GST_ERROR_OBJECT (base, "Failed to push the input frame"
1947 " system_frame_number: %d into the reorder list",
1948 frame->system_frame_number);
1954 if (!_pop_one_frame (base, out_frame)) {
1955 GST_ERROR_OBJECT (base, "Failed to pop the frame from the reorder list");
1963 static inline gboolean
1964 _fill_sps (GstVaH264Enc * self, VAEncSequenceParameterBufferH264 * seq_param)
1966 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1967 GstH264Profile profile;
1968 guint32 constraint_set0_flag, constraint_set1_flag;
1969 guint32 constraint_set2_flag, constraint_set3_flag;
1970 guint32 max_dec_frame_buffering;
1972 /* let max_num_ref_frames <= MaxDpbFrames. */
1973 max_dec_frame_buffering =
1974 MIN (self->gop.num_ref_frames + 1 /* Last frame before bump */ ,
1975 16 /* DPB_MAX_SIZE */ );
1977 constraint_set0_flag = 0;
1978 constraint_set1_flag = 0;
1979 constraint_set2_flag = 0;
1980 constraint_set3_flag = 0;
1982 switch (base->profile) {
1983 case VAProfileH264ConstrainedBaseline:
1984 profile = GST_H264_PROFILE_BASELINE;
1985 /* A.2.1 (baseline profile constraints) */
1986 constraint_set0_flag = 1;
1987 constraint_set1_flag = 1;
1989 case VAProfileH264Main:
1990 profile = GST_H264_PROFILE_MAIN;
1991 /* A.2.2 (main profile constraints) */
1992 constraint_set1_flag = 1;
1994 case VAProfileH264High:
1995 case VAProfileH264MultiviewHigh:
1996 case VAProfileH264StereoHigh:
1997 profile = GST_H264_PROFILE_HIGH;
2003 /* seq_scaling_matrix_present_flag not supported now */
2004 g_assert (seq_param->seq_fields.bits.seq_scaling_matrix_present_flag == 0);
2005 /* pic_order_cnt_type only support 0 now */
2006 g_assert (seq_param->seq_fields.bits.pic_order_cnt_type == 0);
2007 /* only progressive frames encoding is supported now */
2008 g_assert (seq_param->seq_fields.bits.frame_mbs_only_flag);
2011 GST_DEBUG_OBJECT (self, "filling SPS");
2012 self->sequence_hdr = (GstH264SPS) {
2014 .profile_idc = profile,
2015 .constraint_set0_flag = constraint_set0_flag,
2016 .constraint_set1_flag = constraint_set1_flag,
2017 .constraint_set2_flag = constraint_set2_flag,
2018 .constraint_set3_flag = constraint_set3_flag,
2019 .level_idc = self->level_idc,
2021 .chroma_format_idc = seq_param->seq_fields.bits.chroma_format_idc,
2022 .bit_depth_luma_minus8 = seq_param->bit_depth_luma_minus8,
2023 .bit_depth_chroma_minus8 = seq_param->bit_depth_chroma_minus8,
2025 .log2_max_frame_num_minus4 =
2026 seq_param->seq_fields.bits.log2_max_frame_num_minus4,
2027 .pic_order_cnt_type = seq_param->seq_fields.bits.pic_order_cnt_type,
2028 .log2_max_pic_order_cnt_lsb_minus4 =
2029 seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4,
2031 .num_ref_frames = seq_param->max_num_ref_frames,
2032 .gaps_in_frame_num_value_allowed_flag = 0,
2033 .pic_width_in_mbs_minus1 = seq_param->picture_width_in_mbs - 1,
2034 .pic_height_in_map_units_minus1 =
2035 (seq_param->seq_fields.bits.frame_mbs_only_flag ?
2036 seq_param->picture_height_in_mbs - 1 :
2037 seq_param->picture_height_in_mbs / 2 - 1),
2038 .frame_mbs_only_flag = seq_param->seq_fields.bits.frame_mbs_only_flag,
2039 .mb_adaptive_frame_field_flag = 0,
2040 .direct_8x8_inference_flag =
2041 seq_param->seq_fields.bits.direct_8x8_inference_flag,
2042 .frame_cropping_flag = seq_param->frame_cropping_flag,
2043 .frame_crop_left_offset = seq_param->frame_crop_left_offset,
2044 .frame_crop_right_offset = seq_param->frame_crop_right_offset,
2045 .frame_crop_top_offset = seq_param->frame_crop_top_offset,
2046 .frame_crop_bottom_offset = seq_param->frame_crop_bottom_offset,
2048 .vui_parameters_present_flag = seq_param->vui_parameters_present_flag,
2050 .aspect_ratio_info_present_flag =
2051 seq_param->vui_fields.bits.aspect_ratio_info_present_flag,
2052 .aspect_ratio_idc = seq_param->aspect_ratio_idc,
2053 .sar_width = seq_param->sar_width,
2054 .sar_height = seq_param->sar_height,
2055 .overscan_info_present_flag = 0,
2056 .overscan_appropriate_flag = 0,
2057 .chroma_loc_info_present_flag = 0,
2058 .timing_info_present_flag =
2059 seq_param->vui_fields.bits.timing_info_present_flag,
2060 .num_units_in_tick = seq_param->num_units_in_tick,
2061 .time_scale = seq_param->time_scale,
2062 .fixed_frame_rate_flag = seq_param->vui_fields.bits.fixed_frame_rate_flag,
2064 /* We do not write hrd and no need for buffering period SEI. */
2065 .nal_hrd_parameters_present_flag = 0,
2066 .vcl_hrd_parameters_present_flag = 0,
2068 .low_delay_hrd_flag = seq_param->vui_fields.bits.low_delay_hrd_flag,
2069 .pic_struct_present_flag = 1,
2070 .bitstream_restriction_flag =
2071 seq_param->vui_fields.bits.bitstream_restriction_flag,
2072 .motion_vectors_over_pic_boundaries_flag =
2073 seq_param->vui_fields.bits.motion_vectors_over_pic_boundaries_flag,
2074 .max_bytes_per_pic_denom = 2,
2075 .max_bits_per_mb_denom = 1,
2076 .log2_max_mv_length_horizontal =
2077 seq_param->vui_fields.bits.log2_max_mv_length_horizontal,
2078 .log2_max_mv_length_vertical =
2079 seq_param->vui_fields.bits.log2_max_mv_length_vertical,
2080 .num_reorder_frames = self->gop.num_reorder_frames,
2081 .max_dec_frame_buffering = max_dec_frame_buffering,
2090 _add_sequence_header (GstVaH264Enc * self, GstVaH264EncFrame * frame)
2092 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2094 #define SPS_SIZE 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE + MAX_VUI_PARAMS_SIZE + \
2095 2 * MAX_HRD_PARAMS_SIZE) / 8
2096 guint8 packed_sps[SPS_SIZE] = { 0, };
2099 size = sizeof (packed_sps);
2100 if (gst_h264_bit_writer_sps (&self->sequence_hdr, TRUE, packed_sps,
2101 &size) != GST_H264_BIT_WRITER_OK) {
2102 GST_ERROR_OBJECT (self, "Failed to generate the sequence header");
2106 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2107 VAEncPackedHeaderSequence, packed_sps, size * 8, FALSE)) {
2108 GST_ERROR_OBJECT (self, "Failed to add the packed sequence header");
2116 _fill_sequence_param (GstVaH264Enc * self,
2117 VAEncSequenceParameterBufferH264 * sequence)
2119 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2120 gboolean direct_8x8_inference_flag = TRUE;
2122 g_assert (self->gop.log2_max_frame_num >= 4);
2123 g_assert (self->gop.log2_max_pic_order_cnt >= 4);
2125 /* A.2.3 Extended profile:
2126 * Sequence parameter sets shall have direct_8x8_inference_flag
2129 * A.3.3 Profile-specific level limits:
2130 * direct_8x8_inference_flag is not relevant to the Baseline,
2131 * Constrained Baseline, Constrained High, High 10 Intra, High 4:2:2
2132 * Intra, High 4:4:4 Intra, and CAVLC 4:4:4 Intra profiles as these
2133 * profiles do not allow B slice types, and
2134 * direct_8x8_inference_flag is equal to 1 for all levels of the
2135 * Extended profile. Table A-4. We only have constrained baseline
2137 if (base->profile == VAProfileH264ConstrainedBaseline)
2138 direct_8x8_inference_flag = FALSE;
2141 *sequence = (VAEncSequenceParameterBufferH264) {
2142 .seq_parameter_set_id = 0,
2143 .level_idc = self->level_idc,
2145 self->gop.i_period > 0 ? self->gop.i_period : self->gop.idr_period,
2146 .intra_idr_period = self->gop.idr_period,
2147 .ip_period = self->gop.ip_period,
2148 .bits_per_second = self->rc.target_bitrate_bits,
2149 .max_num_ref_frames = self->gop.num_ref_frames,
2150 .picture_width_in_mbs = self->mb_width,
2151 .picture_height_in_mbs = self->mb_height,
2153 .seq_fields.bits = {
2154 /* Only support 4:2:0 now. */
2155 .chroma_format_idc = 1,
2156 .frame_mbs_only_flag = 1,
2157 .mb_adaptive_frame_field_flag = FALSE,
2158 .seq_scaling_matrix_present_flag = FALSE,
2159 .direct_8x8_inference_flag = direct_8x8_inference_flag,
2160 .log2_max_frame_num_minus4 = self->gop.log2_max_frame_num - 4,
2161 .pic_order_cnt_type = 0,
2162 .log2_max_pic_order_cnt_lsb_minus4 = self->gop.log2_max_pic_order_cnt - 4,
2164 .bit_depth_luma_minus8 = 0,
2165 .bit_depth_chroma_minus8 = 0,
2167 .vui_parameters_present_flag = TRUE,
2168 .vui_fields.bits = {
2169 .aspect_ratio_info_present_flag = TRUE,
2170 .timing_info_present_flag = TRUE,
2171 .bitstream_restriction_flag = TRUE,
2172 .log2_max_mv_length_horizontal = 15,
2173 .log2_max_mv_length_vertical = 15,
2174 .fixed_frame_rate_flag = 1,
2175 .low_delay_hrd_flag = 0,
2176 .motion_vectors_over_pic_boundaries_flag = TRUE,
2178 .aspect_ratio_idc = 0xff,
2179 /* FIXME: what if no framerate info is provided */
2180 .sar_width = GST_VIDEO_INFO_PAR_N (&base->input_state->info),
2181 .sar_height = GST_VIDEO_INFO_PAR_D (&base->input_state->info),
2182 .num_units_in_tick = GST_VIDEO_INFO_FPS_D (&base->input_state->info),
2183 .time_scale = GST_VIDEO_INFO_FPS_N (&base->input_state->info) * 2,
2187 /* frame_cropping_flag */
2188 if (base->width & 15 || base->height & 15) {
2189 static const guint SubWidthC[] = { 1, 2, 2, 1 };
2190 static const guint SubHeightC[] = { 1, 2, 1, 1 };
2191 const guint CropUnitX =
2192 SubWidthC[sequence->seq_fields.bits.chroma_format_idc];
2193 const guint CropUnitY =
2194 SubHeightC[sequence->seq_fields.bits.chroma_format_idc] *
2195 (2 - sequence->seq_fields.bits.frame_mbs_only_flag);
2197 sequence->frame_cropping_flag = 1;
2198 sequence->frame_crop_left_offset = 0;
2199 sequence->frame_crop_right_offset = (16 * self->mb_width -
2200 base->width) / CropUnitX;
2201 sequence->frame_crop_top_offset = 0;
2202 sequence->frame_crop_bottom_offset = (16 * self->mb_height -
2203 base->height) / CropUnitY;
2208 _add_sequence_parameter (GstVaH264Enc * self, GstVaEncodePicture * picture,
2209 VAEncSequenceParameterBufferH264 * sequence)
2211 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2213 if (!gst_va_encoder_add_param (base->encoder, picture,
2214 VAEncSequenceParameterBufferType, sequence, sizeof (*sequence))) {
2215 GST_ERROR_OBJECT (self, "Failed to create the sequence parameter");
2222 static inline gboolean
2223 _fill_picture_parameter (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2224 VAEncPictureParameterBufferH264 * pic_param)
2226 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2230 *pic_param = (VAEncPictureParameterBufferH264) {
2233 gst_va_encode_picture_get_reconstruct_surface (frame->picture),
2234 .TopFieldOrderCnt = frame->poc,
2236 .coded_buf = frame->picture->coded_buffer,
2237 /* Only support one sps and pps now. */
2238 .pic_parameter_set_id = 0,
2239 .seq_parameter_set_id = 0,
2240 /* means last encoding picture, EOS nal added. */
2241 .last_picture = frame->last_frame,
2242 .frame_num = frame->frame_num,
2244 .pic_init_qp = self->rc.qp_i,
2245 /* Use slice's these fields to control ref num. */
2246 .num_ref_idx_l0_active_minus1 = 0,
2247 .num_ref_idx_l1_active_minus1 = 0,
2248 .chroma_qp_index_offset = 0,
2249 .second_chroma_qp_index_offset = 0,
2250 /* picture fields */
2251 .pic_fields.bits.idr_pic_flag = (frame->frame_num == 0),
2252 .pic_fields.bits.reference_pic_flag = frame->is_ref,
2253 .pic_fields.bits.entropy_coding_mode_flag = self->use_cabac,
2254 .pic_fields.bits.weighted_pred_flag = 0,
2255 .pic_fields.bits.weighted_bipred_idc = 0,
2256 .pic_fields.bits.constrained_intra_pred_flag = 0,
2257 .pic_fields.bits.transform_8x8_mode_flag = self->use_dct8x8,
2258 /* enable debloking */
2259 .pic_fields.bits.deblocking_filter_control_present_flag = 1,
2260 .pic_fields.bits.redundant_pic_cnt_present_flag = 0,
2261 /* bottom_field_pic_order_in_frame_present_flag */
2262 .pic_fields.bits.pic_order_present_flag = 0,
2263 .pic_fields.bits.pic_scaling_matrix_present_flag = 0,
2267 /* Non I frame, construct reference list. */
2269 if (frame->type != GST_H264_I_SLICE) {
2270 GstVaH264EncFrame *f;
2272 if (g_queue_is_empty (&base->ref_list)) {
2273 GST_ERROR_OBJECT (self, "No reference found for frame type %s",
2274 _slice_type_name (frame->type));
2278 g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
2280 /* ref frames in queue are already sorted by frame_num. */
2281 for (; i < g_queue_get_length (&base->ref_list); i++) {
2282 f = _enc_frame (g_queue_peek_nth (&base->ref_list, i));
2284 pic_param->ReferenceFrames[i].picture_id =
2285 gst_va_encode_picture_get_reconstruct_surface (f->picture);
2286 pic_param->ReferenceFrames[i].TopFieldOrderCnt = f->poc;
2287 pic_param->ReferenceFrames[i].flags =
2288 VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2289 pic_param->ReferenceFrames[i].frame_idx = f->frame_num;
2293 pic_param->ReferenceFrames[i].picture_id = VA_INVALID_ID;
2299 _add_picture_parameter (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2300 VAEncPictureParameterBufferH264 * pic_param)
2302 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2304 if (!gst_va_encoder_add_param (base->encoder, frame->picture,
2305 VAEncPictureParameterBufferType, pic_param,
2306 sizeof (VAEncPictureParameterBufferH264))) {
2307 GST_ERROR_OBJECT (self, "Failed to create the picture parameter");
2315 _fill_pps (VAEncPictureParameterBufferH264 * pic_param, GstH264SPS * sps,
2319 *pps = (GstH264PPS) {
2322 .entropy_coding_mode_flag =
2323 pic_param->pic_fields.bits.entropy_coding_mode_flag,
2324 .pic_order_present_flag =
2325 pic_param->pic_fields.bits.pic_order_present_flag,
2326 .num_slice_groups_minus1 = 0,
2328 .num_ref_idx_l0_active_minus1 = pic_param->num_ref_idx_l0_active_minus1,
2329 .num_ref_idx_l1_active_minus1 = pic_param->num_ref_idx_l1_active_minus1,
2331 .weighted_pred_flag = pic_param->pic_fields.bits.weighted_pred_flag,
2332 .weighted_bipred_idc = pic_param->pic_fields.bits.weighted_bipred_idc,
2333 .pic_init_qp_minus26 = pic_param->pic_init_qp - 26,
2334 .pic_init_qs_minus26 = 0,
2335 .chroma_qp_index_offset = pic_param->chroma_qp_index_offset,
2336 .deblocking_filter_control_present_flag =
2337 pic_param->pic_fields.bits.deblocking_filter_control_present_flag,
2338 .constrained_intra_pred_flag =
2339 pic_param->pic_fields.bits.constrained_intra_pred_flag,
2340 .redundant_pic_cnt_present_flag =
2341 pic_param->pic_fields.bits.redundant_pic_cnt_present_flag,
2342 .transform_8x8_mode_flag =
2343 pic_param->pic_fields.bits.transform_8x8_mode_flag,
2344 /* unsupport scaling lists */
2345 .pic_scaling_matrix_present_flag = 0,
2346 .second_chroma_qp_index_offset = pic_param->second_chroma_qp_index_offset,
2352 _add_picture_header (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2355 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2356 #define PPS_SIZE 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8
2357 guint8 packed_pps[PPS_SIZE] = { 0, };
2361 size = sizeof (packed_pps);
2362 if (gst_h264_bit_writer_pps (pps, TRUE, packed_pps,
2363 &size) != GST_H264_BIT_WRITER_OK) {
2364 GST_ERROR_OBJECT (self, "Failed to generate the picture header");
2368 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2369 VAEncPackedHeaderPicture, packed_pps, size * 8, FALSE)) {
2370 GST_ERROR_OBJECT (self, "Failed to add the packed picture header");
2378 _add_one_slice (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2379 gint start_mb, gint mb_size,
2380 VAEncSliceParameterBufferH264 * slice,
2381 GstVaH264EncFrame * list0[16], guint list0_num,
2382 GstVaH264EncFrame * list1[16], guint list1_num)
2384 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2385 int8_t slice_qp_delta = 0;
2389 if (self->rc.rc_ctrl_mode == VA_RC_CQP) {
2390 if (frame->type == GST_H264_P_SLICE) {
2391 slice_qp_delta = self->rc.qp_p - self->rc.qp_i;
2392 } else if (frame->type == GST_H264_B_SLICE) {
2393 slice_qp_delta = (int8_t) (self->rc.qp_b - self->rc.qp_i);
2395 g_assert (slice_qp_delta <= 51 && slice_qp_delta >= -51);
2398 *slice = (VAEncSliceParameterBufferH264) {
2399 .macroblock_address = start_mb,
2400 .num_macroblocks = mb_size,
2401 .macroblock_info = VA_INVALID_ID,
2402 .slice_type = (uint8_t) frame->type,
2403 /* Only one parameter set supported now. */
2404 .pic_parameter_set_id = 0,
2405 .idr_pic_id = self->gop.total_idr_count,
2406 .pic_order_cnt_lsb = frame->poc,
2407 /* Not support top/bottom. */
2408 .delta_pic_order_cnt_bottom = 0,
2409 .delta_pic_order_cnt[0] = 0,
2410 .delta_pic_order_cnt[1] = 0,
2412 .direct_spatial_mv_pred_flag = TRUE,
2413 /* .num_ref_idx_active_override_flag = , */
2414 /* .num_ref_idx_l0_active_minus1 = , */
2415 /* .num_ref_idx_l1_active_minus1 = , */
2416 /* Set the reference list later. */
2418 .luma_log2_weight_denom = 0,
2419 .chroma_log2_weight_denom = 0,
2420 .luma_weight_l0_flag = 0,
2421 .chroma_weight_l0_flag = 0,
2422 .luma_weight_l1_flag = 0,
2423 .chroma_weight_l1_flag = 0,
2425 .cabac_init_idc = 0,
2426 /* Just use picture default setting. */
2427 .slice_qp_delta = slice_qp_delta,
2429 .disable_deblocking_filter_idc = 0,
2430 .slice_alpha_c0_offset_div2 = 2,
2431 .slice_beta_offset_div2 = 2,
2435 if (frame->type == GST_H264_B_SLICE || frame->type == GST_H264_P_SLICE) {
2436 slice->num_ref_idx_active_override_flag = (list0_num > 0 || list1_num > 0);
2437 slice->num_ref_idx_l0_active_minus1 = list0_num > 0 ? list0_num - 1 : 0;
2438 if (frame->type == GST_H264_B_SLICE)
2439 slice->num_ref_idx_l1_active_minus1 = list1_num > 0 ? list1_num - 1 : 0;
2443 if (frame->type != GST_H264_I_SLICE) {
2444 for (; i < list0_num; i++) {
2445 slice->RefPicList0[i].picture_id =
2446 gst_va_encode_picture_get_reconstruct_surface (list0[i]->picture);
2447 slice->RefPicList0[i].TopFieldOrderCnt = list0[i]->poc;
2448 slice->RefPicList0[i].flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2449 slice->RefPicList0[i].frame_idx = list0[i]->frame_num;
2452 for (; i < G_N_ELEMENTS (slice->RefPicList0); ++i) {
2453 slice->RefPicList0[i].picture_id = VA_INVALID_SURFACE;
2454 slice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID;
2458 if (frame->type == GST_H264_B_SLICE) {
2459 for (; i < list1_num; i++) {
2460 slice->RefPicList1[i].picture_id =
2461 gst_va_encode_picture_get_reconstruct_surface (list1[i]->picture);
2462 slice->RefPicList1[i].TopFieldOrderCnt = list1[i]->poc;
2463 slice->RefPicList1[i].flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2464 slice->RefPicList1[i].frame_idx = list1[i]->frame_num;
2467 for (; i < G_N_ELEMENTS (slice->RefPicList1); ++i) {
2468 slice->RefPicList1[i].picture_id = VA_INVALID_SURFACE;
2469 slice->RefPicList1[i].flags = VA_PICTURE_H264_INVALID;
2472 if (!gst_va_encoder_add_param (base->encoder, frame->picture,
2473 VAEncSliceParameterBufferType, slice,
2474 sizeof (VAEncSliceParameterBufferH264))) {
2475 GST_ERROR_OBJECT (self, "Failed to create the slice parameter");
2483 _poc_asc_compare (const GstVaH264EncFrame ** a, const GstVaH264EncFrame ** b)
2485 return (*a)->poc - (*b)->poc;
2489 _poc_des_compare (const GstVaH264EncFrame ** a, const GstVaH264EncFrame ** b)
2491 return (*b)->poc - (*a)->poc;
2495 _frame_num_asc_compare (const GstVaH264EncFrame ** a,
2496 const GstVaH264EncFrame ** b)
2498 return (*a)->frame_num - (*b)->frame_num;
2502 _frame_num_des_compare (const GstVaH264EncFrame ** a,
2503 const GstVaH264EncFrame ** b)
2505 return (*b)->frame_num - (*a)->frame_num;
2508 /* If all the pic_num in the same order, OK. */
2510 _ref_list_need_reorder (GstVaH264EncFrame * list[16], guint list_num,
2519 for (i = 1; i < list_num; i++) {
2520 pic_num_diff = list[i]->frame_num - list[i - 1]->frame_num;
2521 g_assert (pic_num_diff != 0);
2523 if (pic_num_diff > 0 && !is_asc)
2526 if (pic_num_diff < 0 && is_asc)
2534 _insert_ref_pic_list_modification (GstH264SliceHdr * slice_hdr,
2535 GstVaH264EncFrame * list[16], guint list_num, gboolean is_asc)
2537 GstVaH264EncFrame *list_by_pic_num[16] = { };
2538 guint modification_num, i;
2539 GstH264RefPicListModification *ref_pic_list_modification = NULL;
2540 gint pic_num_diff, pic_num_lx_pred;
2542 memcpy (list_by_pic_num, list, sizeof (GstVaH264EncFrame *) * list_num);
2545 g_qsort_with_data (list_by_pic_num, list_num, sizeof (gpointer),
2546 (GCompareDataFunc) _frame_num_asc_compare, NULL);
2548 g_qsort_with_data (list_by_pic_num, list_num, sizeof (gpointer),
2549 (GCompareDataFunc) _frame_num_des_compare, NULL);
2552 modification_num = 0;
2553 for (i = 0; i < list_num; i++) {
2554 if (list_by_pic_num[i]->poc != list[i]->poc)
2555 modification_num = i + 1;
2557 g_assert (modification_num > 0);
2560 slice_hdr->ref_pic_list_modification_flag_l1 = 1;
2561 slice_hdr->n_ref_pic_list_modification_l1 =
2562 modification_num + 1 /* The end operation. */ ;
2563 ref_pic_list_modification = slice_hdr->ref_pic_list_modification_l1;
2565 slice_hdr->ref_pic_list_modification_flag_l0 = 1;
2566 slice_hdr->n_ref_pic_list_modification_l0 =
2567 modification_num + 1 /* The end operation. */ ;
2568 ref_pic_list_modification = slice_hdr->ref_pic_list_modification_l0;
2571 pic_num_lx_pred = slice_hdr->frame_num;
2572 for (i = 0; i < modification_num; i++) {
2573 pic_num_diff = list[i]->frame_num - pic_num_lx_pred;
2574 /* For the nex loop. */
2575 pic_num_lx_pred = list[i]->frame_num;
2577 g_assert (pic_num_diff != 0);
2579 if (pic_num_diff > 0) {
2580 ref_pic_list_modification->modification_of_pic_nums_idc = 1;
2581 ref_pic_list_modification->value.abs_diff_pic_num_minus1 =
2584 ref_pic_list_modification->modification_of_pic_nums_idc = 0;
2585 ref_pic_list_modification->value.abs_diff_pic_num_minus1 =
2586 (-pic_num_diff) - 1;
2589 ref_pic_list_modification++;
2592 ref_pic_list_modification->modification_of_pic_nums_idc = 3;
2596 _insert_ref_pic_marking_for_unused_frame (GstH264SliceHdr * slice_hdr,
2597 gint cur_frame_num, gint unused_frame_num)
2599 GstH264RefPicMarking *refpicmarking;
2601 slice_hdr->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag = 1;
2602 slice_hdr->dec_ref_pic_marking.n_ref_pic_marking = 2;
2604 refpicmarking = &slice_hdr->dec_ref_pic_marking.ref_pic_marking[0];
2606 refpicmarking->memory_management_control_operation = 1;
2607 refpicmarking->difference_of_pic_nums_minus1 =
2608 cur_frame_num - unused_frame_num - 1;
2610 refpicmarking = &slice_hdr->dec_ref_pic_marking.ref_pic_marking[1];
2611 refpicmarking->memory_management_control_operation = 0;
2615 _add_slice_header (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2616 GstH264PPS * pps, VAEncSliceParameterBufferH264 * slice,
2617 GstVaH264EncFrame * list0[16], guint list0_num,
2618 GstVaH264EncFrame * list1[16], guint list1_num)
2620 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2621 GstH264SliceHdr slice_hdr;
2622 guint size, trail_bits;
2623 GstH264NalUnitType nal_type = GST_H264_NAL_SLICE;
2624 #define SLICE_HDR_SIZE 4 + GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8
2625 guint8 packed_slice_hdr[SLICE_HDR_SIZE] = { 0, };
2626 #undef SLICE_HDR_SIZE
2628 if (frame->frame_num == 0)
2629 nal_type = GST_H264_NAL_SLICE_IDR;
2632 slice_hdr = (GstH264SliceHdr) {
2633 .first_mb_in_slice = slice->macroblock_address,
2634 .type = slice->slice_type,
2636 .frame_num = frame->frame_num,
2637 /* interlaced not supported now. */
2638 .field_pic_flag = 0,
2639 .bottom_field_flag = 0,
2640 .idr_pic_id = (frame->frame_num == 0 ? slice->idr_pic_id : 0),
2641 /* only pic_order_cnt_type 1 is supported now. */
2642 .pic_order_cnt_lsb = slice->pic_order_cnt_lsb,
2643 .delta_pic_order_cnt_bottom = slice->delta_pic_order_cnt_bottom,
2644 /* Only for B frame. */
2645 .direct_spatial_mv_pred_flag =
2646 (frame->type == GST_H264_B_SLICE ?
2647 slice->direct_spatial_mv_pred_flag : 0),
2649 .num_ref_idx_active_override_flag = slice->num_ref_idx_active_override_flag,
2650 .num_ref_idx_l0_active_minus1 = slice->num_ref_idx_l0_active_minus1,
2651 .num_ref_idx_l1_active_minus1 = slice->num_ref_idx_l1_active_minus1,
2652 /* Calculate it later. */
2653 .ref_pic_list_modification_flag_l0 = 0,
2654 .ref_pic_list_modification_flag_l1 = 0,
2655 /* We have weighted_pred_flag and weighted_bipred_idc 0 here, no
2656 * need weight_table. */
2658 .dec_ref_pic_marking = {
2659 .no_output_of_prior_pics_flag = 0,
2660 .long_term_reference_flag = 0,
2661 /* If not sliding_window, we set it later. */
2662 .adaptive_ref_pic_marking_mode_flag = 0,
2665 .cabac_init_idc = slice->cabac_init_idc,
2666 .slice_qp_delta = slice->slice_qp_delta,
2668 .disable_deblocking_filter_idc = slice->disable_deblocking_filter_idc,
2669 .slice_alpha_c0_offset_div2 = slice->slice_alpha_c0_offset_div2,
2670 .slice_beta_offset_div2 = slice->slice_beta_offset_div2,
2674 /* Reorder the ref lists if needed. */
2675 if (list0_num > 1) {
2676 /* list0 is in poc descend order now. */
2677 if (_ref_list_need_reorder (list0, list0_num, FALSE))
2678 _insert_ref_pic_list_modification (&slice_hdr, list0, list0_num, FALSE);
2681 if (list0_num > 1) {
2682 /* list0 is in poc ascend order now. */
2683 if (_ref_list_need_reorder (list1, list1_num, TRUE)) {
2684 _insert_ref_pic_list_modification (&slice_hdr, list1, list1_num, TRUE);
2688 /* Mark the unused reference explicitly which this frame replaces. */
2689 if (frame->unused_for_reference_pic_num >= 0) {
2690 g_assert (frame->is_ref);
2691 _insert_ref_pic_marking_for_unused_frame (&slice_hdr, frame->frame_num,
2692 frame->unused_for_reference_pic_num);
2695 size = sizeof (packed_slice_hdr);
2697 if (gst_h264_bit_writer_slice_hdr (&slice_hdr, TRUE, nal_type, frame->is_ref,
2698 packed_slice_hdr, &size, &trail_bits) != GST_H264_BIT_WRITER_OK) {
2699 GST_ERROR_OBJECT (self, "Failed to generate the slice header");
2703 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2704 VAEncPackedHeaderSlice, packed_slice_hdr, size * 8 + trail_bits,
2706 GST_ERROR_OBJECT (self, "Failed to add the packed slice header");
2714 _add_aud (GstVaH264Enc * self, GstVaH264EncFrame * frame)
2716 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2717 guint8 aud_data[8] = { };
2719 guint8 primary_pic_type = 0;
2721 switch (frame->type) {
2722 case GST_H264_I_SLICE:
2723 primary_pic_type = 0;
2725 case GST_H264_P_SLICE:
2726 primary_pic_type = 1;
2728 case GST_H264_B_SLICE:
2729 primary_pic_type = 2;
2732 g_assert_not_reached ();
2736 size = sizeof (aud_data);
2737 if (gst_h264_bit_writer_aud (primary_pic_type, TRUE, aud_data,
2738 &size) != GST_H264_BIT_WRITER_OK) {
2739 GST_ERROR_OBJECT (self, "Failed to generate the AUD");
2743 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2744 VAEncPackedHeaderRawData, aud_data, size * 8, FALSE)) {
2745 GST_ERROR_OBJECT (self, "Failed to add the AUD");
2753 _create_sei_cc_message (GstVideoCaptionMeta * cc_meta,
2754 GstH264SEIMessage * sei_msg)
2757 GstH264RegisteredUserData *user_data;
2759 sei_msg->payloadType = GST_H264_SEI_REGISTERED_USER_DATA;
2761 user_data = &sei_msg->payload.registered_user_data;
2763 user_data->country_code = 181;
2764 user_data->size = 10 + cc_meta->size;
2766 data = g_malloc (user_data->size);
2768 /* 16-bits itu_t_t35_provider_code */
2771 /* 32-bits ATSC_user_identifier */
2776 /* 8-bits ATSC1_data_user_data_type_code */
2779 * 1 bit process_em_data_flag (0)
2780 * 1 bit process_cc_data_flag (1)
2781 * 1 bit additional_data_flag (0)
2784 data[7] = ((cc_meta->size / 3) & 0x1f) | 0x40;
2785 /* 8 bits em_data, unused */
2788 memcpy (data + 9, cc_meta->data, cc_meta->size);
2791 data[user_data->size - 1] = 255;
2793 user_data->data = data;
2797 _create_sei_cc_data (GPtrArray * cc_list, guint8 * sei_data, guint * data_size)
2799 GArray *msg_list = NULL;
2800 GstH264BitWriterResult ret;
2803 msg_list = g_array_new (TRUE, TRUE, sizeof (GstH264SEIMessage));
2804 g_array_set_clear_func (msg_list, (GDestroyNotify) gst_h264_sei_clear);
2805 g_array_set_size (msg_list, cc_list->len);
2807 for (i = 0; i < cc_list->len; i++) {
2808 GstH264SEIMessage *msg = &g_array_index (msg_list, GstH264SEIMessage, i);
2809 _create_sei_cc_message (g_ptr_array_index (cc_list, i), msg);
2812 ret = gst_h264_bit_writer_sei (msg_list, TRUE, sei_data, data_size);
2814 g_array_unref (msg_list);
2816 return (ret == GST_H264_BIT_WRITER_OK);
2820 _add_sei_cc (GstVaH264Enc * self, GstVideoCodecFrame * gst_frame)
2822 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2823 GstVaH264EncFrame *frame;
2824 GPtrArray *cc_list = NULL;
2825 GstVideoCaptionMeta *cc_meta;
2826 gpointer iter = NULL;
2827 guint8 *packed_sei = NULL;
2830 frame = _enc_frame (gst_frame);
2832 /* SEI header size */
2834 while ((cc_meta = (GstVideoCaptionMeta *)
2835 gst_buffer_iterate_meta_filtered (gst_frame->input_buffer, &iter,
2836 GST_VIDEO_CAPTION_META_API_TYPE))) {
2837 if (cc_meta->caption_type != GST_VIDEO_CAPTION_TYPE_CEA708_RAW)
2841 cc_list = g_ptr_array_new ();
2843 g_ptr_array_add (cc_list, cc_meta);
2844 /* Add enough SEI message size for bitwriter. */
2845 sei_size += cc_meta->size + 50;
2851 packed_sei = g_malloc0 (sei_size);
2853 if (!_create_sei_cc_data (cc_list, packed_sei, &sei_size)) {
2854 GST_WARNING_OBJECT (self, "Failed to write the SEI CC data");
2858 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2859 VAEncPackedHeaderRawData, packed_sei, sei_size * 8, FALSE)) {
2860 GST_WARNING_OBJECT (self, "Failed to add SEI CC data");
2865 g_clear_pointer (&cc_list, g_ptr_array_unref);
2867 g_free (packed_sei);
2871 _encode_one_frame (GstVaH264Enc * self, GstVideoCodecFrame * gst_frame)
2873 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2874 VAEncPictureParameterBufferH264 pic_param;
2876 GstVaH264EncFrame *list0[16] = { NULL, };
2877 guint list0_num = 0;
2878 GstVaH264EncFrame *list1[16] = { NULL, };
2879 guint list1_num = 0;
2880 guint slice_of_mbs, slice_mod_mbs, slice_start_mb, slice_mbs;
2882 GstVaH264EncFrame *frame;
2884 g_return_val_if_fail (gst_frame, FALSE);
2886 frame = _enc_frame (gst_frame);
2888 if (self->aud && !_add_aud (self, frame))
2891 /* Repeat the SPS for IDR. */
2892 if (frame->poc == 0) {
2893 VAEncSequenceParameterBufferH264 sequence;
2895 if (!gst_va_base_enc_add_rate_control_parameter (base, frame->picture,
2896 self->rc.rc_ctrl_mode, self->rc.max_bitrate_bits,
2897 self->rc.target_percentage, self->rc.qp_i, self->rc.min_qp,
2898 self->rc.max_qp, self->rc.mbbrc))
2901 if (!gst_va_base_enc_add_quality_level_parameter (base, frame->picture,
2902 self->rc.target_usage))
2905 if (!gst_va_base_enc_add_frame_rate_parameter (base, frame->picture))
2908 if (!gst_va_base_enc_add_hrd_parameter (base, frame->picture,
2909 self->rc.rc_ctrl_mode, self->rc.cpb_length_bits))
2912 if (!gst_va_base_enc_add_trellis_parameter (base, frame->picture,
2916 _fill_sequence_param (self, &sequence);
2917 if (!_fill_sps (self, &sequence))
2920 if (!_add_sequence_parameter (self, frame->picture, &sequence))
2923 if ((self->packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE)
2924 && !_add_sequence_header (self, frame))
2928 /* Non I frame, construct reference list. */
2929 if (frame->type != GST_H264_I_SLICE) {
2930 GstVaH264EncFrame *vaf;
2931 GstVideoCodecFrame *f;
2933 for (i = g_queue_get_length (&base->ref_list) - 1; i >= 0; i--) {
2934 f = g_queue_peek_nth (&base->ref_list, i);
2935 vaf = _enc_frame (f);
2936 if (vaf->poc > frame->poc)
2939 list0[list0_num] = vaf;
2943 /* reorder to select the most nearest forward frames. */
2944 g_qsort_with_data (list0, list0_num, sizeof (gpointer),
2945 (GCompareDataFunc) _poc_des_compare, NULL);
2947 if (list0_num > self->gop.ref_num_list0)
2948 list0_num = self->gop.ref_num_list0;
2951 if (frame->type == GST_H264_B_SLICE) {
2952 GstVaH264EncFrame *vaf;
2953 GstVideoCodecFrame *f;
2955 for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
2956 f = g_queue_peek_nth (&base->ref_list, i);
2957 vaf = _enc_frame (f);
2958 if (vaf->poc < frame->poc)
2961 list1[list1_num] = vaf;
2965 /* reorder to select the most nearest backward frames. */
2966 g_qsort_with_data (list1, list1_num, sizeof (gpointer),
2967 (GCompareDataFunc) _poc_asc_compare, NULL);
2969 if (list1_num > self->gop.ref_num_list1)
2970 list1_num = self->gop.ref_num_list1;
2973 g_assert (list0_num + list1_num <= self->gop.num_ref_frames);
2975 if (!_fill_picture_parameter (self, frame, &pic_param))
2977 if (!_add_picture_parameter (self, frame, &pic_param))
2979 _fill_pps (&pic_param, &self->sequence_hdr, &pps);
2981 if ((self->packed_headers & VA_ENC_PACKED_HEADER_PICTURE)
2982 && frame->type == GST_H264_I_SLICE
2983 && !_add_picture_header (self, frame, &pps))
2987 /* CC errors are not fatal */
2988 _add_sei_cc (self, gst_frame);
2991 slice_of_mbs = self->mb_width * self->mb_height / self->num_slices;
2992 slice_mod_mbs = self->mb_width * self->mb_height % self->num_slices;
2995 for (i = 0; i < self->num_slices; i++) {
2996 VAEncSliceParameterBufferH264 slice;
2998 slice_mbs = slice_of_mbs;
2999 /* divide the remainder to each equally */
3000 if (slice_mod_mbs) {
3005 if (!_add_one_slice (self, frame, slice_start_mb, slice_mbs, &slice,
3006 list0, list0_num, list1, list1_num))
3009 if ((self->packed_headers & VA_ENC_PACKED_HEADER_SLICE) &&
3010 (!_add_slice_header (self, frame, &pps, &slice, list0, list0_num,
3014 slice_start_mb += slice_mbs;
3017 if (!gst_va_encoder_encode (base->encoder, frame->picture)) {
3018 GST_ERROR_OBJECT (self, "Encode frame error");
3026 gst_va_h264_enc_flush (GstVideoEncoder * venc)
3028 GstVaH264Enc *self = GST_VA_H264_ENC (venc);
3030 /* begin from an IDR after flush. */
3031 self->gop.cur_frame_index = 0;
3032 self->gop.cur_frame_num = 0;
3034 return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (venc);
3038 gst_va_h264_enc_prepare_output (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
3040 GstVaH264Enc *self = GST_VA_H264_ENC (base);
3041 GstVaH264EncFrame *frame_enc;
3043 frame_enc = _enc_frame (frame);
3046 base->start_pts + base->frame_duration * frame_enc->total_frame_count;
3047 /* The PTS should always be later than the DTS. */
3048 frame->dts = base->start_pts + base->frame_duration *
3049 ((gint64) base->output_frame_count -
3050 (gint64) self->gop.num_reorder_frames);
3051 base->output_frame_count++;
3052 frame->duration = base->frame_duration;
3056 _sort_by_frame_num (gconstpointer a, gconstpointer b, gpointer user_data)
3058 GstVaH264EncFrame *frame1 = _enc_frame ((GstVideoCodecFrame *) a);
3059 GstVaH264EncFrame *frame2 = _enc_frame ((GstVideoCodecFrame *) b);
3061 g_assert (frame1->frame_num != frame2->frame_num);
3063 return frame1->frame_num - frame2->frame_num;
3066 static GstVideoCodecFrame *
3067 _find_unused_reference_frame (GstVaH264Enc * self, GstVaH264EncFrame * frame)
3069 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3070 GstVaH264EncFrame *b_vaframe;
3071 GstVideoCodecFrame *b_frame;
3074 /* We still have more space. */
3075 if (g_queue_get_length (&base->ref_list) < self->gop.num_ref_frames)
3078 /* Not b_pyramid, sliding window is enough. */
3079 if (!self->gop.b_pyramid)
3080 return g_queue_peek_head (&base->ref_list);
3082 /* I/P frame, just using sliding window. */
3083 if (frame->type != GST_H264_B_SLICE)
3084 return g_queue_peek_head (&base->ref_list);
3086 /* Choose the B frame with lowest POC. */
3089 for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
3090 GstVaH264EncFrame *vaf;
3091 GstVideoCodecFrame *f;
3093 f = g_queue_peek_nth (&base->ref_list, i);
3094 vaf = _enc_frame (f);
3095 if (vaf->type != GST_H264_B_SLICE)
3100 b_vaframe = _enc_frame (b_frame);
3104 b_vaframe = _enc_frame (b_frame);
3105 g_assert (vaf->poc != b_vaframe->poc);
3106 if (vaf->poc < b_vaframe->poc) {
3108 b_vaframe = _enc_frame (b_frame);
3112 /* No B frame as ref. */
3114 return g_queue_peek_head (&base->ref_list);
3116 if (b_frame != g_queue_peek_head (&base->ref_list)) {
3117 b_vaframe = _enc_frame (b_frame);
3118 frame->unused_for_reference_pic_num = b_vaframe->frame_num;
3119 GST_LOG_OBJECT (self, "The frame with POC: %d, pic_num %d will be"
3120 " replaced by the frame with POC: %d, pic_num %d explicitly by"
3121 " using memory_management_control_operation=1",
3122 b_vaframe->poc, b_vaframe->frame_num, frame->poc, frame->frame_num);
3128 static GstFlowReturn
3129 gst_va_h264_enc_encode_frame (GstVaBaseEnc * base,
3130 GstVideoCodecFrame * gst_frame, gboolean is_last)
3132 GstVaH264Enc *self = GST_VA_H264_ENC (base);
3133 GstVaH264EncFrame *frame;
3134 GstVideoCodecFrame *unused_ref = NULL;
3136 frame = _enc_frame (gst_frame);
3137 frame->last_frame = is_last;
3139 g_assert (frame->picture == NULL);
3140 frame->picture = gst_va_encode_picture_new (base->encoder,
3141 gst_frame->input_buffer);
3143 if (!frame->picture) {
3144 GST_ERROR_OBJECT (self, "Failed to create the encode picture");
3145 return GST_FLOW_ERROR;
3149 unused_ref = _find_unused_reference_frame (self, frame);
3151 if (!_encode_one_frame (self, gst_frame)) {
3152 GST_ERROR_OBJECT (self, "Failed to encode the frame");
3153 return GST_FLOW_ERROR;
3156 g_queue_push_tail (&base->output_list, gst_video_codec_frame_ref (gst_frame));
3158 if (frame->is_ref) {
3160 if (!g_queue_remove (&base->ref_list, unused_ref))
3161 g_assert_not_reached ();
3163 gst_video_codec_frame_unref (unused_ref);
3166 /* Add it into the reference list. */
3167 g_queue_push_tail (&base->ref_list, gst_video_codec_frame_ref (gst_frame));
3168 g_queue_sort (&base->ref_list, _sort_by_frame_num, NULL);
3170 g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
3177 gst_va_h264_enc_new_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
3179 GstVaH264EncFrame *frame_in;
3181 frame_in = gst_va_enc_frame_new ();
3182 frame_in->total_frame_count = base->input_frame_count++;
3183 gst_video_codec_frame_set_user_data (frame, frame_in, gst_va_enc_frame_free);
3189 static const gchar *sink_caps_str =
3190 GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VA,
3192 GST_VIDEO_CAPS_MAKE ("{ NV12 }");
3195 static const gchar *src_caps_str = "video/x-h264";
3198 _register_debug_category (gpointer data)
3200 GST_DEBUG_CATEGORY_INIT (gst_va_h264enc_debug, "vah264enc", 0,
3207 gst_va_h264_enc_init (GTypeInstance * instance, gpointer g_class)
3209 GstVaH264Enc *self = GST_VA_H264_ENC (instance);
3211 /* default values */
3212 self->prop.key_int_max = 0;
3213 self->prop.num_bframes = 0;
3214 self->prop.num_iframes = 0;
3215 self->prop.num_ref_frames = 3;
3216 self->prop.b_pyramid = FALSE;
3217 self->prop.num_slices = 1;
3218 self->prop.min_qp = 1;
3219 self->prop.max_qp = 51;
3220 self->prop.qp_i = 26;
3221 self->prop.qp_p = 26;
3222 self->prop.qp_b = 26;
3223 self->prop.use_dct8x8 = TRUE;
3224 self->prop.use_cabac = TRUE;
3225 self->prop.use_trellis = FALSE;
3226 self->prop.aud = FALSE;
3227 self->prop.cc = TRUE;
3228 self->prop.mbbrc = 0;
3229 self->prop.bitrate = 0;
3230 self->prop.target_percentage = 66;
3231 self->prop.target_usage = 4;
3232 if (properties[PROP_RATE_CONTROL]) {
3233 self->prop.rc_ctrl =
3234 G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])->default_value;
3236 self->prop.rc_ctrl = VA_RC_NONE;
3238 self->prop.cpb_size = 0;
3242 gst_va_h264_enc_set_property (GObject * object, guint prop_id,
3243 const GValue * value, GParamSpec * pspec)
3245 GstVaH264Enc *self = GST_VA_H264_ENC (object);
3246 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3248 GST_OBJECT_LOCK (self);
3251 case PROP_KEY_INT_MAX:
3252 self->prop.key_int_max = g_value_get_uint (value);
3255 self->prop.num_bframes = g_value_get_uint (value);
3258 self->prop.num_iframes = g_value_get_uint (value);
3260 case PROP_NUM_REF_FRAMES:
3261 self->prop.num_ref_frames = g_value_get_uint (value);
3263 case PROP_B_PYRAMID:
3264 self->prop.b_pyramid = g_value_get_boolean (value);
3266 case PROP_NUM_SLICES:
3267 self->prop.num_slices = g_value_get_uint (value);
3270 self->prop.min_qp = g_value_get_uint (value);
3273 self->prop.max_qp = g_value_get_uint (value);
3276 self->prop.qp_i = g_value_get_uint (value);
3277 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3280 self->prop.qp_p = g_value_get_uint (value);
3281 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3284 self->prop.qp_b = g_value_get_uint (value);
3285 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3288 self->prop.use_dct8x8 = g_value_get_boolean (value);
3291 self->prop.use_cabac = g_value_get_boolean (value);
3294 self->prop.use_trellis = g_value_get_boolean (value);
3297 self->prop.aud = g_value_get_boolean (value);
3300 self->prop.cc = g_value_get_boolean (value);
3303 /* Macroblock-level rate control.
3306 * 2: always disable,
3307 * other: reserved. */
3308 switch (g_value_get_enum (value)) {
3309 case GST_VA_FEATURE_DISABLED:
3310 self->prop.mbbrc = 2;
3312 case GST_VA_FEATURE_ENABLED:
3313 self->prop.mbbrc = 1;
3315 case GST_VA_FEATURE_AUTO:
3316 self->prop.mbbrc = 0;
3322 self->prop.bitrate = g_value_get_uint (value);
3323 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3325 case PROP_TARGET_PERCENTAGE:
3326 self->prop.target_percentage = g_value_get_uint (value);
3327 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3329 case PROP_TARGET_USAGE:
3330 self->prop.target_usage = g_value_get_uint (value);
3331 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3333 case PROP_RATE_CONTROL:
3334 self->prop.rc_ctrl = g_value_get_enum (value);
3335 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3338 self->prop.cpb_size = g_value_get_uint (value);
3341 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3344 GST_OBJECT_UNLOCK (self);
3346 #ifndef GST_DISABLE_GST_DEBUG
3347 if (!g_atomic_int_get (&GST_VA_BASE_ENC (self)->reconf)
3348 && base->encoder && gst_va_encoder_is_open (base->encoder)) {
3349 GST_WARNING_OBJECT (self, "Property `%s` change ignored while processing.",
3357 gst_va_h264_enc_get_property (GObject * object, guint prop_id,
3358 GValue * value, GParamSpec * pspec)
3360 GstVaH264Enc *const self = GST_VA_H264_ENC (object);
3362 GST_OBJECT_LOCK (self);
3365 case PROP_KEY_INT_MAX:
3366 g_value_set_uint (value, self->prop.key_int_max);
3369 g_value_set_uint (value, self->prop.num_bframes);
3372 g_value_set_uint (value, self->prop.num_iframes);
3374 case PROP_NUM_REF_FRAMES:
3375 g_value_set_uint (value, self->prop.num_ref_frames);
3377 case PROP_B_PYRAMID:
3378 g_value_set_boolean (value, self->prop.b_pyramid);
3380 case PROP_NUM_SLICES:
3381 g_value_set_uint (value, self->prop.num_slices);
3384 g_value_set_uint (value, self->prop.min_qp);
3387 g_value_set_uint (value, self->prop.max_qp);
3390 g_value_set_uint (value, self->prop.qp_i);
3393 g_value_set_uint (value, self->prop.qp_p);
3396 g_value_set_uint (value, self->prop.qp_b);
3399 g_value_set_boolean (value, self->prop.use_dct8x8);
3402 g_value_set_boolean (value, self->prop.use_cabac);
3405 g_value_set_boolean (value, self->prop.use_trellis);
3408 g_value_set_boolean (value, self->prop.aud);
3411 g_value_set_boolean (value, self->prop.cc);
3414 g_value_set_enum (value, self->prop.mbbrc);
3417 g_value_set_uint (value, self->prop.bitrate);
3419 case PROP_TARGET_PERCENTAGE:
3420 g_value_set_uint (value, self->prop.target_percentage);
3422 case PROP_TARGET_USAGE:
3423 g_value_set_uint (value, self->prop.target_usage);
3425 case PROP_RATE_CONTROL:
3426 g_value_set_enum (value, self->prop.rc_ctrl);
3429 g_value_set_uint (value, self->prop.cpb_size);
3432 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3435 GST_OBJECT_UNLOCK (self);
3439 gst_va_h264_enc_class_init (gpointer g_klass, gpointer class_data)
3441 GstCaps *src_doc_caps, *sink_doc_caps;
3442 GstPadTemplate *sink_pad_templ, *src_pad_templ;
3443 GObjectClass *object_class = G_OBJECT_CLASS (g_klass);
3444 GstElementClass *element_class = GST_ELEMENT_CLASS (g_klass);
3445 GstVideoEncoderClass *venc_class = GST_VIDEO_ENCODER_CLASS (g_klass);
3446 GstVaBaseEncClass *va_enc_class = GST_VA_BASE_ENC_CLASS (g_klass);
3447 GstVaH264EncClass *vah264enc_class = GST_VA_H264_ENC_CLASS (g_klass);
3448 GstVaDisplay *display;
3449 GstVaEncoder *encoder;
3450 struct CData *cdata = class_data;
3452 const gchar *name, *desc;
3453 gint n_props = N_PROPERTIES;
3454 GParamFlags param_flags =
3455 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT;
3457 if (cdata->entrypoint == VAEntrypointEncSlice) {
3458 desc = "VA-API based H.264 video encoder";
3459 name = "VA-API H.264 Encoder";
3461 desc = "VA-API based H.264 low power video encoder";
3462 name = "VA-API H.264 Low Power Encoder";
3465 if (cdata->description)
3466 long_name = g_strdup_printf ("%s in %s", name, cdata->description);
3468 long_name = g_strdup (name);
3470 gst_element_class_set_metadata (element_class, long_name,
3471 "Codec/Encoder/Video/Hardware", desc, "He Junyan <junyan.he@intel.com>");
3473 sink_doc_caps = gst_caps_from_string (sink_caps_str);
3474 src_doc_caps = gst_caps_from_string (src_caps_str);
3476 parent_class = g_type_class_peek_parent (g_klass);
3478 va_enc_class->codec = H264;
3479 va_enc_class->entrypoint = cdata->entrypoint;
3480 va_enc_class->render_device_path = g_strdup (cdata->render_device_path);
3482 sink_pad_templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
3484 gst_element_class_add_pad_template (element_class, sink_pad_templ);
3486 gst_pad_template_set_documentation_caps (sink_pad_templ, sink_doc_caps);
3487 gst_caps_unref (sink_doc_caps);
3489 src_pad_templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
3491 gst_element_class_add_pad_template (element_class, src_pad_templ);
3493 gst_pad_template_set_documentation_caps (src_pad_templ, src_doc_caps);
3494 gst_caps_unref (src_doc_caps);
3496 object_class->set_property = gst_va_h264_enc_set_property;
3497 object_class->get_property = gst_va_h264_enc_get_property;
3499 venc_class->flush = GST_DEBUG_FUNCPTR (gst_va_h264_enc_flush);
3501 va_enc_class->reset_state = GST_DEBUG_FUNCPTR (gst_va_h264_enc_reset_state);
3502 va_enc_class->reconfig = GST_DEBUG_FUNCPTR (gst_va_h264_enc_reconfig);
3503 va_enc_class->new_frame = GST_DEBUG_FUNCPTR (gst_va_h264_enc_new_frame);
3504 va_enc_class->reorder_frame =
3505 GST_DEBUG_FUNCPTR (gst_va_h264_enc_reorder_frame);
3506 va_enc_class->encode_frame = GST_DEBUG_FUNCPTR (gst_va_h264_enc_encode_frame);
3507 va_enc_class->prepare_output =
3508 GST_DEBUG_FUNCPTR (gst_va_h264_enc_prepare_output);
3512 gst_va_display_drm_new_from_path (va_enc_class->render_device_path);
3513 encoder = gst_va_encoder_new (display, va_enc_class->codec,
3514 va_enc_class->entrypoint);
3515 if (gst_va_encoder_get_rate_control_enum (encoder,
3516 vah264enc_class->rate_control)) {
3517 g_snprintf (vah264enc_class->rate_control_type_name,
3518 G_N_ELEMENTS (vah264enc_class->rate_control_type_name) - 1,
3519 "GstVaEncoderRateControl_%" GST_FOURCC_FORMAT "%s_%s",
3520 GST_FOURCC_ARGS (va_enc_class->codec),
3521 (va_enc_class->entrypoint == VAEntrypointEncSliceLP) ? "_LP" : "",
3522 g_path_get_basename (va_enc_class->render_device_path));
3523 vah264enc_class->rate_control_type =
3524 g_enum_register_static (vah264enc_class->rate_control_type_name,
3525 vah264enc_class->rate_control);
3526 gst_type_mark_as_plugin_api (vah264enc_class->rate_control_type, 0);
3528 gst_object_unref (encoder);
3529 gst_object_unref (display);
3533 g_free (cdata->description);
3534 g_free (cdata->render_device_path);
3535 gst_caps_unref (cdata->src_caps);
3536 gst_caps_unref (cdata->sink_caps);
3540 * GstVaH264Enc:key-int-max:
3542 * The maximal distance between two keyframes.
3544 properties[PROP_KEY_INT_MAX] = g_param_spec_uint ("key-int-max",
3545 "Key frame maximal interval",
3546 "The maximal distance between two keyframes. It decides the size of GOP"
3547 " (0: auto-calculate)", 0, MAX_GOP_SIZE, 0, param_flags);
3550 * GstVaH264Enc:b-frames:
3552 * Number of B-frames between two reference frames.
3554 properties[PROP_BFRAMES] = g_param_spec_uint ("b-frames", "B Frames",
3555 "Number of B frames between I and P reference frames", 0, 31, 0,
3559 * GstVaH264Enc:i-frames:
3561 * Force the number of i-frames insertion within one GOP.
3563 properties[PROP_IFRAMES] = g_param_spec_uint ("i-frames", "I Frames",
3564 "Force the number of I frames insertion within one GOP, not including the "
3565 "first IDR frame", 0, 1023, 0, param_flags);
3568 * GstVaH264Enc:ref-frames:
3570 * The number of reference frames.
3572 properties[PROP_NUM_REF_FRAMES] = g_param_spec_uint ("ref-frames",
3573 "Number of Reference Frames",
3574 "Number of reference frames, including both the forward and the backward",
3575 0, 16, 3, param_flags);
3578 * GstVaH264Enc:b-pyramid:
3580 * Enable the b-pyramid reference structure in GOP.
3582 properties[PROP_B_PYRAMID] = g_param_spec_boolean ("b-pyramid", "b pyramid",
3583 "Enable the b-pyramid reference structure in the GOP", FALSE,
3587 * GstVaH264Enc:num-slices:
3589 * The number of slices per frame.
3591 properties[PROP_NUM_SLICES] = g_param_spec_uint ("num-slices",
3592 "Number of Slices", "Number of slices per frame", 1, 200, 1, param_flags);
3595 * GstVaH264Enc:max-qp:
3597 * The maximum quantizer value.
3599 properties[PROP_MAX_QP] = g_param_spec_uint ("max-qp", "Maximum QP",
3600 "Maximum quantizer value for each frame", 0, 51, 51, param_flags);
3603 * GstVaH264Enc:min-qp:
3605 * The minimum quantizer value.
3607 properties[PROP_MIN_QP] = g_param_spec_uint ("min-qp", "Minimum QP",
3608 "Minimum quantizer value for each frame", 0, 51, 1, param_flags);
3613 * The quantizer value for I frame.
3615 * In CQP mode, it specifies the QP of I frame, in other mode, it specifies
3616 * the init QP of all frames.
3618 properties[PROP_QP_I] = g_param_spec_uint ("qpi", "I Frame QP",
3619 "The quantizer value for I frame. In CQP mode, it specifies the QP of I "
3620 "frame, in other mode, it specifies the init QP of all frames", 0, 51, 26,
3621 param_flags | GST_PARAM_MUTABLE_PLAYING);
3626 * The quantizer value for P frame. Available only in CQP mode.
3628 properties[PROP_QP_P] = g_param_spec_uint ("qpp",
3629 "The quantizer value for P frame",
3630 "The quantizer value for P frame. Available only in CQP mode",
3631 0, 51, 26, param_flags | GST_PARAM_MUTABLE_PLAYING);
3636 * The quantizer value for B frame. Available only in CQP mode.
3638 properties[PROP_QP_B] = g_param_spec_uint ("qpb",
3639 "The quantizer value for B frame",
3640 "The quantizer value for B frame. Available only in CQP mode",
3641 0, 51, 26, param_flags | GST_PARAM_MUTABLE_PLAYING);
3644 * GstVaH264Enc:dct8x8:
3646 * Enable adaptive use of 8x8 transforms in I-frames. This improves
3647 * the compression ratio but requires high profile at least.
3649 properties[PROP_DCT8X8] = g_param_spec_boolean ("dct8x8", "Enable 8x8 DCT",
3650 "Enable adaptive use of 8x8 transforms in I-frames", TRUE, param_flags);
3653 * GstVaH264Enc:cabac:
3655 * It enables CABAC entropy coding mode to improve compression ratio,
3656 * but requires main profile at least.
3658 properties[PROP_CABAC] = g_param_spec_boolean ("cabac", "Enable CABAC",
3659 "Enable CABAC entropy coding mode", TRUE, param_flags);
3662 * GstVaH264Enc:trellis:
3664 * It enable the trellis quantization method. Trellis is an improved
3665 * quantization algorithm.
3667 properties[PROP_TRELLIS] = g_param_spec_boolean ("trellis", "Enable trellis",
3668 "Enable the trellis quantization method", FALSE, param_flags);
3673 * Insert the AU (Access Unit) delimeter for each frame.
3675 properties[PROP_AUD] = g_param_spec_boolean ("aud", "Insert AUD",
3676 "Insert AU (Access Unit) delimeter for each frame", FALSE, param_flags);
3679 * GstVaH264Enc:cc-insert:
3681 * Closed Caption Insert mode. Only CEA-708 RAW format is supported for now.
3683 properties[PROP_CC] = g_param_spec_boolean ("cc-insert",
3684 "Insert Closed Captions",
3685 "Insert CEA-708 Closed Captions",
3686 TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3689 * GstVaH264Enc:mbbrc:
3691 * Macroblock level bitrate control. Not available in CQP mode.
3693 properties[PROP_MBBRC] = g_param_spec_enum ("mbbrc",
3694 "Macroblock level Bitrate Control",
3695 "Macroblock level Bitrate Control. Not available in CQP mode",
3696 GST_TYPE_VA_FEATURE, GST_VA_FEATURE_AUTO, param_flags);
3699 * GstVaH264Enc:bitrate:
3701 * The desired target bitrate, expressed in kbps. Not available in CQP mode.
3703 * * **CBR**: This applies equally to the minimum, maximum and target bitrate.
3704 * * **VBR**: This applies to the target bitrate. The driver will use the
3705 * "target-percentage" together to calculate the minimum and maximum
3707 * * **VCM**: This applies to the target bitrate. The minimum and maximum
3708 * bitrate are not needed.
3710 properties[PROP_BITRATE] = g_param_spec_uint ("bitrate", "Bitrate (kbps)",
3711 "The desired bitrate expressed in kbps (0: auto-calculate)",
3712 0, 2000 * 1024, 0, param_flags | GST_PARAM_MUTABLE_PLAYING);
3715 * GstVaH264Enc:target-percentage:
3717 * The target percentage of the max bitrate, and expressed in uint, equal to
3718 * "target percentage" * 100. Available only when rate-control is VBR.
3720 * "target percentage" = "target bitrate" * 100 / "max bitrate"
3722 * The driver uses it to calculate the minimum and maximum bitrate.
3724 properties[PROP_TARGET_PERCENTAGE] = g_param_spec_uint ("target-percentage",
3725 "target bitrate percentage",
3726 "The percentage for 'target bitrate'/'maximum bitrate' (Only in VBR)",
3727 50, 100, 66, param_flags | GST_PARAM_MUTABLE_PLAYING);
3730 * GstVaH264Enc:target-usage:
3732 * The target usage of the encoder.
3734 * It controls and balances the encoding speed and the encoding quality. The
3735 * lower value has better quality but slower speed, the higher value has
3736 * faster speed but lower quality.
3738 properties[PROP_TARGET_USAGE] = g_param_spec_uint ("target-usage",
3740 "The target usage to control and balance the encoding speed/quality",
3741 1, 7, 4, param_flags | GST_PARAM_MUTABLE_PLAYING);
3744 * GstVaH264Enc:cpb-size:
3746 * The desired max CPB size in Kb (0: auto-calculate).
3748 properties[PROP_CPB_SIZE] = g_param_spec_uint ("cpb-size",
3749 "max CPB size in Kb",
3750 "The desired max CPB size in Kb (0: auto-calculate)", 0, 2000 * 1024, 0,
3751 param_flags | GST_PARAM_MUTABLE_PLAYING);
3753 if (vah264enc_class->rate_control_type > 0) {
3754 properties[PROP_RATE_CONTROL] = g_param_spec_enum ("rate-control",
3755 "rate control mode", "The desired rate control mode for the encoder",
3756 vah264enc_class->rate_control_type,
3757 vah264enc_class->rate_control[0].value,
3758 GST_PARAM_CONDITIONALLY_AVAILABLE | GST_PARAM_MUTABLE_PLAYING
3762 properties[PROP_RATE_CONTROL] = NULL;
3765 g_object_class_install_properties (object_class, n_props, properties);
3769 _complete_src_caps (GstCaps * srccaps)
3771 GstCaps *caps = gst_caps_copy (srccaps);
3773 gst_caps_set_simple (caps, "alignment", G_TYPE_STRING, "au", "stream-format",
3774 G_TYPE_STRING, "byte-stream", NULL);
3779 /* bug in mesa gallium which adds P010_10LE. Admit only 420 chroma formats */
3781 _fix_sink_caps (GstVaDisplay * display, GstCaps * sinkcaps)
3786 if (!GST_VA_DISPLAY_IS_IMPLEMENTATION (display, MESA_GALLIUM))
3787 return gst_caps_ref (sinkcaps);
3789 caps = gst_caps_copy (sinkcaps);
3790 for (i = 0; i < gst_caps_get_size (caps); i++) {
3791 GstStructure *st = gst_caps_get_structure (caps, i);
3792 const GValue *formats = gst_structure_get_value (st, "format");
3796 /* let's accept it as is */
3797 if (G_VALUE_HOLDS_STRING (formats))
3800 g_assert (GST_VALUE_HOLDS_LIST (formats));
3802 num = gst_value_list_get_size (formats);
3803 fmts = g_array_sized_new (FALSE, FALSE, sizeof (GstVideoFormat), num);
3804 for (j = 0; j < num; j++) {
3805 const gchar *format =
3806 g_value_get_string (gst_value_list_get_value (formats, j));
3807 GstVideoFormat f = gst_video_format_from_string (format);
3808 if (f != GST_VIDEO_FORMAT_UNKNOWN
3809 && gst_va_chroma_from_video_format (f) == VA_RT_FORMAT_YUV420)
3810 g_array_append_val (fmts, f);
3813 if (fmts->len == 0) {
3814 GST_ERROR ("No valid formats in sink caps template.");
3815 g_array_unref (fmts);
3819 if (fmts->len == 1) {
3820 GValue v = G_VALUE_INIT;
3822 /* let's accept it as is */
3823 g_value_init (&v, G_TYPE_STRING);
3824 g_value_set_string (&v,
3825 gst_video_format_to_string (g_array_index (fmts, GstVideoFormat, 0)));
3826 gst_structure_set_value (st, "format", &v);
3829 GValue val = G_VALUE_INIT;
3830 gst_value_array_init (&val, fmts->len);
3832 for (j = 0; j < fmts->len; j++) {
3833 GValue v = G_VALUE_INIT;
3835 g_value_init (&v, G_TYPE_STRING);
3836 g_value_set_string (&v,
3837 gst_video_format_to_string (g_array_index (fmts, GstVideoFormat,
3839 gst_value_array_append_value (&val, &v);
3843 gst_structure_set_value (st, "format", &val);
3844 g_value_unset (&val);
3847 g_array_unref (fmts);
3854 gst_va_h264_enc_register (GstPlugin * plugin, GstVaDevice * device,
3855 GstCaps * sink_caps, GstCaps * src_caps, guint rank,
3856 VAEntrypoint entrypoint)
3858 static GOnce debug_once = G_ONCE_INIT;
3860 GTypeInfo type_info = {
3861 .class_size = sizeof (GstVaH264EncClass),
3862 .class_init = gst_va_h264_enc_class_init,
3863 .instance_size = sizeof (GstVaH264Enc),
3864 .instance_init = gst_va_h264_enc_init,
3866 struct CData *cdata;
3868 gchar *type_name, *feature_name;
3870 g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE);
3871 g_return_val_if_fail (GST_IS_VA_DEVICE (device), FALSE);
3872 g_return_val_if_fail (GST_IS_CAPS (sink_caps), FALSE);
3873 g_return_val_if_fail (GST_IS_CAPS (src_caps), FALSE);
3874 g_return_val_if_fail (entrypoint == VAEntrypointEncSlice ||
3875 entrypoint == VAEntrypointEncSliceLP, FALSE);
3877 cdata = g_new (struct CData, 1);
3878 cdata->entrypoint = entrypoint;
3879 cdata->description = NULL;
3880 cdata->render_device_path = g_strdup (device->render_device_path);
3881 cdata->sink_caps = _fix_sink_caps (device->display, sink_caps);
3882 cdata->src_caps = _complete_src_caps (src_caps);
3884 /* class data will be leaked if the element never gets instantiated */
3885 GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
3886 GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
3887 GST_MINI_OBJECT_FLAG_SET (cdata->src_caps,
3888 GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
3890 type_info.class_data = cdata;
3891 if (entrypoint == VAEntrypointEncSlice) {
3892 type_name = g_strdup ("GstVaH264Enc");
3893 feature_name = g_strdup ("vah264enc");
3895 type_name = g_strdup ("GstVaH264LPEnc");
3896 feature_name = g_strdup ("vah264lpenc");
3899 /* The first encoder to be registered should use a constant name,
3900 * like vah264enc, for any additional encoders, we create unique
3901 * names, using inserting the render device name. */
3902 if (g_type_from_name (type_name)) {
3903 gchar *basename = g_path_get_basename (device->render_device_path);
3905 g_free (feature_name);
3906 if (entrypoint == VAEntrypointEncSlice) {
3907 type_name = g_strdup_printf ("GstVa%sH264Enc", basename);
3908 feature_name = g_strdup_printf ("va%sh264enc", basename);
3910 type_name = g_strdup_printf ("GstVa%sH264LPEnc", basename);
3911 feature_name = g_strdup_printf ("va%sh264lpenc", basename);
3913 cdata->description = basename;
3914 /* lower rank for non-first device */
3919 g_once (&debug_once, _register_debug_category, NULL);
3920 type = g_type_register_static (GST_TYPE_VA_BASE_ENC,
3921 type_name, &type_info, 0);
3922 ret = gst_element_register (plugin, feature_name, rank, type);
3925 g_free (feature_name);