mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 10:41:04 +00:00
encoder: h264: fix default CPB buffer size.
Fix default CPB buffer size to something more reasonable (1500 ms) and that still fits the level limits. This is a non configurable property for now. The initial CPB removal delay is also fixed to 750 ms. https://bugzilla.gnome.org/show_bug.cgi?id=722087
This commit is contained in:
parent
9d42c86422
commit
9d5fc53899
4 changed files with 67 additions and 26 deletions
|
@ -37,6 +37,12 @@
|
||||||
/* Define the maximum IDR period */
|
/* Define the maximum IDR period */
|
||||||
#define MAX_IDR_PERIOD 512
|
#define MAX_IDR_PERIOD 512
|
||||||
|
|
||||||
|
/* Default CPB length (in milliseconds) */
|
||||||
|
#define DEFAULT_CPB_LENGTH 1500
|
||||||
|
|
||||||
|
/* Scale factor for CPB size (HRD cpb_size_scale: min = 4) */
|
||||||
|
#define SX_CPB_SIZE 4
|
||||||
|
|
||||||
/* Scale factor for bitrate (HRD bit_rate_scale: min = 6) */
|
/* Scale factor for bitrate (HRD bit_rate_scale: min = 6) */
|
||||||
#define SX_BITRATE 6
|
#define SX_BITRATE 6
|
||||||
|
|
||||||
|
@ -249,7 +255,8 @@ bs_error:
|
||||||
/* Write an SPS NAL unit */
|
/* Write an SPS NAL unit */
|
||||||
static gboolean
|
static gboolean
|
||||||
bs_write_sps (GstBitWriter * bs,
|
bs_write_sps (GstBitWriter * bs,
|
||||||
const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile)
|
const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile,
|
||||||
|
const VAEncMiscParameterHRD * hrd_params)
|
||||||
{
|
{
|
||||||
guint8 profile_idc;
|
guint8 profile_idc;
|
||||||
guint32 constraint_set0_flag, constraint_set1_flag;
|
guint32 constraint_set0_flag, constraint_set1_flag;
|
||||||
|
@ -419,13 +426,13 @@ bs_write_sps (GstBitWriter * bs,
|
||||||
/* cpb_cnt_minus1 */
|
/* cpb_cnt_minus1 */
|
||||||
WRITE_UE (bs, 0);
|
WRITE_UE (bs, 0);
|
||||||
WRITE_UINT32 (bs, SX_BITRATE - 6, 4); /* bit_rate_scale */
|
WRITE_UINT32 (bs, SX_BITRATE - 6, 4); /* bit_rate_scale */
|
||||||
WRITE_UINT32 (bs, 6, 4); /* cpb_size_scale */
|
WRITE_UINT32 (bs, SX_CPB_SIZE - 4, 4); /* cpb_size_scale */
|
||||||
|
|
||||||
for (i = 0; i < 1; ++i) {
|
for (i = 0; i < 1; ++i) {
|
||||||
/* bit_rate_value_minus1[0] */
|
/* bit_rate_value_minus1[0] */
|
||||||
WRITE_UE (bs, (seq_param->bits_per_second >> SX_BITRATE) - 1);
|
WRITE_UE (bs, (seq_param->bits_per_second >> SX_BITRATE) - 1);
|
||||||
/* cpb_size_value_minus1[0] */
|
/* cpb_size_value_minus1[0] */
|
||||||
WRITE_UE (bs, seq_param->bits_per_second / 1000 * 8 - 1);
|
WRITE_UE (bs, (hrd_params->buffer_size >> SX_CPB_SIZE) - 1);
|
||||||
/* cbr_flag[0] */
|
/* cbr_flag[0] */
|
||||||
WRITE_UINT32 (bs, 1, 1);
|
WRITE_UINT32 (bs, 1, 1);
|
||||||
}
|
}
|
||||||
|
@ -586,6 +593,8 @@ struct _GstVaapiEncoderH264
|
||||||
GstBuffer *pps_data;
|
GstBuffer *pps_data;
|
||||||
|
|
||||||
guint bitrate_bits; // bitrate (bits)
|
guint bitrate_bits; // bitrate (bits)
|
||||||
|
guint cpb_length; // length of CPB buffer (ms)
|
||||||
|
guint cpb_length_bits; // length of CPB buffer (bits)
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -763,7 +772,9 @@ ensure_level (GstVaapiEncoderH264 * encoder)
|
||||||
if (PicSizeMbs <= limits->MaxFS &&
|
if (PicSizeMbs <= limits->MaxFS &&
|
||||||
MaxDpbMbs <= limits->MaxDpbMbs &&
|
MaxDpbMbs <= limits->MaxDpbMbs &&
|
||||||
MaxMBPS <= limits->MaxMBPS && (!encoder->bitrate_bits
|
MaxMBPS <= limits->MaxMBPS && (!encoder->bitrate_bits
|
||||||
|| encoder->bitrate_bits <= (limits->MaxBR * cpb_factor)))
|
|| encoder->bitrate_bits <= (limits->MaxBR * cpb_factor)) &&
|
||||||
|
(!encoder->cpb_length_bits ||
|
||||||
|
encoder->cpb_length_bits <= (limits->MaxCPB * cpb_factor)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == num_limits)
|
if (i == num_limits)
|
||||||
|
@ -897,7 +908,7 @@ static void
|
||||||
fill_hrd_params (GstVaapiEncoderH264 * encoder, VAEncMiscParameterHRD * hrd)
|
fill_hrd_params (GstVaapiEncoderH264 * encoder, VAEncMiscParameterHRD * hrd)
|
||||||
{
|
{
|
||||||
if (encoder->bitrate_bits > 0) {
|
if (encoder->bitrate_bits > 0) {
|
||||||
hrd->buffer_size = encoder->bitrate_bits * 8;
|
hrd->buffer_size = encoder->cpb_length_bits;
|
||||||
hrd->initial_buffer_fullness = hrd->buffer_size / 2;
|
hrd->initial_buffer_fullness = hrd->buffer_size / 2;
|
||||||
} else {
|
} else {
|
||||||
hrd->buffer_size = 0;
|
hrd->buffer_size = 0;
|
||||||
|
@ -915,14 +926,17 @@ add_packed_sequence_header (GstVaapiEncoderH264 * encoder,
|
||||||
GstBitWriter bs;
|
GstBitWriter bs;
|
||||||
VAEncPackedHeaderParameterBuffer packed_seq_param = { 0 };
|
VAEncPackedHeaderParameterBuffer packed_seq_param = { 0 };
|
||||||
const VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
|
const VAEncSequenceParameterBufferH264 *const seq_param = sequence->param;
|
||||||
|
VAEncMiscParameterHRD hrd_params;
|
||||||
guint32 data_bit_size;
|
guint32 data_bit_size;
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
|
|
||||||
|
fill_hrd_params (encoder, &hrd_params);
|
||||||
|
|
||||||
gst_bit_writer_init (&bs, 128 * 8);
|
gst_bit_writer_init (&bs, 128 * 8);
|
||||||
WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
|
WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
|
||||||
bs_write_nal_header (&bs,
|
bs_write_nal_header (&bs,
|
||||||
GST_VAAPI_ENCODER_H264_NAL_REF_IDC_HIGH, GST_VAAPI_ENCODER_H264_NAL_SPS);
|
GST_VAAPI_ENCODER_H264_NAL_REF_IDC_HIGH, GST_VAAPI_ENCODER_H264_NAL_SPS);
|
||||||
bs_write_sps (&bs, seq_param, encoder->profile);
|
bs_write_sps (&bs, seq_param, encoder->profile, &hrd_params);
|
||||||
g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
|
g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
|
||||||
data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
|
data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
|
||||||
data = GST_BIT_WRITER_DATA (&bs);
|
data = GST_BIT_WRITER_DATA (&bs);
|
||||||
|
@ -1439,7 +1453,7 @@ ensure_misc_params (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
|
||||||
memset (rate_control, 0, sizeof (VAEncMiscParameterRateControl));
|
memset (rate_control, 0, sizeof (VAEncMiscParameterRateControl));
|
||||||
rate_control->bits_per_second = encoder->bitrate_bits;
|
rate_control->bits_per_second = encoder->bitrate_bits;
|
||||||
rate_control->target_percentage = 70;
|
rate_control->target_percentage = 70;
|
||||||
rate_control->window_size = 500;
|
rate_control->window_size = encoder->cpb_length;
|
||||||
rate_control->initial_qp = encoder->init_qp;
|
rate_control->initial_qp = encoder->init_qp;
|
||||||
rate_control->min_qp = encoder->min_qp;
|
rate_control->min_qp = encoder->min_qp;
|
||||||
rate_control->basic_unit_size = 0;
|
rate_control->basic_unit_size = 0;
|
||||||
|
@ -1504,7 +1518,7 @@ static void
|
||||||
ensure_bitrate_hrd (GstVaapiEncoderH264 * encoder)
|
ensure_bitrate_hrd (GstVaapiEncoderH264 * encoder)
|
||||||
{
|
{
|
||||||
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
|
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
|
||||||
guint bitrate;
|
guint bitrate, cpb_size;
|
||||||
|
|
||||||
if (!base_encoder->bitrate) {
|
if (!base_encoder->bitrate) {
|
||||||
encoder->bitrate_bits = 0;
|
encoder->bitrate_bits = 0;
|
||||||
|
@ -1516,6 +1530,13 @@ ensure_bitrate_hrd (GstVaapiEncoderH264 * encoder)
|
||||||
bitrate = (base_encoder->bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
|
bitrate = (base_encoder->bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
|
||||||
GST_DEBUG ("HRD bitrate: %u bits/sec", bitrate);
|
GST_DEBUG ("HRD bitrate: %u bits/sec", bitrate);
|
||||||
encoder->bitrate_bits = bitrate;
|
encoder->bitrate_bits = bitrate;
|
||||||
|
|
||||||
|
/* Round up CPB size. This is an HRD compliance detail */
|
||||||
|
g_assert (SX_CPB_SIZE >= 4);
|
||||||
|
cpb_size = gst_util_uint64_scale (bitrate, encoder->cpb_length, 1000) &
|
||||||
|
~((1U << SX_CPB_SIZE) - 1);
|
||||||
|
GST_DEBUG ("HRD CPB size: %u bits", cpb_size);
|
||||||
|
encoder->cpb_length_bits = cpb_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Estimates a good enough bitrate if none was supplied */
|
/* Estimates a good enough bitrate if none was supplied */
|
||||||
|
@ -2003,6 +2024,9 @@ gst_vaapi_encoder_h264_set_property (GstVaapiEncoder * base_encoder,
|
||||||
case GST_VAAPI_ENCODER_H264_PROP_DCT8X8:
|
case GST_VAAPI_ENCODER_H264_PROP_DCT8X8:
|
||||||
encoder->use_dct8x8 = g_value_get_boolean (value);
|
encoder->use_dct8x8 = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case GST_VAAPI_ENCODER_H264_PROP_CPB_LENGTH:
|
||||||
|
encoder->cpb_length = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
|
return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
@ -2131,6 +2155,18 @@ gst_vaapi_encoder_h264_get_default_properties (void)
|
||||||
"Enable adaptive use of 8x8 transforms in I-frames",
|
"Enable adaptive use of 8x8 transforms in I-frames",
|
||||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstVaapiEncoderH264:cpb-length:
|
||||||
|
*
|
||||||
|
* The size of the CPB buffer in milliseconds.
|
||||||
|
*/
|
||||||
|
GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
|
||||||
|
GST_VAAPI_ENCODER_H264_PROP_CPB_LENGTH,
|
||||||
|
g_param_spec_uint ("cpb-length",
|
||||||
|
"CPB Length", "Length of the CPB buffer in milliseconds",
|
||||||
|
1, 10000, DEFAULT_CPB_LENGTH,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ typedef struct _GstVaapiEncoderH264 GstVaapiEncoderH264;
|
||||||
* @GST_VAAPI_ENCODER_H264_PROP_CABAC: Enable CABAC entropy coding mode (bool).
|
* @GST_VAAPI_ENCODER_H264_PROP_CABAC: Enable CABAC entropy coding mode (bool).
|
||||||
* @GST_VAAPI_ENCODER_H264_PROP_DCT8X8: Enable adaptive use of 8x8
|
* @GST_VAAPI_ENCODER_H264_PROP_DCT8X8: Enable adaptive use of 8x8
|
||||||
* transforms in I-frames (bool).
|
* transforms in I-frames (bool).
|
||||||
|
* @GST_VAAPI_ENCODER_H264_PROP_CPB_LENGTH: Length of the CPB buffer
|
||||||
|
* in milliseconds (uint).
|
||||||
*
|
*
|
||||||
* The set of H.264 encoder specific configurable properties.
|
* The set of H.264 encoder specific configurable properties.
|
||||||
*/
|
*/
|
||||||
|
@ -52,6 +54,7 @@ typedef enum {
|
||||||
GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES = -4,
|
GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES = -4,
|
||||||
GST_VAAPI_ENCODER_H264_PROP_CABAC = -5,
|
GST_VAAPI_ENCODER_H264_PROP_CABAC = -5,
|
||||||
GST_VAAPI_ENCODER_H264_PROP_DCT8X8 = -6,
|
GST_VAAPI_ENCODER_H264_PROP_DCT8X8 = -6,
|
||||||
|
GST_VAAPI_ENCODER_H264_PROP_CPB_LENGTH = -7,
|
||||||
} GstVaapiEncoderH264Prop;
|
} GstVaapiEncoderH264Prop;
|
||||||
|
|
||||||
GstVaapiEncoder *
|
GstVaapiEncoder *
|
||||||
|
|
|
@ -76,24 +76,24 @@ static const struct map gst_vaapi_h264_level_map[] = {
|
||||||
/* Table A-1 - Level limits */
|
/* Table A-1 - Level limits */
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
static const GstVaapiH264LevelLimits gst_vaapi_h264_level_limits[] = {
|
static const GstVaapiH264LevelLimits gst_vaapi_h264_level_limits[] = {
|
||||||
/* level idc MaxMBPS MaxFS MaxDpbMbs MaxBR */
|
/* level idc MaxMBPS MaxFS MaxDpbMbs MaxBR MaxCPB */
|
||||||
{ GST_VAAPI_LEVEL_H264_L1, 10, 1485, 99, 396, 64 },
|
{ GST_VAAPI_LEVEL_H264_L1, 10, 1485, 99, 396, 64, 175 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L1b, 11, 1485, 99, 396, 128 },
|
{ GST_VAAPI_LEVEL_H264_L1b, 11, 1485, 99, 396, 128, 350 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L1_1, 11, 3000, 396, 900, 192 },
|
{ GST_VAAPI_LEVEL_H264_L1_1, 11, 3000, 396, 900, 192, 500 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L1_2, 12, 6000, 396, 2376, 384 },
|
{ GST_VAAPI_LEVEL_H264_L1_2, 12, 6000, 396, 2376, 384, 1000 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L1_3, 13, 11880, 396, 2376, 768 },
|
{ GST_VAAPI_LEVEL_H264_L1_3, 13, 11880, 396, 2376, 768, 2000 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L2, 20, 11880, 396, 2376, 2000 },
|
{ GST_VAAPI_LEVEL_H264_L2, 20, 11880, 396, 2376, 2000, 2000 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L2_1, 21, 19800, 792, 4752, 4000 },
|
{ GST_VAAPI_LEVEL_H264_L2_1, 21, 19800, 792, 4752, 4000, 4000 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L2_2, 22, 20250, 1620, 8100, 4000 },
|
{ GST_VAAPI_LEVEL_H264_L2_2, 22, 20250, 1620, 8100, 4000, 4000 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L3, 30, 40500, 1620, 8100, 10000 },
|
{ GST_VAAPI_LEVEL_H264_L3, 30, 40500, 1620, 8100, 10000, 10000 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L3_1, 31, 108000, 3600, 18000, 14000 },
|
{ GST_VAAPI_LEVEL_H264_L3_1, 31, 108000, 3600, 18000, 14000, 14000 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L3_2, 32, 216000, 5120, 20480, 20000 },
|
{ GST_VAAPI_LEVEL_H264_L3_2, 32, 216000, 5120, 20480, 20000, 20000 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L4, 40, 245760, 8192, 32768, 20000 },
|
{ GST_VAAPI_LEVEL_H264_L4, 40, 245760, 8192, 32768, 20000, 25000 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L4_1, 41, 245760, 8192, 32768, 50000 },
|
{ GST_VAAPI_LEVEL_H264_L4_1, 41, 245760, 8192, 32768, 50000, 62500 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L4_2, 42, 522240, 8704, 34816, 50000 },
|
{ GST_VAAPI_LEVEL_H264_L4_2, 42, 522240, 8704, 34816, 50000, 62500 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L5, 50, 589824, 22080, 110400, 135000 },
|
{ GST_VAAPI_LEVEL_H264_L5, 50, 589824, 22080, 110400, 135000, 135000 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L5_1, 51, 983040, 36864, 184320, 240000 },
|
{ GST_VAAPI_LEVEL_H264_L5_1, 51, 983040, 36864, 184320, 240000, 240000 },
|
||||||
{ GST_VAAPI_LEVEL_H264_L5_2, 52, 2073600, 36864, 184320, 240000 },
|
{ GST_VAAPI_LEVEL_H264_L5_2, 52, 2073600, 36864, 184320, 240000, 240000 },
|
||||||
{ 0, }
|
{ 0, }
|
||||||
};
|
};
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
|
@ -35,6 +35,7 @@ G_BEGIN_DECLS
|
||||||
* @MaxFS: the maximum frame size (MBs)
|
* @MaxFS: the maximum frame size (MBs)
|
||||||
* @MaxDpbMbs: the maxium decoded picture buffer size (MBs)
|
* @MaxDpbMbs: the maxium decoded picture buffer size (MBs)
|
||||||
* @MaxBR: the maximum video bit rate (kbps)
|
* @MaxBR: the maximum video bit rate (kbps)
|
||||||
|
* @MaxCPB: the maximum CPB size (kbits)
|
||||||
*
|
*
|
||||||
* The data structure that describes the limits of an H.264 level.
|
* The data structure that describes the limits of an H.264 level.
|
||||||
*/
|
*/
|
||||||
|
@ -46,6 +47,7 @@ typedef struct
|
||||||
guint32 MaxFS;
|
guint32 MaxFS;
|
||||||
guint32 MaxDpbMbs;
|
guint32 MaxDpbMbs;
|
||||||
guint32 MaxBR;
|
guint32 MaxBR;
|
||||||
|
guint32 MaxCPB;
|
||||||
} GstVaapiH264LevelLimits;
|
} GstVaapiH264LevelLimits;
|
||||||
|
|
||||||
/* Returns GstVaapiProfile from H.264 profile_idc value */
|
/* Returns GstVaapiProfile from H.264 profile_idc value */
|
||||||
|
|
Loading…
Reference in a new issue