From 2f5e5f0784d6935212dfe5a77dc2a9faf594b554 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Wed, 4 Dec 2013 17:55:18 +0100 Subject: [PATCH] encoder: clean-ups and document public APIs. Clean public APIs up so that to better align with the decoder APIs. Most importantly, gst_vaapi_encoder_get_buffer() is changed to only return the VA coded buffer proxy. Also provide useful documentation for the public APIs. --- gst-libs/gst/vaapi/gstvaapiencoder.c | 127 ++++++++++++++++++++++++----- gst-libs/gst/vaapi/gstvaapiencoder.h | 24 +++--- gst-libs/gst/vaapi/gstvaapiencoder_h264.c | 2 +- gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c | 2 +- gst-libs/gst/vaapi/gstvaapiencoder_priv.h | 20 ++--- gst/vaapi/gstvaapiencode.c | 13 +-- 6 files changed, 135 insertions(+), 53 deletions(-) diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.c b/gst-libs/gst/vaapi/gstvaapiencoder.c index f85ce0f..ef2675f 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder.c @@ -18,6 +18,7 @@ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ + #include "sysdeps.h" #include "gstvaapicompat.h" #include "gstvaapiencoder.h" @@ -28,18 +29,42 @@ #define DEBUG 1 #include "gstvaapidebug.h" +/** + * gst_vaapi_encoder_ref: + * @encoder: a #GstVaapiEncoder + * + * Atomically increases the reference count of the given @encoder by one. + * + * Returns: The same @encoder argument + */ GstVaapiEncoder * gst_vaapi_encoder_ref (GstVaapiEncoder * encoder) { return gst_vaapi_object_ref (encoder); } +/** + * gst_vaapi_encoder_unref: + * @encoder: a #GstVaapiEncoder + * + * Atomically decreases the reference count of the @encoder by one. If + * the reference count reaches zero, the encoder will be free'd. + */ void gst_vaapi_encoder_unref (GstVaapiEncoder * encoder) { gst_vaapi_object_unref (encoder); } +/** + * gst_vaapi_encoder_replace: + * @old_encoder_ptr: a pointer to a #GstVaapiEncoder + * @new_encoder: a #GstVaapiEncoder + * + * Atomically replaces the encoder encoder held in @old_encoder_ptr + * with @new_encoder. This means that @old_encoder_ptr shall reference + * a valid encoder. However, @new_encoder can be NULL. + */ void gst_vaapi_encoder_replace (GstVaapiEncoder ** old_encoder_ptr, GstVaapiEncoder * new_encoder) @@ -47,6 +72,7 @@ gst_vaapi_encoder_replace (GstVaapiEncoder ** old_encoder_ptr, gst_vaapi_object_replace (old_encoder_ptr, new_encoder); } +/* Notifies gst_vaapi_encoder_create_coded_buffer() that a new buffer is free */ static void _coded_buffer_proxy_released_notify (GstVaapiEncoder * encoder) { @@ -55,6 +81,7 @@ _coded_buffer_proxy_released_notify (GstVaapiEncoder * encoder) g_mutex_unlock (&encoder->mutex); } +/* Creates a new VA coded buffer object proxy, backed from a pool */ static GstVaapiCodedBufferProxy * gst_vaapi_encoder_create_coded_buffer (GstVaapiEncoder * encoder) { @@ -81,6 +108,7 @@ gst_vaapi_encoder_create_coded_buffer (GstVaapiEncoder * encoder) return codedbuf_proxy; } +/* Notifies gst_vaapi_encoder_create_surface() that a new surface is free */ static void _surface_proxy_released_notify (GstVaapiEncoder * encoder) { @@ -89,6 +117,8 @@ _surface_proxy_released_notify (GstVaapiEncoder * encoder) g_mutex_unlock (&encoder->mutex); } +/* Creates a new VA surface object proxy, backed from a pool and + useful to allocate reconstructed surfaces */ GstVaapiSurfaceProxy * gst_vaapi_encoder_create_surface (GstVaapiEncoder * encoder) { @@ -112,13 +142,16 @@ gst_vaapi_encoder_create_surface (GstVaapiEncoder * encoder) return proxy; } -void -gst_vaapi_encoder_release_surface (GstVaapiEncoder * encoder, - GstVaapiSurfaceProxy * surface) -{ - gst_vaapi_surface_proxy_unref (surface); -} - +/** + * gst_vaapi_encoder_put_frame: + * @encoder: a #GstVaapiEncoder + * @frame: a #GstVideoCodecFrame + * + * Queues a #GstVideoCodedFrame to the HW encoder. The encoder holds + * an extra reference to the @frame. + * + * Return value: a #GstVaapiEncoderStatus + */ GstVaapiEncoderStatus gst_vaapi_encoder_put_frame (GstVaapiEncoder * encoder, GstVideoCodecFrame * frame) @@ -130,7 +163,7 @@ gst_vaapi_encoder_put_frame (GstVaapiEncoder * encoder, for (;;) { picture = NULL; - status = klass->reordering (encoder, frame, FALSE, &picture); + status = klass->reordering (encoder, frame, &picture); if (status == GST_VAAPI_ENCODER_STATUS_NO_SURFACE) break; if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) @@ -174,9 +207,26 @@ error_encode: } } +/** + * gst_vaapi_encoder_get_buffer_with_timeout: + * @encoder: a #GstVaapiEncoder + * @out_codedbuf_proxy_ptr: the next coded buffer as a #GstVaapiCodedBufferProxy + * @timeout: the number of microseconds to wait for the coded buffer, at most + * + * Upon successful return, *@out_codedbuf_proxy_ptr contains the next + * coded buffer as a #GstVaapiCodedBufferProxy. The caller owns this + * object, so gst_vaapi_coded_buffer_proxy_unref() shall be called + * after usage. Otherwise, @GST_VAAPI_DECODER_STATUS_ERROR_NO_BUFFER + * is returned if no coded buffer is available so far (timeout). + * + * The parent frame is available as a #GstVideoCodecFrame attached to + * the user-data anchor of the output coded buffer. Ownership of the + * frame is transferred to the coded buffer. + * + * Return value: a #GstVaapiEncoderStatus + */ GstVaapiEncoderStatus -gst_vaapi_encoder_get_buffer (GstVaapiEncoder * encoder, - GstVideoCodecFrame ** out_frame_ptr, +gst_vaapi_encoder_get_buffer_with_timeout (GstVaapiEncoder * encoder, GstVaapiCodedBufferProxy ** out_codedbuf_proxy_ptr, guint64 timeout) { GstVaapiEncPicture *picture; @@ -191,9 +241,9 @@ gst_vaapi_encoder_get_buffer (GstVaapiEncoder * encoder, if (!gst_vaapi_surface_sync (picture->surface)) goto error_invalid_buffer; - if (out_frame_ptr) - *out_frame_ptr = gst_video_codec_frame_ref (picture->frame); - gst_vaapi_coded_buffer_proxy_set_user_data (codedbuf_proxy, NULL, NULL); + gst_vaapi_coded_buffer_proxy_set_user_data (codedbuf_proxy, + gst_video_codec_frame_ref (picture->frame), + (GDestroyNotify) gst_video_codec_frame_unref); if (out_codedbuf_proxy_ptr) *out_codedbuf_proxy_ptr = gst_vaapi_coded_buffer_proxy_ref (codedbuf_proxy); @@ -209,6 +259,14 @@ error_invalid_buffer: } } +/** + * gst_vaapi_encoder_flush: + * @encoder: a #GstVaapiEncoder + * + * Submits any pending (reordered) frame for encoding. + * + * Return value: a #GstVaapiEncoderStatus + */ GstVaapiEncoderStatus gst_vaapi_encoder_flush (GstVaapiEncoder * encoder) { @@ -217,21 +275,34 @@ gst_vaapi_encoder_flush (GstVaapiEncoder * encoder) return klass->flush (encoder); } +/** + * gst_vaapi_encoder_get_codec_data: + * @encoder: a #GstVaapiEncoder + * @out_codec_data_ptr: the pointer to the resulting codec-data (#GstBuffer) + * + * Returns a codec-data buffer that best represents the encoded + * bitstream. Upon successful return, and if the @out_codec_data_ptr + * contents is not NULL, then the caller function shall deallocates + * that buffer with gst_buffer_unref(). + * + * Return value: a #GstVaapiEncoderStatus + */ GstVaapiEncoderStatus gst_vaapi_encoder_get_codec_data (GstVaapiEncoder * encoder, - GstBuffer ** codec_data) + GstBuffer ** out_codec_data_ptr) { GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_SUCCESS; GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder); - *codec_data = NULL; + *out_codec_data_ptr = NULL; if (!klass->get_codec_data) return GST_VAAPI_ENCODER_STATUS_SUCCESS; - ret = klass->get_codec_data (encoder, codec_data); + ret = klass->get_codec_data (encoder, out_codec_data_ptr); return ret; } +/* Ensures the underlying VA context for encoding is created */ static gboolean gst_vaapi_encoder_ensure_context (GstVaapiEncoder * encoder) { @@ -256,21 +327,32 @@ gst_vaapi_encoder_ensure_context (GstVaapiEncoder * encoder) return TRUE; } +/** + * gst_vaapi_encoder_set_format: + * @encoder: a #GstVaapiEncoder + * @state : a #GstVideoCodecState + * @ref_caps: the set of reference caps (from pad template) + * + * Notifies the encoder of incoming data format (video resolution), + * and additional information like framerate. + * + * Return value: the newly allocated set of caps + */ GstCaps * gst_vaapi_encoder_set_format (GstVaapiEncoder * encoder, - GstVideoCodecState * in_state, GstCaps * ref_caps) + GstVideoCodecState * state, GstCaps * ref_caps) { GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder); GstCaps *out_caps = NULL; - if (!GST_VIDEO_INFO_WIDTH (&in_state->info) || - !GST_VIDEO_INFO_HEIGHT (&in_state->info)) { + if (!GST_VIDEO_INFO_WIDTH (&state->info) || + !GST_VIDEO_INFO_HEIGHT (&state->info)) { GST_WARNING ("encoder set format failed, width or height equal to 0."); return NULL; } - GST_VAAPI_ENCODER_VIDEO_INFO (encoder) = in_state->info; + GST_VAAPI_ENCODER_VIDEO_INFO (encoder) = state->info; - out_caps = klass->set_format (encoder, in_state, ref_caps); + out_caps = klass->set_format (encoder, state, ref_caps); if (!out_caps) goto error; @@ -306,6 +388,7 @@ error: return NULL; } +/* Base encoder initialization (internal) */ static gboolean gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display) { @@ -353,6 +436,7 @@ error_invalid_vtable: } } +/* Base encoder cleanup (internal) */ void gst_vaapi_encoder_finalize (GstVaapiEncoder * encoder) { @@ -374,6 +458,7 @@ gst_vaapi_encoder_finalize (GstVaapiEncoder * encoder) g_mutex_clear (&encoder->mutex); } +/* Helper function to create new GstVaapiEncoder instances (internal) */ GstVaapiEncoder * gst_vaapi_encoder_new (const GstVaapiEncoderClass * klass, GstVaapiDisplay * display) diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.h b/gst-libs/gst/vaapi/gstvaapiencoder.h index 73870f9..6b0a7ed 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder.h @@ -27,6 +27,11 @@ G_BEGIN_DECLS +typedef struct _GstVaapiEncoder GstVaapiEncoder; + +#define GST_VAAPI_ENCODER(encoder) \ + ((GstVaapiEncoder *)(encoder)) + /** * GstVaapiEncoderStatus: * @GST_VAAPI_ENCODER_STATUS_SUCCESS: Success. @@ -55,14 +60,6 @@ typedef enum GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER = -103, } GstVaapiEncoderStatus; -typedef struct _GstVaapiEncoder GstVaapiEncoder; - -#define GST_VAAPI_ENCODER(encoder) \ - ((GstVaapiEncoder *)(encoder)) - -#define GST_VAAPI_ENCODER_CAST(encoder) \ - ((GstVaapiEncoder *)(encoder)) - GstVaapiEncoder * gst_vaapi_encoder_ref (GstVaapiEncoder * encoder); @@ -73,20 +70,19 @@ void gst_vaapi_encoder_replace (GstVaapiEncoder ** old_encoder_ptr, GstVaapiEncoder * new_encoder); -GstCaps *gst_vaapi_encoder_set_format (GstVaapiEncoder * encoder, - GstVideoCodecState * state, GstCaps * ref_caps); - GstVaapiEncoderStatus gst_vaapi_encoder_get_codec_data (GstVaapiEncoder * encoder, - GstBuffer ** codec_data_ptr); + GstBuffer ** out_codec_data_ptr); + +GstCaps *gst_vaapi_encoder_set_format (GstVaapiEncoder * encoder, + GstVideoCodecState * state, GstCaps * ref_caps); GstVaapiEncoderStatus gst_vaapi_encoder_put_frame (GstVaapiEncoder * encoder, GstVideoCodecFrame * frame); GstVaapiEncoderStatus -gst_vaapi_encoder_get_buffer (GstVaapiEncoder * encoder, - GstVideoCodecFrame ** out_frame_ptr, +gst_vaapi_encoder_get_buffer_with_timeout (GstVaapiEncoder * encoder, GstVaapiCodedBufferProxy ** out_codedbuf_proxy_ptr, guint64 timeout); GstVaapiEncoderStatus diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c index 28d948a..076273c 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c @@ -1488,7 +1488,7 @@ gst_vaapi_encoder_h264_get_codec_data (GstVaapiEncoder * base, static GstVaapiEncoderStatus gst_vaapi_encoder_h264_reordering (GstVaapiEncoder * base, - GstVideoCodecFrame * frame, gboolean flush, GstVaapiEncPicture ** output) + GstVideoCodecFrame * frame, GstVaapiEncPicture ** output) { GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264 (base); GstVaapiEncPicture *picture; diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c index ec8d575..1af8f4d 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c @@ -551,7 +551,7 @@ gst_vaapi_encoder_mpeg2_flush (GstVaapiEncoder * base) static GstVaapiEncoderStatus gst_vaapi_encoder_mpeg2_reordering (GstVaapiEncoder * base, - GstVideoCodecFrame * frame, gboolean flush, GstVaapiEncPicture ** output) + GstVideoCodecFrame * frame, GstVaapiEncPicture ** output) { GstVaapiEncoderMpeg2 *encoder = GST_VAAPI_ENCODER_MPEG2 (base); GstVaapiEncPicture *picture = NULL; diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h index 19ab7a6..10b1ff9 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h @@ -30,12 +30,12 @@ G_BEGIN_DECLS +#define GST_VAAPI_ENCODER_CAST(encoder) \ + ((GstVaapiEncoder *)(encoder)) + #define GST_VAAPI_ENCODER_CLASS(klass) \ ((GstVaapiEncoderClass *)(klass)) -#define GST_IS_VAAPI_ENCODER_CLASS(klass) \ - ((klass) != NULL) - #define GST_VAAPI_ENCODER_GET_CLASS(obj) \ GST_VAAPI_ENCODER_CLASS(GST_VAAPI_MINI_OBJECT_GET_CLASS(obj)) @@ -64,11 +64,6 @@ G_BEGIN_DECLS #define GST_VAAPI_ENCODER_RATE_CONTROL(encoder) \ (GST_VAAPI_ENCODER_CAST(encoder)->rate_control) -#define GST_VAAPI_ENCODER_LOG_ERROR(...) GST_ERROR( __VA_ARGS__) -#define GST_VAAPI_ENCODER_LOG_WARNING(...) GST_WARNING( __VA_ARGS__) -#define GST_VAAPI_ENCODER_LOG_DEBUG(...) GST_DEBUG( __VA_ARGS__) -#define GST_VAAPI_ENCODER_LOG_INFO(...) GST_INFO( __VA_ARGS__) - #define GST_VAAPI_ENCODER_CHECK_STATUS(exp, err_num, err_reason, ...) \ if (!(exp)) { \ ret = err_num; \ @@ -116,7 +111,6 @@ struct _GstVaapiEncoderClass GstVaapiEncoderStatus (*reordering) (GstVaapiEncoder * encoder, GstVideoCodecFrame * in, - gboolean flush, GstVaapiEncPicture ** out); GstVaapiEncoderStatus (*encode) (GstVaapiEncoder * encoder, GstVaapiEncPicture * picture, @@ -157,13 +151,17 @@ G_GNUC_INTERNAL void gst_vaapi_encoder_finalize (GstVaapiEncoder * encoder); +G_GNUC_INTERNAL GstVaapiSurfaceProxy * gst_vaapi_encoder_create_surface (GstVaapiEncoder * encoder); -void +static inline void gst_vaapi_encoder_release_surface (GstVaapiEncoder * encoder, - GstVaapiSurfaceProxy * surface); + GstVaapiSurfaceProxy * proxy) +{ + gst_vaapi_surface_proxy_unref (proxy); +} G_END_DECLS diff --git a/gst/vaapi/gstvaapiencode.c b/gst/vaapi/gstvaapiencode.c index 308aecf..bcb3f1d 100644 --- a/gst/vaapi/gstvaapiencode.c +++ b/gst/vaapi/gstvaapiencode.c @@ -223,19 +223,23 @@ gst_vaapiencode_push_frame (GstVaapiEncode * encode, gint64 timeout) { GstVideoEncoder *const venc = GST_VIDEO_ENCODER_CAST (encode); GstVaapiEncodeClass *const klass = GST_VAAPIENCODE_GET_CLASS (encode); - GstVideoCodecFrame *out_frame = NULL; + GstVideoCodecFrame *out_frame; GstVaapiCodedBufferProxy *codedbuf_proxy = NULL; GstVaapiEncoderStatus status; GstBuffer *out_buffer; GstFlowReturn ret; - status = gst_vaapi_encoder_get_buffer (encode->encoder, - &out_frame, &codedbuf_proxy, timeout); + status = gst_vaapi_encoder_get_buffer_with_timeout (encode->encoder, + &codedbuf_proxy, timeout); if (status == GST_VAAPI_ENCODER_STATUS_NO_BUFFER) return GST_VAAPI_ENCODE_FLOW_TIMEOUT; if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) goto error_get_buffer; + out_frame = gst_vaapi_coded_buffer_proxy_get_user_data (codedbuf_proxy); + if (!out_frame) + goto error_get_buffer; + gst_video_codec_frame_ref (out_frame); gst_video_codec_frame_set_user_data (out_frame, NULL, NULL); /* Allocate and copy buffer into system memory */ @@ -287,8 +291,6 @@ gst_vaapiencode_push_frame (GstVaapiEncode * encode, gint64 timeout) error_get_buffer: { GST_ERROR ("failed to get encoded buffer (status %d)", status); - if (out_frame) - gst_video_codec_frame_unref (out_frame); if (codedbuf_proxy) gst_vaapi_coded_buffer_proxy_unref (codedbuf_proxy); return GST_FLOW_ERROR; @@ -298,6 +300,7 @@ error_allocate_buffer: GST_ERROR ("failed to allocate encoded buffer in system memory"); if (out_buffer) gst_buffer_unref (out_buffer); + gst_video_codec_frame_unref (out_frame); return ret; } error_codec_data: -- 2.7.4