diff options
author | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2014-01-10 10:54:22 +0100 |
---|---|---|
committer | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2014-01-13 17:31:55 +0100 |
commit | 5394c75461073a83f28bc92060977f334f034191 (patch) | |
tree | a6839085e8d2aaed671e8e2f4aabffddacad9709 /gst-libs/gst/vaapi | |
parent | 2c4fde0eae02383a9780e8e87ce1e3d442bf80ce (diff) | |
download | gst-vaapi-5394c75461073a83f28bc92060977f334f034191.tar.gz |
encoder: add video codec-state API.
Add interface to communicate the encoder resolution and related info
like framerate, interlaced vs. progressive, etc. This new interface
supersedes gst_vaapi_encoder_set_format() and doesn't use any GstCaps
but rather use GstVideoCodecState.
Note that gst_vaapi_encoder_set_codec_state() is also a synchronization
point for codec config. This means that the encoder is reconfigured
there to match the latest properties.
Diffstat (limited to 'gst-libs/gst/vaapi')
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapiencoder.c | 166 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapiencoder.h | 6 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapiencoder_h264.c | 70 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c | 50 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapiencoder_priv.h | 69 |
5 files changed, 184 insertions, 177 deletions
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.c b/gst-libs/gst/vaapi/gstvaapiencoder.c index 2e6def04..555eaf0b 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder.c @@ -416,16 +416,35 @@ gst_vaapi_encoder_get_codec_data (GstVaapiEncoder * encoder, return ret; } -/* Ensures the underlying VA context for encoding is created */ -static gboolean -gst_vaapi_encoder_ensure_context (GstVaapiEncoder * encoder) +/* Checks video info */ +static GstVaapiEncoderStatus +check_video_info (GstVaapiEncoder * encoder, const GstVideoInfo * vip) +{ + if (!vip->width || !vip->height) + goto error_invalid_resolution; + if (!vip->fps_n || !vip->fps_d) + goto error_invalid_framerate; + return GST_VAAPI_ENCODER_STATUS_SUCCESS; + + /* ERRORS */ +error_invalid_resolution: + { + GST_ERROR ("invalid resolution (%dx%d)", vip->width, vip->height); + return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER; + } +error_invalid_framerate: + { + GST_ERROR ("invalid framerate (%d/%d)", vip->fps_n, vip->fps_d); + return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER; + } +} + +/* Updates video context */ +static void +set_context_info (GstVaapiEncoder * encoder) { GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder); GstVaapiContextInfo *const cip = &encoder->context_info; - GstVaapiContext *context; - - if (GST_VAAPI_ENCODER_CONTEXT (encoder)) - return TRUE; cip->profile = GST_VAAPI_PROFILE_UNKNOWN; cip->entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE; @@ -434,72 +453,107 @@ gst_vaapi_encoder_ensure_context (GstVaapiEncoder * encoder) cip->height = GST_VAAPI_ENCODER_HEIGHT (encoder); cip->ref_frames = 0; klass->set_context_info (encoder); +} - context = gst_vaapi_context_new_full (encoder->display, cip); - if (!context) - return FALSE; +/* Ensures the underlying VA context for encoding is created */ +static gboolean +gst_vaapi_encoder_ensure_context (GstVaapiEncoder * encoder) +{ + GstVaapiContextInfo *const cip = &encoder->context_info; + + set_context_info (encoder); - GST_VAAPI_ENCODER_CONTEXT (encoder) = context; - GST_VAAPI_ENCODER_VA_CONTEXT (encoder) = gst_vaapi_context_get_id (context); + if (encoder->context) { + if (!gst_vaapi_context_reset_full (encoder->context, cip)) + return FALSE; + } else { + encoder->context = gst_vaapi_context_new_full (encoder->display, cip); + if (!encoder->context) + return FALSE; + } + encoder->va_context = gst_vaapi_context_get_id (encoder->context); return TRUE; } +/* Reconfigures the encoder with the new properties */ +static GstVaapiEncoderStatus +gst_vaapi_encoder_reconfigure_internal (GstVaapiEncoder * encoder) +{ + GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder); + GstVaapiEncoderStatus status; + + status = klass->reconfigure (encoder); + if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) + return status; + + if (!gst_vaapi_encoder_ensure_context (encoder)) + goto error_reset_context; + + encoder->codedbuf_pool = gst_vaapi_coded_buffer_pool_new (encoder, + encoder->codedbuf_size); + if (!encoder->codedbuf_pool) + goto error_codedbuf_pool_allocation_failed; + + gst_vaapi_video_pool_set_capacity (encoder->codedbuf_pool, 5); + return GST_VAAPI_ENCODER_STATUS_SUCCESS; + + /* ERRORS */ +error_codedbuf_pool_allocation_failed: + { + GST_ERROR ("failed to initialize coded buffer pool"); + return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED; + } +error_reset_context: + { + GST_ERROR ("failed to update VA context"); + return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED; + } +} + /** - * gst_vaapi_encoder_set_format: + * gst_vaapi_encoder_set_codec_state: * @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. + * Notifies the encoder about the source surface properties. The + * accepted set of properties is: video resolution, colorimetry, + * pixel-aspect-ratio and framerate. + * + * This function is a synchronization point for codec configuration. + * This means that, at this point, the encoder is reconfigured to + * match the new properties and any other change beyond this point has + * zero effect. * - * Return value: the newly allocated set of caps + * Return value: a #GstVaapiEncoderStatus */ -GstCaps * -gst_vaapi_encoder_set_format (GstVaapiEncoder * encoder, - GstVideoCodecState * state, GstCaps * ref_caps) +GstVaapiEncoderStatus +gst_vaapi_encoder_set_codec_state (GstVaapiEncoder * encoder, + GstVideoCodecState * state) { - GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder); - GstCaps *out_caps = NULL; + GstVaapiEncoderStatus status; - 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) = state->info; + g_return_val_if_fail (encoder != NULL, + GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER); + g_return_val_if_fail (state != NULL, + GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER); - out_caps = klass->set_format (encoder, state, ref_caps); - if (!out_caps) - goto error; + if (encoder->num_codedbuf_queued > 0) + goto error_operation_failed; - if (GST_VAAPI_ENCODER_CAPS (encoder) && - gst_caps_is_equal (out_caps, GST_VAAPI_ENCODER_CAPS (encoder))) { - gst_caps_unref (out_caps); - return GST_VAAPI_ENCODER_CAPS (encoder); + if (!gst_video_info_is_equal (&state->info, &encoder->video_info)) { + status = check_video_info (encoder, &state->info); + if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) + return status; + encoder->video_info = state->info; } - gst_caps_replace (&GST_VAAPI_ENCODER_CAPS (encoder), out_caps); - g_assert (GST_VAAPI_ENCODER_CONTEXT (encoder) == NULL); - gst_vaapi_object_replace (&GST_VAAPI_ENCODER_CONTEXT (encoder), NULL); - - if (!gst_vaapi_encoder_ensure_context (encoder)) - goto error; + return gst_vaapi_encoder_reconfigure_internal (encoder); - encoder->codedbuf_pool = gst_vaapi_coded_buffer_pool_new (encoder, - encoder->codedbuf_size); - if (!encoder->codedbuf_pool) { - GST_ERROR ("failed to initialized coded buffer pool"); - goto error; + /* ERRORS */ +error_operation_failed: + { + GST_ERROR ("could not change codec state after encoding started"); + return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED; } - gst_vaapi_video_pool_set_capacity (encoder->codedbuf_pool, 5); - - return out_caps; - -error: - gst_caps_replace (&GST_VAAPI_ENCODER_CAPS (encoder), NULL); - gst_caps_replace (&out_caps, NULL); - GST_ERROR ("encoder set format failed"); - return NULL; } /** @@ -762,11 +816,11 @@ gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display) CHECK_VTABLE_HOOK (init); CHECK_VTABLE_HOOK (finalize); CHECK_VTABLE_HOOK (get_default_properties); + CHECK_VTABLE_HOOK (reconfigure); CHECK_VTABLE_HOOK (encode); CHECK_VTABLE_HOOK (reordering); CHECK_VTABLE_HOOK (flush); CHECK_VTABLE_HOOK (set_context_info); - CHECK_VTABLE_HOOK (set_format); #undef CHECK_VTABLE_HOOK diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.h b/gst-libs/gst/vaapi/gstvaapiencoder.h index a4dbe3ad..8f6e6ae1 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder.h @@ -106,9 +106,9 @@ GstVaapiEncoderStatus gst_vaapi_encoder_get_codec_data (GstVaapiEncoder * encoder, GstBuffer ** out_codec_data_ptr); -GstCaps * -gst_vaapi_encoder_set_format (GstVaapiEncoder * encoder, - GstVideoCodecState * state, GstCaps * ref_caps); +GstVaapiEncoderStatus +gst_vaapi_encoder_set_codec_state (GstVaapiEncoder * encoder, + GstVideoCodecState * state); GstVaapiEncoderStatus gst_vaapi_encoder_set_property (GstVaapiEncoder * encoder, gint prop_id, diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c index 420a0e35..e2323a78 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c @@ -82,14 +82,6 @@ typedef struct guint frame_num; } GstVaapiEncoderH264Ref; -#define GST_VAAPI_H264_CAPS \ - "video/x-h264, " \ - "framerate = (fraction) [0/1, MAX], " \ - "width = (int) [ 1, MAX ], " \ - "height = (int) [ 1, MAX ], " \ - "stream-format = (string) { avc, byte-stream }, " \ - "alignment = (string) { au } " - typedef enum { GST_VAAPI_ENC_H264_REORD_NONE = 0, @@ -1262,12 +1254,6 @@ init_encoder_public_attributes (GstVaapiEncoderH264 * encoder) GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder); guint width_mbs, height_mbs, total_mbs; - if (!GST_VAAPI_ENCODER_WIDTH (encoder) || - !GST_VAAPI_ENCODER_HEIGHT (encoder) || - !GST_VAAPI_ENCODER_FPS_N (encoder) || - !GST_VAAPI_ENCODER_FPS_D (encoder)) { - return FALSE; - } if (!encoder->profile) encoder->profile = GST_VAAPI_ENCODER_H264_DEFAULT_PROFILE; @@ -1317,7 +1303,7 @@ init_encoder_public_attributes (GstVaapiEncoderH264 * encoder) } static gboolean -init_encoder_private_attributes (GstVaapiEncoderH264 * encoder, GstCaps * caps) +init_encoder_private_attributes (GstVaapiEncoderH264 * encoder) { if (encoder->b_frame_num) encoder->cts_offset = GST_SECOND * GST_VAAPI_ENCODER_FPS_D (encoder) / @@ -1625,65 +1611,25 @@ gst_vaapi_encoder_h264_set_context_info (GstVaapiEncoder * base_encoder) GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8); } -static GstCaps * -gst_vaapi_encoder_h264_set_format (GstVaapiEncoder * base, - GstVideoCodecState * in_state, GstCaps * ref_caps) +static GstVaapiEncoderStatus +gst_vaapi_encoder_h264_reconfigure (GstVaapiEncoder * base_encoder) { - GstVaapiEncoderH264 *encoder; - GstCaps *result = NULL, *tmp; - GstStructure *structure; - const GValue *value; - const gchar *stream_format; - - encoder = GST_VAAPI_ENCODER_H264 (base); - - tmp = gst_caps_from_string ("video/x-h264"); - gst_caps_set_simple (tmp, - "width", G_TYPE_INT, GST_VAAPI_ENCODER_WIDTH (encoder), - "height", G_TYPE_INT, GST_VAAPI_ENCODER_HEIGHT (encoder), - "framerate", GST_TYPE_FRACTION, - GST_VAAPI_ENCODER_FPS_N (encoder), GST_VAAPI_ENCODER_FPS_D (encoder), - NULL); - result = gst_caps_intersect (tmp, ref_caps); - gst_caps_unref (tmp); - - /* fixed stream-format and choose byte-stream first */ - structure = gst_caps_get_structure (result, 0); - value = gst_structure_get_value (structure, "stream-format"); - if (value) { - gst_structure_fixate_field_string (structure, "stream-format", - "byte-stream"); - stream_format = gst_structure_get_string (structure, "stream-format"); - } else { - stream_format = "byte-stream"; - gst_structure_set (structure, "stream-format", G_TYPE_STRING, stream_format, - NULL); - } - - if (strcmp (stream_format, "byte-stream") == 0) - encoder->is_avc = FALSE; - else /* need codec data later */ - encoder->is_avc = TRUE; - -#if GST_CHECK_VERSION(1,0,0) - result = gst_caps_fixate (result); -#endif + GstVaapiEncoderH264 *const encoder = + GST_VAAPI_ENCODER_H264_CAST (base_encoder); if (!init_encoder_public_attributes (encoder)) { GST_WARNING ("encoder ensure public attributes failed "); goto error; } - if (!init_encoder_private_attributes (encoder, result)) { + if (!init_encoder_private_attributes (encoder)) { GST_WARNING ("prepare encoding failed "); goto error; } - - return result; + return GST_VAAPI_ENCODER_STATUS_SUCCESS; error: - gst_caps_unref (result); - return NULL; + return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED; } static gboolean diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c index fb7e042e..047289b4 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c @@ -107,13 +107,6 @@ ensure_public_attributes (GstVaapiEncoderMpeg2 * encoder) { GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder); - if (!GST_VAAPI_ENCODER_WIDTH (encoder) || - !GST_VAAPI_ENCODER_HEIGHT (encoder) || - !GST_VAAPI_ENCODER_FPS_N (encoder) || - !GST_VAAPI_ENCODER_FPS_D (encoder)) { - return FALSE; - } - if (encoder->ip_period > encoder->intra_period) { encoder->ip_period = encoder->intra_period - 1; } @@ -680,51 +673,20 @@ gst_vaapi_encoder_mpeg2_set_context_info (GstVaapiEncoder * base_encoder) MAX_SLICE_HDR_SIZE; } -static gboolean -prepare_encoding (GstVaapiEncoderMpeg2 * encoder, GstCaps * caps) -{ - return TRUE; -} - -static GstCaps * -gst_vaapi_encoder_mpeg2_set_format (GstVaapiEncoder * base, - GstVideoCodecState * in_state, GstCaps * ref_caps) +static GstVaapiEncoderStatus +gst_vaapi_encoder_mpeg2_reconfigure (GstVaapiEncoder * base_encoder) { - GstVaapiEncoderMpeg2 *encoder; - GstCaps *result = NULL, *tmp; - encoder = GST_VAAPI_ENCODER_MPEG2 (base); - - tmp = gst_caps_from_string ("video/mpeg"); - gst_caps_set_simple (tmp, - "mpegversion", G_TYPE_INT, 2, - "systemstream", G_TYPE_BOOLEAN, FALSE, - "width", G_TYPE_INT, GST_VAAPI_ENCODER_WIDTH (encoder), - "height", G_TYPE_INT, GST_VAAPI_ENCODER_HEIGHT (encoder), - "framerate", GST_TYPE_FRACTION, - GST_VAAPI_ENCODER_FPS_N (encoder), GST_VAAPI_ENCODER_FPS_D (encoder), - NULL); - result = gst_caps_intersect (tmp, ref_caps); - gst_caps_unref (tmp); - -#if GST_CHECK_VERSION(1,0,0) - result = gst_caps_fixate (result); -#endif + GstVaapiEncoderMpeg2 *const encoder = + GST_VAAPI_ENCODER_MPEG2_CAST (base_encoder); if (!ensure_public_attributes (encoder)) { GST_WARNING ("encoder ensure public attributes failed "); goto error; } - - if (!prepare_encoding (encoder, result)) { - GST_WARNING ("prepare encoding failed "); - goto error; - } - - return result; + return GST_VAAPI_ENCODER_STATUS_SUCCESS; error: - gst_caps_unref (result); - return NULL; + return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED; } static gboolean diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h index 0238ac1b..98bbee38 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h @@ -55,12 +55,60 @@ G_BEGIN_DECLS #define GST_VAAPI_ENCODER_VA_CONTEXT(encoder) \ (GST_VAAPI_ENCODER_CAST(encoder)->va_context) -#define GST_VAAPI_ENCODER_VIDEO_INFO(encoder) (GST_VAAPI_ENCODER_CAST(encoder)->video_info) -#define GST_VAAPI_ENCODER_CAPS(encoder) (GST_VAAPI_ENCODER_CAST(encoder)->caps) -#define GST_VAAPI_ENCODER_WIDTH(encoder) (GST_VAAPI_ENCODER_CAST(encoder)->video_info.width) -#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) +/** + * GST_VAAPI_ENCODER_VIDEO_INFO: + * @encoder: a #GstVaapiEncoder + * + * Macro that evaluates to the #GstVideoInfo of @encoder. + * This is an internal macro that does not do any run-time type check. + */ +#undef GST_VAAPI_ENCODER_VIDEO_INFO +#define GST_VAAPI_ENCODER_VIDEO_INFO(encoder) \ + (&GST_VAAPI_ENCODER_CAST (encoder)->video_info) + +/** + * GST_VAAPI_ENCODER_WIDTH: + * @encoder: a #GstVaapiEncoder + * + * Macro that evaluates to the coded width of the picture. + * This is an internal macro that does not do any run-time type check. + */ +#undef GST_VAAPI_ENCODER_WIDTH +#define GST_VAAPI_ENCODER_WIDTH(encoder) \ + (GST_VAAPI_ENCODER_VIDEO_INFO (encoder)->width) + +/** + * GST_VAAPI_ENCODER_HEIGHT: + * @encoder: a #GstVaapiEncoder + * + * Macro that evaluates to the coded height of the picture. + * This is an internal macro that does not do any run-time type check. + */ +#undef GST_VAAPI_ENCODER_HEIGHT +#define GST_VAAPI_ENCODER_HEIGHT(encoder) \ + (GST_VAAPI_ENCODER_VIDEO_INFO (encoder)->height) + +/** + * GST_VAAPI_ENCODER_FPS_N: + * @encoder: a #GstVaapiEncoder + * + * Macro that evaluates to the coded framerate numerator. + * This is an internal macro that does not do any run-time type check. + */ +#undef GST_VAAPI_ENCODER_FPS_N +#define GST_VAAPI_ENCODER_FPS_N(encoder) \ + (GST_VAAPI_ENCODER_VIDEO_INFO (encoder)->fps_n) + +/** + * GST_VAAPI_ENCODER_FPS_D: + * @encoder: a #GstVaapiEncoder + * + * Macro that evaluates to the coded framerate denominator. + * This is an internal macro that does not do any run-time type check. + */ +#undef GST_VAAPI_ENCODER_FPS_D +#define GST_VAAPI_ENCODER_FPS_D(encoder) \ + (GST_VAAPI_ENCODER_VIDEO_INFO (encoder)->fps_d) /** * GST_VAAPI_ENCODER_RATE_CONTROL: @@ -113,7 +161,6 @@ struct _GstVaapiEncoder GstVaapiDisplay *display; GstVaapiContext *context; GstVaapiContextInfo context_info; - GstCaps *caps; VADisplay va_display; VAContextID va_context; @@ -157,12 +204,10 @@ struct _GstVaapiEncoderClass gboolean (*init) (GstVaapiEncoder * encoder); void (*finalize) (GstVaapiEncoder * encoder); - GstCaps * (*set_format) (GstVaapiEncoder * encoder, - GstVideoCodecState * in_state, - GstCaps * ref_caps); - void (*set_context_info) (GstVaapiEncoder * encoder); + GstVaapiEncoderStatus (*reconfigure) (GstVaapiEncoder * encoder); + GPtrArray * (*get_default_properties) (void); GstVaapiEncoderStatus (*set_property) (GstVaapiEncoder * encoder, gint prop_id, @@ -196,8 +241,8 @@ struct _GstVaapiEncoderClass .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, reconfigure), \ GST_VAAPI_ENCODER_CLASS_HOOK (codec, get_default_properties), \ - GST_VAAPI_ENCODER_CLASS_HOOK (codec, set_format), \ GST_VAAPI_ENCODER_CLASS_HOOK (codec, set_context_info), \ GST_VAAPI_ENCODER_CLASS_HOOK (codec, reordering), \ GST_VAAPI_ENCODER_CLASS_HOOK (codec, encode), \ |