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.
54 #include "gstvah264enc.h"
56 #include <gst/codecparsers/gsth264bitwriter.h>
57 #include <gst/va/gstva.h>
58 #include <gst/va/vasurfaceimage.h>
59 #include <gst/video/video.h>
60 #include <va/va_drmcommon.h>
63 #include "gstvabaseenc.h"
64 #include "gstvaencoder.h"
65 #include "gstvacaps.h"
66 #include "gstvaprofile.h"
67 #include "gstvadisplay_priv.h"
69 GST_DEBUG_CATEGORY_STATIC (gst_va_h264enc_debug);
70 #define GST_CAT_DEFAULT gst_va_h264enc_debug
72 #define GST_VA_H264_ENC(obj) ((GstVaH264Enc *) obj)
73 #define GST_VA_H264_ENC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_FROM_INSTANCE (obj), GstVaH264EncClass))
74 #define GST_VA_H264_ENC_CLASS(klass) ((GstVaH264EncClass *) klass)
76 typedef struct _GstVaH264Enc GstVaH264Enc;
77 typedef struct _GstVaH264EncClass GstVaH264EncClass;
78 typedef struct _GstVaH264EncFrame GstVaH264EncFrame;
79 typedef struct _GstVaH264LevelLimits GstVaH264LevelLimits;
99 PROP_TARGET_PERCENTAGE,
107 static GParamSpec *properties[N_PROPERTIES];
109 static GstElementClass *parent_class = NULL;
111 /* Scale factor for bitrate (HRD bit_rate_scale: min = 6) */
113 /* Scale factor for CPB size (HRD cpb_size_scale: min = 4) */
114 #define SX_CPB_SIZE 4
115 /* Maximum sizes for common headers (in bits) */
116 #define MAX_SPS_HDR_SIZE 16473
117 #define MAX_VUI_PARAMS_SIZE 210
118 #define MAX_HRD_PARAMS_SIZE 4103
119 #define MAX_PPS_HDR_SIZE 101
120 #define MAX_SLICE_HDR_SIZE 397 + 2572 + 6670 + 2402
122 #define MAX_GOP_SIZE 1024
125 struct _GstVaH264EncClass
127 GstVaBaseEncClass parent_class;
144 guint32 num_ref_frames;
155 gboolean use_trellis;
160 guint32 target_percentage;
161 guint32 target_usage;
168 const gchar *level_str;
169 /* Minimum Compression Ratio (A.3.1) */
173 gboolean use_trellis;
175 guint32 packed_headers;
179 /* frames between two IDR [idr, ...., idr) */
181 /* How may IDRs we have encoded */
182 guint32 total_idr_count;
183 /* frames between I/P and P frames [I, B, B, .., B, P) */
185 /* frames between I frames [I, B, B, .., B, P, ..., I), open GOP */
187 /* B frames between I/P and P. */
189 /* Use B pyramid structure in the GOP. */
191 /* Level 0 is the simple B not acting as ref. */
192 guint32 highest_pyramid_level;
193 /* If open GOP, I frames within a GOP. */
195 /* A map of all frames types within a GOP. */
200 guint8 pyramid_level;
201 /* Only for b pyramid */
202 gint left_ref_poc_diff;
203 gint right_ref_poc_diff;
204 } frame_types[MAX_GOP_SIZE];
205 /* current index in the frames types map. */
206 guint cur_frame_index;
207 /* Number of ref frames within current GOP. H264's frame num. */
209 /* Max frame num within a GOP. */
210 guint32 max_frame_num;
211 guint32 log2_max_frame_num;
212 /* Max poc within a GOP. */
213 guint32 max_pic_order_cnt;
214 guint32 log2_max_pic_order_cnt;
216 /* Total ref frames of list0 and list1. */
217 guint32 num_ref_frames;
218 guint32 ref_num_list0;
219 guint32 ref_num_list1;
221 guint num_reorder_frames;
227 guint32 rc_ctrl_mode;
234 /* macroblock bitrate control */
236 guint target_bitrate;
237 guint target_percentage;
240 guint max_bitrate_bits;
241 guint target_bitrate_bits;
242 /* length of CPB buffer */
244 /* length of CPB buffer (bits) */
245 guint cpb_length_bits;
248 GstH264SPS sequence_hdr;
251 struct _GstVaH264EncFrame
253 GstVaEncodePicture *picture;
254 GstH264SliceType type;
257 /* Only for b pyramid */
258 gint left_ref_poc_diff;
259 gint right_ref_poc_diff;
263 /* The pic_num will be marked as unused_for_reference, which is
264 * replaced by this frame. -1 if we do not need to care about it
266 gint unused_for_reference_pic_num;
268 /* The total frame count we handled. */
269 guint total_frame_count;
275 * GstVaH264LevelLimits:
276 * @name: the level name
277 * @level_idc: the H.264 level_idc value
278 * @MaxMBPS: the maximum macroblock processing rate (MB/sec)
279 * @MaxFS: the maximum frame size (MBs)
280 * @MaxDpbMbs: the maxium decoded picture buffer size (MBs)
281 * @MaxBR: the maximum video bit rate (kbps)
282 * @MaxCPB: the maximum CPB size (kbits)
283 * @MinCR: the minimum Compression Ratio
285 * The data structure that describes the limits of an H.264 level.
287 struct _GstVaH264LevelLimits
299 /* Table A-1 - Level limits */
301 static const GstVaH264LevelLimits _va_h264_level_limits[] = {
302 /* level idc MaxMBPS MaxFS MaxDpbMbs MaxBR MaxCPB MinCr */
303 { "1", 10, 1485, 99, 396, 64, 175, 2 },
304 { "1b", 11, 1485, 99, 396, 128, 350, 2 },
305 { "1.1", 11, 3000, 396, 900, 192, 500, 2 },
306 { "1.2", 12, 6000, 396, 2376, 384, 1000, 2 },
307 { "1.3", 13, 11880, 396, 2376, 768, 2000, 2 },
308 { "2", 20, 11880, 396, 2376, 2000, 2000, 2 },
309 { "2.1", 21, 19800, 792, 4752, 4000, 4000, 2 },
310 { "2.2", 22, 20250, 1620, 8100, 4000, 4000, 2 },
311 { "3", 30, 40500, 1620, 8100, 10000, 10000, 2 },
312 { "3.1", 31, 108000, 3600, 18000, 14000, 14000, 4 },
313 { "3.2", 32, 216000, 5120, 20480, 20000, 20000, 4 },
314 { "4", 40, 245760, 8192, 32768, 20000, 25000, 4 },
315 { "4.1", 41, 245760, 8192, 32768, 50000, 62500, 2 },
316 { "4.2", 42, 522240, 8704, 34816, 50000, 62500, 2 },
317 { "5", 50, 589824, 22080, 110400, 135000, 135000, 2 },
318 { "5.1", 51, 983040, 36864, 184320, 240000, 240000, 2 },
319 { "5.2", 52, 2073600, 36864, 184320, 240000, 240000, 2 },
320 { "6", 60, 4177920, 139264, 696320, 240000, 240000, 2 },
321 { "6.1", 61, 8355840, 139264, 696320, 480000, 480000, 2 },
322 { "6.2", 62, 16711680, 139264, 696320, 800000, 800000, 2 },
327 _slice_type_name (GstH264SliceType type)
330 case GST_H264_P_SLICE:
332 case GST_H264_B_SLICE:
334 case GST_H264_I_SLICE:
337 g_assert_not_reached ();
344 _rate_control_get_name (guint32 rc_mode)
359 g_assert_not_reached ();
363 static GstVaH264EncFrame *
364 gst_va_enc_frame_new (void)
366 GstVaH264EncFrame *frame;
368 frame = g_slice_new (GstVaH264EncFrame);
369 frame->frame_num = 0;
370 frame->unused_for_reference_pic_num = -1;
371 frame->picture = NULL;
372 frame->total_frame_count = 0;
373 frame->last_frame = FALSE;
379 gst_va_enc_frame_free (gpointer pframe)
381 GstVaH264EncFrame *frame = pframe;
382 g_clear_pointer (&frame->picture, gst_va_encode_picture_free);
383 g_slice_free (GstVaH264EncFrame, frame);
386 static inline GstVaH264EncFrame *
387 _enc_frame (GstVideoCodecFrame * frame)
389 GstVaH264EncFrame *enc_frame = gst_video_codec_frame_get_user_data (frame);
390 g_assert (enc_frame);
394 /* Normalizes bitrate (and CPB size) for HRD conformance */
396 _calculate_bitrate_hrd (GstVaH264Enc * self)
398 guint bitrate_bits, cpb_bits_size;
400 /* Round down bitrate. This is a hard limit mandated by the user */
401 g_assert (SX_BITRATE >= 6);
402 bitrate_bits = (self->rc.max_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
403 GST_DEBUG_OBJECT (self, "Max bitrate: %u bits/sec", bitrate_bits);
404 self->rc.max_bitrate_bits = bitrate_bits;
406 bitrate_bits = (self->rc.target_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
407 GST_DEBUG_OBJECT (self, "Target bitrate: %u bits/sec", bitrate_bits);
408 self->rc.target_bitrate_bits = bitrate_bits;
410 if (self->rc.cpb_size > 0 && self->rc.cpb_size < (self->rc.max_bitrate / 2)) {
411 GST_INFO_OBJECT (self, "Too small cpb_size: %d", self->rc.cpb_size);
412 self->rc.cpb_size = 0;
415 if (self->rc.cpb_size == 0) {
416 /* We cache 2 second coded data by default. */
417 self->rc.cpb_size = self->rc.max_bitrate * 2;
418 GST_INFO_OBJECT (self, "Adjust cpb_size to: %d", self->rc.cpb_size);
421 /* Round up CPB size. This is an HRD compliance detail */
422 g_assert (SX_CPB_SIZE >= 4);
423 cpb_bits_size = (self->rc.cpb_size * 1000) & ~((1U << SX_CPB_SIZE) - 1);
425 GST_DEBUG_OBJECT (self, "HRD CPB size: %u bits", cpb_bits_size);
426 self->rc.cpb_length_bits = cpb_bits_size;
429 /* Estimates a good enough bitrate if none was supplied */
431 _ensure_rate_control (GstVaH264Enc * self)
433 /* User can specify the properties of: "bitrate", "target-percentage",
434 * "max-qp", "min-qp", "qpi", "qpp", "qpb", "mbbrc", "cpb-size",
435 * "rate-control" and "target-usage" to control the RC behavior.
437 * "target-usage" is different from the others, it controls the encoding
438 * speed and quality, while the others control encoding bit rate and
439 * quality. The lower value has better quality(maybe bigger MV search
440 * range) but slower speed, the higher value has faster speed but lower
443 * The possible composition to control the bit rate and quality:
445 * 1. CQP mode: "rate-control=cqp", then "qpi", "qpp" and "qpb"
446 * specify the QP of I/P/B frames respectively(within the
447 * "max-qp" and "min-qp" range). The QP will not change during
448 * the whole stream. Other properties are ignored.
450 * 2. CBR mode: "rate-control=CBR", then the "bitrate" specify the
451 * target bit rate and the "cpb-size" specifies the max coded
452 * picture buffer size to avoid overflow. If the "bitrate" is not
453 * set, it is calculated by the picture resolution and frame
454 * rate. If "cpb-size" is not set, it is set to the size of
455 * caching 2 second coded data. Encoder will try its best to make
456 * the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
457 * enable bit rate control in macro block level. Other paramters
460 * 3. VBR mode: "rate-control=VBR", then the "bitrate" specify the
461 * target bit rate, "target-percentage" is used to calculate the
462 * max bit rate of VBR mode by ("bitrate" * 100) /
463 * "target-percentage". It is also used by driver to calculate
464 * the min bit rate. The "cpb-size" specifies the max coded
465 * picture buffer size to avoid overflow. If the "bitrate" is not
466 * set, the target bit rate will be calculated by the picture
467 * resolution and frame rate. Encoder will try its best to make
468 * the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
469 * enable bit rate control in macro block level. Other paramters
472 * 4. VCM mode: "rate-control=VCM", then the "bitrate" specify the
473 * target bit rate, and encoder will try its best to make the QP
474 * with in the ["max-qp", "min-qp"] range. Other paramters are
478 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
481 guint32 quality_level;
483 quality_level = gst_va_encoder_get_quality_level (base->encoder,
484 base->profile, base->entrypoint);
485 if (self->rc.target_usage > quality_level) {
486 GST_INFO_OBJECT (self, "User setting target-usage: %d is not supported, "
487 "fallback to %d", self->rc.target_usage, quality_level);
488 self->rc.target_usage = quality_level;
490 self->prop.target_usage = self->rc.target_usage;
491 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TARGET_USAGE]);
494 /* TODO: find a better heuristics to infer a nearer control mode */
495 rc_mode = gst_va_encoder_get_rate_control_mode (base->encoder,
496 base->profile, base->entrypoint);
497 if (!(rc_mode & self->prop.rc_ctrl)) {
498 GST_INFO_OBJECT (self, "The race control mode %s is not supported, "
499 "fallback to %s mode",
500 _rate_control_get_name (self->prop.rc_ctrl),
501 _rate_control_get_name (VA_RC_CQP));
502 self->rc.rc_ctrl_mode = VA_RC_CQP;
504 self->prop.rc_ctrl = self->rc.rc_ctrl_mode;
505 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_RATE_CONTROL]);
508 if (self->rc.min_qp > self->rc.max_qp) {
509 GST_INFO_OBJECT (self, "The min_qp %d is bigger than the max_qp %d, "
510 "set it to the max_qp", self->rc.min_qp, self->rc.max_qp);
511 self->rc.min_qp = self->rc.max_qp;
513 self->prop.min_qp = self->rc.min_qp;
514 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MIN_QP]);
517 /* Make all the qp in the valid range */
518 if (self->rc.qp_i < self->rc.min_qp) {
519 if (self->rc.qp_i != 26)
520 GST_INFO_OBJECT (self, "The qp_i %d is smaller than the min_qp %d, "
521 "set it to the min_qp", self->rc.qp_i, self->rc.min_qp);
522 self->rc.qp_i = self->rc.min_qp;
524 if (self->rc.qp_i > self->rc.max_qp) {
525 if (self->rc.qp_i != 26)
526 GST_INFO_OBJECT (self, "The qp_i %d is bigger than the max_qp %d, "
527 "set it to the max_qp", self->rc.qp_i, self->rc.max_qp);
528 self->rc.qp_i = self->rc.max_qp;
531 if (self->rc.qp_p < self->rc.min_qp) {
532 if (self->rc.qp_p != 26)
533 GST_INFO_OBJECT (self, "The qp_p %d is smaller than the min_qp %d, "
534 "set it to the min_qp", self->rc.qp_p, self->rc.min_qp);
535 self->rc.qp_p = self->rc.min_qp;
537 if (self->rc.qp_p > self->rc.max_qp) {
538 if (self->rc.qp_p != 26)
539 GST_INFO_OBJECT (self, "The qp_p %d is bigger than the max_qp %d, "
540 "set it to the max_qp", self->rc.qp_p, self->rc.max_qp);
541 self->rc.qp_p = self->rc.max_qp;
544 if (self->rc.qp_b < self->rc.min_qp) {
545 if (self->rc.qp_b != 26)
546 GST_INFO_OBJECT (self, "The qp_b %d is smaller than the min_qp %d, "
547 "set it to the min_qp", self->rc.qp_b, self->rc.min_qp);
548 self->rc.qp_b = self->rc.min_qp;
550 if (self->rc.qp_b > self->rc.max_qp) {
551 if (self->rc.qp_b != 26)
552 GST_INFO_OBJECT (self, "The qp_b %d is bigger than the max_qp %d, "
553 "set it to the max_qp", self->rc.qp_b, self->rc.max_qp);
554 self->rc.qp_b = self->rc.max_qp;
557 bitrate = self->prop.bitrate;
558 /* Calculate a bitrate is not set. */
559 if ((self->rc.rc_ctrl_mode == VA_RC_CBR || self->rc.rc_ctrl_mode == VA_RC_VBR
560 || self->rc.rc_ctrl_mode == VA_RC_VCM) && bitrate == 0) {
561 /* Default compression: 48 bits per macroblock in "high-compression" mode */
562 guint bits_per_mb = 48;
565 /* According to the literature and testing, CABAC entropy coding
566 * mode could provide for +10% to +18% improvement in general,
567 * thus estimating +15% here ; and using adaptive 8x8 transforms
568 * in I-frames could bring up to +10% improvement. */
569 if (!self->use_cabac)
570 bits_per_mb += (bits_per_mb * 15) / 100;
571 if (!self->use_dct8x8)
572 bits_per_mb += (bits_per_mb * 10) / 100;
574 factor = (guint64) self->mb_width * self->mb_height * bits_per_mb;
575 bitrate = gst_util_uint64_scale (factor,
576 GST_VIDEO_INFO_FPS_N (&base->input_state->info),
577 GST_VIDEO_INFO_FPS_D (&base->input_state->info)) / 1000;
578 GST_INFO_OBJECT (self, "target bitrate computed to %u kbps", bitrate);
581 /* Adjust the setting based on RC mode. */
582 switch (self->rc.rc_ctrl_mode) {
584 self->rc.max_bitrate = 0;
585 self->rc.target_bitrate = 0;
586 self->rc.target_percentage = 0;
587 self->rc.cpb_size = 0;
590 self->rc.max_bitrate = bitrate;
591 self->rc.target_bitrate = bitrate;
592 self->rc.target_percentage = 100;
593 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
596 g_assert (self->rc.target_percentage >= 10);
597 self->rc.max_bitrate = (guint) gst_util_uint64_scale_int (bitrate,
598 100, self->rc.target_percentage);
599 self->rc.target_bitrate = bitrate;
600 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
603 self->rc.max_bitrate = bitrate;
604 self->rc.target_bitrate = bitrate;
605 self->rc.target_percentage = 0;
606 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
607 self->rc.cpb_size = 0;
609 if (self->gop.num_bframes > 0) {
610 GST_INFO_OBJECT (self, "VCM mode just support I/P mode, no B frame");
611 self->gop.num_bframes = 0;
612 self->gop.b_pyramid = FALSE;
617 if (self->rc.rc_ctrl_mode != VA_RC_CQP)
618 _calculate_bitrate_hrd (self);
621 if (self->rc.cpb_size != self->prop.cpb_size) {
622 self->prop.cpb_size = self->rc.cpb_size;
623 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CPB_SIZE]);
626 if (self->prop.target_percentage != self->rc.target_percentage) {
627 self->prop.target_percentage = self->rc.target_percentage;
628 g_object_notify_by_pspec (G_OBJECT (self),
629 properties[PROP_TARGET_PERCENTAGE]);
632 if (self->prop.qp_i != self->rc.qp_i) {
633 self->prop.qp_i = self->rc.qp_i;
634 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_QP_I]);
636 if (self->prop.qp_p != self->rc.qp_p) {
637 self->prop.qp_p = self->rc.qp_p;
638 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_QP_P]);
640 if (self->prop.qp_b != self->rc.qp_b) {
641 self->prop.qp_b = self->rc.qp_b;
642 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_QP_B]);
647 _get_h264_cpb_nal_factor (VAProfile profile)
653 case VAProfileH264High:
656 case VAProfileH264ConstrainedBaseline:
657 case VAProfileH264Main:
660 case VAProfileH264MultiviewHigh:
661 case VAProfileH264StereoHigh:
662 f = 1500; /* H.10.2.1 (r) */
665 g_assert_not_reached ();
672 /* Derives the level from the currently set limits */
674 _calculate_level (GstVaH264Enc * self)
676 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
677 const guint cpb_factor = _get_h264_cpb_nal_factor (base->profile);
678 guint i, PicSizeMbs, MaxDpbMbs, MaxMBPS;
680 PicSizeMbs = self->mb_width * self->mb_height;
681 MaxDpbMbs = PicSizeMbs * (self->gop.num_ref_frames + 1);
682 MaxMBPS = gst_util_uint64_scale_int_ceil (PicSizeMbs,
683 GST_VIDEO_INFO_FPS_N (&base->input_state->info),
684 GST_VIDEO_INFO_FPS_D (&base->input_state->info));
686 for (i = 0; i < G_N_ELEMENTS (_va_h264_level_limits); i++) {
687 const GstVaH264LevelLimits *const limits = &_va_h264_level_limits[i];
688 if (PicSizeMbs <= limits->MaxFS && MaxDpbMbs <= limits->MaxDpbMbs
689 && MaxMBPS <= limits->MaxMBPS && (!self->rc.max_bitrate_bits
690 || self->rc.max_bitrate_bits <= (limits->MaxBR * 1000 * cpb_factor))
691 && (!self->rc.cpb_length_bits
692 || self->rc.cpb_length_bits <=
693 (limits->MaxCPB * 1000 * cpb_factor))) {
695 self->level_idc = _va_h264_level_limits[i].level_idc;
696 self->level_str = _va_h264_level_limits[i].name;
697 self->min_cr = _va_h264_level_limits[i].MinCR;
703 GST_ERROR_OBJECT (self,
704 "failed to find a suitable level matching codec config");
709 _validate_parameters (GstVaH264Enc * self)
711 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
714 /* Ensure the num_slices provided by the user not exceed the limit
715 * of the number of slices permitted by the stream and by the
717 g_assert (self->num_slices >= 1);
718 max_slices = gst_va_encoder_get_max_slice_num (base->encoder,
719 base->profile, base->entrypoint);
720 if (self->num_slices > max_slices)
721 self->num_slices = max_slices;
722 /* The stream size limit. */
723 if (self->num_slices > ((self->mb_width * self->mb_height + 1) / 2))
724 self->num_slices = ((self->mb_width * self->mb_height + 1) / 2);
726 if (self->prop.num_slices != self->num_slices) {
727 self->prop.num_slices = self->num_slices;
728 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_NUM_SLICES]);
731 /* Ensure trellis. */
732 if (self->use_trellis &&
733 !gst_va_encoder_has_trellis (base->encoder, base->profile,
735 GST_INFO_OBJECT (self, "The trellis is not supported");
736 self->use_trellis = FALSE;
739 if (self->prop.use_trellis != self->use_trellis) {
740 self->prop.use_trellis = self->use_trellis;
741 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TRELLIS]);
745 /* Get log2_max_frame_num_minus4, log2_max_pic_order_cnt_lsb_minus4
746 * value, shall be in the range of 0 to 12, inclusive. */
748 _get_log2_max_num (guint num)
757 /* shall be in the range of 0+4 to 12+4, inclusive. */
760 } else if (ret > 16) {
767 _print_gop_structure (GstVaH264Enc * self)
769 #ifndef GST_DISABLE_GST_DEBUG
773 if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) < GST_LEVEL_INFO)
776 str = g_string_new (NULL);
778 g_string_append_printf (str, "[ ");
780 for (i = 0; i < self->gop.idr_period; i++) {
782 g_string_append_printf (str, "IDR");
785 g_string_append_printf (str, ", ");
788 g_string_append_printf (str, "%s",
789 _slice_type_name (self->gop.frame_types[i].slice_type));
791 if (self->gop.b_pyramid
792 && self->gop.frame_types[i].slice_type == GST_H264_B_SLICE) {
793 g_string_append_printf (str, "<L%d (%d, %d)>",
794 self->gop.frame_types[i].pyramid_level,
795 self->gop.frame_types[i].left_ref_poc_diff,
796 self->gop.frame_types[i].right_ref_poc_diff);
799 if (self->gop.frame_types[i].is_ref) {
800 g_string_append_printf (str, "(ref)");
805 g_string_append_printf (str, " ]");
807 GST_INFO_OBJECT (self, "GOP size: %d, forward reference %d, backward"
808 " reference %d, GOP structure: %s", self->gop.idr_period,
809 self->gop.ref_num_list0, self->gop.ref_num_list1, str->str);
811 g_string_free (str, TRUE);
818 gint left_ref_poc_diff;
819 gint right_ref_poc_diff;
823 _set_pyramid_info (struct PyramidInfo *info, guint len,
824 guint current_level, guint highest_level)
830 if (current_level == highest_level || len == 1) {
831 for (index = 0; index < len; index++) {
832 info[index].level = current_level;
833 info[index].left_ref_poc_diff = (index + 1) * -2;
834 info[index].right_ref_poc_diff = (len - index) * 2;
841 info[index].level = current_level;
842 info[index].left_ref_poc_diff = (index + 1) * -2;
843 info[index].right_ref_poc_diff = (len - index) * 2;
848 _set_pyramid_info (info, index, current_level, highest_level);
851 _set_pyramid_info (&info[index + 1], len - (index + 1),
852 current_level, highest_level);
856 _create_gop_frame_types (GstVaH264Enc * self)
859 guint i_frames = self->gop.num_iframes;
860 struct PyramidInfo pyramid_info[31] = { 0, };
862 if (self->gop.highest_pyramid_level > 0) {
863 g_assert (self->gop.num_bframes > 0);
864 _set_pyramid_info (pyramid_info, self->gop.num_bframes,
865 0, self->gop.highest_pyramid_level);
868 g_assert (self->gop.idr_period <= MAX_GOP_SIZE);
869 for (i = 0; i < self->gop.idr_period; i++) {
871 self->gop.frame_types[i].slice_type = GST_H264_I_SLICE;
872 self->gop.frame_types[i].is_ref = TRUE;
876 /* Intra only stream. */
877 if (self->gop.ip_period == 0) {
878 self->gop.frame_types[i].slice_type = GST_H264_I_SLICE;
879 self->gop.frame_types[i].is_ref = FALSE;
883 if (i % self->gop.ip_period) {
884 guint pyramid_index =
885 i % self->gop.ip_period - 1 /* The first P or IDR */ ;
887 self->gop.frame_types[i].slice_type = GST_H264_B_SLICE;
888 self->gop.frame_types[i].pyramid_level =
889 pyramid_info[pyramid_index].level;
890 self->gop.frame_types[i].is_ref =
891 (self->gop.frame_types[i].pyramid_level <
892 self->gop.highest_pyramid_level);
893 self->gop.frame_types[i].left_ref_poc_diff =
894 pyramid_info[pyramid_index].left_ref_poc_diff;
895 self->gop.frame_types[i].right_ref_poc_diff =
896 pyramid_info[pyramid_index].right_ref_poc_diff;
900 if (self->gop.i_period && i % self->gop.i_period == 0 && i_frames > 0) {
901 /* Replace P with I. */
902 self->gop.frame_types[i].slice_type = GST_H264_I_SLICE;
903 self->gop.frame_types[i].is_ref = TRUE;
908 self->gop.frame_types[i].slice_type = GST_H264_P_SLICE;
909 self->gop.frame_types[i].is_ref = TRUE;
912 /* Force the last one to be a P */
913 if (self->gop.idr_period > 1 && self->gop.ip_period > 0) {
914 self->gop.frame_types[self->gop.idr_period - 1].slice_type =
916 self->gop.frame_types[self->gop.idr_period - 1].is_ref = TRUE;
920 /* Consider the idr_period, num_bframes, L0/L1 reference number.
921 * TODO: Load some preset fixed GOP structure.
922 * TODO: Skip this if in lookahead mode. */
924 _generate_gop_structure (GstVaH264Enc * self)
926 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
927 guint32 list0, list1, gop_ref_num;
930 /* If not set, generate a idr every second */
931 if (self->gop.idr_period == 0) {
932 self->gop.idr_period = (GST_VIDEO_INFO_FPS_N (&base->input_state->info)
933 + GST_VIDEO_INFO_FPS_D (&base->input_state->info) - 1) /
934 GST_VIDEO_INFO_FPS_D (&base->input_state->info);
937 /* Do not use a too huge GOP size. */
938 if (self->gop.idr_period > 1024) {
939 self->gop.idr_period = 1024;
940 GST_INFO_OBJECT (self, "Lowering the GOP size to %d", self->gop.idr_period);
943 if (self->gop.idr_period != self->prop.key_int_max) {
944 self->prop.key_int_max = self->gop.idr_period;
945 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_KEY_INT_MAX]);
948 /* Prefer have more than 1 refs for the GOP which is not very small. */
949 if (self->gop.idr_period > 8) {
950 if (self->gop.num_bframes > (self->gop.idr_period - 1) / 2) {
951 self->gop.num_bframes = (self->gop.idr_period - 1) / 2;
952 GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
953 self->gop.num_bframes);
956 /* beign and end should be ref */
957 if (self->gop.num_bframes > self->gop.idr_period - 1 - 1) {
958 if (self->gop.idr_period > 1) {
959 self->gop.num_bframes = self->gop.idr_period - 1 - 1;
961 self->gop.num_bframes = 0;
963 GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
964 self->gop.num_bframes);
968 if (!gst_va_encoder_get_max_num_reference (base->encoder, base->profile,
969 base->entrypoint, &list0, &list1)) {
970 GST_INFO_OBJECT (self, "Failed to get the max num reference");
975 if (list0 > self->gop.num_ref_frames)
976 list0 = self->gop.num_ref_frames;
977 if (list1 > self->gop.num_ref_frames)
978 list1 = self->gop.num_ref_frames;
981 GST_INFO_OBJECT (self,
982 "No reference support, fallback to intra only stream");
984 /* It does not make sense that if only the list1 exists. */
985 self->gop.num_ref_frames = 0;
987 self->gop.ip_period = 0;
988 self->gop.num_bframes = 0;
989 self->gop.b_pyramid = FALSE;
990 self->gop.highest_pyramid_level = 0;
991 self->gop.num_iframes = self->gop.idr_period - 1 /* The idr */ ;
992 self->gop.ref_num_list0 = 0;
993 self->gop.ref_num_list1 = 0;
997 if (self->gop.num_ref_frames <= 1) {
998 GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
999 " no B frame allowed, fallback to I/P mode", self->gop.num_ref_frames);
1000 self->gop.num_bframes = 0;
1004 /* b_pyramid needs at least 1 ref for B, besides the I/P */
1005 if (self->gop.b_pyramid && self->gop.num_ref_frames <= 2) {
1006 GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
1007 " not enough for b_pyramid", self->gop.num_ref_frames);
1008 self->gop.b_pyramid = FALSE;
1011 if (list1 == 0 && self->gop.num_bframes > 0) {
1012 GST_INFO_OBJECT (self,
1013 "No hw reference support for list 1, fallback to I/P mode");
1014 self->gop.num_bframes = 0;
1015 self->gop.b_pyramid = FALSE;
1018 /* I/P mode, no list1 needed. */
1019 if (self->gop.num_bframes == 0)
1022 /* Not enough B frame, no need for b_pyramid. */
1023 if (self->gop.num_bframes <= 1)
1024 self->gop.b_pyramid = FALSE;
1026 /* b pyramid has only one backward ref. */
1027 if (self->gop.b_pyramid)
1030 if (self->gop.num_ref_frames > list0 + list1) {
1031 self->gop.num_ref_frames = list0 + list1;
1032 GST_INFO_OBJECT (self, "HW limits, lowering the number of reference"
1033 " frames to %d", self->gop.num_ref_frames);
1036 /* How many possible refs within a GOP. */
1037 gop_ref_num = (self->gop.idr_period + self->gop.num_bframes) /
1038 (self->gop.num_bframes + 1);
1040 if (self->gop.num_bframes > 0
1041 /* frame_num % (self->gop.num_bframes + 1) happens to be the end P */
1042 && (self->gop.idr_period % (self->gop.num_bframes + 1) != 1))
1045 /* Adjust reference num based on B frames and B pyramid. */
1046 if (self->gop.num_bframes == 0) {
1047 self->gop.b_pyramid = FALSE;
1048 self->gop.ref_num_list0 = self->gop.num_ref_frames;
1049 self->gop.ref_num_list1 = 0;
1050 } else if (self->gop.b_pyramid) {
1051 guint b_frames = self->gop.num_bframes;
1054 /* b pyramid has only one backward ref. */
1055 g_assert (list1 == 1);
1056 self->gop.ref_num_list1 = list1;
1057 self->gop.ref_num_list0 =
1058 self->gop.num_ref_frames - self->gop.ref_num_list1;
1060 b_frames = b_frames / 2;
1063 /* At least 1 B ref for each level, plus begin and end 2 P/I */
1065 if (b_refs + 2 > self->gop.num_ref_frames)
1068 self->gop.highest_pyramid_level++;
1069 b_frames = b_frames / 2;
1072 GST_INFO_OBJECT (self, "pyramid level is %d",
1073 self->gop.highest_pyramid_level);
1075 /* We prefer list0. Backward refs have more latency. */
1076 self->gop.ref_num_list1 = 1;
1077 self->gop.ref_num_list0 =
1078 self->gop.num_ref_frames - self->gop.ref_num_list1;
1079 /* Balance the forward and backward refs, but not cause a big latency. */
1080 while ((self->gop.num_bframes * self->gop.ref_num_list1 <= 16)
1081 && (self->gop.ref_num_list1 <= gop_ref_num)
1082 && (self->gop.ref_num_list1 < list1)
1083 && (self->gop.ref_num_list0 / self->gop.ref_num_list1 > 4)) {
1084 self->gop.ref_num_list0--;
1085 self->gop.ref_num_list1++;
1088 if (self->gop.ref_num_list0 > list0)
1089 self->gop.ref_num_list0 = list0;
1092 /* It's OK, keep slots for GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME frame. */
1093 if (self->gop.ref_num_list0 > gop_ref_num)
1094 GST_DEBUG_OBJECT (self, "num_ref_frames %d is bigger than gop_ref_num %d",
1095 self->gop.ref_num_list0, gop_ref_num);
1097 /* Include the ref picture itself. */
1098 self->gop.ip_period = 1 + self->gop.num_bframes;
1100 p_frames = gop_ref_num - 1 /* IDR */ ;
1103 if (self->gop.num_iframes > p_frames) {
1104 self->gop.num_iframes = p_frames;
1105 GST_INFO_OBJECT (self, "Too many I frames insertion, lowering it to %d",
1106 self->gop.num_iframes);
1109 if (self->gop.num_iframes > 0) {
1110 guint total_i_frames = self->gop.num_iframes + 1 /* IDR */ ;
1111 self->gop.i_period =
1112 (gop_ref_num / total_i_frames) * (self->gop.num_bframes + 1);
1116 /* init max_frame_num, max_poc */
1117 self->gop.log2_max_frame_num = _get_log2_max_num (self->gop.idr_period);
1118 self->gop.max_frame_num = (1 << self->gop.log2_max_frame_num);
1119 self->gop.log2_max_pic_order_cnt = self->gop.log2_max_frame_num + 1;
1120 self->gop.max_pic_order_cnt = (1 << self->gop.log2_max_pic_order_cnt);
1121 self->gop.num_reorder_frames = self->gop.b_pyramid ?
1122 self->gop.highest_pyramid_level * 2 + 1 /* the last P frame. */ :
1123 self->gop.ref_num_list1;
1124 /* Should not exceed the max ref num. */
1125 self->gop.num_reorder_frames =
1126 MIN (self->gop.num_reorder_frames, self->gop.num_ref_frames);
1127 self->gop.num_reorder_frames = MIN (self->gop.num_reorder_frames, 16);
1129 _create_gop_frame_types (self);
1130 _print_gop_structure (self);
1133 if (self->prop.num_ref_frames != self->gop.num_ref_frames) {
1134 self->prop.num_ref_frames = self->gop.num_ref_frames;
1135 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_NUM_REF_FRAMES]);
1138 if (self->prop.num_iframes != self->gop.num_iframes) {
1139 self->prop.num_iframes = self->gop.num_iframes;
1140 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_IFRAMES]);
1146 _calculate_coded_size (GstVaH264Enc * self)
1148 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1149 guint codedbuf_size = 0;
1151 if (base->profile == VAProfileH264High
1152 || base->profile == VAProfileH264MultiviewHigh
1153 || base->profile == VAProfileH264StereoHigh) {
1154 /* The number of bits of macroblock_layer( ) data for any macroblock
1155 is not greater than 128 + RawMbBits */
1156 guint RawMbBits = 0;
1157 guint BitDepthY = 8;
1158 guint BitDepthC = 8;
1160 guint MbHeightC = 8;
1162 switch (base->rt_format) {
1163 case VA_RT_FORMAT_YUV420:
1169 case VA_RT_FORMAT_YUV422:
1175 case VA_RT_FORMAT_YUV444:
1181 case VA_RT_FORMAT_YUV400:
1187 case VA_RT_FORMAT_YUV420_10:
1192 case VA_RT_FORMAT_YUV422_10:
1197 case VA_RT_FORMAT_YUV444_10:
1204 g_assert_not_reached ();
1208 /* The variable RawMbBits is derived as
1209 * RawMbBits = 256 * BitDepthY + 2 * MbWidthC * MbHeightC * BitDepthC */
1210 RawMbBits = 256 * BitDepthY + 2 * MbWidthC * MbHeightC * BitDepthC;
1211 codedbuf_size = (self->mb_width * self->mb_height) * (128 + RawMbBits) / 8;
1213 /* The number of bits of macroblock_layer( ) data for any macroblock
1214 * is not greater than 3200 */
1215 codedbuf_size = (self->mb_width * self->mb_height) * (3200 / 8);
1218 /* Account for SPS header */
1219 /* XXX: exclude scaling lists, MVC/SVC extensions */
1220 codedbuf_size += 4 /* start code */ + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
1221 MAX_VUI_PARAMS_SIZE + 2 * MAX_HRD_PARAMS_SIZE) / 8;
1223 /* Account for PPS header */
1224 /* XXX: exclude slice groups, scaling lists, MVC/SVC extensions */
1225 codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
1227 /* Account for slice header */
1229 self->num_slices * (4 + GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8);
1231 /* Add 5% for safety */
1232 base->codedbuf_size = (guint) ((gfloat) codedbuf_size * 1.05);
1234 GST_DEBUG_OBJECT (self, "Calculate codedbuf size: %u", base->codedbuf_size);
1238 _get_rtformat (GstVaH264Enc * self, GstVideoFormat format)
1242 chroma = gst_va_chroma_from_video_format (format);
1244 /* Check whether the rtformat is supported. */
1245 if (chroma != VA_RT_FORMAT_YUV420) {
1246 GST_ERROR_OBJECT (self, "Unsupported chroma for video format: %s",
1247 gst_video_format_to_string (format));
1255 _init_packed_headers (GstVaH264Enc * self)
1257 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1258 guint32 packed_headers;
1259 guint32 desired_packed_headers = VA_ENC_PACKED_HEADER_SEQUENCE /* SPS */
1260 | VA_ENC_PACKED_HEADER_PICTURE /* PPS */
1261 | VA_ENC_PACKED_HEADER_SLICE /* Slice headers */
1262 | VA_ENC_PACKED_HEADER_RAW_DATA; /* SEI, AUD, etc. */
1264 self->packed_headers = 0;
1266 packed_headers = gst_va_encoder_get_packed_headers (base->encoder,
1267 base->profile, base->entrypoint);
1269 if (packed_headers == 0)
1272 if (desired_packed_headers & ~packed_headers) {
1273 GST_INFO_OBJECT (self, "Driver does not support some wanted packed headers "
1274 "(wanted %#x, found %#x)", desired_packed_headers, packed_headers);
1277 self->packed_headers = desired_packed_headers & packed_headers;
1284 _decide_profile (GstVaH264Enc * self)
1286 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1287 gboolean ret = FALSE;
1288 GstVideoFormat in_format;
1291 GstCaps *allowed_caps = NULL;
1292 guint num_structures, i;
1293 GstStructure *structure;
1294 const GValue *v_profile;
1295 GPtrArray *candidates = NULL;
1296 gchar *profile_name;
1298 candidates = g_ptr_array_new_with_free_func (g_free);
1300 /* First, check whether the downstream requires a specified profile. */
1301 allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (base));
1303 allowed_caps = gst_pad_query_caps (GST_VIDEO_ENCODER_SRC_PAD (base), NULL);
1305 if (allowed_caps && !gst_caps_is_empty (allowed_caps)) {
1306 num_structures = gst_caps_get_size (allowed_caps);
1307 for (i = 0; i < num_structures; i++) {
1308 structure = gst_caps_get_structure (allowed_caps, i);
1309 v_profile = gst_structure_get_value (structure, "profile");
1313 if (G_VALUE_HOLDS_STRING (v_profile)) {
1314 profile_name = g_strdup (g_value_get_string (v_profile));
1315 g_ptr_array_add (candidates, profile_name);
1316 } else if (GST_VALUE_HOLDS_LIST (v_profile)) {
1319 for (j = 0; j < gst_value_list_get_size (v_profile); j++) {
1320 const GValue *p = gst_value_list_get_value (v_profile, j);
1324 profile_name = g_strdup (g_value_get_string (p));
1325 g_ptr_array_add (candidates, profile_name);
1331 if (candidates->len == 0) {
1332 GST_ERROR_OBJECT (self, "No available profile in caps");
1337 in_format = GST_VIDEO_INFO_FORMAT (&base->input_state->info);
1338 rt_format = _get_rtformat (self, in_format);
1340 GST_ERROR_OBJECT (self, "unsupported video format %s",
1341 gst_video_format_to_string (in_format));
1346 /* Find the suitable profile by features and check the HW
1349 for (i = 0; i < candidates->len; i++) {
1350 profile_name = g_ptr_array_index (candidates, i);
1352 /* dct8x8 require at least high profile. */
1353 if (self->use_dct8x8) {
1354 if (!g_strstr_len (profile_name, -1, "high"))
1358 /* cabac require at least main profile. */
1359 if (self->use_cabac) {
1360 if (!g_strstr_len (profile_name, -1, "main")
1361 && !g_strstr_len (profile_name, -1, "high"))
1365 /* baseline only support I/P mode. */
1366 if (self->gop.num_bframes > 0) {
1367 if (g_strstr_len (profile_name, -1, "baseline"))
1371 profile = gst_va_profile_from_name (H264, profile_name);
1372 if (profile == VAProfileNone)
1375 if (!gst_va_encoder_has_profile_and_entrypoint (base->encoder,
1376 profile, VAEntrypointEncSlice))
1379 if ((rt_format & gst_va_encoder_get_rtformat (base->encoder,
1380 profile, VAEntrypointEncSlice)) == 0)
1383 base->profile = profile;
1384 base->entrypoint = VAEntrypointEncSlice;
1385 base->rt_format = rt_format;
1390 /* Just use the first HW available profile and disable features if
1392 profile_name = NULL;
1393 for (i = 0; i < candidates->len; i++) {
1394 profile_name = g_ptr_array_index (candidates, i);
1395 profile = gst_va_profile_from_name (H264, profile_name);
1396 if (profile == VAProfileNone)
1399 if (!gst_va_encoder_has_profile_and_entrypoint (base->encoder,
1400 profile, VAEntrypointEncSlice))
1403 if ((rt_format & gst_va_encoder_get_rtformat (base->encoder,
1404 profile, VAEntrypointEncSlice)) == 0)
1407 base->profile = profile;
1408 base->entrypoint = VAEntrypointEncSlice;
1409 base->rt_format = rt_format;
1416 if (self->use_dct8x8 && !g_strstr_len (profile_name, -1, "high")) {
1417 GST_INFO_OBJECT (self, "Disable dct8x8, profile %s does not support it",
1418 gst_va_profile_name (base->profile));
1419 self->use_dct8x8 = FALSE;
1420 self->prop.use_dct8x8 = FALSE;
1421 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DCT8X8]);
1424 if (self->use_cabac && (!g_strstr_len (profile_name, -1, "main")
1425 && !g_strstr_len (profile_name, -1, "high"))) {
1426 GST_INFO_OBJECT (self, "Disable cabac, profile %s does not support it",
1427 gst_va_profile_name (base->profile));
1428 self->use_cabac = FALSE;
1429 self->prop.use_cabac = FALSE;
1430 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CABAC]);
1433 if (self->gop.num_bframes > 0 && g_strstr_len (profile_name, -1, "baseline")) {
1434 GST_INFO_OBJECT (self, "No B frames, profile %s does not support it",
1435 gst_va_profile_name (base->profile));
1436 self->gop.num_bframes = 0;
1437 self->gop.b_pyramid = 0;
1441 g_clear_pointer (&candidates, g_ptr_array_unref);
1442 g_clear_pointer (&allowed_caps, gst_caps_unref);
1445 GST_INFO_OBJECT (self, "Select the profile %s",
1446 gst_va_profile_name (profile));
1448 GST_ERROR_OBJECT (self, "Failed to find an available profile");
1454 /* Clear all the info of last reconfig and set the fields based on
1455 * property. The reconfig may change these fields because of the
1456 * profile/level and HW limitation. */
1458 gst_va_h264_enc_reset_state (GstVaH264Enc * self)
1460 gst_va_base_enc_reset_state (GST_VA_BASE_ENC (self));
1462 self->level_idc = 0;
1463 self->level_str = NULL;
1465 self->mb_height = 0;
1466 self->use_cabac = self->prop.use_cabac;
1467 self->use_dct8x8 = self->prop.use_dct8x8;
1468 self->use_trellis = self->prop.use_trellis;
1469 self->num_slices = self->prop.num_slices;
1471 self->gop.idr_period = self->prop.key_int_max;
1472 self->gop.i_period = 0;
1473 self->gop.total_idr_count = 0;
1474 self->gop.ip_period = 0;
1475 self->gop.num_bframes = self->prop.num_bframes;
1476 self->gop.b_pyramid = self->prop.b_pyramid;
1477 self->gop.highest_pyramid_level = 0;
1478 self->gop.num_iframes = self->prop.num_iframes;
1479 memset (self->gop.frame_types, 0, sizeof (self->gop.frame_types));
1480 self->gop.cur_frame_index = 0;
1481 self->gop.cur_frame_num = 0;
1482 self->gop.max_frame_num = 0;
1483 self->gop.log2_max_frame_num = 0;
1484 self->gop.max_pic_order_cnt = 0;
1485 self->gop.log2_max_pic_order_cnt = 0;
1486 self->gop.num_ref_frames = self->prop.num_ref_frames;
1487 self->gop.ref_num_list0 = 0;
1488 self->gop.ref_num_list1 = 0;
1489 self->gop.num_reorder_frames = 0;
1491 self->rc.rc_ctrl_mode = self->prop.rc_ctrl;
1492 self->rc.min_qp = self->prop.min_qp;
1493 self->rc.max_qp = self->prop.max_qp;
1494 self->rc.qp_i = self->prop.qp_i;
1495 self->rc.qp_p = self->prop.qp_p;
1496 self->rc.qp_b = self->prop.qp_b;
1497 self->rc.mbbrc = self->prop.mbbrc;
1498 self->rc.max_bitrate = 0;
1499 self->rc.target_bitrate = 0;
1500 self->rc.target_percentage = self->prop.target_percentage;
1501 self->rc.target_usage = self->prop.target_usage;
1502 self->rc.max_bitrate_bits = 0;
1503 self->rc.target_bitrate_bits = 0;
1504 self->rc.cpb_size = self->prop.cpb_size;
1505 self->rc.cpb_length_bits = 0;
1507 memset (&self->sequence_hdr, 0, sizeof (GstH264SPS));
1511 gst_va_h264_enc_reconfig (GstVaBaseEnc * base)
1513 GstVideoEncoder *venc = GST_VIDEO_ENCODER (base);
1514 GstVaH264Enc *self = GST_VA_H264_ENC (base);
1516 guint max_ref_frames;
1517 GstVideoCodecState *output_state;
1519 gst_va_h264_enc_reset_state (self);
1521 base->width = GST_VIDEO_INFO_WIDTH (&base->input_state->info);
1522 base->height = GST_VIDEO_INFO_HEIGHT (&base->input_state->info);
1524 self->mb_width = GST_ROUND_UP_16 (base->width) / 16;
1525 self->mb_height = GST_ROUND_UP_16 (base->height) / 16;
1527 /* Frame rate is needed for rate control and PTS setting. */
1528 if (GST_VIDEO_INFO_FPS_N (&base->input_state->info) == 0
1529 || GST_VIDEO_INFO_FPS_D (&base->input_state->info) == 0) {
1530 GST_INFO_OBJECT (self, "Unknown framerate, just set to 30 fps");
1531 GST_VIDEO_INFO_FPS_N (&base->input_state->info) = 30;
1532 GST_VIDEO_INFO_FPS_D (&base->input_state->info) = 1;
1534 base->frame_duration = gst_util_uint64_scale (GST_SECOND,
1535 GST_VIDEO_INFO_FPS_D (&base->input_state->info),
1536 GST_VIDEO_INFO_FPS_N (&base->input_state->info));
1538 GST_DEBUG_OBJECT (self, "resolution:%dx%d, MB size: %dx%d,"
1539 " frame duration is %" GST_TIME_FORMAT,
1540 base->width, base->height, self->mb_width, self->mb_height,
1541 GST_TIME_ARGS (base->frame_duration));
1543 if (!_decide_profile (self))
1546 _validate_parameters (self);
1548 _ensure_rate_control (self);
1550 if (!_calculate_level (self))
1553 _generate_gop_structure (self);
1554 _calculate_coded_size (self);
1557 /* num_bframes are modified several times before */
1558 if (self->prop.num_bframes != self->gop.num_bframes) {
1559 self->prop.num_bframes = self->gop.num_bframes;
1560 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BFRAMES]);
1563 if (self->prop.b_pyramid != self->gop.b_pyramid) {
1564 self->prop.b_pyramid = self->gop.b_pyramid;
1565 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_B_PYRAMID]);
1568 if (!_init_packed_headers (self))
1571 max_ref_frames = self->gop.num_ref_frames + 3 /* scratch frames */ ;
1572 if (!gst_va_encoder_open (base->encoder, base->profile, base->entrypoint,
1573 GST_VIDEO_INFO_FORMAT (&base->input_state->info), base->rt_format,
1574 self->mb_width * 16, self->mb_height * 16, base->codedbuf_size,
1575 max_ref_frames, self->rc.rc_ctrl_mode, self->packed_headers)) {
1576 GST_ERROR_OBJECT (self, "Failed to open the VA encoder.");
1581 gst_va_base_enc_add_codec_tag (base, "H264");
1583 out_caps = gst_va_profile_caps (base->profile);
1584 g_assert (out_caps);
1585 out_caps = gst_caps_fixate (out_caps);
1587 if (self->level_str)
1588 gst_caps_set_simple (out_caps, "level", G_TYPE_STRING, self->level_str,
1591 gst_caps_set_simple (out_caps, "width", G_TYPE_INT, base->width,
1592 "height", G_TYPE_INT, base->height, "alignment", G_TYPE_STRING, "au",
1593 "stream-format", G_TYPE_STRING, "byte-stream", NULL);
1595 GST_DEBUG_OBJECT (self, "output caps is %" GST_PTR_FORMAT, out_caps);
1598 gst_video_encoder_set_output_state (venc, out_caps, base->input_state);
1599 gst_video_codec_state_unref (output_state);
1601 if (!gst_video_encoder_negotiate (venc)) {
1602 GST_ERROR_OBJECT (self, "Failed to negotiate with the downstream");
1610 _push_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame * gst_frame,
1613 GstVaH264Enc *self = GST_VA_H264_ENC (base);
1614 GstVaH264EncFrame *frame;
1616 g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
1620 /* Begin a new GOP, should have a empty reorder_list. */
1621 if (self->gop.cur_frame_index == self->gop.idr_period) {
1622 g_assert (g_queue_is_empty (&base->reorder_list));
1623 self->gop.cur_frame_index = 0;
1624 self->gop.cur_frame_num = 0;
1627 frame = _enc_frame (gst_frame);
1629 ((self->gop.cur_frame_index * 2) % self->gop.max_pic_order_cnt);
1631 if (self->gop.cur_frame_index == 0) {
1632 g_assert (frame->poc == 0);
1633 GST_LOG_OBJECT (self, "system_frame_number: %d, an IDR frame, starts"
1634 " a new GOP", gst_frame->system_frame_number);
1636 g_queue_clear_full (&base->ref_list,
1637 (GDestroyNotify) gst_video_codec_frame_unref);
1640 frame->type = self->gop.frame_types[self->gop.cur_frame_index].slice_type;
1641 frame->is_ref = self->gop.frame_types[self->gop.cur_frame_index].is_ref;
1642 frame->pyramid_level =
1643 self->gop.frame_types[self->gop.cur_frame_index].pyramid_level;
1644 frame->left_ref_poc_diff =
1645 self->gop.frame_types[self->gop.cur_frame_index].left_ref_poc_diff;
1646 frame->right_ref_poc_diff =
1647 self->gop.frame_types[self->gop.cur_frame_index].right_ref_poc_diff;
1649 if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (gst_frame)) {
1650 GST_DEBUG_OBJECT (self, "system_frame_number: %d, a force key frame,"
1651 " promote its type from %s to %s", gst_frame->system_frame_number,
1652 _slice_type_name (frame->type), _slice_type_name (GST_H264_I_SLICE));
1653 frame->type = GST_H264_I_SLICE;
1654 frame->is_ref = TRUE;
1657 GST_LOG_OBJECT (self, "Push frame, system_frame_number: %d, poc %d, "
1658 "frame type %s", gst_frame->system_frame_number, frame->poc,
1659 _slice_type_name (frame->type));
1661 self->gop.cur_frame_index++;
1662 g_queue_push_tail (&base->reorder_list,
1663 gst_video_codec_frame_ref (gst_frame));
1666 /* ensure the last one a non-B and end the GOP. */
1667 if (last && self->gop.cur_frame_index < self->gop.idr_period) {
1668 GstVideoCodecFrame *last_frame;
1670 /* Ensure next push will start a new GOP. */
1671 self->gop.cur_frame_index = self->gop.idr_period;
1673 if (!g_queue_is_empty (&base->reorder_list)) {
1674 last_frame = g_queue_peek_tail (&base->reorder_list);
1675 frame = _enc_frame (last_frame);
1676 if (frame->type == GST_H264_B_SLICE) {
1677 frame->type = GST_H264_P_SLICE;
1678 frame->is_ref = TRUE;
1686 struct RefFramesCount
1693 _count_backward_ref_num (gpointer data, gpointer user_data)
1695 GstVaH264EncFrame *frame = _enc_frame (data);
1696 struct RefFramesCount *count = (struct RefFramesCount *) user_data;
1698 g_assert (frame->poc != count->poc);
1699 if (frame->poc > count->poc)
1703 static GstVideoCodecFrame *
1704 _pop_pyramid_b_frame (GstVaH264Enc * self)
1706 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1709 GstVaH264EncFrame *b_vaframe;
1710 GstVideoCodecFrame *b_frame;
1711 struct RefFramesCount count;
1713 g_assert (self->gop.ref_num_list1 == 1);
1718 /* Find the lowest level with smallest poc. */
1719 for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
1720 GstVaH264EncFrame *vaf;
1721 GstVideoCodecFrame *f;
1723 f = g_queue_peek_nth (&base->reorder_list, i);
1727 b_vaframe = _enc_frame (b_frame);
1732 vaf = _enc_frame (f);
1733 if (b_vaframe->pyramid_level < vaf->pyramid_level) {
1740 if (b_vaframe->poc > vaf->poc) {
1748 /* Check whether its refs are already poped. */
1749 g_assert (b_vaframe->left_ref_poc_diff != 0);
1750 g_assert (b_vaframe->right_ref_poc_diff != 0);
1751 for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
1752 GstVaH264EncFrame *vaf;
1753 GstVideoCodecFrame *f;
1755 f = g_queue_peek_nth (&base->reorder_list, i);
1760 vaf = _enc_frame (f);
1761 if (vaf->poc == b_vaframe->poc + b_vaframe->left_ref_poc_diff
1762 || vaf->poc == b_vaframe->poc + b_vaframe->right_ref_poc_diff) {
1770 /* Ensure we already have enough backward refs */
1772 count.poc = b_vaframe->poc;
1773 g_queue_foreach (&base->ref_list, (GFunc) _count_backward_ref_num, &count);
1774 if (count.num >= self->gop.ref_num_list1) {
1775 GstVideoCodecFrame *f;
1777 /* it will unref at pop_frame */
1778 f = g_queue_pop_nth (&base->reorder_list, index);
1779 g_assert (f == b_frame);
1788 _pop_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame ** out_frame)
1790 GstVaH264Enc *self = GST_VA_H264_ENC (base);
1791 GstVaH264EncFrame *vaframe;
1792 GstVideoCodecFrame *frame;
1793 struct RefFramesCount count;
1795 g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
1800 if (g_queue_is_empty (&base->reorder_list))
1803 /* Return the last pushed non-B immediately. */
1804 frame = g_queue_peek_tail (&base->reorder_list);
1805 vaframe = _enc_frame (frame);
1806 if (vaframe->type != GST_H264_B_SLICE) {
1807 frame = g_queue_pop_tail (&base->reorder_list);
1811 if (self->gop.b_pyramid) {
1812 frame = _pop_pyramid_b_frame (self);
1818 g_assert (self->gop.ref_num_list1 > 0);
1820 /* If GOP end, pop anyway. */
1821 if (self->gop.cur_frame_index == self->gop.idr_period) {
1822 frame = g_queue_pop_head (&base->reorder_list);
1826 /* Ensure we already have enough backward refs */
1827 frame = g_queue_peek_head (&base->reorder_list);
1828 vaframe = _enc_frame (frame);
1830 count.poc = vaframe->poc;
1831 g_queue_foreach (&base->ref_list, _count_backward_ref_num, &count);
1832 if (count.num >= self->gop.ref_num_list1) {
1833 frame = g_queue_pop_head (&base->reorder_list);
1840 g_assert (self->gop.cur_frame_num < self->gop.max_frame_num);
1842 vaframe = _enc_frame (frame);
1843 vaframe->frame_num = self->gop.cur_frame_num;
1845 /* Add the frame number for ref frames. */
1846 if (vaframe->is_ref)
1847 self->gop.cur_frame_num++;
1849 if (vaframe->frame_num == 0)
1850 self->gop.total_idr_count++;
1852 if (self->gop.b_pyramid && vaframe->type == GST_H264_B_SLICE) {
1853 GST_LOG_OBJECT (self, "pop a pyramid B frame with system_frame_number:"
1854 " %d, poc: %d, frame num: %d, is_ref: %s, level %d",
1855 frame->system_frame_number, vaframe->poc, vaframe->frame_num,
1856 vaframe->is_ref ? "true" : "false", vaframe->pyramid_level);
1858 GST_LOG_OBJECT (self, "pop a frame with system_frame_number: %d,"
1859 " frame type: %s, poc: %d, frame num: %d, is_ref: %s",
1860 frame->system_frame_number, _slice_type_name (vaframe->type),
1861 vaframe->poc, vaframe->frame_num, vaframe->is_ref ? "true" : "false");
1864 /* unref frame popped from queue or pyramid b_frame */
1865 gst_video_codec_frame_unref (frame);
1871 gst_va_h264_enc_reorder_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame,
1872 gboolean bump_all, GstVideoCodecFrame ** out_frame)
1874 if (!_push_one_frame (base, frame, bump_all)) {
1875 GST_ERROR_OBJECT (base, "Failed to push the input frame"
1876 " system_frame_number: %d into the reorder list",
1877 frame->system_frame_number);
1883 if (!_pop_one_frame (base, out_frame)) {
1884 GST_ERROR_OBJECT (base, "Failed to pop the frame from the reorder list");
1892 static inline gboolean
1893 _fill_sps (GstVaH264Enc * self, VAEncSequenceParameterBufferH264 * seq_param)
1895 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1896 GstH264Profile profile;
1897 guint32 constraint_set0_flag, constraint_set1_flag;
1898 guint32 constraint_set2_flag, constraint_set3_flag;
1899 guint32 max_dec_frame_buffering;
1901 /* let max_num_ref_frames <= MaxDpbFrames. */
1902 max_dec_frame_buffering =
1903 MIN (self->gop.num_ref_frames + 1 /* Last frame before bump */ ,
1904 16 /* DPB_MAX_SIZE */ );
1906 constraint_set0_flag = 0;
1907 constraint_set1_flag = 0;
1908 constraint_set2_flag = 0;
1909 constraint_set3_flag = 0;
1911 switch (base->profile) {
1912 case VAProfileH264ConstrainedBaseline:
1913 profile = GST_H264_PROFILE_BASELINE;
1914 /* A.2.1 (baseline profile constraints) */
1915 constraint_set0_flag = 1;
1916 constraint_set1_flag = 1;
1918 case VAProfileH264Main:
1919 profile = GST_H264_PROFILE_MAIN;
1920 /* A.2.2 (main profile constraints) */
1921 constraint_set1_flag = 1;
1923 case VAProfileH264High:
1924 case VAProfileH264MultiviewHigh:
1925 case VAProfileH264StereoHigh:
1926 profile = GST_H264_PROFILE_HIGH;
1932 /* seq_scaling_matrix_present_flag not supported now */
1933 g_assert (seq_param->seq_fields.bits.seq_scaling_matrix_present_flag == 0);
1934 /* pic_order_cnt_type only support 0 now */
1935 g_assert (seq_param->seq_fields.bits.pic_order_cnt_type == 0);
1936 /* only progressive frames encoding is supported now */
1937 g_assert (seq_param->seq_fields.bits.frame_mbs_only_flag);
1940 GST_DEBUG_OBJECT (self, "filling SPS");
1941 self->sequence_hdr = (GstH264SPS) {
1943 .profile_idc = profile,
1944 .constraint_set0_flag = constraint_set0_flag,
1945 .constraint_set1_flag = constraint_set1_flag,
1946 .constraint_set2_flag = constraint_set2_flag,
1947 .constraint_set3_flag = constraint_set3_flag,
1948 .level_idc = self->level_idc,
1950 .chroma_format_idc = seq_param->seq_fields.bits.chroma_format_idc,
1951 .bit_depth_luma_minus8 = seq_param->bit_depth_luma_minus8,
1952 .bit_depth_chroma_minus8 = seq_param->bit_depth_chroma_minus8,
1954 .log2_max_frame_num_minus4 =
1955 seq_param->seq_fields.bits.log2_max_frame_num_minus4,
1956 .pic_order_cnt_type = seq_param->seq_fields.bits.pic_order_cnt_type,
1957 .log2_max_pic_order_cnt_lsb_minus4 =
1958 seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4,
1960 .num_ref_frames = seq_param->max_num_ref_frames,
1961 .gaps_in_frame_num_value_allowed_flag = 0,
1962 .pic_width_in_mbs_minus1 = seq_param->picture_width_in_mbs - 1,
1963 .pic_height_in_map_units_minus1 =
1964 (seq_param->seq_fields.bits.frame_mbs_only_flag ?
1965 seq_param->picture_height_in_mbs - 1 :
1966 seq_param->picture_height_in_mbs / 2 - 1),
1967 .frame_mbs_only_flag = seq_param->seq_fields.bits.frame_mbs_only_flag,
1968 .mb_adaptive_frame_field_flag = 0,
1969 .direct_8x8_inference_flag =
1970 seq_param->seq_fields.bits.direct_8x8_inference_flag,
1971 .frame_cropping_flag = seq_param->frame_cropping_flag,
1972 .frame_crop_left_offset = seq_param->frame_crop_left_offset,
1973 .frame_crop_right_offset = seq_param->frame_crop_right_offset,
1974 .frame_crop_top_offset = seq_param->frame_crop_top_offset,
1975 .frame_crop_bottom_offset = seq_param->frame_crop_bottom_offset,
1977 .vui_parameters_present_flag = seq_param->vui_parameters_present_flag,
1979 .aspect_ratio_info_present_flag =
1980 seq_param->vui_fields.bits.aspect_ratio_info_present_flag,
1981 .aspect_ratio_idc = seq_param->aspect_ratio_idc,
1982 .sar_width = seq_param->sar_width,
1983 .sar_height = seq_param->sar_height,
1984 .overscan_info_present_flag = 0,
1985 .overscan_appropriate_flag = 0,
1986 .chroma_loc_info_present_flag = 0,
1987 .timing_info_present_flag =
1988 seq_param->vui_fields.bits.timing_info_present_flag,
1989 .num_units_in_tick = seq_param->num_units_in_tick,
1990 .time_scale = seq_param->time_scale,
1991 .fixed_frame_rate_flag = seq_param->vui_fields.bits.fixed_frame_rate_flag,
1993 /* We do not write hrd and no need for buffering period SEI. */
1994 .nal_hrd_parameters_present_flag = 0,
1995 .vcl_hrd_parameters_present_flag = 0,
1997 .low_delay_hrd_flag = seq_param->vui_fields.bits.low_delay_hrd_flag,
1998 .pic_struct_present_flag = 1,
1999 .bitstream_restriction_flag =
2000 seq_param->vui_fields.bits.bitstream_restriction_flag,
2001 .motion_vectors_over_pic_boundaries_flag =
2002 seq_param->vui_fields.bits.motion_vectors_over_pic_boundaries_flag,
2003 .max_bytes_per_pic_denom = 2,
2004 .max_bits_per_mb_denom = 1,
2005 .log2_max_mv_length_horizontal =
2006 seq_param->vui_fields.bits.log2_max_mv_length_horizontal,
2007 .log2_max_mv_length_vertical =
2008 seq_param->vui_fields.bits.log2_max_mv_length_vertical,
2009 .num_reorder_frames = self->gop.num_reorder_frames,
2010 .max_dec_frame_buffering = max_dec_frame_buffering,
2019 _add_sequence_header (GstVaH264Enc * self, GstVaH264EncFrame * frame)
2021 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2023 #define SPS_SIZE 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE + MAX_VUI_PARAMS_SIZE + \
2024 2 * MAX_HRD_PARAMS_SIZE) / 8
2025 guint8 packed_sps[SPS_SIZE] = { 0, };
2028 size = sizeof (packed_sps);
2029 if (gst_h264_bit_writer_sps (&self->sequence_hdr, TRUE, packed_sps,
2030 &size) != GST_H264_BIT_WRITER_OK) {
2031 GST_ERROR_OBJECT (self, "Failed to generate the sequence header");
2035 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2036 VAEncPackedHeaderSequence, packed_sps, size, FALSE)) {
2037 GST_ERROR_OBJECT (self, "Failed to add the packed sequence header");
2045 _fill_sequence_param (GstVaH264Enc * self,
2046 VAEncSequenceParameterBufferH264 * sequence)
2048 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2049 gboolean direct_8x8_inference_flag = TRUE;
2051 g_assert (self->gop.log2_max_frame_num >= 4);
2052 g_assert (self->gop.log2_max_pic_order_cnt >= 4);
2054 /* A.2.3 Extended profile:
2055 * Sequence parameter sets shall have direct_8x8_inference_flag
2058 * A.3.3 Profile-specific level limits:
2059 * direct_8x8_inference_flag is not relevant to the Baseline,
2060 * Constrained Baseline, Constrained High, High 10 Intra, High 4:2:2
2061 * Intra, High 4:4:4 Intra, and CAVLC 4:4:4 Intra profiles as these
2062 * profiles do not allow B slice types, and
2063 * direct_8x8_inference_flag is equal to 1 for all levels of the
2064 * Extended profile. Table A-4. We only have constrained baseline
2066 if (base->profile == VAProfileH264ConstrainedBaseline)
2067 direct_8x8_inference_flag = FALSE;
2070 *sequence = (VAEncSequenceParameterBufferH264) {
2071 .seq_parameter_set_id = 0,
2072 .level_idc = self->level_idc,
2074 self->gop.i_period > 0 ? self->gop.i_period : self->gop.idr_period,
2075 .intra_idr_period = self->gop.idr_period,
2076 .ip_period = self->gop.ip_period,
2077 .bits_per_second = self->rc.target_bitrate_bits,
2078 .max_num_ref_frames = self->gop.num_ref_frames,
2079 .picture_width_in_mbs = self->mb_width,
2080 .picture_height_in_mbs = self->mb_height,
2082 .seq_fields.bits = {
2083 /* Only support 4:2:0 now. */
2084 .chroma_format_idc = 1,
2085 .frame_mbs_only_flag = 1,
2086 .mb_adaptive_frame_field_flag = FALSE,
2087 .seq_scaling_matrix_present_flag = FALSE,
2088 .direct_8x8_inference_flag = direct_8x8_inference_flag,
2089 .log2_max_frame_num_minus4 = self->gop.log2_max_frame_num - 4,
2090 .pic_order_cnt_type = 0,
2091 .log2_max_pic_order_cnt_lsb_minus4 = self->gop.log2_max_pic_order_cnt - 4,
2093 .bit_depth_luma_minus8 = 0,
2094 .bit_depth_chroma_minus8 = 0,
2096 .vui_parameters_present_flag = TRUE,
2097 .vui_fields.bits = {
2098 .aspect_ratio_info_present_flag = TRUE,
2099 .timing_info_present_flag = TRUE,
2100 .bitstream_restriction_flag = TRUE,
2101 .log2_max_mv_length_horizontal = 15,
2102 .log2_max_mv_length_vertical = 15,
2103 .fixed_frame_rate_flag = 1,
2104 .low_delay_hrd_flag = 0,
2105 .motion_vectors_over_pic_boundaries_flag = TRUE,
2107 .aspect_ratio_idc = 0xff,
2108 /* FIXME: what if no framerate info is provided */
2109 .sar_width = GST_VIDEO_INFO_PAR_N (&base->input_state->info),
2110 .sar_height = GST_VIDEO_INFO_PAR_D (&base->input_state->info),
2111 .num_units_in_tick = GST_VIDEO_INFO_FPS_D (&base->input_state->info),
2112 .time_scale = GST_VIDEO_INFO_FPS_N (&base->input_state->info) * 2,
2116 /* frame_cropping_flag */
2117 if (base->width & 15 || base->height & 15) {
2118 static const guint SubWidthC[] = { 1, 2, 2, 1 };
2119 static const guint SubHeightC[] = { 1, 2, 1, 1 };
2120 const guint CropUnitX =
2121 SubWidthC[sequence->seq_fields.bits.chroma_format_idc];
2122 const guint CropUnitY =
2123 SubHeightC[sequence->seq_fields.bits.chroma_format_idc] *
2124 (2 - sequence->seq_fields.bits.frame_mbs_only_flag);
2126 sequence->frame_cropping_flag = 1;
2127 sequence->frame_crop_left_offset = 0;
2128 sequence->frame_crop_right_offset = (16 * self->mb_width -
2129 base->width) / CropUnitX;
2130 sequence->frame_crop_top_offset = 0;
2131 sequence->frame_crop_bottom_offset = (16 * self->mb_height -
2132 base->height) / CropUnitY;
2137 _add_sequence_parameter (GstVaH264Enc * self, GstVaEncodePicture * picture,
2138 VAEncSequenceParameterBufferH264 * sequence)
2140 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2142 if (!gst_va_encoder_add_param (base->encoder, picture,
2143 VAEncSequenceParameterBufferType, sequence, sizeof (*sequence))) {
2144 GST_ERROR_OBJECT (self, "Failed to create the sequence parameter");
2151 static inline gboolean
2152 _fill_picture_parameter (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2153 VAEncPictureParameterBufferH264 * pic_param)
2155 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2159 *pic_param = (VAEncPictureParameterBufferH264) {
2162 gst_va_encode_picture_get_reconstruct_surface (frame->picture),
2163 .TopFieldOrderCnt = frame->poc,
2165 .coded_buf = frame->picture->coded_buffer,
2166 /* Only support one sps and pps now. */
2167 .pic_parameter_set_id = 0,
2168 .seq_parameter_set_id = 0,
2169 /* means last encoding picture, EOS nal added. */
2170 .last_picture = frame->last_frame,
2171 .frame_num = frame->frame_num,
2173 .pic_init_qp = self->rc.qp_i,
2174 /* Use slice's these fields to control ref num. */
2175 .num_ref_idx_l0_active_minus1 = 0,
2176 .num_ref_idx_l1_active_minus1 = 0,
2177 .chroma_qp_index_offset = 0,
2178 .second_chroma_qp_index_offset = 0,
2179 /* picture fields */
2180 .pic_fields.bits.idr_pic_flag = (frame->frame_num == 0),
2181 .pic_fields.bits.reference_pic_flag = frame->is_ref,
2182 .pic_fields.bits.entropy_coding_mode_flag = self->use_cabac,
2183 .pic_fields.bits.weighted_pred_flag = 0,
2184 .pic_fields.bits.weighted_bipred_idc = 0,
2185 .pic_fields.bits.constrained_intra_pred_flag = 0,
2186 .pic_fields.bits.transform_8x8_mode_flag = self->use_dct8x8,
2187 /* enable debloking */
2188 .pic_fields.bits.deblocking_filter_control_present_flag = 1,
2189 .pic_fields.bits.redundant_pic_cnt_present_flag = 0,
2190 /* bottom_field_pic_order_in_frame_present_flag */
2191 .pic_fields.bits.pic_order_present_flag = 0,
2192 .pic_fields.bits.pic_scaling_matrix_present_flag = 0,
2196 /* Non I frame, construct reference list. */
2198 if (frame->type != GST_H264_I_SLICE) {
2199 GstVaH264EncFrame *f;
2201 if (g_queue_is_empty (&base->ref_list)) {
2202 GST_ERROR_OBJECT (self, "No reference found for frame type %s",
2203 _slice_type_name (frame->type));
2207 g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
2209 /* ref frames in queue are already sorted by frame_num. */
2210 for (; i < g_queue_get_length (&base->ref_list); i++) {
2211 f = _enc_frame (g_queue_peek_nth (&base->ref_list, i));
2213 pic_param->ReferenceFrames[i].picture_id =
2214 gst_va_encode_picture_get_reconstruct_surface (f->picture);
2215 pic_param->ReferenceFrames[i].TopFieldOrderCnt = f->poc;
2216 pic_param->ReferenceFrames[i].flags =
2217 VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2218 pic_param->ReferenceFrames[i].frame_idx = f->frame_num;
2222 pic_param->ReferenceFrames[i].picture_id = VA_INVALID_ID;
2228 _add_picture_parameter (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2229 VAEncPictureParameterBufferH264 * pic_param)
2231 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2233 if (!gst_va_encoder_add_param (base->encoder, frame->picture,
2234 VAEncPictureParameterBufferType, pic_param,
2235 sizeof (VAEncPictureParameterBufferH264))) {
2236 GST_ERROR_OBJECT (self, "Failed to create the picture parameter");
2244 _fill_pps (VAEncPictureParameterBufferH264 * pic_param, GstH264SPS * sps,
2248 *pps = (GstH264PPS) {
2251 .entropy_coding_mode_flag =
2252 pic_param->pic_fields.bits.entropy_coding_mode_flag,
2253 .pic_order_present_flag =
2254 pic_param->pic_fields.bits.pic_order_present_flag,
2255 .num_slice_groups_minus1 = 0,
2257 .num_ref_idx_l0_active_minus1 = pic_param->num_ref_idx_l0_active_minus1,
2258 .num_ref_idx_l1_active_minus1 = pic_param->num_ref_idx_l1_active_minus1,
2260 .weighted_pred_flag = pic_param->pic_fields.bits.weighted_pred_flag,
2261 .weighted_bipred_idc = pic_param->pic_fields.bits.weighted_bipred_idc,
2262 .pic_init_qp_minus26 = pic_param->pic_init_qp - 26,
2263 .pic_init_qs_minus26 = 0,
2264 .chroma_qp_index_offset = pic_param->chroma_qp_index_offset,
2265 .deblocking_filter_control_present_flag =
2266 pic_param->pic_fields.bits.deblocking_filter_control_present_flag,
2267 .constrained_intra_pred_flag =
2268 pic_param->pic_fields.bits.constrained_intra_pred_flag,
2269 .redundant_pic_cnt_present_flag =
2270 pic_param->pic_fields.bits.redundant_pic_cnt_present_flag,
2271 .transform_8x8_mode_flag =
2272 pic_param->pic_fields.bits.transform_8x8_mode_flag,
2273 /* unsupport scaling lists */
2274 .pic_scaling_matrix_present_flag = 0,
2275 .second_chroma_qp_index_offset = pic_param->second_chroma_qp_index_offset,
2281 _add_picture_header (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2284 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2285 #define PPS_SIZE 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8
2286 guint8 packed_pps[PPS_SIZE] = { 0, };
2290 size = sizeof (packed_pps);
2291 if (gst_h264_bit_writer_pps (pps, TRUE, packed_pps,
2292 &size) != GST_H264_BIT_WRITER_OK) {
2293 GST_ERROR_OBJECT (self, "Failed to generate the picture header");
2297 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2298 VAEncPackedHeaderPicture, packed_pps, size, FALSE)) {
2299 GST_ERROR_OBJECT (self, "Failed to add the packed picture header");
2307 _add_one_slice (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2308 gint start_mb, gint mb_size,
2309 VAEncSliceParameterBufferH264 * slice,
2310 GstVaH264EncFrame * list0[16], guint list0_num,
2311 GstVaH264EncFrame * list1[16], guint list1_num)
2313 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2314 int8_t slice_qp_delta = 0;
2318 if (self->rc.rc_ctrl_mode == VA_RC_CQP) {
2319 if (frame->type == GST_H264_P_SLICE) {
2320 slice_qp_delta = self->rc.qp_p - self->rc.qp_i;
2321 } else if (frame->type == GST_H264_B_SLICE) {
2322 slice_qp_delta = (int8_t) (self->rc.qp_b - self->rc.qp_i);
2324 g_assert (slice_qp_delta <= 51 && slice_qp_delta >= -51);
2327 *slice = (VAEncSliceParameterBufferH264) {
2328 .macroblock_address = start_mb,
2329 .num_macroblocks = mb_size,
2330 .macroblock_info = VA_INVALID_ID,
2331 .slice_type = (uint8_t) frame->type,
2332 /* Only one parameter set supported now. */
2333 .pic_parameter_set_id = 0,
2334 .idr_pic_id = self->gop.total_idr_count,
2335 .pic_order_cnt_lsb = frame->poc,
2336 /* Not support top/bottom. */
2337 .delta_pic_order_cnt_bottom = 0,
2338 .delta_pic_order_cnt[0] = 0,
2339 .delta_pic_order_cnt[1] = 0,
2341 .direct_spatial_mv_pred_flag = TRUE,
2342 /* .num_ref_idx_active_override_flag = , */
2343 /* .num_ref_idx_l0_active_minus1 = , */
2344 /* .num_ref_idx_l1_active_minus1 = , */
2345 /* Set the reference list later. */
2347 .luma_log2_weight_denom = 0,
2348 .chroma_log2_weight_denom = 0,
2349 .luma_weight_l0_flag = 0,
2350 .chroma_weight_l0_flag = 0,
2351 .luma_weight_l1_flag = 0,
2352 .chroma_weight_l1_flag = 0,
2354 .cabac_init_idc = 0,
2355 /* Just use picture default setting. */
2356 .slice_qp_delta = slice_qp_delta,
2358 .disable_deblocking_filter_idc = 0,
2359 .slice_alpha_c0_offset_div2 = 2,
2360 .slice_beta_offset_div2 = 2,
2364 if (frame->type == GST_H264_B_SLICE || frame->type == GST_H264_P_SLICE) {
2365 slice->num_ref_idx_active_override_flag = (list0_num > 0 || list1_num > 0);
2366 slice->num_ref_idx_l0_active_minus1 = list0_num > 0 ? list0_num - 1 : 0;
2367 if (frame->type == GST_H264_B_SLICE)
2368 slice->num_ref_idx_l1_active_minus1 = list1_num > 0 ? list1_num - 1 : 0;
2372 if (frame->type != GST_H264_I_SLICE) {
2373 for (; i < list0_num; i++) {
2374 slice->RefPicList0[i].picture_id =
2375 gst_va_encode_picture_get_reconstruct_surface (list0[i]->picture);
2376 slice->RefPicList0[i].TopFieldOrderCnt = list0[i]->poc;
2377 slice->RefPicList0[i].flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2378 slice->RefPicList0[i].frame_idx = list0[i]->frame_num;
2381 for (; i < G_N_ELEMENTS (slice->RefPicList0); ++i) {
2382 slice->RefPicList0[i].picture_id = VA_INVALID_SURFACE;
2383 slice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID;
2387 if (frame->type == GST_H264_B_SLICE) {
2388 for (; i < list1_num; i++) {
2389 slice->RefPicList1[i].picture_id =
2390 gst_va_encode_picture_get_reconstruct_surface (list1[i]->picture);
2391 slice->RefPicList1[i].TopFieldOrderCnt = list1[i]->poc;
2392 slice->RefPicList1[i].flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2393 slice->RefPicList1[i].frame_idx = list1[i]->frame_num;
2396 for (; i < G_N_ELEMENTS (slice->RefPicList1); ++i) {
2397 slice->RefPicList1[i].picture_id = VA_INVALID_SURFACE;
2398 slice->RefPicList1[i].flags = VA_PICTURE_H264_INVALID;
2401 if (!gst_va_encoder_add_param (base->encoder, frame->picture,
2402 VAEncSliceParameterBufferType, slice,
2403 sizeof (VAEncSliceParameterBufferH264))) {
2404 GST_ERROR_OBJECT (self, "Failed to create the slice parameter");
2412 _poc_asc_compare (const GstVaH264EncFrame ** a, const GstVaH264EncFrame ** b)
2414 return (*a)->poc - (*b)->poc;
2418 _poc_des_compare (const GstVaH264EncFrame ** a, const GstVaH264EncFrame ** b)
2420 return (*b)->poc - (*a)->poc;
2424 _frame_num_asc_compare (const GstVaH264EncFrame ** a,
2425 const GstVaH264EncFrame ** b)
2427 return (*a)->frame_num - (*b)->frame_num;
2431 _frame_num_des_compare (const GstVaH264EncFrame ** a,
2432 const GstVaH264EncFrame ** b)
2434 return (*b)->frame_num - (*a)->frame_num;
2437 /* If all the pic_num in the same order, OK. */
2439 _ref_list_need_reorder (GstVaH264EncFrame * list[16], guint list_num,
2448 for (i = 1; i < list_num; i++) {
2449 pic_num_diff = list[i]->frame_num - list[i - 1]->frame_num;
2450 g_assert (pic_num_diff != 0);
2452 if (pic_num_diff > 0 && !is_asc)
2455 if (pic_num_diff < 0 && is_asc)
2463 _insert_ref_pic_list_modification (GstH264SliceHdr * slice_hdr,
2464 GstVaH264EncFrame * list[16], guint list_num, gboolean is_asc)
2466 GstVaH264EncFrame *list_by_pic_num[16] = { };
2467 guint modification_num, i;
2468 GstH264RefPicListModification *ref_pic_list_modification = NULL;
2469 gint pic_num_diff, pic_num_lx_pred;
2471 memcpy (list_by_pic_num, list, sizeof (GstVaH264EncFrame *) * list_num);
2474 g_qsort_with_data (list_by_pic_num, list_num, sizeof (gpointer),
2475 (GCompareDataFunc) _frame_num_asc_compare, NULL);
2477 g_qsort_with_data (list_by_pic_num, list_num, sizeof (gpointer),
2478 (GCompareDataFunc) _frame_num_des_compare, NULL);
2481 modification_num = 0;
2482 for (i = 0; i < list_num; i++) {
2483 if (list_by_pic_num[i]->poc != list[i]->poc)
2484 modification_num = i + 1;
2486 g_assert (modification_num > 0);
2489 slice_hdr->ref_pic_list_modification_flag_l1 = 1;
2490 slice_hdr->n_ref_pic_list_modification_l1 =
2491 modification_num + 1 /* The end operation. */ ;
2492 ref_pic_list_modification = slice_hdr->ref_pic_list_modification_l1;
2494 slice_hdr->ref_pic_list_modification_flag_l0 = 1;
2495 slice_hdr->n_ref_pic_list_modification_l0 =
2496 modification_num + 1 /* The end operation. */ ;
2497 ref_pic_list_modification = slice_hdr->ref_pic_list_modification_l0;
2500 pic_num_lx_pred = slice_hdr->frame_num;
2501 for (i = 0; i < modification_num; i++) {
2502 pic_num_diff = list[i]->frame_num - pic_num_lx_pred;
2503 /* For the nex loop. */
2504 pic_num_lx_pred = list[i]->frame_num;
2506 g_assert (pic_num_diff != 0);
2508 if (pic_num_diff > 0) {
2509 ref_pic_list_modification->modification_of_pic_nums_idc = 1;
2510 ref_pic_list_modification->value.abs_diff_pic_num_minus1 =
2513 ref_pic_list_modification->modification_of_pic_nums_idc = 0;
2514 ref_pic_list_modification->value.abs_diff_pic_num_minus1 =
2515 (-pic_num_diff) - 1;
2518 ref_pic_list_modification++;
2521 ref_pic_list_modification->modification_of_pic_nums_idc = 3;
2525 _insert_ref_pic_marking_for_unused_frame (GstH264SliceHdr * slice_hdr,
2526 gint cur_frame_num, gint unused_frame_num)
2528 GstH264RefPicMarking *refpicmarking;
2530 slice_hdr->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag = 1;
2531 slice_hdr->dec_ref_pic_marking.n_ref_pic_marking = 2;
2533 refpicmarking = &slice_hdr->dec_ref_pic_marking.ref_pic_marking[0];
2535 refpicmarking->memory_management_control_operation = 1;
2536 refpicmarking->difference_of_pic_nums_minus1 =
2537 cur_frame_num - unused_frame_num - 1;
2539 refpicmarking = &slice_hdr->dec_ref_pic_marking.ref_pic_marking[1];
2540 refpicmarking->memory_management_control_operation = 0;
2544 _add_slice_header (GstVaH264Enc * self, GstVaH264EncFrame * frame,
2545 GstH264PPS * pps, VAEncSliceParameterBufferH264 * slice,
2546 GstVaH264EncFrame * list0[16], guint list0_num,
2547 GstVaH264EncFrame * list1[16], guint list1_num)
2549 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2550 GstH264SliceHdr slice_hdr;
2552 GstH264NalUnitType nal_type = GST_H264_NAL_SLICE;
2553 #define SLICE_HDR_SIZE 4 + GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8
2554 guint8 packed_slice_hdr[SLICE_HDR_SIZE] = { 0, };
2555 #undef SLICE_HDR_SIZE
2557 if (frame->frame_num == 0)
2558 nal_type = GST_H264_NAL_SLICE_IDR;
2561 slice_hdr = (GstH264SliceHdr) {
2562 .first_mb_in_slice = slice->macroblock_address,
2563 .type = slice->slice_type,
2565 .frame_num = frame->frame_num,
2566 /* interlaced not supported now. */
2567 .field_pic_flag = 0,
2568 .bottom_field_flag = 0,
2569 .idr_pic_id = (frame->frame_num == 0 ? slice->idr_pic_id : 0),
2570 /* only pic_order_cnt_type 1 is supported now. */
2571 .pic_order_cnt_lsb = slice->pic_order_cnt_lsb,
2572 .delta_pic_order_cnt_bottom = slice->delta_pic_order_cnt_bottom,
2573 /* Only for B frame. */
2574 .direct_spatial_mv_pred_flag =
2575 (frame->type == GST_H264_B_SLICE ?
2576 slice->direct_spatial_mv_pred_flag : 0),
2578 .num_ref_idx_active_override_flag = slice->num_ref_idx_active_override_flag,
2579 .num_ref_idx_l0_active_minus1 = slice->num_ref_idx_l0_active_minus1,
2580 .num_ref_idx_l1_active_minus1 = slice->num_ref_idx_l1_active_minus1,
2581 /* Calculate it later. */
2582 .ref_pic_list_modification_flag_l0 = 0,
2583 .ref_pic_list_modification_flag_l1 = 0,
2584 /* We have weighted_pred_flag and weighted_bipred_idc 0 here, no
2585 * need weight_table. */
2587 .dec_ref_pic_marking = {
2588 .no_output_of_prior_pics_flag = 0,
2589 .long_term_reference_flag = 0,
2590 /* If not sliding_window, we set it later. */
2591 .adaptive_ref_pic_marking_mode_flag = 0,
2594 .cabac_init_idc = slice->cabac_init_idc,
2595 .slice_qp_delta = slice->slice_qp_delta,
2597 .disable_deblocking_filter_idc = slice->disable_deblocking_filter_idc,
2598 .slice_alpha_c0_offset_div2 = slice->slice_alpha_c0_offset_div2,
2599 .slice_beta_offset_div2 = slice->slice_beta_offset_div2,
2603 /* Reorder the ref lists if needed. */
2604 if (list0_num > 1) {
2605 /* list0 is in poc descend order now. */
2606 if (_ref_list_need_reorder (list0, list0_num, FALSE))
2607 _insert_ref_pic_list_modification (&slice_hdr, list0, list0_num, FALSE);
2610 if (list0_num > 1) {
2611 /* list0 is in poc ascend order now. */
2612 if (_ref_list_need_reorder (list1, list1_num, TRUE)) {
2613 _insert_ref_pic_list_modification (&slice_hdr, list1, list1_num, TRUE);
2617 /* Mark the unused reference explicitly which this frame replaces. */
2618 if (frame->unused_for_reference_pic_num >= 0) {
2619 g_assert (frame->is_ref);
2620 _insert_ref_pic_marking_for_unused_frame (&slice_hdr, frame->frame_num,
2621 frame->unused_for_reference_pic_num);
2624 size = sizeof (packed_slice_hdr);
2625 if (gst_h264_bit_writer_slice_hdr (&slice_hdr, TRUE, nal_type, frame->is_ref,
2626 packed_slice_hdr, &size) != GST_H264_BIT_WRITER_OK) {
2627 GST_ERROR_OBJECT (self, "Failed to generate the slice header");
2631 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2632 VAEncPackedHeaderSlice, packed_slice_hdr, size, FALSE)) {
2633 GST_ERROR_OBJECT (self, "Failed to add the packed slice header");
2641 _add_aud (GstVaH264Enc * self, GstVaH264EncFrame * frame)
2643 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2644 guint8 aud_data[8] = { };
2646 guint8 primary_pic_type = 0;
2648 switch (frame->type) {
2649 case GST_H264_I_SLICE:
2650 primary_pic_type = 0;
2652 case GST_H264_P_SLICE:
2653 primary_pic_type = 1;
2655 case GST_H264_B_SLICE:
2656 primary_pic_type = 2;
2659 g_assert_not_reached ();
2663 size = sizeof (aud_data);
2664 if (gst_h264_bit_writer_aud (primary_pic_type, TRUE, aud_data,
2665 &size) != GST_H264_BIT_WRITER_OK) {
2666 GST_ERROR_OBJECT (self, "Failed to generate the AUD");
2670 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
2671 VAEncPackedHeaderRawData, aud_data, size, FALSE)) {
2672 GST_ERROR_OBJECT (self, "Failed to add the AUD");
2680 _encode_one_frame (GstVaH264Enc * self, GstVideoCodecFrame * gst_frame)
2682 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2683 VAEncPictureParameterBufferH264 pic_param;
2685 GstVaH264EncFrame *list0[16] = { NULL, };
2686 guint list0_num = 0;
2687 GstVaH264EncFrame *list1[16] = { NULL, };
2688 guint list1_num = 0;
2689 guint slice_of_mbs, slice_mod_mbs, slice_start_mb, slice_mbs;
2691 GstVaH264EncFrame *frame;
2693 g_return_val_if_fail (gst_frame, FALSE);
2695 frame = _enc_frame (gst_frame);
2697 /* Repeat the SPS for IDR. */
2698 if (frame->poc == 0) {
2699 VAEncSequenceParameterBufferH264 sequence;
2701 if (!gst_va_base_enc_add_rate_control_parameter (base, frame->picture,
2702 self->rc.rc_ctrl_mode, self->rc.max_bitrate_bits,
2703 self->rc.target_percentage, self->rc.qp_i, self->rc.min_qp,
2704 self->rc.max_qp, self->rc.mbbrc))
2707 if (!gst_va_base_enc_add_quality_level_parameter (base, frame->picture,
2708 self->rc.target_usage))
2711 if (!gst_va_base_enc_add_frame_rate_parameter (base, frame->picture))
2714 if (!gst_va_base_enc_add_hrd_parameter (base, frame->picture,
2715 self->rc.rc_ctrl_mode, self->rc.cpb_length_bits))
2718 if (!gst_va_base_enc_add_trellis_parameter (base, frame->picture,
2722 _fill_sequence_param (self, &sequence);
2723 if (!_fill_sps (self, &sequence))
2726 if (!_add_sequence_parameter (self, frame->picture, &sequence))
2729 if ((self->packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE)
2730 && !_add_sequence_header (self, frame))
2734 if (self->prop.aud) {
2735 if ((self->packed_headers & VA_ENC_PACKED_HEADER_RAW_DATA)
2736 && !_add_aud (self, frame))
2740 /* Non I frame, construct reference list. */
2741 if (frame->type != GST_H264_I_SLICE) {
2742 GstVaH264EncFrame *vaf;
2743 GstVideoCodecFrame *f;
2745 for (i = g_queue_get_length (&base->ref_list) - 1; i >= 0; i--) {
2746 f = g_queue_peek_nth (&base->ref_list, i);
2747 vaf = _enc_frame (f);
2748 if (vaf->poc > frame->poc)
2751 list0[list0_num] = vaf;
2755 /* reorder to select the most nearest forward frames. */
2756 g_qsort_with_data (list0, list0_num, sizeof (gpointer),
2757 (GCompareDataFunc) _poc_des_compare, NULL);
2759 if (list0_num > self->gop.ref_num_list0)
2760 list0_num = self->gop.ref_num_list0;
2763 if (frame->type == GST_H264_B_SLICE) {
2764 GstVaH264EncFrame *vaf;
2765 GstVideoCodecFrame *f;
2767 for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
2768 f = g_queue_peek_nth (&base->ref_list, i);
2769 vaf = _enc_frame (f);
2770 if (vaf->poc < frame->poc)
2773 list1[list1_num] = vaf;
2777 /* reorder to select the most nearest backward frames. */
2778 g_qsort_with_data (list1, list1_num, sizeof (gpointer),
2779 (GCompareDataFunc) _poc_asc_compare, NULL);
2781 if (list1_num > self->gop.ref_num_list1)
2782 list1_num = self->gop.ref_num_list1;
2785 g_assert (list0_num + list1_num <= self->gop.num_ref_frames);
2787 if (!_fill_picture_parameter (self, frame, &pic_param))
2789 if (!_add_picture_parameter (self, frame, &pic_param))
2791 _fill_pps (&pic_param, &self->sequence_hdr, &pps);
2793 if ((self->packed_headers & VA_ENC_PACKED_HEADER_PICTURE)
2794 && frame->type == GST_H264_I_SLICE
2795 && !_add_picture_header (self, frame, &pps))
2798 slice_of_mbs = self->mb_width * self->mb_height / self->num_slices;
2799 slice_mod_mbs = self->mb_width * self->mb_height % self->num_slices;
2802 for (i = 0; i < self->num_slices; i++) {
2803 VAEncSliceParameterBufferH264 slice;
2805 slice_mbs = slice_of_mbs;
2806 /* divide the remainder to each equally */
2807 if (slice_mod_mbs) {
2812 if (!_add_one_slice (self, frame, slice_start_mb, slice_mbs, &slice,
2813 list0, list0_num, list1, list1_num))
2816 if ((self->packed_headers & VA_ENC_PACKED_HEADER_SLICE) &&
2817 (!_add_slice_header (self, frame, &pps, &slice, list0, list0_num,
2821 slice_start_mb += slice_mbs;
2824 if (!gst_va_encoder_encode (base->encoder, frame->picture)) {
2825 GST_ERROR_OBJECT (self, "Encode frame error");
2833 gst_va_h264_enc_start (GstVideoEncoder * venc)
2835 GstVaH264Enc *self = GST_VA_H264_ENC (venc);
2837 gst_va_h264_enc_reset_state (self);
2839 return GST_VIDEO_ENCODER_CLASS (parent_class)->start (venc);
2843 gst_va_h264_enc_stop (GstVideoEncoder * venc)
2845 GstVaH264Enc *self = GST_VA_H264_ENC (venc);
2847 gst_va_h264_enc_reset_state (self);
2849 return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (venc);
2853 gst_va_h264_enc_flush (GstVideoEncoder * venc)
2855 GstVaH264Enc *self = GST_VA_H264_ENC (venc);
2857 /* begin from an IDR after flush. */
2858 self->gop.cur_frame_index = 0;
2859 self->gop.cur_frame_num = 0;
2861 return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (venc);
2865 gst_va_h264_enc_prepare_output (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
2867 GstVaH264Enc *self = GST_VA_H264_ENC (base);
2868 GstVaH264EncFrame *frame_enc;
2870 frame_enc = _enc_frame (frame);
2873 base->start_pts + base->frame_duration * frame_enc->total_frame_count;
2874 /* The PTS should always be later than the DTS. */
2875 frame->dts = base->start_pts + base->frame_duration *
2876 ((gint64) base->output_frame_count -
2877 (gint64) self->gop.num_reorder_frames);
2878 base->output_frame_count++;
2879 frame->duration = base->frame_duration;
2883 _sort_by_frame_num (gconstpointer a, gconstpointer b, gpointer user_data)
2885 GstVaH264EncFrame *frame1 = _enc_frame ((GstVideoCodecFrame *) a);
2886 GstVaH264EncFrame *frame2 = _enc_frame ((GstVideoCodecFrame *) b);
2888 g_assert (frame1->frame_num != frame2->frame_num);
2890 return frame1->frame_num - frame2->frame_num;
2893 static GstVideoCodecFrame *
2894 _find_unused_reference_frame (GstVaH264Enc * self, GstVaH264EncFrame * frame)
2896 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2897 GstVaH264EncFrame *b_vaframe;
2898 GstVideoCodecFrame *b_frame;
2901 /* We still have more space. */
2902 if (g_queue_get_length (&base->ref_list) < self->gop.num_ref_frames)
2905 /* Not b_pyramid, sliding window is enough. */
2906 if (!self->gop.b_pyramid)
2907 return g_queue_peek_head (&base->ref_list);
2909 /* I/P frame, just using sliding window. */
2910 if (frame->type != GST_H264_B_SLICE)
2911 return g_queue_peek_head (&base->ref_list);
2913 /* Choose the B frame with lowest POC. */
2916 for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
2917 GstVaH264EncFrame *vaf;
2918 GstVideoCodecFrame *f;
2920 f = g_queue_peek_nth (&base->ref_list, i);
2921 vaf = _enc_frame (f);
2922 if (vaf->type != GST_H264_B_SLICE)
2927 b_vaframe = _enc_frame (b_frame);
2931 b_vaframe = _enc_frame (b_frame);
2932 g_assert (vaf->poc != b_vaframe->poc);
2933 if (vaf->poc < b_vaframe->poc) {
2935 b_vaframe = _enc_frame (b_frame);
2939 /* No B frame as ref. */
2941 return g_queue_peek_head (&base->ref_list);
2943 if (b_frame != g_queue_peek_head (&base->ref_list)) {
2944 b_vaframe = _enc_frame (b_frame);
2945 frame->unused_for_reference_pic_num = b_vaframe->frame_num;
2946 GST_LOG_OBJECT (self, "The frame with POC: %d, pic_num %d will be"
2947 " replaced by the frame with POC: %d, pic_num %d explicitly by"
2948 " using memory_management_control_operation=1",
2949 b_vaframe->poc, b_vaframe->frame_num, frame->poc, frame->frame_num);
2955 static GstFlowReturn
2956 gst_va_h264_enc_encode_frame (GstVaBaseEnc * base,
2957 GstVideoCodecFrame * gst_frame, gboolean is_last)
2959 GstVaH264Enc *self = GST_VA_H264_ENC (base);
2960 GstVaH264EncFrame *frame;
2961 GstVideoCodecFrame *unused_ref = NULL;
2963 frame = _enc_frame (gst_frame);
2964 frame->last_frame = is_last;
2966 g_assert (frame->picture == NULL);
2967 frame->picture = gst_va_encode_picture_new (base->encoder,
2968 gst_frame->input_buffer);
2970 if (!frame->picture) {
2971 GST_ERROR_OBJECT (self, "Failed to create the encode picture");
2972 return GST_FLOW_ERROR;
2976 unused_ref = _find_unused_reference_frame (self, frame);
2978 if (!_encode_one_frame (self, gst_frame)) {
2979 GST_ERROR_OBJECT (self, "Failed to encode the frame");
2980 return GST_FLOW_ERROR;
2983 g_queue_push_tail (&base->output_list, gst_video_codec_frame_ref (gst_frame));
2985 if (frame->is_ref) {
2987 if (!g_queue_remove (&base->ref_list, unused_ref))
2988 g_assert_not_reached ();
2990 gst_video_codec_frame_unref (unused_ref);
2993 /* Add it into the reference list. */
2994 g_queue_push_tail (&base->ref_list, gst_video_codec_frame_ref (gst_frame));
2995 g_queue_sort (&base->ref_list, _sort_by_frame_num, NULL);
2997 g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
3004 gst_va_h264_enc_new_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
3006 GstVaH264EncFrame *frame_in;
3008 frame_in = gst_va_enc_frame_new ();
3009 frame_in->total_frame_count = base->input_frame_count++;
3010 gst_video_codec_frame_set_user_data (frame, frame_in, gst_va_enc_frame_free);
3016 static const gchar *sink_caps_str =
3017 GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VA,
3019 GST_VIDEO_CAPS_MAKE ("{ NV12 }");
3022 static const gchar *src_caps_str = "video/x-h264";
3025 _register_debug_category (gpointer data)
3027 GST_DEBUG_CATEGORY_INIT (gst_va_h264enc_debug, "vah264enc", 0,
3034 gst_va_h264_enc_init (GTypeInstance * instance, gpointer g_class)
3036 GstVaH264Enc *self = GST_VA_H264_ENC (instance);
3038 /* default values */
3039 self->prop.key_int_max = 0;
3040 self->prop.num_bframes = 0;
3041 self->prop.num_iframes = 0;
3042 self->prop.num_ref_frames = 3;
3043 self->prop.b_pyramid = FALSE;
3044 self->prop.num_slices = 1;
3045 self->prop.min_qp = 1;
3046 self->prop.max_qp = 51;
3047 self->prop.qp_i = 26;
3048 self->prop.qp_p = 26;
3049 self->prop.qp_b = 26;
3050 self->prop.use_dct8x8 = TRUE;
3051 self->prop.use_cabac = TRUE;
3052 self->prop.use_trellis = FALSE;
3053 self->prop.aud = FALSE;
3054 self->prop.mbbrc = 0;
3055 self->prop.bitrate = 0;
3056 self->prop.target_percentage = 66;
3057 self->prop.target_usage = 4;
3058 self->prop.rc_ctrl = VA_RC_CBR;
3059 self->prop.cpb_size = 0;
3063 gst_va_h264_enc_set_property (GObject * object, guint prop_id,
3064 const GValue * value, GParamSpec * pspec)
3066 GstVaH264Enc *const self = GST_VA_H264_ENC (object);
3067 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3069 if (base->encoder && gst_va_encoder_is_open (base->encoder)) {
3070 GST_ERROR_OBJECT (object,
3071 "failed to set any property after encoding started");
3075 GST_OBJECT_LOCK (self);
3078 case PROP_KEY_INT_MAX:
3079 self->prop.key_int_max = g_value_get_uint (value);
3082 self->prop.num_bframes = g_value_get_uint (value);
3085 self->prop.num_iframes = g_value_get_uint (value);
3087 case PROP_NUM_REF_FRAMES:
3088 self->prop.num_ref_frames = g_value_get_uint (value);
3090 case PROP_B_PYRAMID:
3091 self->prop.b_pyramid = g_value_get_boolean (value);
3093 case PROP_NUM_SLICES:
3094 self->prop.num_slices = g_value_get_uint (value);
3097 self->prop.min_qp = g_value_get_uint (value);
3100 self->prop.max_qp = g_value_get_uint (value);
3103 self->prop.qp_i = g_value_get_uint (value);
3106 self->prop.qp_p = g_value_get_uint (value);
3109 self->prop.qp_b = g_value_get_uint (value);
3112 self->prop.use_dct8x8 = g_value_get_boolean (value);
3115 self->prop.use_cabac = g_value_get_boolean (value);
3118 self->prop.use_trellis = g_value_get_boolean (value);
3121 self->prop.aud = g_value_get_boolean (value);
3124 /* Macroblock-level rate control.
3127 * 2: always disable,
3128 * other: reserved. */
3129 switch (g_value_get_enum (value)) {
3130 case GST_VA_FEATURE_DISABLED:
3131 self->prop.mbbrc = 2;
3133 case GST_VA_FEATURE_ENABLED:
3134 self->prop.mbbrc = 1;
3136 case GST_VA_FEATURE_AUTO:
3137 self->prop.mbbrc = 0;
3143 self->prop.bitrate = g_value_get_uint (value);
3145 case PROP_TARGET_PERCENTAGE:
3146 self->prop.target_percentage = g_value_get_uint (value);
3148 case PROP_TARGET_USAGE:
3149 self->prop.target_usage = g_value_get_uint (value);
3151 case PROP_RATE_CONTROL:
3152 self->prop.rc_ctrl = g_value_get_enum (value);
3155 self->prop.cpb_size = g_value_get_uint (value);
3158 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3161 GST_OBJECT_UNLOCK (self);
3165 gst_va_h264_enc_get_property (GObject * object, guint prop_id,
3166 GValue * value, GParamSpec * pspec)
3168 GstVaH264Enc *const self = GST_VA_H264_ENC (object);
3170 GST_OBJECT_LOCK (self);
3173 case PROP_KEY_INT_MAX:
3174 g_value_set_uint (value, self->prop.key_int_max);
3177 g_value_set_uint (value, self->prop.num_bframes);
3180 g_value_set_uint (value, self->prop.num_iframes);
3182 case PROP_NUM_REF_FRAMES:
3183 g_value_set_uint (value, self->prop.num_ref_frames);
3185 case PROP_B_PYRAMID:
3186 g_value_set_boolean (value, self->prop.b_pyramid);
3188 case PROP_NUM_SLICES:
3189 g_value_set_uint (value, self->prop.num_slices);
3192 g_value_set_uint (value, self->prop.min_qp);
3195 g_value_set_uint (value, self->prop.max_qp);
3198 g_value_set_uint (value, self->prop.qp_i);
3201 g_value_set_uint (value, self->prop.qp_p);
3204 g_value_set_uint (value, self->prop.qp_b);
3207 g_value_set_boolean (value, self->prop.use_dct8x8);
3210 g_value_set_boolean (value, self->prop.use_cabac);
3213 g_value_set_boolean (value, self->prop.use_trellis);
3216 g_value_set_boolean (value, self->prop.aud);
3219 g_value_set_enum (value, self->prop.mbbrc);
3222 g_value_set_uint (value, self->prop.bitrate);
3224 case PROP_TARGET_PERCENTAGE:
3225 g_value_set_uint (value, self->prop.target_percentage);
3227 case PROP_TARGET_USAGE:
3228 g_value_set_uint (value, self->prop.target_usage);
3230 case PROP_RATE_CONTROL:
3231 g_value_set_enum (value, self->prop.rc_ctrl);
3234 g_value_set_uint (value, self->prop.cpb_size);
3237 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3240 GST_OBJECT_UNLOCK (self);
3244 gst_va_h264_enc_dispose (GObject * object)
3246 G_OBJECT_CLASS (parent_class)->dispose (object);
3250 gst_va_h264_enc_class_init (gpointer g_klass, gpointer class_data)
3252 GstCaps *src_doc_caps, *sink_doc_caps;
3253 GstPadTemplate *sink_pad_templ, *src_pad_templ;
3254 GObjectClass *const object_class = G_OBJECT_CLASS (g_klass);
3255 GstElementClass *const element_class = GST_ELEMENT_CLASS (g_klass);
3256 GstVideoEncoderClass *const venc_class = GST_VIDEO_ENCODER_CLASS (g_klass);
3257 GstVaBaseEncClass *va_enc_class = GST_VA_BASE_ENC_CLASS (g_klass);
3258 struct CData *cdata = class_data;
3261 if (cdata->description) {
3262 long_name = g_strdup_printf ("VA-API H.264 Encoder in %s",
3263 cdata->description);
3265 long_name = g_strdup ("VA-API H.264 Encoder");
3268 gst_element_class_set_metadata (element_class, long_name,
3269 "Codec/Encoder/Video/Hardware", "VA-API based H.264 video encoder",
3270 "He Junyan <junyan.he@intel.com>");
3272 sink_doc_caps = gst_caps_from_string (sink_caps_str);
3273 src_doc_caps = gst_caps_from_string (src_caps_str);
3275 parent_class = g_type_class_peek_parent (g_klass);
3277 va_enc_class->codec = H264;
3278 va_enc_class->render_device_path = g_strdup (cdata->render_device_path);
3280 sink_pad_templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
3282 gst_element_class_add_pad_template (element_class, sink_pad_templ);
3284 gst_pad_template_set_documentation_caps (sink_pad_templ, sink_doc_caps);
3285 gst_caps_unref (sink_doc_caps);
3287 src_pad_templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
3289 gst_element_class_add_pad_template (element_class, src_pad_templ);
3291 gst_pad_template_set_documentation_caps (src_pad_templ, src_doc_caps);
3292 gst_caps_unref (src_doc_caps);
3294 object_class->dispose = gst_va_h264_enc_dispose;
3295 object_class->set_property = gst_va_h264_enc_set_property;
3296 object_class->get_property = gst_va_h264_enc_get_property;
3298 venc_class->start = GST_DEBUG_FUNCPTR (gst_va_h264_enc_start);
3299 venc_class->stop = GST_DEBUG_FUNCPTR (gst_va_h264_enc_stop);
3300 venc_class->flush = GST_DEBUG_FUNCPTR (gst_va_h264_enc_flush);
3302 va_enc_class->reconfig = GST_DEBUG_FUNCPTR (gst_va_h264_enc_reconfig);
3303 va_enc_class->new_frame = GST_DEBUG_FUNCPTR (gst_va_h264_enc_new_frame);
3304 va_enc_class->reorder_frame =
3305 GST_DEBUG_FUNCPTR (gst_va_h264_enc_reorder_frame);
3306 va_enc_class->encode_frame = GST_DEBUG_FUNCPTR (gst_va_h264_enc_encode_frame);
3307 va_enc_class->prepare_output =
3308 GST_DEBUG_FUNCPTR (gst_va_h264_enc_prepare_output);
3311 g_free (cdata->description);
3312 g_free (cdata->render_device_path);
3313 gst_caps_unref (cdata->src_caps);
3314 gst_caps_unref (cdata->sink_caps);
3318 * GstVaEncoder:key-int-max:
3320 * The maximal distance between two keyframes.
3322 properties[PROP_KEY_INT_MAX] = g_param_spec_uint ("key-int-max",
3323 "Key frame maximal interval",
3324 "The maximal distance between two keyframes. It decides the size of GOP"
3325 " (0: auto-calculate)", 0, MAX_GOP_SIZE, 0,
3326 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3329 * GstVaH264Enc:b-frames:
3331 * Number of B-frames between two reference frames.
3333 properties[PROP_BFRAMES] = g_param_spec_uint ("b-frames", "B Frames",
3334 "Number of B frames between I and P reference frames", 0, 31, 0,
3335 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3338 * GstVaH264Enc:i-frames:
3340 * Force the number of i-frames insertion within one GOP.
3342 properties[PROP_IFRAMES] = g_param_spec_uint ("i-frames", "I Frames",
3343 "Force the number of I frames insertion within one GOP, not including the "
3344 "first IDR frame", 0, 1023, 0,
3345 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3348 * GstVaH264Enc:ref-frames:
3350 * The number of reference frames.
3352 properties[PROP_NUM_REF_FRAMES] = g_param_spec_uint ("ref-frames",
3353 "Number of Reference Frames",
3354 "Number of reference frames, including both the forward and the backward",
3355 0, 16, 3, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3358 * GstVaH264Enc:b-pyramid:
3360 * Enable the b-pyramid reference structure in GOP.
3362 properties[PROP_B_PYRAMID] = g_param_spec_boolean ("b-pyramid", "b pyramid",
3363 "Enable the b-pyramid reference structure in the GOP", FALSE,
3364 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3366 * GstVaH264Enc:num-slices:
3368 * The number of slices per frame.
3370 properties[PROP_NUM_SLICES] = g_param_spec_uint ("num-slices",
3371 "Number of Slices", "Number of slices per frame", 1, 200, 1,
3372 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3375 * GstVaH264Enc:max-qp:
3377 * The maximum quantizer value.
3379 properties[PROP_MAX_QP] = g_param_spec_uint ("max-qp", "Maximum QP",
3380 "Maximum quantizer value for each frame", 0, 51, 51,
3381 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3384 * GstVaH264Enc:min-qp:
3386 * The minimum quantizer value.
3388 properties[PROP_MIN_QP] = g_param_spec_uint ("min-qp", "Minimum QP",
3389 "Minimum quantizer value for each frame", 0, 51, 1,
3390 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3395 * The quantizer value for I frame. In CQP mode, it specifies the QP of
3396 * I frame, in other mode, it specifies the init QP of all frames.
3398 properties[PROP_QP_I] = g_param_spec_uint ("qpi", "I Frame QP",
3399 "The quantizer value for I frame. In CQP mode, it specifies the QP of I "
3400 "frame, in other mode, it specifies the init QP of all frames", 0, 51, 26,
3401 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3406 * The quantizer value for P frame. This is available only in CQP mode.
3408 properties[PROP_QP_P] = g_param_spec_uint ("qpp",
3409 "The quantizer value for P frame",
3410 "The quantizer value for P frame. This is available only in CQP mode",
3412 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3417 * The quantizer value for B frame. This is available only in CQP mode.
3419 properties[PROP_QP_B] = g_param_spec_uint ("qpb",
3420 "The quantizer value for B frame",
3421 "The quantizer value for B frame. This is available only in CQP mode",
3423 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3426 * GstVaH264Enc:dct8x8:
3428 * Enable adaptive use of 8x8 transforms in I-frames. This improves
3429 * the compression ratio but requires high profile at least.
3431 properties[PROP_DCT8X8] = g_param_spec_boolean ("dct8x8",
3433 "Enable adaptive use of 8x8 transforms in I-frames", TRUE,
3434 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3437 * GstVaH264Enc:cabac:
3439 * It enables CABAC entropy coding mode to improve compression ratio,
3440 * but requires main profile at least.
3442 properties[PROP_CABAC] = g_param_spec_boolean ("cabac", "Enable CABAC",
3443 "Enable CABAC entropy coding mode", TRUE,
3444 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3447 * GstVaH264Enc:trellis:
3449 * It enable the trellis quantization method.
3450 * Trellis is an improved quantization algorithm.
3452 properties[PROP_TRELLIS] = g_param_spec_boolean ("trellis", "Enable trellis",
3453 "Enable the trellis quantization method", FALSE,
3454 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3459 * Insert the AU (Access Unit) delimeter for each frame.
3461 properties[PROP_AUD] = g_param_spec_boolean ("aud", "Insert AUD",
3462 "Insert AU (Access Unit) delimeter for each frame", FALSE,
3463 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3466 * GstVaH264Enc:mbbrc:
3468 * Macroblock level bitrate control.
3469 * This is not compatible with Constant QP rate control.
3471 properties[PROP_MBBRC] = g_param_spec_enum ("mbbrc",
3472 "Macroblock level Bitrate Control",
3473 "Macroblock level Bitrate Control. It is not compatible with CQP",
3474 GST_TYPE_VA_FEATURE, GST_VA_FEATURE_AUTO,
3475 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3478 * GstVaH264Enc:bitrate:
3480 * The desired target bitrate, expressed in kbps.
3481 * This is not available in CQP mode.
3483 * CBR: This applies equally to the minimum, maximum and target bitrate.
3484 * VBR: This applies to the target bitrate. The driver will use the
3485 * "target-percentage" together to calculate the minimum and maximum bitrate.
3486 * VCM: This applies to the target bitrate. The minimum and maximum bitrate
3489 properties[PROP_BITRATE] = g_param_spec_uint ("bitrate", "Bitrate (kbps)",
3490 "The desired bitrate expressed in kbps (0: auto-calculate)",
3492 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3495 * GstVaH264Enc:target-percentage:
3497 * The target percentage of the max bitrate, and expressed in uint,
3498 * equal to "target percentage"*100.
3499 * "target percentage" = "target bitrate" * 100 / "max bitrate"
3500 * This is available only when rate-control is VBR.
3501 * The driver uses it to calculate the minimum and maximum bitrate.
3503 properties[PROP_TARGET_PERCENTAGE] = g_param_spec_uint ("target-percentage",
3504 "target bitrate percentage",
3505 "The percentage for 'target bitrate'/'maximum bitrate' (Only in VBR)",
3507 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3510 * GstVaH264Enc:target-usage:
3512 * The target usage of the encoder. It controls and balances the encoding
3513 * speed and the encoding quality. The lower value has better quality but
3514 * slower speed, the higher value has faster speed but lower quality.
3516 properties[PROP_TARGET_USAGE] = g_param_spec_uint ("target-usage",
3518 "The target usage to control and balance the encoding speed/quality",
3519 1, 7, 4, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3522 * GstVaH264Enc:cpb-size:
3524 * The desired max CPB size in Kb (0: auto-calculate).
3526 properties[PROP_CPB_SIZE] = g_param_spec_uint ("cpb-size",
3527 "max CPB size in Kb",
3528 "The desired max CPB size in Kb (0: auto-calculate)", 0, 2000 * 1024, 0,
3529 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3532 * GstVaH264Enc:rate-control:
3534 * The desired rate control mode for the encoder.
3536 properties[PROP_RATE_CONTROL] = g_param_spec_enum ("rate-control",
3537 "rate control mode", "The desired rate control mode for the encoder",
3538 GST_TYPE_VA_ENCODER_RATE_CONTROL, VA_RC_CBR,
3539 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
3541 g_object_class_install_properties (object_class, N_PROPERTIES, properties);
3543 gst_type_mark_as_plugin_api (gst_va_encoder_rate_control_get_type (), 0);
3547 * @GST_VA_FEATURE_DISABLED: The feature is disabled.
3548 * @GST_VA_FEATURE_ENABLED: The feature is enabled.
3549 * @GST_VA_FEATURE_AUTO: The feature is enabled automatically.
3553 gst_type_mark_as_plugin_api (GST_TYPE_VA_FEATURE, 0);
3557 _complete_src_caps (GstCaps * srccaps)
3559 GstCaps *caps = gst_caps_copy (srccaps);
3561 gst_caps_set_simple (caps, "alignment", G_TYPE_STRING, "au", "stream-format",
3562 G_TYPE_STRING, "byte-stream", NULL);
3568 gst_va_h264_enc_register (GstPlugin * plugin, GstVaDevice * device,
3569 GstCaps * sink_caps, GstCaps * src_caps, guint rank)
3571 static GOnce debug_once = G_ONCE_INIT;
3573 GTypeInfo type_info = {
3574 .class_size = sizeof (GstVaH264EncClass),
3575 .class_init = gst_va_h264_enc_class_init,
3576 .instance_size = sizeof (GstVaH264Enc),
3577 .instance_init = gst_va_h264_enc_init,
3579 struct CData *cdata;
3581 gchar *type_name, *feature_name;
3583 g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE);
3584 g_return_val_if_fail (GST_IS_VA_DEVICE (device), FALSE);
3585 g_return_val_if_fail (GST_IS_CAPS (sink_caps), FALSE);
3586 g_return_val_if_fail (GST_IS_CAPS (src_caps), FALSE);
3588 cdata = g_new (struct CData, 1);
3589 cdata->description = NULL;
3590 cdata->render_device_path = g_strdup (device->render_device_path);
3591 cdata->sink_caps = gst_caps_ref (sink_caps);
3592 cdata->src_caps = _complete_src_caps (src_caps);
3594 /* class data will be leaked if the element never gets instantiated */
3595 GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
3596 GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
3597 GST_MINI_OBJECT_FLAG_SET (cdata->src_caps,
3598 GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
3600 type_info.class_data = cdata;
3601 type_name = g_strdup ("GstVaH264Enc");
3602 feature_name = g_strdup ("vah264enc");
3604 /* The first encoder to be registered should use a constant name,
3605 * like vah264enc, for any additional encoders, we create unique
3606 * names, using inserting the render device name. */
3607 if (g_type_from_name (type_name)) {
3608 gchar *basename = g_path_get_basename (device->render_device_path);
3610 g_free (feature_name);
3611 type_name = g_strdup_printf ("GstVa%sH264Enc", basename);
3612 feature_name = g_strdup_printf ("va%sh264enc", basename);
3613 cdata->description = basename;
3614 /* lower rank for non-first device */
3619 g_once (&debug_once, _register_debug_category, NULL);
3620 type = g_type_register_static (GST_TYPE_VA_BASE_ENC,
3621 type_name, &type_info, 0);
3622 ret = gst_element_register (plugin, feature_name, rank, type);
3625 g_free (feature_name);