summaryrefslogtreecommitdiff
path: root/gst-libs/gst/vaapi
diff options
context:
space:
mode:
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>2014-01-06 15:10:36 +0100
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>2014-01-13 17:31:54 +0100
commita24c52e4d0b3d0c168b30939aae406879c6c6a94 (patch)
tree40fcd88481d33409390d4a6846a164b576e2d569 /gst-libs/gst/vaapi
parent076d75aeb89b2b7cc09a2297f8fa6ebecab6cf68 (diff)
downloadgst-vaapi-a24c52e4d0b3d0c168b30939aae406879c6c6a94.tar.gz
encoder: add rate control API.
Add gst_vaapi_encoder_set_rate_control() interface to request a new rate control mode for encoding. Changing the rate control mode is only valid prior to encoding the very first frame. Afterwards, an error ("operation-failed") is issued. https://bugzilla.gnome.org/show_bug.cgi?id=719529
Diffstat (limited to 'gst-libs/gst/vaapi')
-rw-r--r--gst-libs/gst/vaapi/gstvaapiencoder.c103
-rw-r--r--gst-libs/gst/vaapi/gstvaapiencoder.h11
-rw-r--r--gst-libs/gst/vaapi/gstvaapiencoder_h264.c15
-rw-r--r--gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c12
-rw-r--r--gst-libs/gst/vaapi/gstvaapiencoder_mpeg2_priv.h1
-rw-r--r--gst-libs/gst/vaapi/gstvaapiencoder_priv.h35
-rw-r--r--gst-libs/gst/vaapi/gstvaapitypes.h4
7 files changed, 178 insertions, 3 deletions
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.c b/gst-libs/gst/vaapi/gstvaapiencoder.c
index a9cd85d8..05f9b3d2 100644
--- a/gst-libs/gst/vaapi/gstvaapiencoder.c
+++ b/gst-libs/gst/vaapi/gstvaapiencoder.c
@@ -25,6 +25,7 @@
#include "gstvaapiencoder_priv.h"
#include "gstvaapicontext.h"
#include "gstvaapidisplay_priv.h"
+#include "gstvaapiutils.h"
#define DEBUG 1
#include "gstvaapidebug.h"
@@ -180,6 +181,7 @@ gst_vaapi_encoder_put_frame (GstVaapiEncoder * encoder,
gst_vaapi_coded_buffer_proxy_set_user_data (codedbuf_proxy,
picture, (GDestroyNotify) gst_vaapi_enc_picture_unref);
g_async_queue_push (encoder->codedbuf_queue, codedbuf_proxy);
+ encoder->num_codedbuf_queued++;
/* Try again with any pending reordered frame now available for encoding */
frame = NULL;
@@ -388,6 +390,107 @@ error:
return NULL;
}
+/* Determine the supported rate control modes */
+static gboolean
+get_rate_control_mask (GstVaapiEncoder * encoder)
+{
+ const GstVaapiEncoderClassData *const cdata =
+ GST_VAAPI_ENCODER_GET_CLASS (encoder)->class_data;
+ GstVaapiProfile profile;
+ GArray *profiles;
+ guint i, rate_control_mask = 0;
+
+ if (encoder->rate_control_mask)
+ return encoder->rate_control_mask;
+
+ profiles = gst_vaapi_display_get_encode_profiles (encoder->display);
+ if (!profiles)
+ goto cleanup;
+
+ // Pick a profile matching the class codec
+ for (i = 0; i < profiles->len; i++) {
+ profile = g_array_index (profiles, GstVaapiProfile, i);
+ if (gst_vaapi_profile_get_codec (profile) == cdata->codec)
+ break;
+ }
+
+ if (i != profiles->len) {
+ VAConfigAttrib attrib;
+ VAStatus status;
+
+ attrib.type = VAConfigAttribRateControl;
+ GST_VAAPI_DISPLAY_LOCK (encoder->display);
+ status =
+ vaGetConfigAttributes (GST_VAAPI_DISPLAY_VADISPLAY (encoder->display),
+ gst_vaapi_profile_get_va_profile (profile), VAEntrypointEncSlice,
+ &attrib, 1);
+ GST_VAAPI_DISPLAY_UNLOCK (encoder->display);
+ if (vaapi_check_status (status, "vaGetConfigAttributes()")) {
+ for (i = 0; i < 32; i++) {
+ if (!(attrib.value & (1 << i)))
+ continue;
+ rate_control_mask |= 1 << to_GstVaapiRateControl (1 << i);
+ }
+ }
+ }
+ g_array_unref (profiles);
+ GST_INFO ("supported rate controls: 0x%08x", rate_control_mask);
+
+cleanup:
+ encoder->rate_control_mask = cdata->rate_control_mask & rate_control_mask;
+ return encoder->rate_control_mask;
+}
+
+/**
+ * gst_vaapi_encoder_set_rate_control:
+ * @encoder: a #GstVaapiEncoder
+ * @rate_control: the requested rate control
+ *
+ * Notifies the @encoder to use the supplied @rate_control mode.
+ *
+ * If the underlying encoder does not support that rate control mode,
+ * then @GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_RATE_CONTROL is
+ * returned.
+ *
+ * The rate control mode can only be specified before the first frame
+ * is to be encoded. Afterwards, any change to this parameter is
+ * invalid and @GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED is
+ * returned.
+ *
+ * Return value: a #GstVaapiEncoderStatus
+ */
+GstVaapiEncoderStatus
+gst_vaapi_encoder_set_rate_control (GstVaapiEncoder * encoder,
+ GstVaapiRateControl rate_control)
+{
+ guint32 rate_control_mask;
+
+ g_return_val_if_fail (encoder != NULL,
+ GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER);
+
+ if (encoder->rate_control != rate_control && encoder->num_codedbuf_queued > 0)
+ goto error_operation_failed;
+
+ rate_control_mask = get_rate_control_mask (encoder);
+ if (!(rate_control_mask & (1U << rate_control)))
+ goto error_unsupported_rate_control;
+
+ encoder->rate_control = rate_control;
+ return GST_VAAPI_ENCODER_STATUS_SUCCESS;
+
+ /* ERRORS */
+error_operation_failed:
+ {
+ GST_ERROR ("could not change rate control mode after encoding started");
+ return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
+ }
+error_unsupported_rate_control:
+ {
+ GST_ERROR ("unsupported rate control mode (%d)", rate_control);
+ return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_RATE_CONTROL;
+ }
+}
+
/* Base encoder initialization (internal) */
static gboolean
gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display)
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.h b/gst-libs/gst/vaapi/gstvaapiencoder.h
index d548b5b1..03305414 100644
--- a/gst-libs/gst/vaapi/gstvaapiencoder.h
+++ b/gst-libs/gst/vaapi/gstvaapiencoder.h
@@ -40,6 +40,11 @@ typedef struct _GstVaapiEncoder GstVaapiEncoder;
* hold the encoded picture.
* @GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN: Unknown error.
* @GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED: No memory left.
+ * @GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED: The requested
+ * operation failed to execute properly. e.g. invalid point in time to
+ * execute the operation.
+ * @GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_RATE_CONTROL:
+ * Unsupported rate control value.
* @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER: Invalid parameter.
* @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_BUFFER: Invalid buffer.
* @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_SURFACE: Invalid surface.
@@ -55,6 +60,8 @@ typedef enum
GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN = -1,
GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED = -2,
+ GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED = -3,
+ GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_RATE_CONTROL = -4,
GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER = -100,
GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_BUFFER = -101,
GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_SURFACE = -102,
@@ -80,6 +87,10 @@ gst_vaapi_encoder_set_format (GstVaapiEncoder * encoder,
GstVideoCodecState * state, GstCaps * ref_caps);
GstVaapiEncoderStatus
+gst_vaapi_encoder_set_rate_control (GstVaapiEncoder * encoder,
+ GstVaapiRateControl rate_control);
+
+GstVaapiEncoderStatus
gst_vaapi_encoder_put_frame (GstVaapiEncoder * encoder,
GstVideoCodecFrame * frame);
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c
index d5bef53c..2da7f5d4 100644
--- a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c
+++ b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c
@@ -36,6 +36,17 @@
#define DEBUG 1
#include "gstvaapidebug.h"
+/* Define default rate control mode ("constant-qp") */
+#define DEFAULT_RATECONTROL GST_VAAPI_RATECONTROL_CQP
+
+/* Supported set of VA rate controls, within this implementation */
+#define SUPPORTED_RATECONTROLS \
+ (GST_VAAPI_RATECONTROL_MASK (NONE) | \
+ GST_VAAPI_RATECONTROL_MASK (CQP) | \
+ GST_VAAPI_RATECONTROL_MASK (CBR) | \
+ GST_VAAPI_RATECONTROL_MASK (VBR) | \
+ GST_VAAPI_RATECONTROL_MASK (VBR_CONSTRAINED))
+
#define GST_VAAPI_ENCODER_H264_NAL_REF_IDC_NONE 0
#define GST_VAAPI_ENCODER_H264_NAL_REF_IDC_LOW 1
#define GST_VAAPI_ENCODER_H264_NAL_REF_IDC_MEDIUM 2
@@ -1690,6 +1701,8 @@ gst_vaapi_encoder_h264_init (GstVaapiEncoder * base)
{
GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264 (base);
+ base->rate_control = DEFAULT_RATECONTROL;
+
/* init attributes */
encoder->profile = 0;
encoder->level = 0;
@@ -1756,6 +1769,8 @@ gst_vaapi_encoder_h264_finalize (GstVaapiEncoder * base)
}
+GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (H264);
+
static inline const GstVaapiEncoderClass *
gst_vaapi_encoder_h264_class (void)
{
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c
index c4b6b201..3c1c34b6 100644
--- a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c
+++ b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c
@@ -37,6 +37,14 @@
#define DEBUG 1
#include "gstvaapidebug.h"
+/* Define default rate control mode ("constant-qp") */
+#define DEFAULT_RATECONTROL GST_VAAPI_RATECONTROL_CQP
+
+/* Supported set of VA rate controls, within this implementation */
+#define SUPPORTED_RATECONTROLS \
+ (GST_VAAPI_RATECONTROL_MASK (NONE) | \
+ GST_VAAPI_RATECONTROL_MASK (CQP) | \
+ GST_VAAPI_RATECONTROL_MASK (CBR))
static gboolean
gst_bit_writer_write_sps (GstBitWriter * bitwriter,
@@ -720,6 +728,8 @@ gst_vaapi_encoder_mpeg2_init (GstVaapiEncoder * base)
{
GstVaapiEncoderMpeg2 *encoder = GST_VAAPI_ENCODER_MPEG2 (base);
+ base->rate_control = DEFAULT_RATECONTROL;
+
/* re-ordering */
g_queue_init (&encoder->b_frames);
encoder->dump_frames = FALSE;
@@ -778,6 +788,8 @@ gst_vaapi_encoder_mpeg2_finalize (GstVaapiEncoder * base)
g_queue_clear (&encoder->b_frames);
}
+GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (MPEG2);
+
static inline const GstVaapiEncoderClass *
gst_vaapi_encoder_mpeg2_class (void)
{
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2_priv.h b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2_priv.h
index ff20dbe5..71e14041 100644
--- a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2_priv.h
+++ b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2_priv.h
@@ -48,7 +48,6 @@ typedef enum
#define GST_VAAPI_ENCODER_MPEG2_DEFAULT_PROFILE GST_ENCODER_MPEG2_PROFILE_MAIN
#define GST_VAAPI_ENCODER_MPEG2_DEFAULT_LEVEL GST_VAAPI_ENCODER_MPEG2_LEVEL_HIGH
-#define GST_VAAPI_ENCODER_MPEG2_DEFAULT_RATE_CONTROL GST_VAAPI_RATECONTROL_CQP
#define GST_VAAPI_ENCODER_MPEG2_MIN_CQP 2
#define GST_VAAPI_ENCODER_MPEG2_MAX_CQP 62
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h
index bd17c8f4..a3ec6db5 100644
--- a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h
+++ b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h
@@ -61,8 +61,17 @@ G_BEGIN_DECLS
#define GST_VAAPI_ENCODER_HEIGHT(encoder) (GST_VAAPI_ENCODER_CAST(encoder)->video_info.height)
#define GST_VAAPI_ENCODER_FPS_N(encoder) (GST_VAAPI_ENCODER_CAST(encoder)->video_info.fps_n)
#define GST_VAAPI_ENCODER_FPS_D(encoder) (GST_VAAPI_ENCODER_CAST(encoder)->video_info.fps_d)
-#define GST_VAAPI_ENCODER_RATE_CONTROL(encoder) \
- (GST_VAAPI_ENCODER_CAST(encoder)->rate_control)
+
+/**
+ * GST_VAAPI_ENCODER_RATE_CONTROL:
+ * @encoder: a #GstVaapiEncoder
+ *
+ * Macro that evaluates to the rate control.
+ * This is an internal macro that does not do any run-time type check.
+ */
+#undef GST_VAAPI_ENCODER_RATE_CONTROL
+#define GST_VAAPI_ENCODER_RATE_CONTROL(encoder) \
+ (GST_VAAPI_ENCODER_CAST (encoder)->rate_control)
#define GST_VAAPI_ENCODER_CHECK_STATUS(exp, err_num, err_reason, ...) \
if (!(exp)) { \
@@ -72,6 +81,7 @@ G_BEGIN_DECLS
}
typedef struct _GstVaapiEncoderClass GstVaapiEncoderClass;
+typedef struct _GstVaapiEncoderClassData GstVaapiEncoderClassData;
struct _GstVaapiEncoder
{
@@ -87,6 +97,7 @@ struct _GstVaapiEncoder
VAContextID va_context;
GstVideoInfo video_info;
GstVaapiRateControl rate_control;
+ guint32 rate_control_mask;
GMutex mutex;
GCond surface_free;
@@ -94,13 +105,32 @@ struct _GstVaapiEncoder
guint codedbuf_size;
GstVaapiVideoPool *codedbuf_pool;
GAsyncQueue *codedbuf_queue;
+ guint32 num_codedbuf_queued;
};
+struct _GstVaapiEncoderClassData
+{
+ /*< private >*/
+ GstVaapiCodec codec;
+
+ GstVaapiRateControl default_rate_control;
+ guint32 rate_control_mask;
+};
+
+#define GST_VAAPI_ENCODER_DEFINE_CLASS_DATA(CODEC) \
+ static const GstVaapiEncoderClassData g_class_data = { \
+ .codec = G_PASTE (GST_VAAPI_CODEC_, CODEC), \
+ .default_rate_control = DEFAULT_RATECONTROL, \
+ .rate_control_mask = SUPPORTED_RATECONTROLS, \
+ }
+
struct _GstVaapiEncoderClass
{
/*< private >*/
GstVaapiMiniObjectClass parent_class;
+ const GstVaapiEncoderClassData *class_data;
+
gboolean (*init) (GstVaapiEncoder * encoder);
void (*finalize) (GstVaapiEncoder * encoder);
@@ -135,6 +165,7 @@ struct _GstVaapiEncoderClass
#define GST_VAAPI_ENCODER_CLASS_INIT(CODEC, codec) \
GST_VAAPI_ENCODER_CLASS_INIT_BASE (CODEC), \
+ .class_data = &g_class_data, \
GST_VAAPI_ENCODER_CLASS_HOOK (codec, init), \
GST_VAAPI_ENCODER_CLASS_HOOK (codec, finalize), \
GST_VAAPI_ENCODER_CLASS_HOOK (codec, set_format), \
diff --git a/gst-libs/gst/vaapi/gstvaapitypes.h b/gst-libs/gst/vaapi/gstvaapitypes.h
index 771ad75d..159b85b3 100644
--- a/gst-libs/gst/vaapi/gstvaapitypes.h
+++ b/gst-libs/gst/vaapi/gstvaapitypes.h
@@ -144,6 +144,10 @@ typedef enum {
GST_VAAPI_RATECONTROL_VBR_CONSTRAINED,
} GstVaapiRateControl;
+/* Define a mask for GstVaapiRateControl */
+#define GST_VAAPI_RATECONTROL_MASK(RC) \
+ (1 << G_PASTE(GST_VAAPI_RATECONTROL_,RC))
+
G_END_DECLS
#endif /* GST_VAAPI_TYPES_H */