From bc020c05f988e15434d2501ffeaec32f97c4b527 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Wed, 27 Nov 2013 16:27:31 +0100 Subject: [PATCH] vaapiencode: add initial support for GStreamer 0.10. --- configure.ac | 5 - gst-libs/gst/vaapi/gstvaapiencoder_h264.c | 2 + gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c | 2 + gst-libs/gst/video/Makefile.am | 4 +- gst/vaapi/gstvaapiencode.c | 149 ++++++++++++++++++--- gst/vaapi/gstvaapiencode.h | 4 + gst/vaapi/gstvaapiencode_h264.c | 8 ++ gst/vaapi/gstvaapiencode_mpeg2.c | 8 ++ 8 files changed, 154 insertions(+), 28 deletions(-) diff --git a/configure.ac b/configure.ac index 39ac91301d..3710658931 100644 --- a/configure.ac +++ b/configure.ac @@ -706,11 +706,6 @@ if test "$enable_encoders" = "yes"; then ]) CPPFLAGS="$saved_CPPFLAGS" fi - - if test "$USE_GST_API_1_0p" != "yes"; then - AC_MSG_WARN([GStreamer API < 1.0, disabling encoders]) - USE_ENCODERS=0 - fi fi dnl VA/Wayland API diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c index ddded58e15..818bdf735c 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c @@ -1643,7 +1643,9 @@ gst_vaapi_encoder_h264_set_format (GstVaapiEncoder * base, else /* need codec data later */ encoder->is_avc = TRUE; +#if GST_CHECK_VERSION(1,0,0) result = gst_caps_fixate (result); +#endif if (!init_encoder_public_attributes (encoder)) { GST_WARNING ("encoder ensure public attributes failed "); diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c index 2c6e682df1..4b5ae8ea57 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c @@ -670,7 +670,9 @@ gst_vaapi_encoder_mpeg2_set_format (GstVaapiEncoder * base, result = gst_caps_intersect (tmp, ref_caps); gst_caps_unref (tmp); +#if GST_CHECK_VERSION(1,0,0) result = gst_caps_fixate (result); +#endif if (!ensure_public_attributes (encoder)) { GST_WARNING ("encoder ensure public attributes failed "); diff --git a/gst-libs/gst/video/Makefile.am b/gst-libs/gst/video/Makefile.am index 3b6ceb459c..d890cae07e 100644 --- a/gst-libs/gst/video/Makefile.am +++ b/gst-libs/gst/video/Makefile.am @@ -22,8 +22,8 @@ gen_source_c = gen_source_h = if USE_GST_API_0_10 -gen_source_c += gstvideodecoder.c gstvideoutils.c video.c -gen_source_h += gstvideodecoder.h gstvideoutils.h video.h +gen_source_c += gstvideodecoder.c gstvideoencoder.c gstvideoutils.c video.c +gen_source_h += gstvideodecoder.h gstvideoencoder.h gstvideoutils.h video.h endif GENFILES = \ diff --git a/gst/vaapi/gstvaapiencode.c b/gst/vaapi/gstvaapiencode.c index 215be01b1b..7a0da3b8f7 100644 --- a/gst/vaapi/gstvaapiencode.c +++ b/gst/vaapi/gstvaapiencode.c @@ -27,8 +27,10 @@ #include "gstvaapivideocontext.h" #include "gstvaapipluginutil.h" #include "gstvaapivideometa.h" +#if GST_CHECK_VERSION(1,0,0) #include "gstvaapivideomemory.h" #include "gstvaapivideobufferpool.h" +#endif #define GST_PLUGIN_NAME "vaapiencode" #define GST_PLUGIN_DESC "A VA-API based video encoder" @@ -107,11 +109,49 @@ G_DEFINE_TYPE_WITH_CODE (GstVaapiEncode, #endif ) -static gboolean -gst_vaapiencode_query (GstPad * pad, GstObject * parent, - GstQuery * query) +static inline gboolean +ensure_display (GstVaapiEncode * encode) { - GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (parent); + return gst_vaapi_ensure_display (encode, + GST_VAAPI_DISPLAY_TYPE_ANY, &encode->display); +} + +static gboolean +ensure_uploader (GstVaapiEncode * encode) +{ +#if !GST_CHECK_VERSION(1,0,0) + if (!ensure_display (encode)) + return FALSE; + + if (!encode->uploader) { + encode->uploader = gst_vaapi_uploader_new (encode->display); + if (!encode->uploader) + return FALSE; + } + + if (!gst_vaapi_uploader_ensure_display (encode->uploader, encode->display)) + return FALSE; +#endif + return TRUE; +} + +static gboolean +ensure_uploader_caps (GstVaapiEncode * encode) +{ +#if !GST_CHECK_VERSION(1,0,0) + if (GST_VIDEO_INFO_IS_YUV (&encode->sink_video_info) && + !gst_vaapi_uploader_ensure_caps (encode->uploader, encode->sinkpad_caps, + NULL)) + return FALSE; +#endif + return TRUE; +} + +static gboolean +gst_vaapiencode_query (GST_PAD_QUERY_FUNCTION_ARGS) +{ + GstVaapiEncode *const encode = + GST_VAAPIENCODE_CAST (gst_pad_get_parent_element (pad)); gboolean success; GST_INFO_OBJECT(encode, "query type %s", GST_QUERY_TYPE_NAME(query)); @@ -119,9 +159,13 @@ gst_vaapiencode_query (GstPad * pad, GstObject * parent, if (gst_vaapi_reply_to_query (query, encode->display)) success = TRUE; else if (GST_PAD_IS_SINK (pad)) - success = encode->sinkpad_query (pad, parent, query); + success = GST_PAD_QUERY_FUNCTION_CALL (encode->sinkpad_query, + encode->sinkpad, parent, query); else - success = encode->srcpad_query (pad, parent, query);; + success = GST_PAD_QUERY_FUNCTION_CALL (encode->srcpad_query, + encode->srcpad, parent, query); + + gst_object_unref (encode); return success; } @@ -129,7 +173,6 @@ static GstFlowReturn gst_vaapiencode_default_allocate_buffer (GstVaapiEncode * encode, GstVaapiCodedBuffer * coded_buf, GstBuffer ** outbuf_ptr) { - GstVideoEncoder *const venc = GST_VIDEO_ENCODER_CAST (encode); GstBuffer *buf; gint32 buf_size; @@ -143,7 +186,13 @@ gst_vaapiencode_default_allocate_buffer (GstVaapiEncode * encode, if (buf_size <= 0) goto error_invalid_buffer; - buf = gst_video_encoder_allocate_output_buffer (venc, buf_size); +#if GST_CHECK_VERSION(1,0,0) + buf = + gst_video_encoder_allocate_output_buffer (GST_VIDEO_ENCODER_CAST (encode), + buf_size); +#else + buf = gst_buffer_new_and_alloc (buf_size); +#endif if (!buf) goto error_create_buffer; if (!gst_vaapi_coded_buffer_get_buffer (coded_buf, buf)) @@ -240,12 +289,14 @@ gst_vaapiencode_push_frame (GstVaapiEncode * encode, gint64 ms_timeout) gst_caps_ref (encode->srcpad_caps), old_state); gst_video_codec_state_unref (old_state); gst_video_codec_state_unref (new_state); +#if GST_CHECK_VERSION(1,0,0) if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER_CAST (encode))) { GST_ERROR ("failed to negotiate with caps %" GST_PTR_FORMAT, encode->srcpad_caps); ret = GST_FLOW_NOT_NEGOTIATED; goto error_unlock; } +#endif GST_DEBUG ("updated srcpad caps to: %" GST_PTR_FORMAT, encode->srcpad_caps); } @@ -294,11 +345,25 @@ gst_vaapiencode_get_caps_impl (GstVideoEncoder * venc) if (encode->sinkpad_caps) caps = gst_caps_ref (encode->sinkpad_caps); - else + else { +#if GST_CHECK_VERSION(1,0,0) caps = gst_pad_get_pad_template_caps (encode->sinkpad); +#else + caps = gst_caps_from_string (GST_VAAPI_SURFACE_CAPS); + + if (caps && ensure_uploader (encode)) { + GstCaps *const yuv_caps = gst_vaapi_uploader_get_caps (encode->uploader); + if (yuv_caps) { + caps = gst_caps_make_writable (caps); + gst_caps_append (caps, gst_caps_copy (yuv_caps)); + } + } +#endif + } return caps; } +#if GST_CHECK_VERSION(1,0,0) static GstCaps * gst_vaapiencode_get_caps (GstVideoEncoder * venc, GstCaps * filter) { @@ -312,25 +377,24 @@ gst_vaapiencode_get_caps (GstVideoEncoder * venc, GstCaps * filter) } return out_caps; } +#else +#define gst_vaapiencode_get_caps gst_vaapiencode_get_caps_impl +#endif static gboolean gst_vaapiencode_destroy (GstVaapiEncode * encode) { gst_vaapi_encoder_replace (&encode->encoder, NULL); +#if GST_CHECK_VERSION(1,0,0) g_clear_object (&encode->video_buffer_pool); +#endif + g_clear_object (&encode->uploader); gst_caps_replace (&encode->sinkpad_caps, NULL); gst_caps_replace (&encode->srcpad_caps, NULL); gst_vaapi_display_replace (&encode->display, NULL); return TRUE; } -static inline gboolean -ensure_display (GstVaapiEncode * encode) -{ - return gst_vaapi_ensure_display (encode, - GST_VAAPI_DISPLAY_TYPE_ANY, &encode->display); -} - static gboolean ensure_encoder (GstVaapiEncode * encode) { @@ -340,6 +404,10 @@ ensure_encoder (GstVaapiEncode * encode) if (!ensure_display (encode)) return FALSE; + if (!ensure_uploader (encode)) + return FALSE; + if (!ensure_uploader_caps (encode)) + return FALSE; encode->encoder = klass->create_encoder (encode, encode->display); if (!encode->encoder) @@ -375,6 +443,17 @@ gst_vaapiencode_update_sink_caps (GstVaapiEncode * encode, { gst_caps_replace (&encode->sinkpad_caps, state->caps); encode->sink_video_info = state->info; + +#if !GST_CHECK_VERSION(1,0,0) + if (GST_VIDEO_INFO_IS_YUV (&encode->sink_video_info)) { + /* Ensure the uploader is set up for upstream allocated buffers */ + GstVaapiUploader *const uploader = encode->uploader; + if (!gst_vaapi_uploader_ensure_display (uploader, encode->display)) + return FALSE; + if (!gst_vaapi_uploader_ensure_caps (uploader, state->caps, NULL)) + return FALSE; + } +#endif return TRUE; } @@ -440,6 +519,7 @@ static gboolean gst_vaapiencode_ensure_video_buffer_pool (GstVaapiEncode * encode, GstCaps * caps) { +#if GST_CHECK_VERSION(1,0,0) GstBufferPool *pool; GstCaps *pool_caps; GstStructure *config; @@ -496,6 +576,9 @@ error_pool_config: gst_object_unref (pool); return FALSE; } +#else + return TRUE; +#endif } static gboolean @@ -515,11 +598,13 @@ gst_vaapiencode_set_format (GstVideoEncoder * venc, GstVideoCodecState * state) if (!gst_vaapiencode_update_src_caps (encode, state)) return FALSE; +#if GST_CHECK_VERSION(1,0,0) if (encode->out_caps_done && !gst_video_encoder_negotiate (venc)) { GST_ERROR ("failed to negotiate with caps %" GST_PTR_FORMAT, encode->srcpad_caps); return FALSE; } +#endif return gst_pad_start_task (encode->srcpad, (GstTaskFunction) gst_vaapiencode_buffer_loop, encode, NULL); @@ -544,8 +629,10 @@ get_source_buffer (GstVaapiEncode * encode, GstBuffer * src_buffer, { GstVaapiVideoMeta *meta; GstBuffer *out_buffer; +#if GST_CHECK_VERSION(1,0,0) GstVideoFrame src_frame, out_frame; gboolean success; +#endif *out_buffer_ptr = NULL; meta = gst_buffer_get_vaapi_video_meta (src_buffer); @@ -554,6 +641,7 @@ get_source_buffer (GstVaapiEncode * encode, GstBuffer * src_buffer, return GST_FLOW_OK; } +#if GST_CHECK_VERSION(1,0,0) if (!GST_VIDEO_INFO_IS_YUV (&encode->sink_video_info)) goto error_invalid_buffer; @@ -605,11 +693,6 @@ error_activate_pool: GST_ERROR ("failed to activate buffer pool"); return GST_FLOW_ERROR; } -error_create_buffer: - { - GST_WARNING ("failed to create buffer. Skipping this frame"); - return GST_FLOW_OK; - } error_map_dst_buffer: { gst_video_frame_unmap (&src_frame); @@ -621,6 +704,26 @@ error_map_src_buffer: gst_buffer_unref (out_buffer); return GST_FLOW_OK; } +#else + out_buffer = gst_vaapi_uploader_get_buffer (encode->uploader); + if (!out_buffer) + goto error_create_buffer; + if (!gst_vaapi_uploader_process (encode->uploader, src_buffer, out_buffer)) + goto error_copy_buffer; + + gst_buffer_copy_metadata (out_buffer, src_buffer, + GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS); + + *out_buffer_ptr = out_buffer; + return GST_FLOW_OK; +#endif + + /* ERRORS */ +error_create_buffer: + { + GST_WARNING ("failed to create buffer. Skipping this frame"); + return GST_FLOW_OK; + } error_copy_buffer: { GST_WARNING ("failed to upload buffer to VA surface. Skipping this frame"); @@ -723,6 +826,7 @@ gst_vaapiencode_finish (GstVideoEncoder * venc) return ret; } +#if GST_CHECK_VERSION(1,0,0) static gboolean gst_vaapiencode_propose_allocation (GstVideoEncoder * venc, GstQuery * query) { @@ -752,6 +856,7 @@ error_no_caps: return FALSE; } } +#endif static void gst_vaapiencode_finalize (GObject * object) @@ -809,8 +914,10 @@ gst_vaapiencode_class_init (GstVaapiEncodeClass * klass) venc_class->finish = GST_DEBUG_FUNCPTR (gst_vaapiencode_finish); venc_class->getcaps = GST_DEBUG_FUNCPTR (gst_vaapiencode_get_caps); +#if GST_CHECK_VERSION(1,0,0) venc_class->propose_allocation = GST_DEBUG_FUNCPTR (gst_vaapiencode_propose_allocation); +#endif klass->allocate_buffer = gst_vaapiencode_default_allocate_buffer; diff --git a/gst/vaapi/gstvaapiencode.h b/gst/vaapi/gstvaapiencode.h index e492acb701..ee7176ee8d 100644 --- a/gst/vaapi/gstvaapiencode.h +++ b/gst/vaapi/gstvaapiencode.h @@ -26,6 +26,7 @@ #include #include #include "gst/vaapi/gstvaapiencoder_objects.h" +#include "gstvaapiuploader.h" G_BEGIN_DECLS @@ -63,8 +64,11 @@ struct _GstVaapiEncode GstVaapiDisplay *display; GstVaapiEncoder *encoder; + GstVaapiUploader *uploader; +#if GST_CHECK_VERSION(1,0,0) GstBufferPool *video_buffer_pool; +#endif guint video_buffer_size; guint32 is_running:1; diff --git a/gst/vaapi/gstvaapiencode_h264.c b/gst/vaapi/gstvaapiencode_h264.c index d3d75153a5..1c108abca5 100644 --- a/gst/vaapi/gstvaapiencode_h264.c +++ b/gst/vaapi/gstvaapiencode_h264.c @@ -26,7 +26,9 @@ #include "gst/vaapi/gstvaapiencoder_h264_priv.h" #include "gstvaapiencode_h264.h" #include "gstvaapipluginutil.h" +#if GST_CHECK_VERSION(1,0,0) #include "gstvaapivideomemory.h" +#endif GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h264_encode_debug); #define GST_CAT_DEFAULT gst_vaapi_h264_encode_debug @@ -41,7 +43,13 @@ static const char gst_vaapiencode_h264_sink_caps_str[] = GST_VAAPI_SURFACE_CAPS ", " #endif GST_CAPS_INTERLACED_FALSE "; " +#if GST_CHECK_VERSION(1,0,0) GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ", " +#else + "video/x-raw-yuv, " + "width = (int) [ 1, MAX ], " + "height = (int) [ 1, MAX ], " +#endif GST_CAPS_INTERLACED_FALSE; static const char gst_vaapiencode_h264_src_caps_str[] = diff --git a/gst/vaapi/gstvaapiencode_mpeg2.c b/gst/vaapi/gstvaapiencode_mpeg2.c index fa3e152417..cfd6581c10 100644 --- a/gst/vaapi/gstvaapiencode_mpeg2.c +++ b/gst/vaapi/gstvaapiencode_mpeg2.c @@ -26,7 +26,9 @@ #include "gst/vaapi/gstvaapiencoder_mpeg2_priv.h" #include "gstvaapiencode_mpeg2.h" #include "gstvaapipluginutil.h" +#if GST_CHECK_VERSION(1,0,0) #include "gstvaapivideomemory.h" +#endif GST_DEBUG_CATEGORY_STATIC (gst_vaapi_mpeg2_encode_debug); #define GST_CAT_DEFAULT gst_vaapi_mpeg2_encode_debug @@ -41,7 +43,13 @@ static const char gst_vaapiencode_mpeg2_sink_caps_str[] = GST_VAAPI_SURFACE_CAPS ", " #endif GST_CAPS_INTERLACED_FALSE "; " +#if GST_CHECK_VERSION(1,0,0) GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ", " +#else + "video/x-raw-yuv, " + "width = (int) [ 1, MAX ], " + "height = (int) [ 1, MAX ], " +#endif GST_CAPS_INTERLACED_FALSE; static const char gst_vaapiencode_mpeg2_src_caps_str[] =