diff --git a/gst/vaapi/gstvaapipostproc.c b/gst/vaapi/gstvaapipostproc.c index 2dd9ce3dfd..fb014d16f5 100644 --- a/gst/vaapi/gstvaapipostproc.c +++ b/gst/vaapi/gstvaapipostproc.c @@ -43,7 +43,7 @@ #define GST_PLUGIN_NAME "vaapipostproc" #define GST_PLUGIN_DESC "A video postprocessing filter" -GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapipostproc); +GST_DEBUG_CATEGORY_STATIC (gst_debug_vaapipostproc); #define GST_CAT_DEFAULT gst_debug_vaapipostproc #if GST_CHECK_VERSION(1,1,0) @@ -56,73 +56,77 @@ GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapipostproc); #endif /* Default templates */ +/* *INDENT-OFF* */ static const char gst_vaapipostproc_sink_caps_str[] = - GST_VAAPIPOSTPROC_SURFACE_CAPS ", " - GST_CAPS_INTERLACED_MODES "; " + GST_VAAPIPOSTPROC_SURFACE_CAPS ", " + GST_CAPS_INTERLACED_MODES "; " #if GST_CHECK_VERSION(1,0,0) - GST_VIDEO_CAPS_MAKE(GST_VIDEO_FORMATS_ALL) ", " + GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ", " #else - "video/x-raw-yuv, " - "width = " GST_VIDEO_SIZE_RANGE ", " - "height = " GST_VIDEO_SIZE_RANGE ", " - "framerate = " GST_VIDEO_FPS_RANGE ", " + "video/x-raw-yuv, " + "width = " GST_VIDEO_SIZE_RANGE ", " + "height = " GST_VIDEO_SIZE_RANGE ", " + "framerate = " GST_VIDEO_FPS_RANGE ", " #endif - GST_CAPS_INTERLACED_MODES; + GST_CAPS_INTERLACED_MODES; +/* *INDENT-ON* */ +/* *INDENT-OFF* */ static const char gst_vaapipostproc_src_caps_str[] = - GST_VAAPIPOSTPROC_SURFACE_CAPS ", " - GST_CAPS_INTERLACED_FALSE "; " + GST_VAAPIPOSTPROC_SURFACE_CAPS ", " + GST_CAPS_INTERLACED_FALSE "; " #if GST_CHECK_VERSION(1,1,0) - GST_VIDEO_CAPS_MAKE_WITH_FEATURES( - GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, "RGBA") ", " - GST_CAPS_INTERLACED_FALSE "; " + GST_VIDEO_CAPS_MAKE_WITH_FEATURES ( + GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, "RGBA") ", " + GST_CAPS_INTERLACED_FALSE "; " #endif #if GST_CHECK_VERSION(1,0,0) - GST_VIDEO_CAPS_MAKE(GST_VIDEO_FORMATS_ALL) ", " + GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ", " #else - "video/x-raw-yuv, " - "width = " GST_VIDEO_SIZE_RANGE ", " - "height = " GST_VIDEO_SIZE_RANGE ", " - "framerate = " GST_VIDEO_FPS_RANGE ", " + "video/x-raw-yuv, " + "width = " GST_VIDEO_SIZE_RANGE ", " + "height = " GST_VIDEO_SIZE_RANGE ", " + "framerate = " GST_VIDEO_FPS_RANGE ", " #endif - GST_CAPS_INTERLACED_FALSE; + GST_CAPS_INTERLACED_FALSE; +/* *INDENT-ON* */ +/* *INDENT-OFF* */ static GstStaticPadTemplate gst_vaapipostproc_sink_factory = - GST_STATIC_PAD_TEMPLATE( - "sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS(gst_vaapipostproc_sink_caps_str)); + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (gst_vaapipostproc_sink_caps_str)); +/* *INDENT-ON* */ +/* *INDENT-OFF* */ static GstStaticPadTemplate gst_vaapipostproc_src_factory = - GST_STATIC_PAD_TEMPLATE( - "src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS(gst_vaapipostproc_src_caps_str)); + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (gst_vaapipostproc_src_caps_str)); +/* *INDENT-ON* */ -G_DEFINE_TYPE_WITH_CODE( - GstVaapiPostproc, - gst_vaapipostproc, - GST_TYPE_BASE_TRANSFORM, - GST_VAAPI_PLUGIN_BASE_INIT_INTERFACES) +G_DEFINE_TYPE_WITH_CODE (GstVaapiPostproc, gst_vaapipostproc, + GST_TYPE_BASE_TRANSFORM, GST_VAAPI_PLUGIN_BASE_INIT_INTERFACES); -enum { - PROP_0, +enum +{ + PROP_0, - PROP_FORMAT, - PROP_WIDTH, - PROP_HEIGHT, - PROP_FORCE_ASPECT_RATIO, - PROP_DEINTERLACE_MODE, - PROP_DEINTERLACE_METHOD, - PROP_DENOISE, - PROP_SHARPEN, - PROP_HUE, - PROP_SATURATION, - PROP_BRIGHTNESS, - PROP_CONTRAST, - PROP_SCALE_METHOD, + PROP_FORMAT, + PROP_WIDTH, + PROP_HEIGHT, + PROP_FORCE_ASPECT_RATIO, + PROP_DEINTERLACE_MODE, + PROP_DEINTERLACE_METHOD, + PROP_DENOISE, + PROP_SHARPEN, + PROP_HUE, + PROP_SATURATION, + PROP_BRIGHTNESS, + PROP_CONTRAST, + PROP_SCALE_METHOD, }; #define DEFAULT_FORMAT GST_VIDEO_FORMAT_ENCODED @@ -133,1102 +137,1090 @@ enum { gst_vaapi_deinterlace_mode_get_type() static GType -gst_vaapi_deinterlace_mode_get_type(void) +gst_vaapi_deinterlace_mode_get_type (void) { - static GType deinterlace_mode_type = 0; + static GType deinterlace_mode_type = 0; - static const GEnumValue mode_types[] = { - { GST_VAAPI_DEINTERLACE_MODE_AUTO, - "Auto detection", "auto" }, - { GST_VAAPI_DEINTERLACE_MODE_INTERLACED, - "Force deinterlacing", "interlaced" }, - { GST_VAAPI_DEINTERLACE_MODE_DISABLED, - "Never deinterlace", "disabled" }, - { 0, NULL, NULL }, - }; + static const GEnumValue mode_types[] = { + {GST_VAAPI_DEINTERLACE_MODE_AUTO, + "Auto detection", "auto"}, + {GST_VAAPI_DEINTERLACE_MODE_INTERLACED, + "Force deinterlacing", "interlaced"}, + {GST_VAAPI_DEINTERLACE_MODE_DISABLED, + "Never deinterlace", "disabled"}, + {0, NULL, NULL}, + }; - if (!deinterlace_mode_type) { - deinterlace_mode_type = - g_enum_register_static("GstVaapiDeinterlaceMode", mode_types); - } - return deinterlace_mode_type; + if (!deinterlace_mode_type) { + deinterlace_mode_type = + g_enum_register_static ("GstVaapiDeinterlaceMode", mode_types); + } + return deinterlace_mode_type; } static void -ds_reset(GstVaapiDeinterlaceState *ds) +ds_reset (GstVaapiDeinterlaceState * ds) { - guint i; + guint i; - for (i = 0; i < G_N_ELEMENTS(ds->buffers); i++) - gst_buffer_replace(&ds->buffers[i], NULL); - ds->buffers_index = 0; - ds->num_surfaces = 0; - ds->deint = FALSE; - ds->tff = FALSE; + for (i = 0; i < G_N_ELEMENTS (ds->buffers); i++) + gst_buffer_replace (&ds->buffers[i], NULL); + ds->buffers_index = 0; + ds->num_surfaces = 0; + ds->deint = FALSE; + ds->tff = FALSE; } static void -ds_add_buffer(GstVaapiDeinterlaceState *ds, GstBuffer *buf) +ds_add_buffer (GstVaapiDeinterlaceState * ds, GstBuffer * buf) { - gst_buffer_replace(&ds->buffers[ds->buffers_index], buf); - ds->buffers_index = (ds->buffers_index + 1) % G_N_ELEMENTS(ds->buffers); + gst_buffer_replace (&ds->buffers[ds->buffers_index], buf); + ds->buffers_index = (ds->buffers_index + 1) % G_N_ELEMENTS (ds->buffers); } static inline GstBuffer * -ds_get_buffer(GstVaapiDeinterlaceState *ds, guint index) +ds_get_buffer (GstVaapiDeinterlaceState * ds, guint index) { - /* Note: the index increases towards older buffers. - i.e. buffer at index 0 means the immediately preceding buffer - in the history, buffer at index 1 means the one preceding the - surface at index 0, etc. */ - const guint n = ds->buffers_index + G_N_ELEMENTS(ds->buffers) - index - 1; - return ds->buffers[n % G_N_ELEMENTS(ds->buffers)]; + /* Note: the index increases towards older buffers. + i.e. buffer at index 0 means the immediately preceding buffer + in the history, buffer at index 1 means the one preceding the + surface at index 0, etc. */ + const guint n = ds->buffers_index + G_N_ELEMENTS (ds->buffers) - index - 1; + return ds->buffers[n % G_N_ELEMENTS (ds->buffers)]; } static void -ds_set_surfaces(GstVaapiDeinterlaceState *ds) +ds_set_surfaces (GstVaapiDeinterlaceState * ds) { - GstVaapiVideoMeta *meta; - guint i; + GstVaapiVideoMeta *meta; + guint i; - ds->num_surfaces = 0; - for (i = 0; i < G_N_ELEMENTS(ds->buffers); i++) { - GstBuffer * const buf = ds_get_buffer(ds, i); - if (!buf) - break; + ds->num_surfaces = 0; + for (i = 0; i < G_N_ELEMENTS (ds->buffers); i++) { + GstBuffer *const buf = ds_get_buffer (ds, i); + if (!buf) + break; - meta = gst_buffer_get_vaapi_video_meta(buf); - ds->surfaces[ds->num_surfaces++] = - gst_vaapi_video_meta_get_surface(meta); - } + meta = gst_buffer_get_vaapi_video_meta (buf); + ds->surfaces[ds->num_surfaces++] = gst_vaapi_video_meta_get_surface (meta); + } } static GstVaapiFilterOpInfo * -find_filter_op(GPtrArray *filter_ops, GstVaapiFilterOp op) +find_filter_op (GPtrArray * filter_ops, GstVaapiFilterOp op) { - guint i; + guint i; - if (filter_ops) { - for (i = 0; i < filter_ops->len; i++) { - GstVaapiFilterOpInfo * const filter_op = - g_ptr_array_index(filter_ops, i); - if (filter_op->op == op) - return filter_op; - } + if (filter_ops) { + for (i = 0; i < filter_ops->len; i++) { + GstVaapiFilterOpInfo *const filter_op = g_ptr_array_index (filter_ops, i); + if (filter_op->op == op) + return filter_op; } - return NULL; + } + return NULL; } static inline gboolean -gst_vaapipostproc_ensure_display(GstVaapiPostproc *postproc) +gst_vaapipostproc_ensure_display (GstVaapiPostproc * postproc) { - return gst_vaapi_plugin_base_ensure_display(GST_VAAPI_PLUGIN_BASE(postproc)); + return + gst_vaapi_plugin_base_ensure_display (GST_VAAPI_PLUGIN_BASE (postproc)); } static gboolean -gst_vaapipostproc_ensure_uploader(GstVaapiPostproc *postproc) +gst_vaapipostproc_ensure_uploader (GstVaapiPostproc * postproc) { - if (!gst_vaapipostproc_ensure_display(postproc)) - return FALSE; - if (!gst_vaapi_plugin_base_ensure_uploader(GST_VAAPI_PLUGIN_BASE(postproc))) - return FALSE; - return TRUE; + if (!gst_vaapipostproc_ensure_display (postproc)) + return FALSE; + if (!gst_vaapi_plugin_base_ensure_uploader (GST_VAAPI_PLUGIN_BASE (postproc))) + return FALSE; + return TRUE; } static gboolean -gst_vaapipostproc_ensure_filter(GstVaapiPostproc *postproc) +gst_vaapipostproc_ensure_filter (GstVaapiPostproc * postproc) { - if (postproc->filter) - return TRUE; - - if (!gst_vaapipostproc_ensure_display(postproc)) - return FALSE; - - postproc->filter = gst_vaapi_filter_new( - GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc)); - if (!postproc->filter) - return FALSE; + if (postproc->filter) return TRUE; + + if (!gst_vaapipostproc_ensure_display (postproc)) + return FALSE; + + postproc->filter = + gst_vaapi_filter_new (GST_VAAPI_PLUGIN_BASE_DISPLAY (postproc)); + if (!postproc->filter) + return FALSE; + return TRUE; } static gboolean -gst_vaapipostproc_ensure_filter_caps(GstVaapiPostproc *postproc) +gst_vaapipostproc_ensure_filter_caps (GstVaapiPostproc * postproc) { - if (!gst_vaapipostproc_ensure_filter(postproc)) - return FALSE; + if (!gst_vaapipostproc_ensure_filter (postproc)) + return FALSE; - postproc->filter_ops = gst_vaapi_filter_get_operations(postproc->filter); - if (!postproc->filter_ops) - return FALSE; + postproc->filter_ops = gst_vaapi_filter_get_operations (postproc->filter); + if (!postproc->filter_ops) + return FALSE; - postproc->filter_formats = gst_vaapi_filter_get_formats(postproc->filter); - if (!postproc->filter_formats) - return FALSE; - return TRUE; + postproc->filter_formats = gst_vaapi_filter_get_formats (postproc->filter); + if (!postproc->filter_formats) + return FALSE; + return TRUE; } static gboolean -gst_vaapipostproc_create(GstVaapiPostproc *postproc) +gst_vaapipostproc_create (GstVaapiPostproc * postproc) { - if (!gst_vaapi_plugin_base_open(GST_VAAPI_PLUGIN_BASE(postproc))) - return FALSE; - if (!gst_vaapipostproc_ensure_display(postproc)) - return FALSE; - if (!gst_vaapipostproc_ensure_uploader(postproc)) - return FALSE; + if (!gst_vaapi_plugin_base_open (GST_VAAPI_PLUGIN_BASE (postproc))) + return FALSE; + if (!gst_vaapipostproc_ensure_display (postproc)) + return FALSE; + if (!gst_vaapipostproc_ensure_uploader (postproc)) + return FALSE; - postproc->use_vpp = FALSE; - postproc->has_vpp = gst_vaapipostproc_ensure_filter(postproc); - return TRUE; + postproc->use_vpp = FALSE; + postproc->has_vpp = gst_vaapipostproc_ensure_filter (postproc); + return TRUE; } static void -gst_vaapipostproc_destroy_filter(GstVaapiPostproc *postproc) +gst_vaapipostproc_destroy_filter (GstVaapiPostproc * postproc) { - if (postproc->filter_formats) { - g_array_unref(postproc->filter_formats); - postproc->filter_formats = NULL; - } + if (postproc->filter_formats) { + g_array_unref (postproc->filter_formats); + postproc->filter_formats = NULL; + } - if (postproc->filter_ops) { - g_ptr_array_unref(postproc->filter_ops); - postproc->filter_ops = NULL; - } - gst_vaapi_filter_replace(&postproc->filter, NULL); - gst_vaapi_video_pool_replace(&postproc->filter_pool, NULL); - postproc->filter_pool_active = FALSE; + if (postproc->filter_ops) { + g_ptr_array_unref (postproc->filter_ops); + postproc->filter_ops = NULL; + } + gst_vaapi_filter_replace (&postproc->filter, NULL); + gst_vaapi_video_pool_replace (&postproc->filter_pool, NULL); + postproc->filter_pool_active = FALSE; } static void -gst_vaapipostproc_destroy(GstVaapiPostproc *postproc) +gst_vaapipostproc_destroy (GstVaapiPostproc * postproc) { - ds_reset(&postproc->deinterlace_state); - gst_vaapipostproc_destroy_filter(postproc); + ds_reset (&postproc->deinterlace_state); + gst_vaapipostproc_destroy_filter (postproc); - gst_caps_replace(&postproc->allowed_sinkpad_caps, NULL); - gst_caps_replace(&postproc->allowed_srcpad_caps, NULL); - gst_vaapi_plugin_base_close(GST_VAAPI_PLUGIN_BASE(postproc)); + gst_caps_replace (&postproc->allowed_sinkpad_caps, NULL); + gst_caps_replace (&postproc->allowed_srcpad_caps, NULL); + gst_vaapi_plugin_base_close (GST_VAAPI_PLUGIN_BASE (postproc)); } static gboolean -gst_vaapipostproc_start(GstBaseTransform *trans) +gst_vaapipostproc_start (GstBaseTransform * trans) { - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans); + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans); - ds_reset(&postproc->deinterlace_state); - if (!gst_vaapi_plugin_base_open(GST_VAAPI_PLUGIN_BASE(postproc))) - return FALSE; - if (!gst_vaapipostproc_ensure_display(postproc)) - return FALSE; + ds_reset (&postproc->deinterlace_state); + if (!gst_vaapi_plugin_base_open (GST_VAAPI_PLUGIN_BASE (postproc))) + return FALSE; + if (!gst_vaapipostproc_ensure_display (postproc)) + return FALSE; + return TRUE; +} + +static gboolean +gst_vaapipostproc_stop (GstBaseTransform * trans) +{ + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans); + + ds_reset (&postproc->deinterlace_state); + gst_vaapi_plugin_base_close (GST_VAAPI_PLUGIN_BASE (postproc)); + postproc->filter_pool_active = FALSE; + return TRUE; +} + +static gboolean +should_deinterlace_buffer (GstVaapiPostproc * postproc, GstBuffer * buf) +{ + if (!(postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE) || + postproc->deinterlace_mode == GST_VAAPI_DEINTERLACE_MODE_DISABLED) + return FALSE; + + if (postproc->deinterlace_mode == GST_VAAPI_DEINTERLACE_MODE_INTERLACED) return TRUE; -} -static gboolean -gst_vaapipostproc_stop(GstBaseTransform *trans) -{ - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans); + g_assert (postproc->deinterlace_mode == GST_VAAPI_DEINTERLACE_MODE_AUTO); - ds_reset(&postproc->deinterlace_state); - gst_vaapi_plugin_base_close(GST_VAAPI_PLUGIN_BASE(postproc)); - postproc->filter_pool_active = FALSE; - return TRUE; -} - -static gboolean -should_deinterlace_buffer(GstVaapiPostproc *postproc, GstBuffer *buf) -{ - if (!(postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE) || - postproc->deinterlace_mode == GST_VAAPI_DEINTERLACE_MODE_DISABLED) - return FALSE; - - if (postproc->deinterlace_mode == GST_VAAPI_DEINTERLACE_MODE_INTERLACED) - return TRUE; - - g_assert(postproc->deinterlace_mode == GST_VAAPI_DEINTERLACE_MODE_AUTO); - - switch (GST_VIDEO_INFO_INTERLACE_MODE(&postproc->sinkpad_info)) { + switch (GST_VIDEO_INFO_INTERLACE_MODE (&postproc->sinkpad_info)) { case GST_VIDEO_INTERLACE_MODE_INTERLEAVED: - return TRUE; + return TRUE; case GST_VIDEO_INTERLACE_MODE_PROGRESSIVE: - return FALSE; + return FALSE; case GST_VIDEO_INTERLACE_MODE_MIXED: #if GST_CHECK_VERSION(1,0,0) - if (GST_BUFFER_FLAG_IS_SET(buf, GST_VIDEO_BUFFER_FLAG_INTERLACED)) - return TRUE; + if (GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_FLAG_INTERLACED)) + return TRUE; #else - if (!GST_BUFFER_FLAG_IS_SET(buf, GST_VIDEO_BUFFER_PROGRESSIVE)) - return TRUE; + if (!GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_PROGRESSIVE)) + return TRUE; #endif - break; + break; default: - GST_ERROR("unhandled \"interlace-mode\", disabling deinterlacing" ); - break; - } - return FALSE; + GST_ERROR ("unhandled \"interlace-mode\", disabling deinterlacing"); + break; + } + return FALSE; } static GstBuffer * -create_output_buffer(GstVaapiPostproc *postproc) +create_output_buffer (GstVaapiPostproc * postproc) { - GstBuffer *outbuf; + GstBuffer *outbuf; #if GST_CHECK_VERSION(1,0,0) - GstBufferPool * const pool = - GST_VAAPI_PLUGIN_BASE(postproc)->srcpad_buffer_pool; - GstFlowReturn ret; + GstBufferPool *const pool = + GST_VAAPI_PLUGIN_BASE (postproc)->srcpad_buffer_pool; + GstFlowReturn ret; - g_return_val_if_fail(pool != NULL, NULL); + g_return_val_if_fail (pool != NULL, NULL); - if (!postproc->filter_pool_active) { - if (!gst_buffer_pool_set_active(pool, TRUE)) - goto error_activate_pool; - postproc->filter_pool_active = TRUE; - } + if (!postproc->filter_pool_active) { + if (!gst_buffer_pool_set_active (pool, TRUE)) + goto error_activate_pool; + postproc->filter_pool_active = TRUE; + } - outbuf = NULL; - ret = gst_buffer_pool_acquire_buffer(pool, &outbuf, NULL); - if (ret != GST_FLOW_OK || !outbuf) - goto error_create_buffer; + outbuf = NULL; + ret = gst_buffer_pool_acquire_buffer (pool, &outbuf, NULL); + if (ret != GST_FLOW_OK || !outbuf) + goto error_create_buffer; #else - /* Create a raw VA video buffer without GstVaapiVideoMeta attached - to it yet, as this will be done next in the transform() hook */ - outbuf = gst_vaapi_video_buffer_new_empty(); - if (!outbuf) - goto error_create_buffer; + /* Create a raw VA video buffer without GstVaapiVideoMeta attached + to it yet, as this will be done next in the transform() hook */ + outbuf = gst_vaapi_video_buffer_new_empty (); + if (!outbuf) + goto error_create_buffer; - gst_buffer_set_caps(outbuf, GST_VAAPI_PLUGIN_BASE_SRC_PAD_CAPS(postproc)); + gst_buffer_set_caps (outbuf, GST_VAAPI_PLUGIN_BASE_SRC_PAD_CAPS (postproc)); #endif - return outbuf; + return outbuf; - /* ERRORS */ + /* ERRORS */ #if GST_CHECK_VERSION(1,0,0) error_activate_pool: - { - GST_ERROR("failed to activate output video buffer pool"); - return NULL; - } + { + GST_ERROR ("failed to activate output video buffer pool"); + return NULL; + } #endif error_create_buffer: - { - GST_ERROR("failed to create output video buffer"); - return NULL; - } + { + GST_ERROR ("failed to create output video buffer"); + return NULL; + } } static gboolean -append_output_buffer_metadata(GstVaapiPostproc *postproc, GstBuffer *outbuf, - GstBuffer *inbuf, guint flags) +append_output_buffer_metadata (GstVaapiPostproc * postproc, GstBuffer * outbuf, + GstBuffer * inbuf, guint flags) { - GstVaapiVideoMeta *inbuf_meta, *outbuf_meta; - GstVaapiSurfaceProxy *proxy; + GstVaapiVideoMeta *inbuf_meta, *outbuf_meta; + GstVaapiSurfaceProxy *proxy; - gst_buffer_copy_into(outbuf, inbuf, flags | GST_BUFFER_COPY_FLAGS, 0, -1); + gst_buffer_copy_into (outbuf, inbuf, flags | GST_BUFFER_COPY_FLAGS, 0, -1); - /* GstVideoCropMeta */ + /* GstVideoCropMeta */ #if GST_CHECK_VERSION(1,0,0) - if (!postproc->use_vpp) { - GstVideoCropMeta * const crop_meta = - gst_buffer_get_video_crop_meta(inbuf); - if (crop_meta) { - GstVideoCropMeta * const out_crop_meta = - gst_buffer_add_video_crop_meta(outbuf); - if (out_crop_meta) - *out_crop_meta = *crop_meta; - } + if (!postproc->use_vpp) { + GstVideoCropMeta *const crop_meta = gst_buffer_get_video_crop_meta (inbuf); + if (crop_meta) { + GstVideoCropMeta *const out_crop_meta = + gst_buffer_add_video_crop_meta (outbuf); + if (out_crop_meta) + *out_crop_meta = *crop_meta; } + } #endif - /* GstVaapiVideoMeta */ - inbuf_meta = gst_buffer_get_vaapi_video_meta(inbuf); - g_return_val_if_fail(inbuf_meta != NULL, FALSE); - proxy = gst_vaapi_video_meta_get_surface_proxy(inbuf_meta); + /* GstVaapiVideoMeta */ + inbuf_meta = gst_buffer_get_vaapi_video_meta (inbuf); + g_return_val_if_fail (inbuf_meta != NULL, FALSE); + proxy = gst_vaapi_video_meta_get_surface_proxy (inbuf_meta); - outbuf_meta = gst_buffer_get_vaapi_video_meta(outbuf); - g_return_val_if_fail(outbuf_meta != NULL, FALSE); - proxy = gst_vaapi_surface_proxy_copy(proxy); - if (!proxy) - return FALSE; + outbuf_meta = gst_buffer_get_vaapi_video_meta (outbuf); + g_return_val_if_fail (outbuf_meta != NULL, FALSE); + proxy = gst_vaapi_surface_proxy_copy (proxy); + if (!proxy) + return FALSE; - gst_vaapi_video_meta_set_surface_proxy(outbuf_meta, proxy); - gst_vaapi_surface_proxy_unref(proxy); - return TRUE; + gst_vaapi_video_meta_set_surface_proxy (outbuf_meta, proxy); + gst_vaapi_surface_proxy_unref (proxy); + return TRUE; } static gboolean -deint_method_is_advanced(GstVaapiDeinterlaceMethod deint_method) +deint_method_is_advanced (GstVaapiDeinterlaceMethod deint_method) { - gboolean is_advanced; + gboolean is_advanced; - switch (deint_method) { + switch (deint_method) { case GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE: case GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED: - is_advanced = TRUE; - break; + is_advanced = TRUE; + break; default: - is_advanced = FALSE; - break; - } - return is_advanced; + is_advanced = FALSE; + break; + } + return is_advanced; } static GstVaapiDeinterlaceMethod -get_next_deint_method(GstVaapiDeinterlaceMethod deint_method) +get_next_deint_method (GstVaapiDeinterlaceMethod deint_method) { - switch (deint_method) { + switch (deint_method) { case GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED: - deint_method = GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE; - break; + deint_method = GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE; + break; default: - /* Default to basic "bob" for all others */ - deint_method = GST_VAAPI_DEINTERLACE_METHOD_BOB; - break; - } - return deint_method; + /* Default to basic "bob" for all others */ + deint_method = GST_VAAPI_DEINTERLACE_METHOD_BOB; + break; + } + return deint_method; } static gboolean -set_best_deint_method(GstVaapiPostproc *postproc, guint flags, - GstVaapiDeinterlaceMethod *deint_method_ptr) +set_best_deint_method (GstVaapiPostproc * postproc, guint flags, + GstVaapiDeinterlaceMethod * deint_method_ptr) { - GstVaapiDeinterlaceMethod deint_method = postproc->deinterlace_method; - gboolean success; + GstVaapiDeinterlaceMethod deint_method = postproc->deinterlace_method; + gboolean success; - for (;;) { - success = gst_vaapi_filter_set_deinterlacing(postproc->filter, - deint_method, flags); - if (success || deint_method == GST_VAAPI_DEINTERLACE_METHOD_BOB) - break; - deint_method = get_next_deint_method(deint_method); - } - *deint_method_ptr = deint_method; - return success; + for (;;) { + success = gst_vaapi_filter_set_deinterlacing (postproc->filter, + deint_method, flags); + if (success || deint_method == GST_VAAPI_DEINTERLACE_METHOD_BOB) + break; + deint_method = get_next_deint_method (deint_method); + } + *deint_method_ptr = deint_method; + return success; } static GstFlowReturn -gst_vaapipostproc_process_vpp(GstBaseTransform *trans, GstBuffer *inbuf, - GstBuffer *outbuf) +gst_vaapipostproc_process_vpp (GstBaseTransform * trans, GstBuffer * inbuf, + GstBuffer * outbuf) { - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans); - GstVaapiDeinterlaceState * const ds = &postproc->deinterlace_state; - GstVaapiVideoMeta *inbuf_meta, *outbuf_meta; - GstVaapiSurface *inbuf_surface, *outbuf_surface; - GstVaapiSurfaceProxy *proxy; - GstVaapiFilterStatus status; - GstClockTime timestamp; - GstFlowReturn ret; - GstBuffer *fieldbuf; - GstVaapiDeinterlaceMethod deint_method; - guint flags, deint_flags; - gboolean tff, deint, deint_refs, deint_changed; - GstVaapiRectangle *crop_rect = NULL; + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans); + GstVaapiDeinterlaceState *const ds = &postproc->deinterlace_state; + GstVaapiVideoMeta *inbuf_meta, *outbuf_meta; + GstVaapiSurface *inbuf_surface, *outbuf_surface; + GstVaapiSurfaceProxy *proxy; + GstVaapiFilterStatus status; + GstClockTime timestamp; + GstFlowReturn ret; + GstBuffer *fieldbuf; + GstVaapiDeinterlaceMethod deint_method; + guint flags, deint_flags; + gboolean tff, deint, deint_refs, deint_changed; + GstVaapiRectangle *crop_rect = NULL; #if GST_CHECK_VERSION(1,0,0) - GstVaapiRectangle tmp_rect; + GstVaapiRectangle tmp_rect; #endif - /* Validate filters */ - if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_FORMAT) && - !gst_vaapi_filter_set_format(postproc->filter, postproc->format)) - return GST_FLOW_NOT_SUPPORTED; + /* Validate filters */ + if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_FORMAT) && + !gst_vaapi_filter_set_format (postproc->filter, postproc->format)) + return GST_FLOW_NOT_SUPPORTED; - if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_DENOISE) && - !gst_vaapi_filter_set_denoising_level(postproc->filter, - postproc->denoise_level)) - return GST_FLOW_NOT_SUPPORTED; + if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_DENOISE) && + !gst_vaapi_filter_set_denoising_level (postproc->filter, + postproc->denoise_level)) + return GST_FLOW_NOT_SUPPORTED; - if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_SHARPEN) && - !gst_vaapi_filter_set_sharpening_level(postproc->filter, - postproc->sharpen_level)) - return GST_FLOW_NOT_SUPPORTED; + if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_SHARPEN) && + !gst_vaapi_filter_set_sharpening_level (postproc->filter, + postproc->sharpen_level)) + return GST_FLOW_NOT_SUPPORTED; - if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_HUE) && - !gst_vaapi_filter_set_hue(postproc->filter, - postproc->hue)) - return GST_FLOW_NOT_SUPPORTED; + if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_HUE) && + !gst_vaapi_filter_set_hue (postproc->filter, postproc->hue)) + return GST_FLOW_NOT_SUPPORTED; - if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_SATURATION) && - !gst_vaapi_filter_set_saturation(postproc->filter, - postproc->saturation)) - return GST_FLOW_NOT_SUPPORTED; + if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_SATURATION) && + !gst_vaapi_filter_set_saturation (postproc->filter, postproc->saturation)) + return GST_FLOW_NOT_SUPPORTED; - if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_BRIGHTNESS) && - !gst_vaapi_filter_set_brightness(postproc->filter, - postproc->brightness)) - return GST_FLOW_NOT_SUPPORTED; + if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_BRIGHTNESS) && + !gst_vaapi_filter_set_brightness (postproc->filter, postproc->brightness)) + return GST_FLOW_NOT_SUPPORTED; - if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_CONTRAST) && - !gst_vaapi_filter_set_contrast(postproc->filter, - postproc->contrast)) - return GST_FLOW_NOT_SUPPORTED; + if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_CONTRAST) && + !gst_vaapi_filter_set_contrast (postproc->filter, postproc->contrast)) + return GST_FLOW_NOT_SUPPORTED; - if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_SCALE) && - !gst_vaapi_filter_set_scaling(postproc->filter, - postproc->scale_method)) - return GST_FLOW_NOT_SUPPORTED; + if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_SCALE) && + !gst_vaapi_filter_set_scaling (postproc->filter, postproc->scale_method)) + return GST_FLOW_NOT_SUPPORTED; - inbuf_meta = gst_buffer_get_vaapi_video_meta(inbuf); - if (!inbuf_meta) - goto error_invalid_buffer; - inbuf_surface = gst_vaapi_video_meta_get_surface(inbuf_meta); + inbuf_meta = gst_buffer_get_vaapi_video_meta (inbuf); + if (!inbuf_meta) + goto error_invalid_buffer; + inbuf_surface = gst_vaapi_video_meta_get_surface (inbuf_meta); #if GST_CHECK_VERSION(1,0,0) - GstVideoCropMeta * const crop_meta = - gst_buffer_get_video_crop_meta(inbuf); - if (crop_meta) { - crop_rect = &tmp_rect; - crop_rect->x = crop_meta->x; - crop_rect->y = crop_meta->y; - crop_rect->width = crop_meta->width; - crop_rect->height = crop_meta->height; - } + GstVideoCropMeta *const crop_meta = gst_buffer_get_video_crop_meta (inbuf); + if (crop_meta) { + crop_rect = &tmp_rect; + crop_rect->x = crop_meta->x; + crop_rect->y = crop_meta->y; + crop_rect->width = crop_meta->width; + crop_rect->height = crop_meta->height; + } #endif - if (!crop_rect) - crop_rect = (GstVaapiRectangle *) - gst_vaapi_video_meta_get_render_rect(inbuf_meta); + if (!crop_rect) + crop_rect = (GstVaapiRectangle *) + gst_vaapi_video_meta_get_render_rect (inbuf_meta); - timestamp = GST_BUFFER_TIMESTAMP(inbuf); - tff = GST_BUFFER_FLAG_IS_SET(inbuf, GST_VIDEO_BUFFER_FLAG_TFF); - deint = should_deinterlace_buffer(postproc, inbuf); + timestamp = GST_BUFFER_TIMESTAMP (inbuf); + tff = GST_BUFFER_FLAG_IS_SET (inbuf, GST_VIDEO_BUFFER_FLAG_TFF); + deint = should_deinterlace_buffer (postproc, inbuf); - /* Drop references if deinterlacing conditions changed */ - deint_changed = deint != ds->deint; - if (deint_changed || (ds->num_surfaces > 0 && tff != ds->tff)) - ds_reset(ds); + /* Drop references if deinterlacing conditions changed */ + deint_changed = deint != ds->deint; + if (deint_changed || (ds->num_surfaces > 0 && tff != ds->tff)) + ds_reset (ds); - deint_method = postproc->deinterlace_method; - deint_refs = deint_method_is_advanced(deint_method); - if (deint_refs && 0) { - GstBuffer * const prev_buf = ds_get_buffer(ds, 0); - GstClockTime prev_pts, pts = GST_BUFFER_TIMESTAMP(inbuf); - /* Reset deinterlacing state when there is a discontinuity */ - if (prev_buf && (prev_pts = GST_BUFFER_TIMESTAMP(prev_buf)) != pts) { - const GstClockTimeDiff pts_diff = GST_CLOCK_DIFF(prev_pts, pts); - if (pts_diff < 0 || (postproc->field_duration > 0 && - pts_diff >= postproc->field_duration * 3 - 1)) - ds_reset(ds); - } + deint_method = postproc->deinterlace_method; + deint_refs = deint_method_is_advanced (deint_method); + if (deint_refs && 0) { + GstBuffer *const prev_buf = ds_get_buffer (ds, 0); + GstClockTime prev_pts, pts = GST_BUFFER_TIMESTAMP (inbuf); + /* Reset deinterlacing state when there is a discontinuity */ + if (prev_buf && (prev_pts = GST_BUFFER_TIMESTAMP (prev_buf)) != pts) { + const GstClockTimeDiff pts_diff = GST_CLOCK_DIFF (prev_pts, pts); + if (pts_diff < 0 || (postproc->field_duration > 0 && + pts_diff >= postproc->field_duration * 3 - 1)) + ds_reset (ds); } + } - ds->deint = deint; - ds->tff = tff; + ds->deint = deint; + ds->tff = tff; - flags = gst_vaapi_video_meta_get_render_flags(inbuf_meta) & - ~GST_VAAPI_PICTURE_STRUCTURE_MASK; + flags = gst_vaapi_video_meta_get_render_flags (inbuf_meta) & + ~GST_VAAPI_PICTURE_STRUCTURE_MASK; - /* First field */ - if (postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE) { - fieldbuf = create_output_buffer(postproc); - if (!fieldbuf) - goto error_create_buffer; + /* First field */ + if (postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE) { + fieldbuf = create_output_buffer (postproc); + if (!fieldbuf) + goto error_create_buffer; - outbuf_meta = gst_buffer_get_vaapi_video_meta(fieldbuf); - if (!outbuf_meta) - goto error_create_meta; - - proxy = gst_vaapi_surface_proxy_new_from_pool( - GST_VAAPI_SURFACE_POOL(postproc->filter_pool)); - if (!proxy) - goto error_create_proxy; - gst_vaapi_video_meta_set_surface_proxy(outbuf_meta, proxy); - gst_vaapi_surface_proxy_unref(proxy); - - if (deint) { - deint_flags = (tff ? GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD : 0); - if (tff) - deint_flags |= GST_VAAPI_DEINTERLACE_FLAG_TFF; - if (!set_best_deint_method(postproc, deint_flags, &deint_method)) - goto error_op_deinterlace; - - if (deint_method != postproc->deinterlace_method) { - GST_DEBUG("unsupported deinterlace-method %u. Using %u instead", - postproc->deinterlace_method, deint_method); - postproc->deinterlace_method = deint_method; - deint_refs = deint_method_is_advanced(deint_method); - } - - if (deint_refs) { - ds_set_surfaces(ds); - if (!gst_vaapi_filter_set_deinterlacing_references( - postproc->filter, ds->surfaces, ds->num_surfaces, - NULL, 0)) - goto error_op_deinterlace; - } - } - else if (deint_changed) { - // Reset internal filter to non-deinterlacing mode - deint_method = GST_VAAPI_DEINTERLACE_METHOD_NONE; - if (!gst_vaapi_filter_set_deinterlacing(postproc->filter, - deint_method, 0)) - goto error_op_deinterlace; - } - - outbuf_surface = gst_vaapi_video_meta_get_surface(outbuf_meta); - gst_vaapi_filter_set_cropping_rectangle(postproc->filter, crop_rect); - status = gst_vaapi_filter_process(postproc->filter, inbuf_surface, - outbuf_surface, flags); - if (status != GST_VAAPI_FILTER_STATUS_SUCCESS) - goto error_process_vpp; - - GST_BUFFER_TIMESTAMP(fieldbuf) = timestamp; - GST_BUFFER_DURATION(fieldbuf) = postproc->field_duration; - ret = gst_pad_push(trans->srcpad, fieldbuf); - if (ret != GST_FLOW_OK) - goto error_push_buffer; - } - fieldbuf = NULL; - - /* Second field */ - outbuf_meta = gst_buffer_get_vaapi_video_meta(outbuf); + outbuf_meta = gst_buffer_get_vaapi_video_meta (fieldbuf); if (!outbuf_meta) - goto error_create_meta; + goto error_create_meta; - proxy = gst_vaapi_surface_proxy_new_from_pool( - GST_VAAPI_SURFACE_POOL(postproc->filter_pool)); + proxy = + gst_vaapi_surface_proxy_new_from_pool (GST_VAAPI_SURFACE_POOL + (postproc->filter_pool)); if (!proxy) - goto error_create_proxy; - gst_vaapi_video_meta_set_surface_proxy(outbuf_meta, proxy); - gst_vaapi_surface_proxy_unref(proxy); + goto error_create_proxy; + gst_vaapi_video_meta_set_surface_proxy (outbuf_meta, proxy); + gst_vaapi_surface_proxy_unref (proxy); if (deint) { - deint_flags = (tff ? 0 : GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD); - if (tff) - deint_flags |= GST_VAAPI_DEINTERLACE_FLAG_TFF; - if (!gst_vaapi_filter_set_deinterlacing(postproc->filter, - deint_method, deint_flags)) - goto error_op_deinterlace; - - if (deint_refs && !gst_vaapi_filter_set_deinterlacing_references( - postproc->filter, ds->surfaces, ds->num_surfaces, NULL, 0)) - goto error_op_deinterlace; - } - else if (deint_changed && !gst_vaapi_filter_set_deinterlacing( - postproc->filter, deint_method, 0)) + deint_flags = (tff ? GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD : 0); + if (tff) + deint_flags |= GST_VAAPI_DEINTERLACE_FLAG_TFF; + if (!set_best_deint_method (postproc, deint_flags, &deint_method)) goto error_op_deinterlace; - outbuf_surface = gst_vaapi_video_meta_get_surface(outbuf_meta); - gst_vaapi_filter_set_cropping_rectangle(postproc->filter, crop_rect); - status = gst_vaapi_filter_process(postproc->filter, inbuf_surface, + if (deint_method != postproc->deinterlace_method) { + GST_DEBUG ("unsupported deinterlace-method %u. Using %u instead", + postproc->deinterlace_method, deint_method); + postproc->deinterlace_method = deint_method; + deint_refs = deint_method_is_advanced (deint_method); + } + + if (deint_refs) { + ds_set_surfaces (ds); + if (!gst_vaapi_filter_set_deinterlacing_references (postproc->filter, + ds->surfaces, ds->num_surfaces, NULL, 0)) + goto error_op_deinterlace; + } + } else if (deint_changed) { + // Reset internal filter to non-deinterlacing mode + deint_method = GST_VAAPI_DEINTERLACE_METHOD_NONE; + if (!gst_vaapi_filter_set_deinterlacing (postproc->filter, + deint_method, 0)) + goto error_op_deinterlace; + } + + outbuf_surface = gst_vaapi_video_meta_get_surface (outbuf_meta); + gst_vaapi_filter_set_cropping_rectangle (postproc->filter, crop_rect); + status = gst_vaapi_filter_process (postproc->filter, inbuf_surface, outbuf_surface, flags); if (status != GST_VAAPI_FILTER_STATUS_SUCCESS) - goto error_process_vpp; + goto error_process_vpp; - if (!(postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE)) - gst_buffer_copy_into(outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1); - else { - GST_BUFFER_TIMESTAMP(outbuf) = timestamp + postproc->field_duration; - GST_BUFFER_DURATION(outbuf) = postproc->field_duration; - } - - if (deint && deint_refs) - ds_add_buffer(ds, inbuf); - postproc->use_vpp = TRUE; - return GST_FLOW_OK; - - /* ERRORS */ -error_invalid_buffer: - { - GST_ERROR("failed to validate source buffer"); - return GST_FLOW_ERROR; - } -error_create_buffer: - { - GST_ERROR("failed to create output buffer"); - return GST_FLOW_ERROR; - } -error_create_meta: - { - GST_ERROR("failed to create new output buffer meta"); - gst_buffer_replace(&fieldbuf, NULL); - return GST_FLOW_ERROR; - } -error_create_proxy: - { - GST_ERROR("failed to create surface proxy from pool"); - gst_buffer_replace(&fieldbuf, NULL); - return GST_FLOW_ERROR; - } -error_op_deinterlace: - { - GST_ERROR("failed to apply deinterlacing filter"); - gst_buffer_replace(&fieldbuf, NULL); - return GST_FLOW_NOT_SUPPORTED; - } -error_process_vpp: - { - GST_ERROR("failed to apply VPP filters (error %d)", status); - gst_buffer_replace(&fieldbuf, NULL); - return GST_FLOW_ERROR; - } -error_push_buffer: - { - if (ret != GST_FLOW_FLUSHING) - GST_ERROR("failed to push output buffer to video sink"); - return GST_FLOW_ERROR; - } -} - -static GstFlowReturn -gst_vaapipostproc_process(GstBaseTransform *trans, GstBuffer *inbuf, - GstBuffer *outbuf) -{ - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans); - GstVaapiVideoMeta *meta; - GstClockTime timestamp; - GstFlowReturn ret; - GstBuffer *fieldbuf; - guint fieldbuf_flags, outbuf_flags, flags; - gboolean tff, deint; - - meta = gst_buffer_get_vaapi_video_meta(inbuf); - if (!meta) - goto error_invalid_buffer; - - timestamp = GST_BUFFER_TIMESTAMP(inbuf); - tff = GST_BUFFER_FLAG_IS_SET(inbuf, GST_VIDEO_BUFFER_FLAG_TFF); - deint = should_deinterlace_buffer(postproc, inbuf); - - flags = gst_vaapi_video_meta_get_render_flags(meta) & - ~GST_VAAPI_PICTURE_STRUCTURE_MASK; - - /* First field */ - fieldbuf = create_output_buffer(postproc); - if (!fieldbuf) - goto error_create_buffer; - append_output_buffer_metadata(postproc, fieldbuf, inbuf, 0); - - meta = gst_buffer_get_vaapi_video_meta(fieldbuf); - fieldbuf_flags = flags; - fieldbuf_flags |= deint ? ( - tff ? - GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD : - GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD) : - GST_VAAPI_PICTURE_STRUCTURE_FRAME; - gst_vaapi_video_meta_set_render_flags(meta, fieldbuf_flags); - - GST_BUFFER_TIMESTAMP(fieldbuf) = timestamp; - GST_BUFFER_DURATION(fieldbuf) = postproc->field_duration; - ret = gst_pad_push(trans->srcpad, fieldbuf); + GST_BUFFER_TIMESTAMP (fieldbuf) = timestamp; + GST_BUFFER_DURATION (fieldbuf) = postproc->field_duration; + ret = gst_pad_push (trans->srcpad, fieldbuf); if (ret != GST_FLOW_OK) - goto error_push_buffer; + goto error_push_buffer; + } + fieldbuf = NULL; - /* Second field */ - append_output_buffer_metadata(postproc, outbuf, inbuf, 0); + /* Second field */ + outbuf_meta = gst_buffer_get_vaapi_video_meta (outbuf); + if (!outbuf_meta) + goto error_create_meta; - meta = gst_buffer_get_vaapi_video_meta(outbuf); - outbuf_flags = flags; - outbuf_flags |= deint ? ( - tff ? - GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD : - GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD) : - GST_VAAPI_PICTURE_STRUCTURE_FRAME; - gst_vaapi_video_meta_set_render_flags(meta, outbuf_flags); + proxy = + gst_vaapi_surface_proxy_new_from_pool (GST_VAAPI_SURFACE_POOL + (postproc->filter_pool)); + if (!proxy) + goto error_create_proxy; + gst_vaapi_video_meta_set_surface_proxy (outbuf_meta, proxy); + gst_vaapi_surface_proxy_unref (proxy); - GST_BUFFER_TIMESTAMP(outbuf) = timestamp + postproc->field_duration; - GST_BUFFER_DURATION(outbuf) = postproc->field_duration; - return GST_FLOW_OK; + if (deint) { + deint_flags = (tff ? 0 : GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD); + if (tff) + deint_flags |= GST_VAAPI_DEINTERLACE_FLAG_TFF; + if (!gst_vaapi_filter_set_deinterlacing (postproc->filter, + deint_method, deint_flags)) + goto error_op_deinterlace; - /* ERRORS */ + if (deint_refs + && !gst_vaapi_filter_set_deinterlacing_references (postproc->filter, + ds->surfaces, ds->num_surfaces, NULL, 0)) + goto error_op_deinterlace; + } else if (deint_changed + && !gst_vaapi_filter_set_deinterlacing (postproc->filter, deint_method, + 0)) + goto error_op_deinterlace; + + outbuf_surface = gst_vaapi_video_meta_get_surface (outbuf_meta); + gst_vaapi_filter_set_cropping_rectangle (postproc->filter, crop_rect); + status = gst_vaapi_filter_process (postproc->filter, inbuf_surface, + outbuf_surface, flags); + if (status != GST_VAAPI_FILTER_STATUS_SUCCESS) + goto error_process_vpp; + + if (!(postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE)) + gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1); + else { + GST_BUFFER_TIMESTAMP (outbuf) = timestamp + postproc->field_duration; + GST_BUFFER_DURATION (outbuf) = postproc->field_duration; + } + + if (deint && deint_refs) + ds_add_buffer (ds, inbuf); + postproc->use_vpp = TRUE; + return GST_FLOW_OK; + + /* ERRORS */ error_invalid_buffer: - { - GST_ERROR("failed to validate source buffer"); - return GST_FLOW_ERROR; - } + { + GST_ERROR ("failed to validate source buffer"); + return GST_FLOW_ERROR; + } error_create_buffer: - { - GST_ERROR("failed to create output buffer"); - return GST_FLOW_EOS; - } + { + GST_ERROR ("failed to create output buffer"); + return GST_FLOW_ERROR; + } +error_create_meta: + { + GST_ERROR ("failed to create new output buffer meta"); + gst_buffer_replace (&fieldbuf, NULL); + return GST_FLOW_ERROR; + } +error_create_proxy: + { + GST_ERROR ("failed to create surface proxy from pool"); + gst_buffer_replace (&fieldbuf, NULL); + return GST_FLOW_ERROR; + } +error_op_deinterlace: + { + GST_ERROR ("failed to apply deinterlacing filter"); + gst_buffer_replace (&fieldbuf, NULL); + return GST_FLOW_NOT_SUPPORTED; + } +error_process_vpp: + { + GST_ERROR ("failed to apply VPP filters (error %d)", status); + gst_buffer_replace (&fieldbuf, NULL); + return GST_FLOW_ERROR; + } error_push_buffer: - { - if (ret != GST_FLOW_FLUSHING) - GST_ERROR("failed to push output buffer to video sink"); - return GST_FLOW_EOS; - } + { + if (ret != GST_FLOW_FLUSHING) + GST_ERROR ("failed to push output buffer to video sink"); + return GST_FLOW_ERROR; + } } static GstFlowReturn -gst_vaapipostproc_passthrough(GstBaseTransform *trans, GstBuffer *inbuf, - GstBuffer *outbuf) +gst_vaapipostproc_process (GstBaseTransform * trans, GstBuffer * inbuf, + GstBuffer * outbuf) { - GstVaapiVideoMeta *meta; + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans); + GstVaapiVideoMeta *meta; + GstClockTime timestamp; + GstFlowReturn ret; + GstBuffer *fieldbuf; + guint fieldbuf_flags, outbuf_flags, flags; + gboolean tff, deint; - /* No video processing needed, simply copy buffer metadata */ - meta = gst_buffer_get_vaapi_video_meta(inbuf); - if (!meta) - goto error_invalid_buffer; + meta = gst_buffer_get_vaapi_video_meta (inbuf); + if (!meta) + goto error_invalid_buffer; - append_output_buffer_metadata(GST_VAAPIPOSTPROC(trans), outbuf, inbuf, - GST_BUFFER_COPY_TIMESTAMPS); - return GST_FLOW_OK; + timestamp = GST_BUFFER_TIMESTAMP (inbuf); + tff = GST_BUFFER_FLAG_IS_SET (inbuf, GST_VIDEO_BUFFER_FLAG_TFF); + deint = should_deinterlace_buffer (postproc, inbuf); - /* ERRORS */ + flags = gst_vaapi_video_meta_get_render_flags (meta) & + ~GST_VAAPI_PICTURE_STRUCTURE_MASK; + + /* First field */ + fieldbuf = create_output_buffer (postproc); + if (!fieldbuf) + goto error_create_buffer; + append_output_buffer_metadata (postproc, fieldbuf, inbuf, 0); + + meta = gst_buffer_get_vaapi_video_meta (fieldbuf); + fieldbuf_flags = flags; + fieldbuf_flags |= deint ? (tff ? + GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD : + GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD) : + GST_VAAPI_PICTURE_STRUCTURE_FRAME; + gst_vaapi_video_meta_set_render_flags (meta, fieldbuf_flags); + + GST_BUFFER_TIMESTAMP (fieldbuf) = timestamp; + GST_BUFFER_DURATION (fieldbuf) = postproc->field_duration; + ret = gst_pad_push (trans->srcpad, fieldbuf); + if (ret != GST_FLOW_OK) + goto error_push_buffer; + + /* Second field */ + append_output_buffer_metadata (postproc, outbuf, inbuf, 0); + + meta = gst_buffer_get_vaapi_video_meta (outbuf); + outbuf_flags = flags; + outbuf_flags |= deint ? (tff ? + GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD : + GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD) : + GST_VAAPI_PICTURE_STRUCTURE_FRAME; + gst_vaapi_video_meta_set_render_flags (meta, outbuf_flags); + + GST_BUFFER_TIMESTAMP (outbuf) = timestamp + postproc->field_duration; + GST_BUFFER_DURATION (outbuf) = postproc->field_duration; + return GST_FLOW_OK; + + /* ERRORS */ error_invalid_buffer: - { - GST_ERROR("failed to validate source buffer"); - return GST_FLOW_ERROR; - } + { + GST_ERROR ("failed to validate source buffer"); + return GST_FLOW_ERROR; + } +error_create_buffer: + { + GST_ERROR ("failed to create output buffer"); + return GST_FLOW_EOS; + } +error_push_buffer: + { + if (ret != GST_FLOW_FLUSHING) + GST_ERROR ("failed to push output buffer to video sink"); + return GST_FLOW_EOS; + } +} + +static GstFlowReturn +gst_vaapipostproc_passthrough (GstBaseTransform * trans, GstBuffer * inbuf, + GstBuffer * outbuf) +{ + GstVaapiVideoMeta *meta; + + /* No video processing needed, simply copy buffer metadata */ + meta = gst_buffer_get_vaapi_video_meta (inbuf); + if (!meta) + goto error_invalid_buffer; + + append_output_buffer_metadata (GST_VAAPIPOSTPROC (trans), outbuf, inbuf, + GST_BUFFER_COPY_TIMESTAMPS); + return GST_FLOW_OK; + + /* ERRORS */ +error_invalid_buffer: + { + GST_ERROR ("failed to validate source buffer"); + return GST_FLOW_ERROR; + } } static gboolean -is_deinterlace_enabled(GstVaapiPostproc *postproc, GstVideoInfo *vip) +is_deinterlace_enabled (GstVaapiPostproc * postproc, GstVideoInfo * vip) { - gboolean deinterlace; + gboolean deinterlace; - switch (postproc->deinterlace_mode) { + switch (postproc->deinterlace_mode) { case GST_VAAPI_DEINTERLACE_MODE_AUTO: - deinterlace = GST_VIDEO_INFO_IS_INTERLACED(vip); - break; + deinterlace = GST_VIDEO_INFO_IS_INTERLACED (vip); + break; case GST_VAAPI_DEINTERLACE_MODE_INTERLACED: - deinterlace = TRUE; - break; + deinterlace = TRUE; + break; default: - deinterlace = FALSE; - break; - } - return deinterlace; + deinterlace = FALSE; + break; + } + return deinterlace; } static gboolean -video_info_changed(GstVideoInfo *old_vip, GstVideoInfo *new_vip) +video_info_changed (GstVideoInfo * old_vip, GstVideoInfo * new_vip) { - if (GST_VIDEO_INFO_FORMAT(old_vip) != GST_VIDEO_INFO_FORMAT(new_vip)) - return TRUE; - if (GST_VIDEO_INFO_INTERLACE_MODE(old_vip) != - GST_VIDEO_INFO_INTERLACE_MODE(new_vip)) - return TRUE; - if (GST_VIDEO_INFO_WIDTH(old_vip) != GST_VIDEO_INFO_WIDTH(new_vip)) - return TRUE; - if (GST_VIDEO_INFO_HEIGHT(old_vip) != GST_VIDEO_INFO_HEIGHT(new_vip)) - return TRUE; + if (GST_VIDEO_INFO_FORMAT (old_vip) != GST_VIDEO_INFO_FORMAT (new_vip)) + return TRUE; + if (GST_VIDEO_INFO_INTERLACE_MODE (old_vip) != + GST_VIDEO_INFO_INTERLACE_MODE (new_vip)) + return TRUE; + if (GST_VIDEO_INFO_WIDTH (old_vip) != GST_VIDEO_INFO_WIDTH (new_vip)) + return TRUE; + if (GST_VIDEO_INFO_HEIGHT (old_vip) != GST_VIDEO_INFO_HEIGHT (new_vip)) + return TRUE; + return FALSE; +} + +static gboolean +gst_vaapipostproc_update_sink_caps (GstVaapiPostproc * postproc, GstCaps * caps, + gboolean * caps_changed_ptr) +{ + GstVideoInfo vi; + gboolean deinterlace; + + if (!gst_video_info_from_caps (&vi, caps)) return FALSE; + + if (video_info_changed (&vi, &postproc->sinkpad_info)) + postproc->sinkpad_info = vi, *caps_changed_ptr = TRUE; + + deinterlace = is_deinterlace_enabled (postproc, &vi); + if (deinterlace) + postproc->flags |= GST_VAAPI_POSTPROC_FLAG_DEINTERLACE; + postproc->field_duration = GST_VIDEO_INFO_FPS_N (&vi) > 0 ? + gst_util_uint64_scale (GST_SECOND, GST_VIDEO_INFO_FPS_D (&vi), + (1 + deinterlace) * GST_VIDEO_INFO_FPS_N (&vi)) : 0; + + postproc->get_va_surfaces = gst_caps_has_vaapi_surface (caps); + return TRUE; } static gboolean -gst_vaapipostproc_update_sink_caps(GstVaapiPostproc *postproc, GstCaps *caps, - gboolean *caps_changed_ptr) +gst_vaapipostproc_update_src_caps (GstVaapiPostproc * postproc, GstCaps * caps, + gboolean * caps_changed_ptr) { - GstVideoInfo vi; - gboolean deinterlace; + GstVideoInfo vi; - if (!gst_video_info_from_caps(&vi, caps)) - return FALSE; + if (!gst_video_info_from_caps (&vi, caps)) + return FALSE; - if (video_info_changed(&vi, &postproc->sinkpad_info)) - postproc->sinkpad_info = vi, *caps_changed_ptr = TRUE; + if (video_info_changed (&vi, &postproc->srcpad_info)) + postproc->srcpad_info = vi, *caps_changed_ptr = TRUE; - deinterlace = is_deinterlace_enabled(postproc, &vi); - if (deinterlace) - postproc->flags |= GST_VAAPI_POSTPROC_FLAG_DEINTERLACE; - postproc->field_duration = GST_VIDEO_INFO_FPS_N(&vi) > 0 ? - gst_util_uint64_scale(GST_SECOND, GST_VIDEO_INFO_FPS_D(&vi), - (1 + deinterlace) * GST_VIDEO_INFO_FPS_N(&vi)) : 0; + if (postproc->format != GST_VIDEO_INFO_FORMAT (&postproc->sinkpad_info) && + postproc->format != DEFAULT_FORMAT) + postproc->flags |= GST_VAAPI_POSTPROC_FLAG_FORMAT; - postproc->get_va_surfaces = gst_caps_has_vaapi_surface(caps); - return TRUE; + if ((postproc->width || postproc->height) && + postproc->width != GST_VIDEO_INFO_WIDTH (&postproc->sinkpad_info) && + postproc->height != GST_VIDEO_INFO_HEIGHT (&postproc->sinkpad_info)) + postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SIZE; + return TRUE; } static gboolean -gst_vaapipostproc_update_src_caps(GstVaapiPostproc *postproc, GstCaps *caps, - gboolean *caps_changed_ptr) +ensure_allowed_sinkpad_caps (GstVaapiPostproc * postproc) { - GstVideoInfo vi; + GstCaps *out_caps, *raw_caps; - if (!gst_video_info_from_caps(&vi, caps)) - return FALSE; - - if (video_info_changed(&vi, &postproc->srcpad_info)) - postproc->srcpad_info = vi, *caps_changed_ptr = TRUE; - - if (postproc->format != GST_VIDEO_INFO_FORMAT(&postproc->sinkpad_info) && - postproc->format != DEFAULT_FORMAT) - postproc->flags |= GST_VAAPI_POSTPROC_FLAG_FORMAT; - - if ((postproc->width || postproc->height) && - postproc->width != GST_VIDEO_INFO_WIDTH(&postproc->sinkpad_info) && - postproc->height != GST_VIDEO_INFO_HEIGHT(&postproc->sinkpad_info)) - postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SIZE; + if (postproc->allowed_sinkpad_caps) return TRUE; -} -static gboolean -ensure_allowed_sinkpad_caps(GstVaapiPostproc *postproc) -{ - GstCaps *out_caps, *raw_caps; + /* Create VA caps */ + out_caps = gst_caps_from_string (GST_VAAPIPOSTPROC_SURFACE_CAPS ", " + GST_CAPS_INTERLACED_MODES); + if (!out_caps) { + GST_ERROR ("failed to create VA sink caps"); + return FALSE; + } - if (postproc->allowed_sinkpad_caps) - return TRUE; + /* Append raw video caps */ + if (gst_vaapipostproc_ensure_uploader (postproc)) { + raw_caps = GST_VAAPI_PLUGIN_BASE_UPLOADER_CAPS (postproc); + if (raw_caps) { + out_caps = gst_caps_make_writable (out_caps); + gst_caps_append (out_caps, gst_caps_copy (raw_caps)); + } else + GST_WARNING ("failed to create YUV sink caps"); + } + postproc->allowed_sinkpad_caps = out_caps; - /* Create VA caps */ - out_caps = gst_caps_from_string(GST_VAAPIPOSTPROC_SURFACE_CAPS ", " - GST_CAPS_INTERLACED_MODES); - if (!out_caps) { - GST_ERROR("failed to create VA sink caps"); - return FALSE; - } - - /* Append raw video caps */ - if (gst_vaapipostproc_ensure_uploader(postproc)) { - raw_caps = GST_VAAPI_PLUGIN_BASE_UPLOADER_CAPS(postproc); - if (raw_caps) { - out_caps = gst_caps_make_writable(out_caps); - gst_caps_append(out_caps, gst_caps_copy(raw_caps)); - } - else - GST_WARNING("failed to create YUV sink caps"); - } - postproc->allowed_sinkpad_caps = out_caps; - - /* XXX: append VA/VPP filters */ - return TRUE; + /* XXX: append VA/VPP filters */ + return TRUE; } /* Fixup output caps so that to reflect the supported set of pixel formats */ static GstCaps * -expand_allowed_srcpad_caps(GstVaapiPostproc *postproc, GstCaps *caps) +expand_allowed_srcpad_caps (GstVaapiPostproc * postproc, GstCaps * caps) { - GValue value = G_VALUE_INIT, v_format = G_VALUE_INIT; - guint i, num_structures; - gboolean had_filter; + GValue value = G_VALUE_INIT, v_format = G_VALUE_INIT; + guint i, num_structures; + gboolean had_filter; - had_filter = postproc->filter != NULL; - if (!had_filter && !gst_vaapipostproc_ensure_filter(postproc)) - goto cleanup; - if (!gst_vaapipostproc_ensure_filter_caps(postproc)) - goto cleanup; + had_filter = postproc->filter != NULL; + if (!had_filter && !gst_vaapipostproc_ensure_filter (postproc)) + goto cleanup; + if (!gst_vaapipostproc_ensure_filter_caps (postproc)) + goto cleanup; - /* Reset "format" field for each structure */ - if (!gst_vaapi_value_set_format_list(&value, postproc->filter_formats)) - goto cleanup; - if (gst_vaapi_value_set_format(&v_format, GST_VIDEO_FORMAT_ENCODED)) { - gst_value_list_prepend_value(&value, &v_format); - g_value_unset(&v_format); - } + /* Reset "format" field for each structure */ + if (!gst_vaapi_value_set_format_list (&value, postproc->filter_formats)) + goto cleanup; + if (gst_vaapi_value_set_format (&v_format, GST_VIDEO_FORMAT_ENCODED)) { + gst_value_list_prepend_value (&value, &v_format); + g_value_unset (&v_format); + } - num_structures = gst_caps_get_size(caps); - for (i = 0; i < num_structures; i++) { + num_structures = gst_caps_get_size (caps); + for (i = 0; i < num_structures; i++) { #if GST_CHECK_VERSION(1,1,0) - GstCapsFeatures * const features = gst_caps_get_features (caps, i); - if (gst_caps_features_contains(features, - GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META)) - continue; + GstCapsFeatures *const features = gst_caps_get_features (caps, i); + if (gst_caps_features_contains (features, + GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META)) + continue; #endif - GstStructure * const structure = gst_caps_get_structure(caps, i); - if (!structure) - continue; - gst_structure_set_value(structure, "format", &value); - } - g_value_unset(&value); + GstStructure *const structure = gst_caps_get_structure (caps, i); + if (!structure) + continue; + gst_structure_set_value (structure, "format", &value); + } + g_value_unset (&value); cleanup: - if (!had_filter) - gst_vaapipostproc_destroy_filter(postproc); - return caps; + if (!had_filter) + gst_vaapipostproc_destroy_filter (postproc); + return caps; } static gboolean -ensure_allowed_srcpad_caps(GstVaapiPostproc *postproc) +ensure_allowed_srcpad_caps (GstVaapiPostproc * postproc) { - GstCaps *out_caps; + GstCaps *out_caps; - if (postproc->allowed_srcpad_caps) - return TRUE; + if (postproc->allowed_srcpad_caps) + return TRUE; - /* Create initial caps from pad template */ - out_caps = gst_caps_from_string(gst_vaapipostproc_src_caps_str); - if (!out_caps) { - GST_ERROR("failed to create VA src caps"); - return FALSE; - } + /* Create initial caps from pad template */ + out_caps = gst_caps_from_string (gst_vaapipostproc_src_caps_str); + if (!out_caps) { + GST_ERROR ("failed to create VA src caps"); + return FALSE; + } - postproc->allowed_srcpad_caps = - expand_allowed_srcpad_caps(postproc, out_caps); - return postproc->allowed_srcpad_caps != NULL; + postproc->allowed_srcpad_caps = + expand_allowed_srcpad_caps (postproc, out_caps); + return postproc->allowed_srcpad_caps != NULL; } static void -find_best_size(GstVaapiPostproc *postproc, GstVideoInfo *vip, - guint *width_ptr, guint *height_ptr) +find_best_size (GstVaapiPostproc * postproc, GstVideoInfo * vip, + guint * width_ptr, guint * height_ptr) { - guint width, height; + guint width, height; - width = GST_VIDEO_INFO_WIDTH(vip); - height = GST_VIDEO_INFO_HEIGHT(vip); - if (postproc->width && postproc->height) { - width = postproc->width; - height = postproc->height; + width = GST_VIDEO_INFO_WIDTH (vip); + height = GST_VIDEO_INFO_HEIGHT (vip); + if (postproc->width && postproc->height) { + width = postproc->width; + height = postproc->height; + } else if (postproc->keep_aspect) { + const gdouble ratio = (gdouble) width / height; + if (postproc->width) { + width = postproc->width; + height = postproc->width / ratio; + } else if (postproc->height) { + height = postproc->height; + width = postproc->height * ratio; } - else if (postproc->keep_aspect) { - const gdouble ratio = (gdouble)width / height; - if (postproc->width) { - width = postproc->width; - height = postproc->width / ratio; - } - else if (postproc->height) { - height = postproc->height; - width = postproc->height * ratio; - } - } - else if (postproc->width) - width = postproc->width; - else if (postproc->height) - height = postproc->height; + } else if (postproc->width) + width = postproc->width; + else if (postproc->height) + height = postproc->height; - *width_ptr = width; - *height_ptr = height; + *width_ptr = width; + *height_ptr = height; } static GstCaps * -gst_vaapipostproc_transform_caps_impl(GstBaseTransform *trans, - GstPadDirection direction, GstCaps *caps) +gst_vaapipostproc_transform_caps_impl (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps) { - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans); - GstVideoInfo vi; - GstVideoFormat format, out_format; - GstCaps *out_caps; + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans); + GstVideoInfo vi; + GstVideoFormat format, out_format; + GstCaps *out_caps; #if GST_CHECK_VERSION(1,1,0) - GstVaapiCapsFeature feature; - const gchar *feature_str; + GstVaapiCapsFeature feature; + const gchar *feature_str; #endif - guint width, height; + guint width, height; - /* Generate the sink pad caps, that could be fixated afterwards */ - if (direction == GST_PAD_SRC) { - if (!ensure_allowed_sinkpad_caps(postproc)) - return NULL; - return gst_caps_ref(postproc->allowed_sinkpad_caps); - } + /* Generate the sink pad caps, that could be fixated afterwards */ + if (direction == GST_PAD_SRC) { + if (!ensure_allowed_sinkpad_caps (postproc)) + return NULL; + return gst_caps_ref (postproc->allowed_sinkpad_caps); + } - /* Generate complete set of src pad caps if non-fixated sink pad - caps are provided */ - if (!gst_caps_is_fixed(caps)) { - if (!ensure_allowed_srcpad_caps(postproc)) - return NULL; - return gst_caps_ref(postproc->allowed_srcpad_caps); - } + /* Generate complete set of src pad caps if non-fixated sink pad + caps are provided */ + if (!gst_caps_is_fixed (caps)) { + if (!ensure_allowed_srcpad_caps (postproc)) + return NULL; + return gst_caps_ref (postproc->allowed_srcpad_caps); + } - /* Generate the expected src pad caps, from the current fixated - sink pad caps */ - if (!gst_video_info_from_caps(&vi, caps)) - return NULL; + /* Generate the expected src pad caps, from the current fixated + sink pad caps */ + if (!gst_video_info_from_caps (&vi, caps)) + return NULL; - // Set double framerate in interlaced mode - if (is_deinterlace_enabled(postproc, &vi)) { - gint fps_n = GST_VIDEO_INFO_FPS_N(&vi); - gint fps_d = GST_VIDEO_INFO_FPS_D(&vi); - if (!gst_util_fraction_multiply(fps_n, fps_d, 2, 1, &fps_n, &fps_d)) - return NULL; - GST_VIDEO_INFO_FPS_N(&vi) = fps_n; - GST_VIDEO_INFO_FPS_D(&vi) = fps_d; - } + // Set double framerate in interlaced mode + if (is_deinterlace_enabled (postproc, &vi)) { + gint fps_n = GST_VIDEO_INFO_FPS_N (&vi); + gint fps_d = GST_VIDEO_INFO_FPS_D (&vi); + if (!gst_util_fraction_multiply (fps_n, fps_d, 2, 1, &fps_n, &fps_d)) + return NULL; + GST_VIDEO_INFO_FPS_N (&vi) = fps_n; + GST_VIDEO_INFO_FPS_D (&vi) = fps_d; + } - // Signal the other pad that we only generate progressive frames - GST_VIDEO_INFO_INTERLACE_MODE(&vi) = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE; + // Signal the other pad that we only generate progressive frames + GST_VIDEO_INFO_INTERLACE_MODE (&vi) = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE; - // Update size from user-specified parameters - format = GST_VIDEO_INFO_FORMAT(&vi); + // Update size from user-specified parameters + format = GST_VIDEO_INFO_FORMAT (&vi); #if GST_CHECK_VERSION(1,1,0) - /* XXX: this is a workaround until auto-plugging is fixed when - * format=ENCODED + memory:VASurface caps feature are provided. - * use the downstream negotiated video format as the output format - * if the user didn't explicitly ask for colorspace conversion. - * Use a filter caps which contain all raw video formats, (excluding - * GST_VIDEO_FORMAT_ENCODED) */ - if (postproc->format != DEFAULT_FORMAT) - out_format = postproc->format; - else { - GstCaps *peer_caps, *filter_caps; - GstVideoInfo peer_vi; - filter_caps = gst_caps_from_string (GST_VIDEO_CAPS_MAKE(GST_VIDEO_FORMATS_ALL)); - peer_caps = gst_pad_peer_query_caps( - GST_BASE_TRANSFORM_SRC_PAD(trans), filter_caps); - if (!gst_caps_is_fixed(peer_caps)) - peer_caps = gst_caps_fixate (peer_caps); - gst_video_info_from_caps(&peer_vi, peer_caps); - out_format = GST_VIDEO_INFO_FORMAT (&peer_vi); - gst_caps_unref (filter_caps); - if (peer_caps) - gst_caps_unref (peer_caps); - } + /* XXX: this is a workaround until auto-plugging is fixed when + * format=ENCODED + memory:VASurface caps feature are provided. + * use the downstream negotiated video format as the output format + * if the user didn't explicitly ask for colorspace conversion. + * Use a filter caps which contain all raw video formats, (excluding + * GST_VIDEO_FORMAT_ENCODED) */ + if (postproc->format != DEFAULT_FORMAT) + out_format = postproc->format; + else { + GstCaps *peer_caps, *filter_caps; + GstVideoInfo peer_vi; + filter_caps = + gst_caps_from_string (GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL)); + peer_caps = + gst_pad_peer_query_caps (GST_BASE_TRANSFORM_SRC_PAD (trans), + filter_caps); + if (!gst_caps_is_fixed (peer_caps)) + peer_caps = gst_caps_fixate (peer_caps); + gst_video_info_from_caps (&peer_vi, peer_caps); + out_format = GST_VIDEO_INFO_FORMAT (&peer_vi); + gst_caps_unref (filter_caps); + if (peer_caps) + gst_caps_unref (peer_caps); + } #else - out_format = GST_VIDEO_FORMAT_ENCODED; + out_format = GST_VIDEO_FORMAT_ENCODED; #endif - find_best_size(postproc, &vi, &width, &height); - gst_video_info_change_format(&vi, out_format, width, height); + find_best_size (postproc, &vi, &width, &height); + gst_video_info_change_format (&vi, out_format, width, height); #if GST_CHECK_VERSION(1,1,0) - out_caps = gst_video_info_to_caps(&vi); - if (!out_caps) - return NULL; + out_caps = gst_video_info_to_caps (&vi); + if (!out_caps) + return NULL; - feature = gst_vaapi_find_preferred_caps_feature( - GST_BASE_TRANSFORM_SRC_PAD(trans), out_format); - if (feature) { - feature_str = gst_vaapi_caps_feature_to_string(feature); + feature = + gst_vaapi_find_preferred_caps_feature (GST_BASE_TRANSFORM_SRC_PAD (trans), + out_format); + if (feature) { + feature_str = gst_vaapi_caps_feature_to_string (feature); + if (feature_str) + gst_caps_set_features (out_caps, 0, + gst_caps_features_new (feature_str, NULL)); + + if (out_format == GST_VIDEO_FORMAT_ENCODED && + feature != GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE) { + GstCaps *sink_caps, *peer_caps = + gst_pad_peer_query_caps (GST_BASE_TRANSFORM_SRC_PAD (trans), + postproc->allowed_srcpad_caps); + + if (feature == GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META) + format = GST_VIDEO_FORMAT_RGBA; + + gst_video_info_change_format (&vi, format, width, height); + sink_caps = gst_video_info_to_caps (&vi); + if (sink_caps) { if (feature_str) - gst_caps_set_features(out_caps, 0, - gst_caps_features_new(feature_str, NULL)); - - if (out_format == GST_VIDEO_FORMAT_ENCODED && - feature != GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE) { - GstCaps *sink_caps, *peer_caps = - gst_pad_peer_query_caps(GST_BASE_TRANSFORM_SRC_PAD(trans), - postproc->allowed_srcpad_caps); - - if (feature == GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META) - format = GST_VIDEO_FORMAT_RGBA; - - gst_video_info_change_format(&vi, format, width, height); - sink_caps = gst_video_info_to_caps(&vi); - if (sink_caps) { - if (feature_str) - gst_caps_set_features(sink_caps, 0, - gst_caps_features_new(feature_str, NULL)); - if (gst_caps_can_intersect(peer_caps, sink_caps)) - gst_caps_set_simple(out_caps, "format", G_TYPE_STRING, - gst_video_format_to_string(format), NULL); - gst_caps_unref(sink_caps); - } - gst_caps_unref(peer_caps); - } + gst_caps_set_features (sink_caps, 0, + gst_caps_features_new (feature_str, NULL)); + if (gst_caps_can_intersect (peer_caps, sink_caps)) + gst_caps_set_simple (out_caps, "format", G_TYPE_STRING, + gst_video_format_to_string (format), NULL); + gst_caps_unref (sink_caps); + } + gst_caps_unref (peer_caps); } + } #else - /* XXX: gst_video_info_to_caps() from GStreamer 0.10 does not - reconstruct suitable caps for "encoded" video formats */ - out_caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS_NAME); - if (!out_caps) - return NULL; + /* XXX: gst_video_info_to_caps() from GStreamer 0.10 does not + reconstruct suitable caps for "encoded" video formats */ + out_caps = gst_caps_from_string (GST_VAAPI_SURFACE_CAPS_NAME); + if (!out_caps) + return NULL; - gst_caps_set_simple(out_caps, - "type", G_TYPE_STRING, "vaapi", - "opengl", G_TYPE_BOOLEAN, USE_GLX, - "width", G_TYPE_INT, GST_VIDEO_INFO_WIDTH(&vi), - "height", G_TYPE_INT, GST_VIDEO_INFO_HEIGHT(&vi), - "framerate", GST_TYPE_FRACTION, GST_VIDEO_INFO_FPS_N(&vi), - GST_VIDEO_INFO_FPS_D(&vi), - "pixel-aspect-ratio", GST_TYPE_FRACTION, GST_VIDEO_INFO_PAR_N(&vi), - GST_VIDEO_INFO_PAR_D(&vi), - NULL); + gst_caps_set_simple (out_caps, + "type", G_TYPE_STRING, "vaapi", + "opengl", G_TYPE_BOOLEAN, USE_GLX, + "width", G_TYPE_INT, GST_VIDEO_INFO_WIDTH (&vi), + "height", G_TYPE_INT, GST_VIDEO_INFO_HEIGHT (&vi), + "framerate", GST_TYPE_FRACTION, GST_VIDEO_INFO_FPS_N (&vi), + GST_VIDEO_INFO_FPS_D (&vi), + "pixel-aspect-ratio", GST_TYPE_FRACTION, GST_VIDEO_INFO_PAR_N (&vi), + GST_VIDEO_INFO_PAR_D (&vi), NULL); - gst_caps_set_interlaced(out_caps, &vi); + gst_caps_set_interlaced (out_caps, &vi); #endif - return out_caps; + return out_caps; } #if GST_CHECK_VERSION(1,0,0) static GstCaps * -gst_vaapipostproc_transform_caps(GstBaseTransform *trans, - GstPadDirection direction, GstCaps *caps, GstCaps *filter) +gst_vaapipostproc_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, GstCaps * filter) { - GstCaps *out_caps; + GstCaps *out_caps; - caps = gst_vaapipostproc_transform_caps_impl(trans, direction, caps); - if (caps && filter) { - out_caps = gst_caps_intersect_full(caps, filter, - GST_CAPS_INTERSECT_FIRST); - gst_caps_unref(caps); - return out_caps; - } - return caps; + caps = gst_vaapipostproc_transform_caps_impl (trans, direction, caps); + if (caps && filter) { + out_caps = gst_caps_intersect_full (caps, filter, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (caps); + return out_caps; + } + return caps; } #else #define gst_vaapipostproc_transform_caps \ @@ -1242,531 +1234,521 @@ typedef guint GstBaseTransformSizeType; #endif static gboolean -gst_vaapipostproc_transform_size(GstBaseTransform *trans, - GstPadDirection direction, GstCaps *caps, GstBaseTransformSizeType size, - GstCaps *othercaps, GstBaseTransformSizeType *othersize) +gst_vaapipostproc_transform_size (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps, GstBaseTransformSizeType size, + GstCaps * othercaps, GstBaseTransformSizeType * othersize) { - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans); + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans); - if (direction == GST_PAD_SINK || postproc->get_va_surfaces) - *othersize = 0; - else - *othersize = size; - return TRUE; + if (direction == GST_PAD_SINK || postproc->get_va_surfaces) + *othersize = 0; + else + *othersize = size; + return TRUE; } static GstFlowReturn -gst_vaapipostproc_transform(GstBaseTransform *trans, GstBuffer *inbuf, - GstBuffer *outbuf) +gst_vaapipostproc_transform (GstBaseTransform * trans, GstBuffer * inbuf, + GstBuffer * outbuf) { - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans); - GstBuffer *buf; - GstFlowReturn ret; + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans); + GstBuffer *buf; + GstFlowReturn ret; - ret = gst_vaapi_plugin_base_get_input_buffer( - GST_VAAPI_PLUGIN_BASE(postproc), inbuf, &buf); - if (ret != GST_FLOW_OK) - return GST_FLOW_ERROR; + ret = + gst_vaapi_plugin_base_get_input_buffer (GST_VAAPI_PLUGIN_BASE (postproc), + inbuf, &buf); + if (ret != GST_FLOW_OK) + return GST_FLOW_ERROR; - ret = GST_FLOW_NOT_SUPPORTED; - if (postproc->flags) { - /* Use VA/VPP extensions to process this frame */ - if (postproc->has_vpp && - (postproc->flags != GST_VAAPI_POSTPROC_FLAG_DEINTERLACE || - deint_method_is_advanced(postproc->deinterlace_method))) { - ret = gst_vaapipostproc_process_vpp(trans, buf, outbuf); - if (ret != GST_FLOW_NOT_SUPPORTED) - goto done; - GST_WARNING("unsupported VPP filters. Disabling"); - } - - /* Only append picture structure meta data (top/bottom field) */ - if (postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE) { - ret = gst_vaapipostproc_process(trans, buf, outbuf); - if (ret != GST_FLOW_NOT_SUPPORTED) - goto done; - } + ret = GST_FLOW_NOT_SUPPORTED; + if (postproc->flags) { + /* Use VA/VPP extensions to process this frame */ + if (postproc->has_vpp && + (postproc->flags != GST_VAAPI_POSTPROC_FLAG_DEINTERLACE || + deint_method_is_advanced (postproc->deinterlace_method))) { + ret = gst_vaapipostproc_process_vpp (trans, buf, outbuf); + if (ret != GST_FLOW_NOT_SUPPORTED) + goto done; + GST_WARNING ("unsupported VPP filters. Disabling"); } - /* Fallback: passthrough to the downstream element as is */ - ret = gst_vaapipostproc_passthrough(trans, buf, outbuf); + /* Only append picture structure meta data (top/bottom field) */ + if (postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE) { + ret = gst_vaapipostproc_process (trans, buf, outbuf); + if (ret != GST_FLOW_NOT_SUPPORTED) + goto done; + } + } + + /* Fallback: passthrough to the downstream element as is */ + ret = gst_vaapipostproc_passthrough (trans, buf, outbuf); done: - gst_buffer_unref(buf); - return ret; + gst_buffer_unref (buf); + return ret; } static GstFlowReturn -gst_vaapipostproc_prepare_output_buffer(GstBaseTransform *trans, - GstBuffer *inbuf, +gst_vaapipostproc_prepare_output_buffer (GstBaseTransform * trans, + GstBuffer * inbuf, #if !GST_CHECK_VERSION(1,0,0) - gint size, GstCaps *caps, + gint size, GstCaps * caps, #endif - GstBuffer **outbuf_ptr) + GstBuffer ** outbuf_ptr) { - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans); + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans); - *outbuf_ptr = create_output_buffer(postproc); - return *outbuf_ptr ? GST_FLOW_OK : GST_FLOW_ERROR; + *outbuf_ptr = create_output_buffer (postproc); + return *outbuf_ptr ? GST_FLOW_OK : GST_FLOW_ERROR; } static gboolean -ensure_srcpad_buffer_pool(GstVaapiPostproc *postproc, GstCaps *caps) +ensure_srcpad_buffer_pool (GstVaapiPostproc * postproc, GstCaps * caps) { - GstVideoInfo vi; - GstVaapiVideoPool *pool; + GstVideoInfo vi; + GstVaapiVideoPool *pool; - gst_video_info_init(&vi); - gst_video_info_from_caps(&vi, caps); - gst_video_info_change_format(&vi, postproc->format, - GST_VIDEO_INFO_WIDTH(&vi), GST_VIDEO_INFO_HEIGHT(&vi)); + gst_video_info_init (&vi); + gst_video_info_from_caps (&vi, caps); + gst_video_info_change_format (&vi, postproc->format, + GST_VIDEO_INFO_WIDTH (&vi), GST_VIDEO_INFO_HEIGHT (&vi)); - if (postproc->filter_pool && !video_info_changed(&vi, &postproc->filter_pool_info)) - return TRUE; - postproc->filter_pool_info = vi; - - pool = gst_vaapi_surface_pool_new(GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc), - &postproc->filter_pool_info); - if (!pool) - return FALSE; - - gst_vaapi_video_pool_replace(&postproc->filter_pool, pool); - gst_vaapi_video_pool_unref(pool); + if (postproc->filter_pool + && !video_info_changed (&vi, &postproc->filter_pool_info)) return TRUE; + postproc->filter_pool_info = vi; + + pool = gst_vaapi_surface_pool_new (GST_VAAPI_PLUGIN_BASE_DISPLAY (postproc), + &postproc->filter_pool_info); + if (!pool) + return FALSE; + + gst_vaapi_video_pool_replace (&postproc->filter_pool, pool); + gst_vaapi_video_pool_unref (pool); + return TRUE; } static gboolean -gst_vaapipostproc_set_caps(GstBaseTransform *trans, GstCaps *caps, - GstCaps *out_caps) +gst_vaapipostproc_set_caps (GstBaseTransform * trans, GstCaps * caps, + GstCaps * out_caps) { - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans); - gboolean caps_changed = FALSE; + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans); + gboolean caps_changed = FALSE; - if (!gst_vaapipostproc_update_sink_caps(postproc, caps, &caps_changed)) - return FALSE; - if (!gst_vaapipostproc_update_src_caps(postproc, out_caps, &caps_changed)) - return FALSE; + if (!gst_vaapipostproc_update_sink_caps (postproc, caps, &caps_changed)) + return FALSE; + if (!gst_vaapipostproc_update_src_caps (postproc, out_caps, &caps_changed)) + return FALSE; - if (caps_changed) { - gst_vaapipostproc_destroy(postproc); - if (!gst_vaapipostproc_create(postproc)) - return FALSE; - if (!gst_vaapi_plugin_base_set_caps(GST_VAAPI_PLUGIN_BASE(trans), - caps, out_caps)) - return FALSE; - } + if (caps_changed) { + gst_vaapipostproc_destroy (postproc); + if (!gst_vaapipostproc_create (postproc)) + return FALSE; + if (!gst_vaapi_plugin_base_set_caps (GST_VAAPI_PLUGIN_BASE (trans), + caps, out_caps)) + return FALSE; + } - if (!ensure_srcpad_buffer_pool(postproc, out_caps)) - return FALSE; + if (!ensure_srcpad_buffer_pool (postproc, out_caps)) + return FALSE; + return TRUE; +} + +static gboolean +gst_vaapipostproc_query (GstBaseTransform * trans, GstPadDirection direction, + GstQuery * query) +{ + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans); + + GST_INFO_OBJECT (trans, "query type `%s'", GST_QUERY_TYPE_NAME (query)); + + if (gst_vaapi_reply_to_query (query, + GST_VAAPI_PLUGIN_BASE_DISPLAY (postproc))) { + GST_DEBUG ("sharing display %p", GST_VAAPI_PLUGIN_BASE_DISPLAY (postproc)); return TRUE; -} + } -static gboolean -gst_vaapipostproc_query(GstBaseTransform *trans, GstPadDirection direction, - GstQuery *query) -{ - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans); - - GST_INFO_OBJECT(trans, "query type `%s'", GST_QUERY_TYPE_NAME(query)); - - if (gst_vaapi_reply_to_query(query, GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc))) { - GST_DEBUG("sharing display %p", GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc)); - return TRUE; - } - - return GST_BASE_TRANSFORM_CLASS(gst_vaapipostproc_parent_class)->query( - trans, direction, query); + return + GST_BASE_TRANSFORM_CLASS (gst_vaapipostproc_parent_class)->query (trans, + direction, query); } #if GST_CHECK_VERSION(1,0,0) static gboolean -gst_vaapipostproc_propose_allocation(GstBaseTransform *trans, - GstQuery *decide_query, GstQuery *query) +gst_vaapipostproc_propose_allocation (GstBaseTransform * trans, + GstQuery * decide_query, GstQuery * query) { - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans); - GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(trans); + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans); + GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (trans); - /* Let vaapidecode allocate the video buffers */ - if (postproc->get_va_surfaces) - return FALSE; - if (!gst_vaapi_plugin_base_propose_allocation(plugin, query)) - return FALSE; - return TRUE; + /* Let vaapidecode allocate the video buffers */ + if (postproc->get_va_surfaces) + return FALSE; + if (!gst_vaapi_plugin_base_propose_allocation (plugin, query)) + return FALSE; + return TRUE; } static gboolean -gst_vaapipostproc_decide_allocation(GstBaseTransform *trans, GstQuery *query) +gst_vaapipostproc_decide_allocation (GstBaseTransform * trans, GstQuery * query) { - return gst_vaapi_plugin_base_decide_allocation(GST_VAAPI_PLUGIN_BASE(trans), - query, 0); + return gst_vaapi_plugin_base_decide_allocation (GST_VAAPI_PLUGIN_BASE (trans), + query, 0); } #endif static void -gst_vaapipostproc_finalize(GObject *object) +gst_vaapipostproc_finalize (GObject * object) { - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(object); + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (object); - gst_vaapipostproc_destroy(postproc); + gst_vaapipostproc_destroy (postproc); - gst_vaapi_plugin_base_finalize(GST_VAAPI_PLUGIN_BASE(postproc)); - G_OBJECT_CLASS(gst_vaapipostproc_parent_class)->finalize(object); + gst_vaapi_plugin_base_finalize (GST_VAAPI_PLUGIN_BASE (postproc)); + G_OBJECT_CLASS (gst_vaapipostproc_parent_class)->finalize (object); } static void -gst_vaapipostproc_set_property( - GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec -) +gst_vaapipostproc_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) { - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(object); + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (object); - switch (prop_id) { + switch (prop_id) { case PROP_FORMAT: - postproc->format = g_value_get_enum(value); - break; + postproc->format = g_value_get_enum (value); + break; case PROP_WIDTH: - postproc->width = g_value_get_uint(value); - break; + postproc->width = g_value_get_uint (value); + break; case PROP_HEIGHT: - postproc->height = g_value_get_uint(value); - break; + postproc->height = g_value_get_uint (value); + break; case PROP_FORCE_ASPECT_RATIO: - postproc->keep_aspect = g_value_get_boolean(value); - break; + postproc->keep_aspect = g_value_get_boolean (value); + break; case PROP_DEINTERLACE_MODE: - postproc->deinterlace_mode = g_value_get_enum(value); - break; + postproc->deinterlace_mode = g_value_get_enum (value); + break; case PROP_DEINTERLACE_METHOD: - postproc->deinterlace_method = g_value_get_enum(value); - break; - case PROP_DENOISE: - postproc->denoise_level = g_value_get_float(value); - postproc->flags |= GST_VAAPI_POSTPROC_FLAG_DENOISE; - break; - case PROP_SHARPEN: - postproc->sharpen_level = g_value_get_float(value); - postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SHARPEN; - break; - case PROP_HUE: - postproc->hue = g_value_get_float(value); - postproc->flags |= GST_VAAPI_POSTPROC_FLAG_HUE; - break; - case PROP_SATURATION: - postproc->saturation = g_value_get_float(value); - postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SATURATION; - break; - case PROP_BRIGHTNESS: - postproc->brightness = g_value_get_float(value); - postproc->flags |= GST_VAAPI_POSTPROC_FLAG_BRIGHTNESS; - break; - case PROP_CONTRAST: - postproc->contrast = g_value_get_float(value); - postproc->flags |= GST_VAAPI_POSTPROC_FLAG_CONTRAST; - break; - case PROP_SCALE_METHOD: - postproc->scale_method = g_value_get_enum(value); - postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SCALE; - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -gst_vaapipostproc_get_property( - GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec -) -{ - GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(object); - - switch (prop_id) { - case PROP_FORMAT: - g_value_set_enum(value, postproc->format); - break; - case PROP_WIDTH: - g_value_set_uint(value, postproc->width); - break; - case PROP_HEIGHT: - g_value_set_uint(value, postproc->height); - break; - case PROP_FORCE_ASPECT_RATIO: - g_value_set_boolean(value, postproc->keep_aspect); - break; - case PROP_DEINTERLACE_MODE: - g_value_set_enum(value, postproc->deinterlace_mode); - break; - case PROP_DEINTERLACE_METHOD: - g_value_set_enum(value, postproc->deinterlace_method); - break; + postproc->deinterlace_method = g_value_get_enum (value); + break; case PROP_DENOISE: - g_value_set_float(value, postproc->denoise_level); - break; + postproc->denoise_level = g_value_get_float (value); + postproc->flags |= GST_VAAPI_POSTPROC_FLAG_DENOISE; + break; case PROP_SHARPEN: - g_value_set_float(value, postproc->sharpen_level); - break; + postproc->sharpen_level = g_value_get_float (value); + postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SHARPEN; + break; case PROP_HUE: - g_value_set_float(value, postproc->hue); - break; + postproc->hue = g_value_get_float (value); + postproc->flags |= GST_VAAPI_POSTPROC_FLAG_HUE; + break; case PROP_SATURATION: - g_value_set_float(value, postproc->saturation); - break; + postproc->saturation = g_value_get_float (value); + postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SATURATION; + break; case PROP_BRIGHTNESS: - g_value_set_float(value, postproc->brightness); - break; + postproc->brightness = g_value_get_float (value); + postproc->flags |= GST_VAAPI_POSTPROC_FLAG_BRIGHTNESS; + break; case PROP_CONTRAST: - g_value_set_float(value, postproc->contrast); - break; + postproc->contrast = g_value_get_float (value); + postproc->flags |= GST_VAAPI_POSTPROC_FLAG_CONTRAST; + break; case PROP_SCALE_METHOD: - g_value_set_enum(value, postproc->scale_method); - break; + postproc->scale_method = g_value_get_enum (value); + postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SCALE; + break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void -gst_vaapipostproc_class_init(GstVaapiPostprocClass *klass) +gst_vaapipostproc_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) { - GObjectClass * const object_class = G_OBJECT_CLASS(klass); - GstElementClass * const element_class = GST_ELEMENT_CLASS(klass); - GstBaseTransformClass * const trans_class = GST_BASE_TRANSFORM_CLASS(klass); - GstPadTemplate *pad_template; - GPtrArray *filter_ops; - GstVaapiFilterOpInfo *filter_op; + GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (object); - GST_DEBUG_CATEGORY_INIT(gst_debug_vaapipostproc, - GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC); + switch (prop_id) { + case PROP_FORMAT: + g_value_set_enum (value, postproc->format); + break; + case PROP_WIDTH: + g_value_set_uint (value, postproc->width); + break; + case PROP_HEIGHT: + g_value_set_uint (value, postproc->height); + break; + case PROP_FORCE_ASPECT_RATIO: + g_value_set_boolean (value, postproc->keep_aspect); + break; + case PROP_DEINTERLACE_MODE: + g_value_set_enum (value, postproc->deinterlace_mode); + break; + case PROP_DEINTERLACE_METHOD: + g_value_set_enum (value, postproc->deinterlace_method); + break; + case PROP_DENOISE: + g_value_set_float (value, postproc->denoise_level); + break; + case PROP_SHARPEN: + g_value_set_float (value, postproc->sharpen_level); + break; + case PROP_HUE: + g_value_set_float (value, postproc->hue); + break; + case PROP_SATURATION: + g_value_set_float (value, postproc->saturation); + break; + case PROP_BRIGHTNESS: + g_value_set_float (value, postproc->brightness); + break; + case PROP_CONTRAST: + g_value_set_float (value, postproc->contrast); + break; + case PROP_SCALE_METHOD: + g_value_set_enum (value, postproc->scale_method); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} - gst_vaapi_plugin_base_class_init(GST_VAAPI_PLUGIN_BASE_CLASS(klass)); +static void +gst_vaapipostproc_class_init (GstVaapiPostprocClass * klass) +{ + GObjectClass *const object_class = G_OBJECT_CLASS (klass); + GstElementClass *const element_class = GST_ELEMENT_CLASS (klass); + GstBaseTransformClass *const trans_class = GST_BASE_TRANSFORM_CLASS (klass); + GstPadTemplate *pad_template; + GPtrArray *filter_ops; + GstVaapiFilterOpInfo *filter_op; - object_class->finalize = gst_vaapipostproc_finalize; - object_class->set_property = gst_vaapipostproc_set_property; - object_class->get_property = gst_vaapipostproc_get_property; - trans_class->start = gst_vaapipostproc_start; - trans_class->stop = gst_vaapipostproc_stop; - trans_class->transform_caps = gst_vaapipostproc_transform_caps; - trans_class->transform_size = gst_vaapipostproc_transform_size; - trans_class->transform = gst_vaapipostproc_transform; - trans_class->set_caps = gst_vaapipostproc_set_caps; - trans_class->query = gst_vaapipostproc_query; + GST_DEBUG_CATEGORY_INIT (gst_debug_vaapipostproc, + GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC); + + gst_vaapi_plugin_base_class_init (GST_VAAPI_PLUGIN_BASE_CLASS (klass)); + + object_class->finalize = gst_vaapipostproc_finalize; + object_class->set_property = gst_vaapipostproc_set_property; + object_class->get_property = gst_vaapipostproc_get_property; + trans_class->start = gst_vaapipostproc_start; + trans_class->stop = gst_vaapipostproc_stop; + trans_class->transform_caps = gst_vaapipostproc_transform_caps; + trans_class->transform_size = gst_vaapipostproc_transform_size; + trans_class->transform = gst_vaapipostproc_transform; + trans_class->set_caps = gst_vaapipostproc_set_caps; + trans_class->query = gst_vaapipostproc_query; #if GST_CHECK_VERSION(1,0,0) - trans_class->propose_allocation = gst_vaapipostproc_propose_allocation; - trans_class->decide_allocation = gst_vaapipostproc_decide_allocation; + trans_class->propose_allocation = gst_vaapipostproc_propose_allocation; + trans_class->decide_allocation = gst_vaapipostproc_decide_allocation; #endif - trans_class->prepare_output_buffer = - gst_vaapipostproc_prepare_output_buffer; + trans_class->prepare_output_buffer = gst_vaapipostproc_prepare_output_buffer; - gst_element_class_set_static_metadata(element_class, - "VA-API video postprocessing", - "Filter/Converter/Video;Filter/Converter/Video/Scaler;" - "Filter/Effect/Video;Filter/Effect/Video/Deinterlace", - GST_PLUGIN_DESC, - "Gwenole Beauchesne "); + gst_element_class_set_static_metadata (element_class, + "VA-API video postprocessing", + "Filter/Converter/Video;Filter/Converter/Video/Scaler;" + "Filter/Effect/Video;Filter/Effect/Video/Deinterlace", + GST_PLUGIN_DESC, "Gwenole Beauchesne "); - /* sink pad */ - pad_template = gst_static_pad_template_get(&gst_vaapipostproc_sink_factory); - gst_element_class_add_pad_template(element_class, pad_template); + /* sink pad */ + pad_template = gst_static_pad_template_get (&gst_vaapipostproc_sink_factory); + gst_element_class_add_pad_template (element_class, pad_template); - /* src pad */ - pad_template = gst_static_pad_template_get(&gst_vaapipostproc_src_factory); - gst_element_class_add_pad_template(element_class, pad_template); + /* src pad */ + pad_template = gst_static_pad_template_get (&gst_vaapipostproc_src_factory); + gst_element_class_add_pad_template (element_class, pad_template); - /** - * GstVaapiPostproc:deinterlace-mode: - * - * This selects whether the deinterlacing should always be applied or if - * they should only be applied on content that has the "interlaced" flag - * on the caps. - */ - g_object_class_install_property - (object_class, - PROP_DEINTERLACE_MODE, - g_param_spec_enum("deinterlace-mode", - "Deinterlace mode", - "Deinterlace mode to use", - GST_VAAPI_TYPE_DEINTERLACE_MODE, - DEFAULT_DEINTERLACE_MODE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstVaapiPostproc:deinterlace-mode: + * + * This selects whether the deinterlacing should always be applied + * or if they should only be applied on content that has the + * "interlaced" flag on the caps. + */ + g_object_class_install_property + (object_class, + PROP_DEINTERLACE_MODE, + g_param_spec_enum ("deinterlace-mode", + "Deinterlace mode", + "Deinterlace mode to use", + GST_VAAPI_TYPE_DEINTERLACE_MODE, + DEFAULT_DEINTERLACE_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - /** - * GstVaapiPostproc:deinterlace-method: - * - * This selects the deinterlacing method to apply. - */ - g_object_class_install_property - (object_class, - PROP_DEINTERLACE_METHOD, - g_param_spec_enum("deinterlace-method", - "Deinterlace method", - "Deinterlace method to use", - GST_VAAPI_TYPE_DEINTERLACE_METHOD, - DEFAULT_DEINTERLACE_METHOD, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstVaapiPostproc:deinterlace-method: + * + * This selects the deinterlacing method to apply. + */ + g_object_class_install_property + (object_class, + PROP_DEINTERLACE_METHOD, + g_param_spec_enum ("deinterlace-method", + "Deinterlace method", + "Deinterlace method to use", + GST_VAAPI_TYPE_DEINTERLACE_METHOD, + DEFAULT_DEINTERLACE_METHOD, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - filter_ops = gst_vaapi_filter_get_operations(NULL); - if (!filter_ops) - return; + filter_ops = gst_vaapi_filter_get_operations (NULL); + if (!filter_ops) + return; - /** - * GstVaapiPostproc:format: - * - * The forced output pixel format, expressed as a #GstVideoFormat. - */ - filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_FORMAT); - if (filter_op) - g_object_class_install_property(object_class, - PROP_FORMAT, filter_op->pspec); + /** + * GstVaapiPostproc:format: + * + * The forced output pixel format, expressed as a #GstVideoFormat. + */ + filter_op = find_filter_op (filter_ops, GST_VAAPI_FILTER_OP_FORMAT); + if (filter_op) + g_object_class_install_property (object_class, + PROP_FORMAT, filter_op->pspec); - /** - * GstVaapiPostproc:width: - * - * The forced output width in pixels. If set to zero, the width is - * calculated from the height if aspect ration is preserved, or - * inherited from the sink caps width - */ - g_object_class_install_property - (object_class, - PROP_WIDTH, - g_param_spec_uint("width", - "Width", - "Forced output width", - 0, G_MAXINT, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstVaapiPostproc:width: + * + * The forced output width in pixels. If set to zero, the width is + * calculated from the height if aspect ration is preserved, or + * inherited from the sink caps width + */ + g_object_class_install_property + (object_class, + PROP_WIDTH, + g_param_spec_uint ("width", + "Width", + "Forced output width", + 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - /** - * GstVaapiPostproc:height: - * - * The forced output height in pixels. If set to zero, the height - * is calculated from the width if aspect ration is preserved, or - * inherited from the sink caps height - */ - g_object_class_install_property - (object_class, - PROP_HEIGHT, - g_param_spec_uint("height", - "Height", - "Forced output height", - 0, G_MAXINT, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstVaapiPostproc:height: + * + * The forced output height in pixels. If set to zero, the height is + * calculated from the width if aspect ration is preserved, or + * inherited from the sink caps height + */ + g_object_class_install_property + (object_class, + PROP_HEIGHT, + g_param_spec_uint ("height", + "Height", + "Forced output height", + 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - /** - * GstVaapiPostproc:force-aspect-ratio: - * - * When enabled, scaling respects video aspect ratio; when - * disabled, the video is distorted to fit the width and height - * properties. - */ - g_object_class_install_property - (object_class, - PROP_FORCE_ASPECT_RATIO, - g_param_spec_boolean("force-aspect-ratio", - "Force aspect ratio", - "When enabled, scaling will respect original aspect ratio", - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstVaapiPostproc:force-aspect-ratio: + * + * When enabled, scaling respects video aspect ratio; when disabled, + * the video is distorted to fit the width and height properties. + */ + g_object_class_install_property + (object_class, + PROP_FORCE_ASPECT_RATIO, + g_param_spec_boolean ("force-aspect-ratio", + "Force aspect ratio", + "When enabled, scaling will respect original aspect ratio", + TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - /** - * GstVaapiPostproc:denoise: - * - * The level of noise reduction to apply. - */ - filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_DENOISE); - if (filter_op) - g_object_class_install_property(object_class, - PROP_DENOISE, filter_op->pspec); + /** + * GstVaapiPostproc:denoise: + * + * The level of noise reduction to apply. + */ + filter_op = find_filter_op (filter_ops, GST_VAAPI_FILTER_OP_DENOISE); + if (filter_op) + g_object_class_install_property (object_class, + PROP_DENOISE, filter_op->pspec); - /** - * GstVaapiPostproc:sharpen: - * - * The level of sharpening to apply for positive values, or the - * level of blurring for negative values. - */ - filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_SHARPEN); - if (filter_op) - g_object_class_install_property(object_class, - PROP_SHARPEN, filter_op->pspec); + /** + * GstVaapiPostproc:sharpen: + * + * The level of sharpening to apply for positive values, or the + * level of blurring for negative values. + */ + filter_op = find_filter_op (filter_ops, GST_VAAPI_FILTER_OP_SHARPEN); + if (filter_op) + g_object_class_install_property (object_class, + PROP_SHARPEN, filter_op->pspec); - /** - * GstVaapiPostproc:hue: - * - * The color hue, expressed as a float value. Range is -180.0 to - * 180.0. Default value is 0.0 and represents no modification. - */ - filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_HUE); - if (filter_op) - g_object_class_install_property(object_class, - PROP_HUE, filter_op->pspec); + /** + * GstVaapiPostproc:hue: + * + * The color hue, expressed as a float value. Range is -180.0 to + * 180.0. Default value is 0.0 and represents no modification. + */ + filter_op = find_filter_op (filter_ops, GST_VAAPI_FILTER_OP_HUE); + if (filter_op) + g_object_class_install_property (object_class, PROP_HUE, filter_op->pspec); - /** - * GstVaapiPostproc:saturation: - * - * The color saturation, expressed as a float value. Range is 0.0 - * to 2.0. Default value is 1.0 and represents no modification. - */ - filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_SATURATION); - if (filter_op) - g_object_class_install_property(object_class, - PROP_SATURATION, filter_op->pspec); + /** + * GstVaapiPostproc:saturation: + * + * The color saturation, expressed as a float value. Range is 0.0 to + * 2.0. Default value is 1.0 and represents no modification. + */ + filter_op = find_filter_op (filter_ops, GST_VAAPI_FILTER_OP_SATURATION); + if (filter_op) + g_object_class_install_property (object_class, + PROP_SATURATION, filter_op->pspec); - /** - * GstVaapiPostproc:brightness: - * - * The color brightness, expressed as a float value. Range is -1.0 - * to 1.0. Default value is 0.0 and represents no modification. - */ - filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_BRIGHTNESS); - if (filter_op) - g_object_class_install_property(object_class, - PROP_BRIGHTNESS, filter_op->pspec); + /** + * GstVaapiPostproc:brightness: + * + * The color brightness, expressed as a float value. Range is -1.0 + * to 1.0. Default value is 0.0 and represents no modification. + */ + filter_op = find_filter_op (filter_ops, GST_VAAPI_FILTER_OP_BRIGHTNESS); + if (filter_op) + g_object_class_install_property (object_class, + PROP_BRIGHTNESS, filter_op->pspec); - /** - * GstVaapiPostproc:contrast: - * - * The color contrast, expressed as a float value. Range is 0.0 to - * 2.0. Default value is 1.0 and represents no modification. - */ - filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_CONTRAST); - if (filter_op) - g_object_class_install_property(object_class, - PROP_CONTRAST, filter_op->pspec); + /** + * GstVaapiPostproc:contrast: + * + * The color contrast, expressed as a float value. Range is 0.0 to + * 2.0. Default value is 1.0 and represents no modification. + */ + filter_op = find_filter_op (filter_ops, GST_VAAPI_FILTER_OP_CONTRAST); + if (filter_op) + g_object_class_install_property (object_class, + PROP_CONTRAST, filter_op->pspec); - /** - * GstVaapiPostproc:scale-method: - * - * The scaling method to use, expressed as an enum value. See - * #GstVaapiScaleMethod. - */ - filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_SCALING); - if (filter_op) - g_object_class_install_property(object_class, - PROP_SCALE_METHOD, filter_op->pspec); + /** + * GstVaapiPostproc:scale-method: + * + * The scaling method to use, expressed as an enum value. See + * #GstVaapiScaleMethod. + */ + filter_op = find_filter_op (filter_ops, GST_VAAPI_FILTER_OP_SCALING); + if (filter_op) + g_object_class_install_property (object_class, + PROP_SCALE_METHOD, filter_op->pspec); - g_ptr_array_unref(filter_ops); + g_ptr_array_unref (filter_ops); } static void -gst_vaapipostproc_init(GstVaapiPostproc *postproc) +gst_vaapipostproc_init (GstVaapiPostproc * postproc) { - gst_vaapi_plugin_base_init(GST_VAAPI_PLUGIN_BASE(postproc), GST_CAT_DEFAULT); + gst_vaapi_plugin_base_init (GST_VAAPI_PLUGIN_BASE (postproc), + GST_CAT_DEFAULT); - postproc->format = DEFAULT_FORMAT; - postproc->deinterlace_mode = DEFAULT_DEINTERLACE_MODE; - postproc->deinterlace_method = DEFAULT_DEINTERLACE_METHOD; - postproc->field_duration = GST_CLOCK_TIME_NONE; - postproc->keep_aspect = TRUE; - postproc->get_va_surfaces = TRUE; + postproc->format = DEFAULT_FORMAT; + postproc->deinterlace_mode = DEFAULT_DEINTERLACE_MODE; + postproc->deinterlace_method = DEFAULT_DEINTERLACE_METHOD; + postproc->field_duration = GST_CLOCK_TIME_NONE; + postproc->keep_aspect = TRUE; + postproc->get_va_surfaces = TRUE; - gst_video_info_init(&postproc->sinkpad_info); - gst_video_info_init(&postproc->srcpad_info); - gst_video_info_init(&postproc->filter_pool_info); + gst_video_info_init (&postproc->sinkpad_info); + gst_video_info_init (&postproc->srcpad_info); + gst_video_info_init (&postproc->filter_pool_info); } diff --git a/gst/vaapi/gstvaapipostproc.h b/gst/vaapi/gstvaapipostproc.h index af6fdf9dc1..aaa621019a 100644 --- a/gst/vaapi/gstvaapipostproc.h +++ b/gst/vaapi/gstvaapipostproc.h @@ -31,32 +31,23 @@ G_BEGIN_DECLS #define GST_TYPE_VAAPIPOSTPROC \ - (gst_vaapipostproc_get_type()) - -#define GST_VAAPIPOSTPROC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), \ - GST_TYPE_VAAPIPOSTPROC, \ - GstVaapiPostproc)) - -#define GST_VAAPIPOSTPROC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), \ - GST_TYPE_VAAPIPOSTPROC, \ - GstVaapiPostprocClass)) - + (gst_vaapipostproc_get_type ()) +#define GST_VAAPIPOSTPROC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPIPOSTPROC, GstVaapiPostproc)) +#define GST_VAAPIPOSTPROC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VAAPIPOSTPROC, \ + GstVaapiPostprocClass)) #define GST_IS_VAAPIPOSTPROC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_VAAPIPOSTPROC)) - + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_VAAPIPOSTPROC)) #define GST_IS_VAAPIPOSTPROC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VAAPIPOSTPROC)) + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VAAPIPOSTPROC)) +#define GST_VAAPIPOSTPROC_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_VAAPIPOSTPROC, \ + GstVaapiPostprocClass)) -#define GST_VAAPIPOSTPROC_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), \ - GST_TYPE_VAAPIPOSTPROC, \ - GstVaapiPostprocClass)) - -typedef struct _GstVaapiPostproc GstVaapiPostproc; -typedef struct _GstVaapiPostprocClass GstVaapiPostprocClass; -typedef struct _GstVaapiDeinterlaceState GstVaapiDeinterlaceState; +typedef struct _GstVaapiPostproc GstVaapiPostproc; +typedef struct _GstVaapiPostprocClass GstVaapiPostprocClass; +typedef struct _GstVaapiDeinterlaceState GstVaapiDeinterlaceState; /** * GstVaapiDeinterlaceMode: @@ -64,10 +55,11 @@ typedef struct _GstVaapiDeinterlaceState GstVaapiDeinterlaceState; * @GST_VAAPI_DEINTERLACE_MODE_INTERLACED: Force deinterlacing. * @GST_VAAPI_DEINTERLACE_MODE_DISABLED: Never perform deinterlacing. */ -typedef enum { - GST_VAAPI_DEINTERLACE_MODE_AUTO = 0, - GST_VAAPI_DEINTERLACE_MODE_INTERLACED, - GST_VAAPI_DEINTERLACE_MODE_DISABLED, +typedef enum +{ + GST_VAAPI_DEINTERLACE_MODE_AUTO = 0, + GST_VAAPI_DEINTERLACE_MODE_INTERLACED, + GST_VAAPI_DEINTERLACE_MODE_DISABLED, } GstVaapiDeinterlaceMode; /* @@ -97,20 +89,21 @@ typedef enum { * * The set of operations that are to be performed for each frame. */ -typedef enum { - GST_VAAPI_POSTPROC_FLAG_FORMAT = 1 << GST_VAAPI_FILTER_OP_FORMAT, - GST_VAAPI_POSTPROC_FLAG_DENOISE = 1 << GST_VAAPI_FILTER_OP_DENOISE, - GST_VAAPI_POSTPROC_FLAG_SHARPEN = 1 << GST_VAAPI_FILTER_OP_SHARPEN, - GST_VAAPI_POSTPROC_FLAG_HUE = 1 << GST_VAAPI_FILTER_OP_HUE, - GST_VAAPI_POSTPROC_FLAG_SATURATION = 1 << GST_VAAPI_FILTER_OP_SATURATION, - GST_VAAPI_POSTPROC_FLAG_BRIGHTNESS = 1 << GST_VAAPI_FILTER_OP_BRIGHTNESS, - GST_VAAPI_POSTPROC_FLAG_CONTRAST = 1 << GST_VAAPI_FILTER_OP_CONTRAST, - GST_VAAPI_POSTPROC_FLAG_DEINTERLACE = 1 << GST_VAAPI_FILTER_OP_DEINTERLACING, - GST_VAAPI_POSTPROC_FLAG_SCALE = 1 << GST_VAAPI_FILTER_OP_SCALING, +typedef enum +{ + GST_VAAPI_POSTPROC_FLAG_FORMAT = 1 << GST_VAAPI_FILTER_OP_FORMAT, + GST_VAAPI_POSTPROC_FLAG_DENOISE = 1 << GST_VAAPI_FILTER_OP_DENOISE, + GST_VAAPI_POSTPROC_FLAG_SHARPEN = 1 << GST_VAAPI_FILTER_OP_SHARPEN, + GST_VAAPI_POSTPROC_FLAG_HUE = 1 << GST_VAAPI_FILTER_OP_HUE, + GST_VAAPI_POSTPROC_FLAG_SATURATION = 1 << GST_VAAPI_FILTER_OP_SATURATION, + GST_VAAPI_POSTPROC_FLAG_BRIGHTNESS = 1 << GST_VAAPI_FILTER_OP_BRIGHTNESS, + GST_VAAPI_POSTPROC_FLAG_CONTRAST = 1 << GST_VAAPI_FILTER_OP_CONTRAST, + GST_VAAPI_POSTPROC_FLAG_DEINTERLACE = 1 << GST_VAAPI_FILTER_OP_DEINTERLACING, + GST_VAAPI_POSTPROC_FLAG_SCALE = 1 << GST_VAAPI_FILTER_OP_SCALING, - /* Additional custom flags */ - GST_VAAPI_POSTPROC_FLAG_CUSTOM = 1 << 20, - GST_VAAPI_POSTPROC_FLAG_SIZE = GST_VAAPI_POSTPROC_FLAG_CUSTOM, + /* Additional custom flags */ + GST_VAAPI_POSTPROC_FLAG_CUSTOM = 1 << 20, + GST_VAAPI_POSTPROC_FLAG_SIZE = GST_VAAPI_POSTPROC_FLAG_CUSTOM, } GstVaapiPostprocFlags; /* @@ -124,65 +117,68 @@ typedef enum { * * Context used to maintain deinterlacing state. */ -struct _GstVaapiDeinterlaceState { - GstBuffer *buffers[GST_VAAPI_DEINTERLACE_MAX_REFERENCES]; - guint buffers_index; - GstVaapiSurface *surfaces[GST_VAAPI_DEINTERLACE_MAX_REFERENCES]; - guint num_surfaces; - guint deint : 1; - guint tff : 1; +struct _GstVaapiDeinterlaceState +{ + GstBuffer *buffers[GST_VAAPI_DEINTERLACE_MAX_REFERENCES]; + guint buffers_index; + GstVaapiSurface *surfaces[GST_VAAPI_DEINTERLACE_MAX_REFERENCES]; + guint num_surfaces; + guint deint:1; + guint tff:1; }; -struct _GstVaapiPostproc { - /*< private >*/ - GstVaapiPluginBase parent_instance; +struct _GstVaapiPostproc +{ + /*< private >*/ + GstVaapiPluginBase parent_instance; - GstVaapiFilter *filter; - GPtrArray *filter_ops; - GstVaapiVideoPool *filter_pool; - GstVideoInfo filter_pool_info; - gboolean filter_pool_active; - GArray *filter_formats; - GstVideoFormat format; /* output video format (encoded) */ - guint width; - guint height; - guint flags; + GstVaapiFilter *filter; + GPtrArray *filter_ops; + GstVaapiVideoPool *filter_pool; + GstVideoInfo filter_pool_info; + gboolean filter_pool_active; + GArray *filter_formats; + GstVideoFormat format; /* output video format (encoded) */ + guint width; + guint height; + guint flags; - GstCaps *allowed_sinkpad_caps; - GstVideoInfo sinkpad_info; - GstCaps *allowed_srcpad_caps; - GstVideoInfo srcpad_info; + GstCaps *allowed_sinkpad_caps; + GstVideoInfo sinkpad_info; + GstCaps *allowed_srcpad_caps; + GstVideoInfo srcpad_info; - /* Deinterlacing */ - GstVaapiDeinterlaceMode deinterlace_mode; - GstVaapiDeinterlaceMethod deinterlace_method; - GstVaapiDeinterlaceState deinterlace_state; - GstClockTime field_duration; + /* Deinterlacing */ + GstVaapiDeinterlaceMode deinterlace_mode; + GstVaapiDeinterlaceMethod deinterlace_method; + GstVaapiDeinterlaceState deinterlace_state; + GstClockTime field_duration; - /* Basic filter values */ - gfloat denoise_level; - gfloat sharpen_level; + /* Basic filter values */ + gfloat denoise_level; + gfloat sharpen_level; - /* Color balance filter values */ - GstVaapiScaleMethod scale_method; - gfloat hue; - gfloat saturation; - gfloat brightness; - gfloat contrast; + /* Color balance filter values */ + GstVaapiScaleMethod scale_method; + gfloat hue; + gfloat saturation; + gfloat brightness; + gfloat contrast; - guint get_va_surfaces : 1; - guint has_vpp : 1; - guint use_vpp : 1; - guint keep_aspect : 1; + guint get_va_surfaces:1; + guint has_vpp:1; + guint use_vpp:1; + guint keep_aspect:1; }; -struct _GstVaapiPostprocClass { - /*< private >*/ - GstVaapiPluginBaseClass parent_class; +struct _GstVaapiPostprocClass +{ + /*< private >*/ + GstVaapiPluginBaseClass parent_class; }; GType -gst_vaapipostproc_get_type(void) G_GNUC_CONST; +gst_vaapipostproc_get_type (void) G_GNUC_CONST; G_END_DECLS diff --git a/gst/vaapi/gstvaapiuploader.c b/gst/vaapi/gstvaapiuploader.c index 6d99c855fd..6c702b929c 100644 --- a/gst/vaapi/gstvaapiuploader.c +++ b/gst/vaapi/gstvaapiuploader.c @@ -36,475 +36,464 @@ #define GST_HELPER_NAME "vaapiupload" #define GST_HELPER_DESC "VA-API video uploader" -GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapi_uploader); +GST_DEBUG_CATEGORY_STATIC (gst_debug_vaapi_uploader); #define GST_CAT_DEFAULT gst_debug_vaapi_uploader -G_DEFINE_TYPE(GstVaapiUploader, gst_vaapi_uploader, G_TYPE_OBJECT) +G_DEFINE_TYPE (GstVaapiUploader, gst_vaapi_uploader, G_TYPE_OBJECT); #define GST_VAAPI_UPLOADER_CAST(obj) \ - ((GstVaapiUploader *)(obj)) + ((GstVaapiUploader *)(obj)) +#define GST_VAAPI_UPLOADER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_VAAPI_TYPE_UPLOADER, \ + GstVaapiUploaderPrivate)) -#define GST_VAAPI_UPLOADER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ - GST_VAAPI_TYPE_UPLOADER, \ - GstVaapiUploaderPrivate)) - -struct _GstVaapiUploaderPrivate { - GstVaapiDisplay *display; - GstCaps *allowed_caps; - GstVaapiVideoPool *images; - GstVideoInfo image_info; - GstVaapiVideoPool *surfaces; - GstVideoInfo surface_info; - guint direct_rendering; +struct _GstVaapiUploaderPrivate +{ + GstVaapiDisplay *display; + GstCaps *allowed_caps; + GstVaapiVideoPool *images; + GstVideoInfo image_info; + GstVaapiVideoPool *surfaces; + GstVideoInfo surface_info; + guint direct_rendering; }; -enum { - PROP_0, +enum +{ + PROP_0, - PROP_DISPLAY, + PROP_DISPLAY, }; static void -gst_vaapi_uploader_destroy(GstVaapiUploader *uploader) +gst_vaapi_uploader_destroy (GstVaapiUploader * uploader) { - GstVaapiUploaderPrivate * const priv = uploader->priv; + GstVaapiUploaderPrivate *const priv = uploader->priv; - gst_caps_replace(&priv->allowed_caps, NULL); - gst_vaapi_video_pool_replace(&priv->images, NULL); - gst_vaapi_video_pool_replace(&priv->surfaces, NULL); - gst_vaapi_display_replace(&priv->display, NULL); + gst_caps_replace (&priv->allowed_caps, NULL); + gst_vaapi_video_pool_replace (&priv->images, NULL); + gst_vaapi_video_pool_replace (&priv->surfaces, NULL); + gst_vaapi_display_replace (&priv->display, NULL); } static gboolean -ensure_display(GstVaapiUploader *uploader, GstVaapiDisplay *display) +ensure_display (GstVaapiUploader * uploader, GstVaapiDisplay * display) { - GstVaapiUploaderPrivate * const priv = uploader->priv; + GstVaapiUploaderPrivate *const priv = uploader->priv; - gst_vaapi_display_replace(&priv->display, display); + gst_vaapi_display_replace (&priv->display, display); + return TRUE; +} + +static gboolean +ensure_image (GstVaapiImage * image) +{ + guint i, num_planes, width, height; + + /* Make the image fully dirty */ + if (!gst_vaapi_image_map (image)) + return FALSE; + + gst_vaapi_image_get_size (image, &width, &height); + + num_planes = gst_vaapi_image_get_plane_count (image); + for (i = 0; i < num_planes; i++) { + guchar *const plane = gst_vaapi_image_get_plane (image, i); + if (plane) + memset (plane, 0, gst_vaapi_image_get_pitch (image, i)); + } + + if (!gst_vaapi_image_unmap (image)) + gst_vaapi_image_unmap (image); + return TRUE; +} + +static gboolean +ensure_allowed_caps (GstVaapiUploader * uploader) +{ + GstVaapiUploaderPrivate *const priv = uploader->priv; + GstVaapiSurface *surface = NULL; + GArray *formats = NULL, *out_formats = NULL; + GstCaps *out_caps; + guint i; + gboolean success = FALSE; + + enum + { WIDTH = 64, HEIGHT = 64 }; + + if (priv->allowed_caps) return TRUE; -} -static gboolean -ensure_image(GstVaapiImage *image) -{ - guint i, num_planes, width, height; + formats = gst_vaapi_display_get_image_formats (priv->display); + if (!formats) + goto cleanup; - /* Make the image fully dirty */ - if (!gst_vaapi_image_map(image)) - return FALSE; + out_formats = g_array_sized_new (FALSE, FALSE, sizeof (GstVideoFormat), + formats->len); + if (!out_formats) + goto cleanup; - gst_vaapi_image_get_size(image, &width, &height); + surface = gst_vaapi_surface_new (priv->display, + GST_VAAPI_CHROMA_TYPE_YUV420, WIDTH, HEIGHT); + if (!surface) + goto cleanup; - num_planes = gst_vaapi_image_get_plane_count(image); - for (i = 0; i < num_planes; i++) { - guchar * const plane = gst_vaapi_image_get_plane(image, i); - if (plane) - memset(plane, 0, gst_vaapi_image_get_pitch(image, i)); - } + for (i = 0; i < formats->len; i++) { + const GstVideoFormat format = g_array_index (formats, GstVideoFormat, i); + GstVaapiImage *image; - if (!gst_vaapi_image_unmap(image)) - gst_vaapi_image_unmap(image); - return TRUE; -} + if (format == GST_VIDEO_FORMAT_UNKNOWN) + continue; + image = gst_vaapi_image_new (priv->display, format, WIDTH, HEIGHT); + if (!image) + continue; + if (ensure_image (image) && gst_vaapi_surface_put_image (surface, image)) + g_array_append_val (out_formats, format); + gst_vaapi_object_unref (image); + } -static gboolean -ensure_allowed_caps(GstVaapiUploader *uploader) -{ - GstVaapiUploaderPrivate * const priv = uploader->priv; - GstVaapiSurface *surface = NULL; - GArray *formats = NULL, *out_formats = NULL; - GstCaps *out_caps; - guint i; - gboolean success = FALSE; + out_caps = gst_vaapi_video_format_new_template_caps_from_list (out_formats); + if (!out_caps) + goto cleanup; - enum { WIDTH = 64, HEIGHT = 64 }; - - if (priv->allowed_caps) - return TRUE; - - formats = gst_vaapi_display_get_image_formats(priv->display); - if (!formats) - goto cleanup; - - out_formats = g_array_sized_new(FALSE, FALSE, sizeof(GstVideoFormat), - formats->len); - if (!out_formats) - goto cleanup; - - surface = gst_vaapi_surface_new(priv->display, - GST_VAAPI_CHROMA_TYPE_YUV420, WIDTH, HEIGHT); - if (!surface) - goto cleanup; - - for (i = 0; i < formats->len; i++) { - const GstVideoFormat format = - g_array_index(formats, GstVideoFormat, i); - GstVaapiImage *image; - - if (format == GST_VIDEO_FORMAT_UNKNOWN) - continue; - image = gst_vaapi_image_new(priv->display, format, WIDTH, HEIGHT); - if (!image) - continue; - if (ensure_image(image) && gst_vaapi_surface_put_image(surface, image)) - g_array_append_val(out_formats, format); - gst_vaapi_object_unref(image); - } - - out_caps = gst_vaapi_video_format_new_template_caps_from_list(out_formats); - if (!out_caps) - goto cleanup; - - gst_caps_replace(&priv->allowed_caps, out_caps); - gst_caps_unref(out_caps); - success = TRUE; + gst_caps_replace (&priv->allowed_caps, out_caps); + gst_caps_unref (out_caps); + success = TRUE; cleanup: - if (out_formats) - g_array_unref(out_formats); - if (formats) - g_array_unref(formats); - if (surface) - gst_vaapi_object_unref(surface); - return success; + if (out_formats) + g_array_unref (out_formats); + if (formats) + g_array_unref (formats); + if (surface) + gst_vaapi_object_unref (surface); + return success; } static gboolean -ensure_image_pool(GstVaapiUploader *uploader, GstCaps *caps, - gboolean *caps_changed_ptr) +ensure_image_pool (GstVaapiUploader * uploader, GstCaps * caps, + gboolean * caps_changed_ptr) { - GstVaapiUploaderPrivate * const priv = uploader->priv; - GstVaapiVideoPool *pool; - GstVideoInfo vi; - GstVideoFormat format; - guint width, height; + GstVaapiUploaderPrivate *const priv = uploader->priv; + GstVaapiVideoPool *pool; + GstVideoInfo vi; + GstVideoFormat format; + guint width, height; - if (!gst_video_info_from_caps(&vi, caps)) - return FALSE; + if (!gst_video_info_from_caps (&vi, caps)) + return FALSE; - format = GST_VIDEO_INFO_FORMAT(&vi); - width = GST_VIDEO_INFO_WIDTH(&vi); - height = GST_VIDEO_INFO_HEIGHT(&vi); + format = GST_VIDEO_INFO_FORMAT (&vi); + width = GST_VIDEO_INFO_WIDTH (&vi); + height = GST_VIDEO_INFO_HEIGHT (&vi); - *caps_changed_ptr = - format != GST_VIDEO_INFO_FORMAT(&priv->image_info) || - width != GST_VIDEO_INFO_WIDTH(&priv->image_info) || - height != GST_VIDEO_INFO_HEIGHT(&priv->image_info); - if (!*caps_changed_ptr) - return TRUE; - - pool = gst_vaapi_image_pool_new(priv->display, &vi); - if (!pool) - return FALSE; - - gst_video_info_set_format(&priv->image_info, format, width, height); - gst_vaapi_video_pool_replace(&priv->images, pool); - gst_vaapi_video_pool_unref(pool); + *caps_changed_ptr = + format != GST_VIDEO_INFO_FORMAT (&priv->image_info) || + width != GST_VIDEO_INFO_WIDTH (&priv->image_info) || + height != GST_VIDEO_INFO_HEIGHT (&priv->image_info); + if (!*caps_changed_ptr) return TRUE; + + pool = gst_vaapi_image_pool_new (priv->display, &vi); + if (!pool) + return FALSE; + + gst_video_info_set_format (&priv->image_info, format, width, height); + gst_vaapi_video_pool_replace (&priv->images, pool); + gst_vaapi_video_pool_unref (pool); + return TRUE; } static gboolean -ensure_surface_pool(GstVaapiUploader *uploader, GstCaps *caps, - gboolean *caps_changed_ptr) +ensure_surface_pool (GstVaapiUploader * uploader, GstCaps * caps, + gboolean * caps_changed_ptr) { - GstVaapiUploaderPrivate * const priv = uploader->priv; - GstVaapiVideoPool *pool; - GstVideoInfo vi; - GstVideoFormat format; - guint width, height; + GstVaapiUploaderPrivate *const priv = uploader->priv; + GstVaapiVideoPool *pool; + GstVideoInfo vi; + GstVideoFormat format; + guint width, height; - if (!gst_video_info_from_caps(&vi, caps)) - return FALSE; + if (!gst_video_info_from_caps (&vi, caps)) + return FALSE; - format = GST_VIDEO_INFO_FORMAT(&vi); - width = GST_VIDEO_INFO_WIDTH(&vi); - height = GST_VIDEO_INFO_HEIGHT(&vi); + format = GST_VIDEO_INFO_FORMAT (&vi); + width = GST_VIDEO_INFO_WIDTH (&vi); + height = GST_VIDEO_INFO_HEIGHT (&vi); - *caps_changed_ptr = - format != GST_VIDEO_INFO_FORMAT(&priv->surface_info) || - width != GST_VIDEO_INFO_WIDTH(&priv->surface_info) || - height != GST_VIDEO_INFO_HEIGHT(&priv->surface_info); - if (!*caps_changed_ptr) - return TRUE; - - /* Always try to downsample source buffers to YUV 4:2:0 format as - this saves memory bandwidth for further rendering */ - /* XXX: this also means that visual quality is not preserved */ - if (format != GST_VIDEO_FORMAT_ENCODED) { - const GstVaapiChromaType chroma_type = - gst_vaapi_video_format_get_chroma_type(format); - if (chroma_type != GST_VAAPI_CHROMA_TYPE_YUV420) { - const GstVideoFormat image_format = - GST_VIDEO_INFO_FORMAT(&priv->image_info); - GST_INFO("use implicit conversion of %s buffers to NV12 surfaces", - gst_video_format_to_string(image_format)); - gst_video_info_set_format(&vi, GST_VIDEO_FORMAT_NV12, width, height); - } - } - - pool = gst_vaapi_surface_pool_new(priv->display, &vi); - if (!pool) - return FALSE; - - gst_video_info_set_format(&priv->surface_info, format, width, height); - gst_vaapi_video_pool_replace(&priv->surfaces, pool); - gst_vaapi_video_pool_unref(pool); + *caps_changed_ptr = + format != GST_VIDEO_INFO_FORMAT (&priv->surface_info) || + width != GST_VIDEO_INFO_WIDTH (&priv->surface_info) || + height != GST_VIDEO_INFO_HEIGHT (&priv->surface_info); + if (!*caps_changed_ptr) return TRUE; -} -static void -gst_vaapi_uploader_finalize(GObject *object) -{ - gst_vaapi_uploader_destroy(GST_VAAPI_UPLOADER_CAST(object)); - - G_OBJECT_CLASS(gst_vaapi_uploader_parent_class)->finalize(object); -} - -static void -gst_vaapi_uploader_set_property(GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - GstVaapiUploader * const uploader = GST_VAAPI_UPLOADER_CAST(object); - - switch (prop_id) { - case PROP_DISPLAY: - ensure_display(uploader, g_value_get_pointer(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; + /* Always try to downsample source buffers to YUV 4:2:0 format as + this saves memory bandwidth for further rendering */ + /* XXX: this also means that visual quality is not preserved */ + if (format != GST_VIDEO_FORMAT_ENCODED) { + const GstVaapiChromaType chroma_type = + gst_vaapi_video_format_get_chroma_type (format); + if (chroma_type != GST_VAAPI_CHROMA_TYPE_YUV420) { + const GstVideoFormat image_format = + GST_VIDEO_INFO_FORMAT (&priv->image_info); + GST_INFO ("use implicit conversion of %s buffers to NV12 surfaces", + gst_video_format_to_string (image_format)); + gst_video_info_set_format (&vi, GST_VIDEO_FORMAT_NV12, width, height); } + } + + pool = gst_vaapi_surface_pool_new (priv->display, &vi); + if (!pool) + return FALSE; + + gst_video_info_set_format (&priv->surface_info, format, width, height); + gst_vaapi_video_pool_replace (&priv->surfaces, pool); + gst_vaapi_video_pool_unref (pool); + return TRUE; } static void -gst_vaapi_uploader_get_property(GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) +gst_vaapi_uploader_finalize (GObject * object) { - GstVaapiUploader * const uploader = GST_VAAPI_UPLOADER_CAST(object); + gst_vaapi_uploader_destroy (GST_VAAPI_UPLOADER_CAST (object)); - switch (prop_id) { + G_OBJECT_CLASS (gst_vaapi_uploader_parent_class)->finalize (object); +} + +static void +gst_vaapi_uploader_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVaapiUploader *const uploader = GST_VAAPI_UPLOADER_CAST (object); + + switch (prop_id) { case PROP_DISPLAY: - g_value_set_pointer(value, uploader->priv->display); - break; + ensure_display (uploader, g_value_get_pointer (value)); + break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void -gst_vaapi_uploader_class_init(GstVaapiUploaderClass *klass) +gst_vaapi_uploader_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) { - GObjectClass * const object_class = G_OBJECT_CLASS(klass); + GstVaapiUploader *const uploader = GST_VAAPI_UPLOADER_CAST (object); - GST_DEBUG_CATEGORY_INIT(gst_debug_vaapi_uploader, - GST_HELPER_NAME, 0, GST_HELPER_DESC); - - g_type_class_add_private(klass, sizeof(GstVaapiUploaderPrivate)); - - object_class->finalize = gst_vaapi_uploader_finalize; - object_class->set_property = gst_vaapi_uploader_set_property; - object_class->get_property = gst_vaapi_uploader_get_property; - - g_object_class_install_property( - object_class, - PROP_DISPLAY, - g_param_spec_pointer( - "display", - "Display", - "The GstVaapiDisplay this object is bound to", - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_pointer (value, uploader->priv->display); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void -gst_vaapi_uploader_init(GstVaapiUploader *uploader) +gst_vaapi_uploader_class_init (GstVaapiUploaderClass * klass) { - GstVaapiUploaderPrivate *priv; + GObjectClass *const object_class = G_OBJECT_CLASS (klass); - priv = GST_VAAPI_UPLOADER_GET_PRIVATE(uploader); - uploader->priv = priv; + GST_DEBUG_CATEGORY_INIT (gst_debug_vaapi_uploader, + GST_HELPER_NAME, 0, GST_HELPER_DESC); - gst_video_info_init(&priv->image_info); - gst_video_info_init(&priv->surface_info); + g_type_class_add_private (klass, sizeof (GstVaapiUploaderPrivate)); + + object_class->finalize = gst_vaapi_uploader_finalize; + object_class->set_property = gst_vaapi_uploader_set_property; + object_class->get_property = gst_vaapi_uploader_get_property; + + g_object_class_install_property (object_class, + PROP_DISPLAY, + g_param_spec_pointer ("display", + "Display", + "The GstVaapiDisplay this object is bound to", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_vaapi_uploader_init (GstVaapiUploader * uploader) +{ + GstVaapiUploaderPrivate *priv; + + priv = GST_VAAPI_UPLOADER_GET_PRIVATE (uploader); + uploader->priv = priv; + + gst_video_info_init (&priv->image_info); + gst_video_info_init (&priv->surface_info); } GstVaapiUploader * -gst_vaapi_uploader_new(GstVaapiDisplay *display) +gst_vaapi_uploader_new (GstVaapiDisplay * display) { - return g_object_new(GST_VAAPI_TYPE_UPLOADER, "display", display, NULL); + return g_object_new (GST_VAAPI_TYPE_UPLOADER, "display", display, NULL); } gboolean -gst_vaapi_uploader_ensure_display( - GstVaapiUploader *uploader, - GstVaapiDisplay *display -) +gst_vaapi_uploader_ensure_display (GstVaapiUploader * uploader, + GstVaapiDisplay * display) { - g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), FALSE); - g_return_val_if_fail(display != NULL, FALSE); + g_return_val_if_fail (GST_VAAPI_IS_UPLOADER (uploader), FALSE); + g_return_val_if_fail (display != NULL, FALSE); - return ensure_display(uploader,display); + return ensure_display (uploader, display); } gboolean -gst_vaapi_uploader_ensure_caps( - GstVaapiUploader *uploader, - GstCaps *src_caps, - GstCaps *out_caps -) +gst_vaapi_uploader_ensure_caps (GstVaapiUploader * uploader, + GstCaps * src_caps, GstCaps * out_caps) { - GstVaapiUploaderPrivate *priv; - GstVaapiImage *image; - gboolean image_caps_changed, surface_caps_changed; + GstVaapiUploaderPrivate *priv; + GstVaapiImage *image; + gboolean image_caps_changed, surface_caps_changed; - g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), FALSE); - g_return_val_if_fail(src_caps != NULL, FALSE); + g_return_val_if_fail (GST_VAAPI_IS_UPLOADER (uploader), FALSE); + g_return_val_if_fail (src_caps != NULL, FALSE); - if (!out_caps) - out_caps = src_caps; + if (!out_caps) + out_caps = src_caps; - if (!ensure_image_pool(uploader, src_caps, &image_caps_changed)) - return FALSE; - if (!ensure_surface_pool(uploader, out_caps, &surface_caps_changed)) - return FALSE; - if (!image_caps_changed && !surface_caps_changed) - return TRUE; - - priv = uploader->priv; - priv->direct_rendering = 0; - - /* Check if we can alias source and output buffers (same data_size) */ - image = gst_vaapi_video_pool_get_object(priv->images); - if (image) { - if ((gst_vaapi_image_get_format(image) == - GST_VIDEO_INFO_FORMAT(&priv->image_info)) && - gst_vaapi_image_is_linear(image) && - (gst_vaapi_image_get_data_size(image) == - GST_VIDEO_INFO_SIZE(&priv->image_info))) - priv->direct_rendering = 1; - gst_vaapi_video_pool_put_object(priv->images, image); - } - - GST_INFO("direct-rendering: level %u", priv->direct_rendering); + if (!ensure_image_pool (uploader, src_caps, &image_caps_changed)) + return FALSE; + if (!ensure_surface_pool (uploader, out_caps, &surface_caps_changed)) + return FALSE; + if (!image_caps_changed && !surface_caps_changed) return TRUE; + + priv = uploader->priv; + priv->direct_rendering = 0; + + /* Check if we can alias source and output buffers (same data_size) */ + image = gst_vaapi_video_pool_get_object (priv->images); + if (image) { + if ((gst_vaapi_image_get_format (image) == + GST_VIDEO_INFO_FORMAT (&priv->image_info)) && + gst_vaapi_image_is_linear (image) && + (gst_vaapi_image_get_data_size (image) == + GST_VIDEO_INFO_SIZE (&priv->image_info))) + priv->direct_rendering = 1; + gst_vaapi_video_pool_put_object (priv->images, image); + } + + GST_INFO ("direct-rendering: level %u", priv->direct_rendering); + return TRUE; } gboolean -gst_vaapi_uploader_process( - GstVaapiUploader *uploader, - GstBuffer *src_buffer, - GstBuffer *out_buffer -) +gst_vaapi_uploader_process (GstVaapiUploader * uploader, + GstBuffer * src_buffer, GstBuffer * out_buffer) { - GstVaapiVideoMeta *src_meta, *out_meta; - GstVaapiSurface *surface; - GstVaapiImage *image; + GstVaapiVideoMeta *src_meta, *out_meta; + GstVaapiSurface *surface; + GstVaapiImage *image; - g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), FALSE); + g_return_val_if_fail (GST_VAAPI_IS_UPLOADER (uploader), FALSE); - out_meta = gst_buffer_get_vaapi_video_meta(out_buffer); - if (!out_meta) { - GST_WARNING("expected an output video buffer"); + out_meta = gst_buffer_get_vaapi_video_meta (out_buffer); + if (!out_meta) { + GST_WARNING ("expected an output video buffer"); + return FALSE; + } + + surface = gst_vaapi_video_meta_get_surface (out_meta); + g_return_val_if_fail (surface != NULL, FALSE); + + src_meta = gst_buffer_get_vaapi_video_meta (src_buffer); + if (src_meta) { + /* GstVaapiVideoBuffer with mapped VA image */ + image = gst_vaapi_video_meta_get_image (src_meta); + if (!image || !gst_vaapi_image_unmap (image)) + return FALSE; + } else { + /* Regular GstBuffer that needs to be uploaded to a VA image */ + image = gst_vaapi_video_meta_get_image (out_meta); + if (!image) { + image = gst_vaapi_video_pool_get_object (uploader->priv->images); + if (!image) return FALSE; + gst_vaapi_video_meta_set_image (out_meta, image); } + if (!gst_vaapi_image_update_from_buffer (image, src_buffer, NULL)) + return FALSE; + } + g_return_val_if_fail (image != NULL, FALSE); - surface = gst_vaapi_video_meta_get_surface(out_meta); - g_return_val_if_fail(surface != NULL, FALSE); + if (!gst_vaapi_surface_put_image (surface, image)) { + GST_WARNING ("failed to upload YUV buffer to VA surface"); + return FALSE; + } - src_meta = gst_buffer_get_vaapi_video_meta(src_buffer); - if (src_meta) { - /* GstVaapiVideoBuffer with mapped VA image */ - image = gst_vaapi_video_meta_get_image(src_meta); - if (!image || !gst_vaapi_image_unmap(image)) - return FALSE; - } - else { - /* Regular GstBuffer that needs to be uploaded to a VA image */ - image = gst_vaapi_video_meta_get_image(out_meta); - if (!image) { - image = gst_vaapi_video_pool_get_object(uploader->priv->images); - if (!image) - return FALSE; - gst_vaapi_video_meta_set_image(out_meta, image); - } - if (!gst_vaapi_image_update_from_buffer(image, src_buffer, NULL)) - return FALSE; - } - g_return_val_if_fail(image != NULL, FALSE); - - if (!gst_vaapi_surface_put_image(surface, image)) { - GST_WARNING("failed to upload YUV buffer to VA surface"); - return FALSE; - } - - /* Map again for next uploads */ - if (!gst_vaapi_image_map(image)) - return FALSE; - return TRUE; + /* Map again for next uploads */ + if (!gst_vaapi_image_map (image)) + return FALSE; + return TRUE; } GstCaps * -gst_vaapi_uploader_get_caps(GstVaapiUploader *uploader) +gst_vaapi_uploader_get_caps (GstVaapiUploader * uploader) { - g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), NULL); + g_return_val_if_fail (GST_VAAPI_IS_UPLOADER (uploader), NULL); - if (!ensure_allowed_caps(uploader)) - return NULL; - return uploader->priv->allowed_caps; + if (!ensure_allowed_caps (uploader)) + return NULL; + return uploader->priv->allowed_caps; } GstBuffer * -gst_vaapi_uploader_get_buffer(GstVaapiUploader *uploader) +gst_vaapi_uploader_get_buffer (GstVaapiUploader * uploader) { - GstVaapiUploaderPrivate *priv; - GstVaapiImage *image; - GstVaapiVideoMeta *meta; - GstVaapiSurfaceProxy *proxy; - GstBuffer *buffer; + GstVaapiUploaderPrivate *priv; + GstVaapiImage *image; + GstVaapiVideoMeta *meta; + GstVaapiSurfaceProxy *proxy; + GstBuffer *buffer; - g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), NULL); + g_return_val_if_fail (GST_VAAPI_IS_UPLOADER (uploader), NULL); - priv = uploader->priv; + priv = uploader->priv; - buffer = gst_vaapi_video_buffer_new_from_pool(priv->images); - if (!buffer) { - GST_WARNING("failed to allocate video buffer"); - goto error; - } + buffer = gst_vaapi_video_buffer_new_from_pool (priv->images); + if (!buffer) { + GST_WARNING ("failed to allocate video buffer"); + goto error; + } - proxy = gst_vaapi_surface_proxy_new_from_pool( - GST_VAAPI_SURFACE_POOL(priv->surfaces)); - if (!proxy) { - GST_WARNING("failed to allocate VA surface"); - goto error; - } + proxy = + gst_vaapi_surface_proxy_new_from_pool (GST_VAAPI_SURFACE_POOL + (priv->surfaces)); + if (!proxy) { + GST_WARNING ("failed to allocate VA surface"); + goto error; + } - meta = gst_buffer_get_vaapi_video_meta(buffer); - gst_vaapi_video_meta_set_surface_proxy(meta, proxy); - gst_vaapi_surface_proxy_unref(proxy); - - image = gst_vaapi_video_meta_get_image(meta); - if (!gst_vaapi_image_map(image)) { - GST_WARNING("failed to map VA image"); - goto error; - } + meta = gst_buffer_get_vaapi_video_meta (buffer); + gst_vaapi_video_meta_set_surface_proxy (meta, proxy); + gst_vaapi_surface_proxy_unref (proxy); + image = gst_vaapi_video_meta_get_image (meta); + if (!gst_vaapi_image_map (image)) { + GST_WARNING ("failed to map VA image"); + goto error; + } #if !GST_CHECK_VERSION(1,0,0) - GST_BUFFER_DATA(buffer) = gst_vaapi_image_get_plane(image, 0); - GST_BUFFER_SIZE(buffer) = gst_vaapi_image_get_data_size(image); + GST_BUFFER_DATA (buffer) = gst_vaapi_image_get_plane (image, 0); + GST_BUFFER_SIZE (buffer) = gst_vaapi_image_get_data_size (image); #endif - return buffer; + return buffer; error: - gst_buffer_unref(buffer); - return buffer; + gst_buffer_unref (buffer); + return buffer; } gboolean -gst_vaapi_uploader_has_direct_rendering(GstVaapiUploader *uploader) +gst_vaapi_uploader_has_direct_rendering (GstVaapiUploader * uploader) { - g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), FALSE); + g_return_val_if_fail (GST_VAAPI_IS_UPLOADER (uploader), FALSE); - return uploader->priv->direct_rendering; + return uploader->priv->direct_rendering; } diff --git a/gst/vaapi/gstvaapiuploader.h b/gst/vaapi/gstvaapiuploader.h index c52af73a79..1d9f94b0ea 100644 --- a/gst/vaapi/gstvaapiuploader.h +++ b/gst/vaapi/gstvaapiuploader.h @@ -30,87 +30,73 @@ G_BEGIN_DECLS #define GST_VAAPI_TYPE_UPLOADER \ - (gst_vaapi_uploader_get_type()) - -#define GST_VAAPI_UPLOADER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), \ - GST_VAAPI_TYPE_UPLOADER, \ - GstVaapiUploader)) - -#define GST_VAAPI_UPLOADER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), \ - GST_VAAPI_TYPE_UPLOADER, \ - GstVaapiUploaderClass)) - + (gst_vaapi_uploader_get_type ()) +#define GST_VAAPI_UPLOADER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_VAAPI_TYPE_UPLOADER, \ + GstVaapiUploader)) +#define GST_VAAPI_UPLOADER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_VAAPI_TYPE_UPLOADER, \ + GstVaapiUploaderClass)) #define GST_VAAPI_IS_UPLOADER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_UPLOADER)) - + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_VAAPI_TYPE_UPLOADER)) #define GST_VAAPI_IS_UPLOADER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_UPLOADER)) + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_VAAPI_TYPE_UPLOADER)) +#define GST_VAAPI_UPLOADER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_VAAPI_TYPE_UPLOADER, \ + GstVaapiUploaderClass)) -#define GST_VAAPI_UPLOADER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), \ - GST_VAAPI_TYPE_UPLOADER, \ - GstVaapiUploaderClass)) +typedef struct _GstVaapiUploader GstVaapiUploader; +typedef struct _GstVaapiUploaderPrivate GstVaapiUploaderPrivate; +typedef struct _GstVaapiUploaderClass GstVaapiUploaderClass; -typedef struct _GstVaapiUploader GstVaapiUploader; -typedef struct _GstVaapiUploaderPrivate GstVaapiUploaderPrivate; -typedef struct _GstVaapiUploaderClass GstVaapiUploaderClass; +struct _GstVaapiUploader +{ + /*< private >*/ + GObject parent_instance; -struct _GstVaapiUploader { - /*< private >*/ - GObject parent_instance; - - GstVaapiUploaderPrivate *priv; + GstVaapiUploaderPrivate *priv; }; -struct _GstVaapiUploaderClass { - /*< private >*/ - GObjectClass parent_class; +struct _GstVaapiUploaderClass +{ + /*< private >*/ + GObjectClass parent_class; }; G_GNUC_INTERNAL GType -gst_vaapi_uploader_get_type(void) G_GNUC_CONST; +gst_vaapi_uploader_get_type (void) G_GNUC_CONST; G_GNUC_INTERNAL GstVaapiUploader * -gst_vaapi_uploader_new(GstVaapiDisplay *display); +gst_vaapi_uploader_new (GstVaapiDisplay * display); G_GNUC_INTERNAL gboolean -gst_vaapi_uploader_ensure_display( - GstVaapiUploader *uploader, - GstVaapiDisplay *display -); +gst_vaapi_uploader_ensure_display (GstVaapiUploader * uploader, + GstVaapiDisplay * display); G_GNUC_INTERNAL gboolean -gst_vaapi_uploader_ensure_caps( - GstVaapiUploader *uploader, - GstCaps *src_caps, - GstCaps *out_caps -); +gst_vaapi_uploader_ensure_caps (GstVaapiUploader * uploader, + GstCaps * src_caps, GstCaps * out_caps); G_GNUC_INTERNAL gboolean -gst_vaapi_uploader_process( - GstVaapiUploader *uploader, - GstBuffer *src_buffer, - GstBuffer *out_buffer -); +gst_vaapi_uploader_process (GstVaapiUploader * uploader, + GstBuffer * src_buffer, GstBuffer * out_buffer); G_GNUC_INTERNAL GstCaps * -gst_vaapi_uploader_get_caps(GstVaapiUploader *uploader); +gst_vaapi_uploader_get_caps (GstVaapiUploader * uploader); G_GNUC_INTERNAL GstBuffer * -gst_vaapi_uploader_get_buffer(GstVaapiUploader *uploader); +gst_vaapi_uploader_get_buffer (GstVaapiUploader * uploader); G_GNUC_INTERNAL gboolean -gst_vaapi_uploader_has_direct_rendering(GstVaapiUploader *uploader); +gst_vaapi_uploader_has_direct_rendering (GstVaapiUploader * uploader); G_END_DECLS