encoder: h264: fix hardware profile lookup.

Fix lookup for a suitable HW profile, as to be used by the underlying
hardware, based on heuristics that lead to characterize the SW profile,
i.e. the one used by the SW level encoding logic.

Also fix constraint_set0_flag (A.2.1) and constraint_set1_flag (A.2.2)
as they should respectively match the baseline and main profile.

https://bugzilla.gnome.org/show_bug.cgi?id=719827
This commit is contained in:
Gwenole Beauchesne 2014-01-10 17:02:44 +01:00
parent e2f8c059a5
commit 2b482e8e4b
3 changed files with 76 additions and 26 deletions

View file

@ -45,6 +45,7 @@ typedef struct _GstVaapiEncoder GstVaapiEncoder;
* execute the operation. * execute the operation.
* @GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_RATE_CONTROL: * @GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_RATE_CONTROL:
* Unsupported rate control value. * Unsupported rate control value.
* @GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE: Unsupported profile.
* @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER: Invalid parameter. * @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER: Invalid parameter.
* @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_BUFFER: Invalid buffer. * @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_BUFFER: Invalid buffer.
* @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_SURFACE: Invalid surface. * @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_SURFACE: Invalid surface.
@ -62,6 +63,7 @@ typedef enum
GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED = -2, GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED = -2,
GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED = -3, GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED = -3,
GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_RATE_CONTROL = -4, GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_RATE_CONTROL = -4,
GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE = -5,
GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER = -100, GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER = -100,
GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_BUFFER = -101, GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_BUFFER = -101,
GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_SURFACE = -102, GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_SURFACE = -102,

View file

@ -26,6 +26,7 @@
#include "gstvaapicompat.h" #include "gstvaapicompat.h"
#include "gstvaapiencoder_h264.h" #include "gstvaapiencoder_h264.h"
#include "gstvaapiencoder_h264_priv.h" #include "gstvaapiencoder_h264_priv.h"
#include "gstvaapiutils_h264_priv.h"
#include "gstvaapicodedbufferproxy_priv.h" #include "gstvaapicodedbufferproxy_priv.h"
#include "gstvaapisurface.h" #include "gstvaapisurface.h"
@ -130,22 +131,6 @@ h264_get_log2_max_frame_num (guint num)
return ret; return ret;
} }
static inline guint
_profile_to_value (GstVaapiProfile profile)
{
switch (profile) {
case GST_VAAPI_PROFILE_H264_BASELINE:
return 66;
case GST_VAAPI_PROFILE_H264_MAIN:
return 77;
case GST_VAAPI_PROFILE_H264_HIGH:
return 100;
default:
break;
}
return 0;
}
static inline void static inline void
_check_sps_pps_status (GstVaapiEncoderH264 * encoder, _check_sps_pps_status (GstVaapiEncoderH264 * encoder,
const guint8 * nal, guint32 size) const guint8 * nal, guint32 size)
@ -175,6 +160,61 @@ _check_sps_pps_status (GstVaapiEncoderH264 * encoder,
} }
} }
/* Derives the profile supported by the underlying hardware */
static gboolean
ensure_hw_profile (GstVaapiEncoderH264 * encoder)
{
GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
GstVaapiProfile profile, profiles[4];
guint i, num_profiles = 0;
profiles[num_profiles++] = encoder->profile;
switch (encoder->profile) {
case GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE:
profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_BASELINE;
profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_MAIN;
// fall-through
case GST_VAAPI_PROFILE_H264_MAIN:
profiles[num_profiles++] = GST_VAAPI_PROFILE_H264_HIGH;
break;
default:
break;
}
profile = GST_VAAPI_PROFILE_UNKNOWN;
for (i = 0; i < num_profiles; i++) {
if (gst_vaapi_display_has_encoder (display, profiles[i], entrypoint)) {
profile = profiles[i];
break;
}
}
if (profile == GST_VAAPI_PROFILE_UNKNOWN)
goto error_unsupported_profile;
GST_VAAPI_ENCODER_CAST (encoder)->profile = profile;
return TRUE;
/* ERRORS */
error_unsupported_profile:
{
GST_ERROR ("unsupported HW profile (0x%08x)", encoder->profile);
return FALSE;
}
}
/* Derives the minimum profile from the active coding tools */
static gboolean
ensure_profile (GstVaapiEncoderH264 * encoder)
{
GstVaapiProfile profile;
profile = GST_VAAPI_PROFILE_H264_BASELINE;
encoder->profile = profile;
return TRUE;
}
static void static void
_set_level (GstVaapiEncoderH264 * encoder) _set_level (GstVaapiEncoderH264 * encoder)
{ {
@ -377,6 +417,7 @@ static gboolean
gst_bit_writer_write_sps (GstBitWriter * bitwriter, gst_bit_writer_write_sps (GstBitWriter * bitwriter,
const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile) const VAEncSequenceParameterBufferH264 * seq_param, GstVaapiProfile profile)
{ {
guint8 profile_idc;
guint32 constraint_set0_flag, constraint_set1_flag; guint32 constraint_set0_flag, constraint_set1_flag;
guint32 constraint_set2_flag, constraint_set3_flag; guint32 constraint_set2_flag, constraint_set3_flag;
guint32 gaps_in_frame_num_value_allowed_flag = 0; // ?? guint32 gaps_in_frame_num_value_allowed_flag = 0; // ??
@ -391,13 +432,18 @@ gst_bit_writer_write_sps (GstBitWriter * bitwriter,
!seq_param->seq_fields.bits.frame_mbs_only_flag; !seq_param->seq_fields.bits.frame_mbs_only_flag;
guint32 i = 0; guint32 i = 0;
constraint_set0_flag = profile == GST_VAAPI_PROFILE_H264_BASELINE; profile_idc = gst_vaapi_utils_h264_get_profile_idc (profile);
constraint_set1_flag = profile <= GST_VAAPI_PROFILE_H264_MAIN; constraint_set0_flag = /* A.2.1 (baseline profile constraints) */
profile == GST_VAAPI_PROFILE_H264_BASELINE ||
profile == GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
constraint_set1_flag = /* A.2.2 (main profile constraints) */
profile == GST_VAAPI_PROFILE_H264_MAIN ||
profile == GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE;
constraint_set2_flag = 0; constraint_set2_flag = 0;
constraint_set3_flag = 0; constraint_set3_flag = 0;
/* profile_idc */ /* profile_idc */
gst_bit_writer_put_bits_uint32 (bitwriter, _profile_to_value (profile), 8); gst_bit_writer_put_bits_uint32 (bitwriter, profile_idc, 8);
/* constraint_set0_flag */ /* constraint_set0_flag */
gst_bit_writer_put_bits_uint32 (bitwriter, constraint_set0_flag, 1); gst_bit_writer_put_bits_uint32 (bitwriter, constraint_set0_flag, 1);
/* constraint_set1_flag */ /* constraint_set1_flag */
@ -1234,8 +1280,8 @@ ensure_misc (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
static gboolean static gboolean
ensure_profile_and_level (GstVaapiEncoderH264 * encoder) ensure_profile_and_level (GstVaapiEncoderH264 * encoder)
{ {
if (!encoder->profile) if (!ensure_profile (encoder))
encoder->profile = GST_VAAPI_ENCODER_H264_DEFAULT_PROFILE; return FALSE;
_set_level (encoder); _set_level (encoder);
return TRUE; return TRUE;
@ -1551,7 +1597,7 @@ end:
return GST_VAAPI_ENCODER_STATUS_SUCCESS; return GST_VAAPI_ENCODER_STATUS_SUCCESS;
} }
static void static GstVaapiEncoderStatus
set_context_info (GstVaapiEncoder * base_encoder) set_context_info (GstVaapiEncoder * base_encoder)
{ {
GstVaapiEncoderH264 *const encoder = GstVaapiEncoderH264 *const encoder =
@ -1569,7 +1615,9 @@ set_context_info (GstVaapiEncoder * base_encoder)
MAX_SLICE_HDR_SIZE = 397 + 2572 + 6670 + 2402, MAX_SLICE_HDR_SIZE = 397 + 2572 + 6670 + 2402,
}; };
base_encoder->profile = encoder->profile; if (!ensure_hw_profile (encoder))
return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
base_encoder->num_ref_frames = base_encoder->num_ref_frames =
(encoder->num_bframes ? 2 : 1) + DEFAULT_SURFACES_COUNT; (encoder->num_bframes ? 2 : 1) + DEFAULT_SURFACES_COUNT;
@ -1591,6 +1639,8 @@ set_context_info (GstVaapiEncoder * base_encoder)
/* Account for slice header. At most 200 slices are supported */ /* Account for slice header. At most 200 slices are supported */
base_encoder->codedbuf_size += 200 * (4 + base_encoder->codedbuf_size += 200 * (4 +
GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8); GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8);
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
} }
static GstVaapiEncoderStatus static GstVaapiEncoderStatus
@ -1608,8 +1658,7 @@ gst_vaapi_encoder_h264_reconfigure (GstVaapiEncoder * base_encoder)
goto error; goto error;
reset_properties (encoder); reset_properties (encoder);
set_context_info (base_encoder); return set_context_info (base_encoder);
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
error: error:
return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED; return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;

View file

@ -48,7 +48,6 @@ typedef enum
GST_VAAPI_ENCODER_H264_LEVEL_51 = 51, /* 4096x2304 format, < 251658240 samples/sec */ GST_VAAPI_ENCODER_H264_LEVEL_51 = 51, /* 4096x2304 format, < 251658240 samples/sec */
} GstVaapiEncoderH264Level; } GstVaapiEncoderH264Level;
#define GST_VAAPI_ENCODER_H264_DEFAULT_PROFILE GST_VAAPI_PROFILE_H264_BASELINE
#define GST_VAAPI_ENCODER_H264_DEFAULT_LEVEL GST_VAAPI_ENCODER_H264_LEVEL_31 #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