mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-10 03:19:40 +00:00
encoder: h264: derive profile and level from active coding tools.
Automatically derive the minimum profile and level to be used for encoding, based on the activated coding tools. The encoder will be trying to generate a bitstream that has the best chances to be decoded on most platforms by default. Also change the default profile to "constrained-baseline" so that to ensure maximum compatibility when the stream is decoded. https://bugzilla.gnome.org/show_bug.cgi?id=719691
This commit is contained in:
parent
2b482e8e4b
commit
b59a5572af
3 changed files with 77 additions and 104 deletions
|
@ -209,96 +209,52 @@ ensure_profile (GstVaapiEncoderH264 * encoder)
|
||||||
{
|
{
|
||||||
GstVaapiProfile profile;
|
GstVaapiProfile profile;
|
||||||
|
|
||||||
profile = GST_VAAPI_PROFILE_H264_BASELINE;
|
/* Always start from "constrained-baseline" profile for maximum
|
||||||
|
compatibility */
|
||||||
|
profile = GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
|
||||||
|
|
||||||
|
/* Main profile coding tools */
|
||||||
|
if (encoder->num_bframes > 0)
|
||||||
|
profile = GST_VAAPI_PROFILE_H264_MAIN;
|
||||||
|
|
||||||
encoder->profile = profile;
|
encoder->profile = profile;
|
||||||
|
encoder->profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
_set_level (GstVaapiEncoderH264 * encoder)
|
ensure_level (GstVaapiEncoderH264 * encoder)
|
||||||
{
|
{
|
||||||
guint pic_mb_size;
|
const guint bitrate = GST_VAAPI_ENCODER_CAST (encoder)->bitrate;
|
||||||
guint MaxDpbMbs, MaxMBPS;
|
const GstVaapiH264LevelLimits *limits_table;
|
||||||
guint dbp_level, mbps_level, profile_level;
|
guint i, num_limits, PicSizeMbs, MaxDpbMbs, MaxMBPS;
|
||||||
|
|
||||||
if (encoder->level_idc) {
|
PicSizeMbs = encoder->mb_width * encoder->mb_height;
|
||||||
if (encoder->level_idc < GST_VAAPI_ENCODER_H264_LEVEL_10)
|
MaxDpbMbs = PicSizeMbs * ((encoder->num_bframes) ? 2 : 1);
|
||||||
encoder->level_idc = GST_VAAPI_ENCODER_H264_LEVEL_10;
|
MaxMBPS = gst_util_uint64_scale_int_ceil (PicSizeMbs,
|
||||||
else if (encoder->level_idc > GST_VAAPI_ENCODER_H264_LEVEL_51)
|
GST_VAAPI_ENCODER_FPS_N (encoder), GST_VAAPI_ENCODER_FPS_D (encoder));
|
||||||
encoder->level_idc = GST_VAAPI_ENCODER_H264_LEVEL_51;
|
|
||||||
return;
|
limits_table = gst_vaapi_utils_h264_get_level_limits_table (&num_limits);
|
||||||
|
for (i = 0; i < num_limits; i++) {
|
||||||
|
const GstVaapiH264LevelLimits *const limits = &limits_table[i];
|
||||||
|
if (PicSizeMbs <= limits->MaxFS &&
|
||||||
|
MaxDpbMbs <= limits->MaxDpbMbs &&
|
||||||
|
MaxMBPS <= limits->MaxMBPS && (!bitrate || bitrate <= limits->MaxBR))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (i == num_limits)
|
||||||
|
goto error_unsupported_level;
|
||||||
|
|
||||||
/* calculate level */
|
encoder->level = limits_table[i].level;
|
||||||
pic_mb_size = ((GST_VAAPI_ENCODER_WIDTH (encoder) + 15) / 16) *
|
encoder->level_idc = limits_table[i].level_idc;
|
||||||
((GST_VAAPI_ENCODER_HEIGHT (encoder) + 15) / 16);
|
return TRUE;
|
||||||
MaxDpbMbs = pic_mb_size * ((encoder->num_bframes) ? 2 : 1);
|
|
||||||
MaxMBPS = pic_mb_size * GST_VAAPI_ENCODER_FPS_N (encoder) /
|
|
||||||
GST_VAAPI_ENCODER_FPS_D (encoder);
|
|
||||||
|
|
||||||
/* calculate from MaxDbpMbs */
|
/* ERRORS */
|
||||||
if (MaxDpbMbs > 110400)
|
error_unsupported_level:
|
||||||
dbp_level = GST_VAAPI_ENCODER_H264_LEVEL_51;
|
{
|
||||||
else if (MaxDpbMbs > 34816)
|
GST_ERROR ("failed to find a suitable level matching codec config");
|
||||||
dbp_level = GST_VAAPI_ENCODER_H264_LEVEL_50;
|
return FALSE;
|
||||||
else if (MaxDpbMbs > 32768)
|
}
|
||||||
dbp_level = GST_VAAPI_ENCODER_H264_LEVEL_42;
|
|
||||||
else if (MaxDpbMbs > 20480) /* 41 or 40 */
|
|
||||||
dbp_level = GST_VAAPI_ENCODER_H264_LEVEL_41;
|
|
||||||
else if (MaxDpbMbs > 18000)
|
|
||||||
dbp_level = GST_VAAPI_ENCODER_H264_LEVEL_32;
|
|
||||||
else if (MaxDpbMbs > 8100)
|
|
||||||
dbp_level = GST_VAAPI_ENCODER_H264_LEVEL_31;
|
|
||||||
else if (MaxDpbMbs > 4752) /* 30 or 22 */
|
|
||||||
dbp_level = GST_VAAPI_ENCODER_H264_LEVEL_30;
|
|
||||||
else if (MaxDpbMbs > 2376)
|
|
||||||
dbp_level = GST_VAAPI_ENCODER_H264_LEVEL_21;
|
|
||||||
else if (MaxDpbMbs > 900) /* 20, 13, 12 */
|
|
||||||
dbp_level = GST_VAAPI_ENCODER_H264_LEVEL_20;
|
|
||||||
else if (MaxDpbMbs > 396)
|
|
||||||
dbp_level = GST_VAAPI_ENCODER_H264_LEVEL_11;
|
|
||||||
else
|
|
||||||
dbp_level = GST_VAAPI_ENCODER_H264_LEVEL_10;
|
|
||||||
|
|
||||||
/* calculate from Max Mb processing rate */
|
|
||||||
if (MaxMBPS > 589824)
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_51;
|
|
||||||
else if (MaxMBPS > 522240)
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_50;
|
|
||||||
else if (MaxMBPS > 245760)
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_42;
|
|
||||||
else if (MaxMBPS > 216000) /* 40 or 41 */
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_41;
|
|
||||||
else if (MaxMBPS > 108000)
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_32;
|
|
||||||
else if (MaxMBPS > 40500)
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_31;
|
|
||||||
else if (MaxMBPS > 20250)
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_30;
|
|
||||||
else if (MaxMBPS > 19800)
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_22;
|
|
||||||
else if (MaxMBPS > 11800)
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_21;
|
|
||||||
else if (MaxMBPS > 6000) /*13 or 20 */
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_20;
|
|
||||||
else if (MaxMBPS > 3000)
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_12;
|
|
||||||
else if (MaxMBPS > 1485)
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_11;
|
|
||||||
else
|
|
||||||
mbps_level = GST_VAAPI_ENCODER_H264_LEVEL_10;
|
|
||||||
|
|
||||||
if (encoder->profile == GST_VAAPI_PROFILE_H264_HIGH)
|
|
||||||
profile_level = GST_VAAPI_ENCODER_H264_LEVEL_41;
|
|
||||||
else if (encoder->profile == GST_VAAPI_PROFILE_H264_MAIN)
|
|
||||||
profile_level = GST_VAAPI_ENCODER_H264_LEVEL_30;
|
|
||||||
else
|
|
||||||
profile_level = GST_VAAPI_ENCODER_H264_LEVEL_20;
|
|
||||||
|
|
||||||
encoder->level_idc = (dbp_level > mbps_level ? dbp_level : mbps_level);
|
|
||||||
if (encoder->level_idc < profile_level)
|
|
||||||
encoder->level_idc = profile_level;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -1015,7 +971,7 @@ fill_va_picture_param (GstVaapiEncoderH264 * encoder,
|
||||||
pic_param->pic_fields.bits.weighted_pred_flag = FALSE;
|
pic_param->pic_fields.bits.weighted_pred_flag = FALSE;
|
||||||
pic_param->pic_fields.bits.weighted_bipred_idc = 0;
|
pic_param->pic_fields.bits.weighted_bipred_idc = 0;
|
||||||
pic_param->pic_fields.bits.constrained_intra_pred_flag = 0;
|
pic_param->pic_fields.bits.constrained_intra_pred_flag = 0;
|
||||||
pic_param->pic_fields.bits.transform_8x8_mode_flag = (encoder->profile >= GST_VAAPI_PROFILE_H264_HIGH); /* enable 8x8 */
|
pic_param->pic_fields.bits.transform_8x8_mode_flag = (encoder->profile_idc >= 100); /* enable 8x8 */
|
||||||
/* enable debloking */
|
/* enable debloking */
|
||||||
pic_param->pic_fields.bits.deblocking_filter_control_present_flag = TRUE;
|
pic_param->pic_fields.bits.deblocking_filter_control_present_flag = TRUE;
|
||||||
pic_param->pic_fields.bits.redundant_pic_cnt_present_flag = FALSE;
|
pic_param->pic_fields.bits.redundant_pic_cnt_present_flag = FALSE;
|
||||||
|
@ -1282,8 +1238,8 @@ ensure_profile_and_level (GstVaapiEncoderH264 * encoder)
|
||||||
{
|
{
|
||||||
if (!ensure_profile (encoder))
|
if (!ensure_profile (encoder))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
if (!ensure_level (encoder))
|
||||||
_set_level (encoder);
|
return FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1831,3 +1787,32 @@ gst_vaapi_encoder_h264_get_default_properties (void)
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_encoder_h264_get_profile_and_level:
|
||||||
|
* @encoder: a #GstVaapiEncoderH264
|
||||||
|
* @out_profile_ptr: return location for the #GstVaapiProfile
|
||||||
|
* @out_level_ptr: return location for the #GstVaapiLevelH264
|
||||||
|
*
|
||||||
|
* Queries the H.264 @encoder for the active profile and level. That
|
||||||
|
* information is only constructed and valid after the encoder is
|
||||||
|
* configured, i.e. after the gst_vaapi_encoder_set_codec_state()
|
||||||
|
* function is called.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE on success
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_vaapi_encoder_h264_get_profile_and_level (GstVaapiEncoderH264 * encoder,
|
||||||
|
GstVaapiProfile * out_profile_ptr, GstVaapiLevelH264 * out_level_ptr)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (encoder != NULL, FALSE);
|
||||||
|
|
||||||
|
if (!encoder->profile || !encoder->level)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (out_profile_ptr)
|
||||||
|
*out_profile_ptr = encoder->profile;
|
||||||
|
if (out_level_ptr)
|
||||||
|
*out_level_ptr = encoder->level;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#define GST_VAAPI_ENCODER_H264_H
|
#define GST_VAAPI_ENCODER_H264_H
|
||||||
|
|
||||||
#include <gst/vaapi/gstvaapiencoder.h>
|
#include <gst/vaapi/gstvaapiencoder.h>
|
||||||
|
#include <gst/vaapi/gstvaapiutils_h264.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
@ -54,6 +55,10 @@ gst_vaapi_encoder_h264_new (GstVaapiDisplay * display);
|
||||||
GPtrArray *
|
GPtrArray *
|
||||||
gst_vaapi_encoder_h264_get_default_properties (void);
|
gst_vaapi_encoder_h264_get_default_properties (void);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_vaapi_encoder_h264_get_profile_and_level (GstVaapiEncoderH264 * encoder,
|
||||||
|
GstVaapiProfile * out_profile_ptr, GstVaapiLevelH264 * out_level_ptr);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /*GST_VAAPI_ENCODER_H264_H */
|
#endif /*GST_VAAPI_ENCODER_H264_H */
|
||||||
|
|
|
@ -23,32 +23,13 @@
|
||||||
#define GST_VAAPI_ENCODER_H264_PRIV_H
|
#define GST_VAAPI_ENCODER_H264_PRIV_H
|
||||||
|
|
||||||
#include "gstvaapiencoder_priv.h"
|
#include "gstvaapiencoder_priv.h"
|
||||||
|
#include "gstvaapiutils_h264.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define GST_VAAPI_ENCODER_H264_CAST(encoder) \
|
#define GST_VAAPI_ENCODER_H264_CAST(encoder) \
|
||||||
((GstVaapiEncoderH264 *)(encoder))
|
((GstVaapiEncoderH264 *)(encoder))
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_10 = 10, /* QCIF format, < 380160 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_11 = 11, /* CIF format, < 768000 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_12 = 12, /* CIF format, < 1536000 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_13 = 13, /* CIF format, < 3041280 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_20 = 20, /* CIF format, < 3041280 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_21 = 21, /* HHR format, < 5068800 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_22 = 22, /* SD/4CIF format, < 5184000 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_30 = 30, /* SD/4CIF format, < 10368000 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_31 = 31, /* 720pHD format, < 27648000 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_32 = 32, /* SXGA format, < 55296000 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_40 = 40, /* 2Kx1K format, < 62914560 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_41 = 41, /* 2Kx1K format, < 62914560 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_42 = 42, /* 2Kx1K format, < 125829120 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_50 = 50, /* 3672x1536 format, < 150994944 samples/sec */
|
|
||||||
GST_VAAPI_ENCODER_H264_LEVEL_51 = 51, /* 4096x2304 format, < 251658240 samples/sec */
|
|
||||||
} GstVaapiEncoderH264Level;
|
|
||||||
|
|
||||||
#define GST_VAAPI_ENCODER_H264_DEFAULT_LEVEL GST_VAAPI_ENCODER_H264_LEVEL_31
|
|
||||||
#define GST_VAAPI_ENCODER_H264_MAX_IDR_PERIOD 512
|
#define GST_VAAPI_ENCODER_H264_MAX_IDR_PERIOD 512
|
||||||
|
|
||||||
struct _GstVaapiEncoderH264
|
struct _GstVaapiEncoderH264
|
||||||
|
@ -56,7 +37,9 @@ struct _GstVaapiEncoderH264
|
||||||
GstVaapiEncoder parent_instance;
|
GstVaapiEncoder parent_instance;
|
||||||
|
|
||||||
GstVaapiProfile profile;
|
GstVaapiProfile profile;
|
||||||
guint32 level_idc;
|
GstVaapiLevelH264 level;
|
||||||
|
guint8 profile_idc;
|
||||||
|
guint8 level_idc;
|
||||||
guint32 idr_period;
|
guint32 idr_period;
|
||||||
guint32 init_qp;
|
guint32 init_qp;
|
||||||
guint32 min_qp;
|
guint32 min_qp;
|
||||||
|
|
Loading…
Reference in a new issue