*/
/**
- * SECTION:gstvaapipostproc
- * @short_description: A video postprocessing filter
+ * SECTION:element-vaapipostproc
+ * @short_description: A VA-API base video postprocessing filter
*
* vaapipostproc consists in various postprocessing algorithms to be
- * applied to VA surfaces. So far, only basic bob deinterlacing is
- * implemented.
+ * applied to VA surfaces.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch-1.0 videotestsrc ! vaapipostproc ! video/x-raw width=1920, height=1080 ! vaapisink
+ * ]|
+ * </refsect2>
*/
-#include "gst/vaapi/sysdeps.h"
+#include "gstcompat.h"
#include <gst/video/video.h>
#include "gstvaapipostproc.h"
#include "gstvaapipluginutil.h"
#include "gstvaapivideobuffer.h"
-#if GST_CHECK_VERSION(1,0,0)
#include "gstvaapivideobufferpool.h"
#include "gstvaapivideomemory.h"
-#endif
#define GST_PLUGIN_NAME "vaapipostproc"
-#define GST_PLUGIN_DESC "A video postprocessing filter"
+#define GST_PLUGIN_DESC "A VA-API 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)
-# define GST_VAAPIPOSTPROC_SURFACE_CAPS \
- GST_VIDEO_CAPS_MAKE_WITH_FEATURES( \
- GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, "{ ENCODED, I420, YV12, NV12 }")
-#else
-# define GST_VAAPIPOSTPROC_SURFACE_CAPS \
- GST_VAAPI_SURFACE_CAPS
-#endif
-
/* Default templates */
+/* *INDENT-OFF* */
static const char gst_vaapipostproc_sink_caps_str[] =
- GST_VAAPIPOSTPROC_SURFACE_CAPS ", "
- GST_CAPS_INTERLACED_MODES "; "
-#if GST_CHECK_VERSION(1,0,0)
- 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 ", "
+ GST_VAAPI_MAKE_SURFACE_CAPS ", "
+ GST_CAPS_INTERLACED_MODES "; "
+#if (USE_GLX || USE_EGL)
+ GST_VAAPI_MAKE_GLTEXUPLOAD_CAPS "; "
#endif
- GST_CAPS_INTERLACED_MODES;
+ GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ", "
+ 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_VAAPI_MAKE_SURFACE_CAPS ", "
+ GST_CAPS_INTERLACED_FALSE "; "
+#if (USE_GLX || USE_EGL)
+ GST_VAAPI_MAKE_GLTEXUPLOAD_CAPS "; "
+#endif
+ GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ", "
+ 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));
-
-G_DEFINE_TYPE_WITH_CODE(
- GstVaapiPostproc,
- gst_vaapipostproc,
- GST_TYPE_BASE_TRANSFORM,
- GST_VAAPI_PLUGIN_BASE_INIT_INTERFACES)
-
-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,
+ GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (gst_vaapipostproc_src_caps_str));
+/* *INDENT-ON* */
+
+static void gst_vaapipostproc_colorbalance_init (gpointer iface, gpointer data);
+
+G_DEFINE_TYPE_WITH_CODE (GstVaapiPostproc, gst_vaapipostproc,
+ GST_TYPE_BASE_TRANSFORM, GST_VAAPI_PLUGIN_BASE_INIT_INTERFACES
+ G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
+ gst_vaapipostproc_colorbalance_init));
+
+static GstVideoFormat native_formats[] =
+ { GST_VIDEO_FORMAT_NV12, GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_I420 };
+
+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_SKIN_TONE_ENHANCEMENT,
};
#define DEFAULT_FORMAT GST_VIDEO_FORMAT_ENCODED
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 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;
+ 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},
+ };
+
+ 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;
-
- 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;
+ 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;
}
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;
-
- 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);
- }
+ 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;
+
+ 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;
-
- 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;
- }
+ 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;
}
- 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_filter (GstVaapiPostproc * postproc)
{
- if (!gst_vaapipostproc_ensure_display(postproc))
- return FALSE;
- if (!gst_vaapi_plugin_base_ensure_uploader(GST_VAAPI_PLUGIN_BASE(postproc)))
- return FALSE;
+ if (postproc->filter)
return TRUE;
-}
-static gboolean
-gst_vaapipostproc_ensure_filter(GstVaapiPostproc *postproc)
-{
- if (postproc->filter)
- return TRUE;
+ if (!gst_vaapipostproc_ensure_display (postproc))
+ return FALSE;
- if (!gst_vaapipostproc_ensure_display(postproc))
- return FALSE;
+ gst_caps_replace (&postproc->allowed_srcpad_caps, NULL);
+ gst_caps_replace (&postproc->allowed_sinkpad_caps, NULL);
- postproc->filter = gst_vaapi_filter_new(
- GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc));
- if (!postproc->filter)
- return FALSE;
- return TRUE;
+ 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_vaapipostproc_ensure_filter(postproc))
- postproc->use_vpp = TRUE;
- return TRUE;
+ if (!gst_vaapi_plugin_base_open (GST_VAAPI_PLUGIN_BASE (postproc)))
+ return FALSE;
+ if (!gst_vaapipostproc_ensure_display (postproc))
+ return FALSE;
+
+ 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_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);
+ 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;
+ }
+ if (postproc->cb_channels) {
+ g_list_free_full (postproc->cb_channels, g_object_unref);
+ postproc->cb_channels = NULL;
+ }
+ gst_vaapi_filter_replace (&postproc->filter, NULL);
+ gst_vaapi_video_pool_replace (&postproc->filter_pool, NULL);
}
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;
- return TRUE;
+ ds_reset (&postproc->deinterlace_state);
+ if (!gst_vaapi_plugin_base_open (GST_VAAPI_PLUGIN_BASE (postproc)))
+ return FALSE;
+ if (!gst_vaapipostproc_ensure_filter (postproc))
+ return FALSE;
+ return TRUE;
}
static gboolean
-gst_vaapipostproc_stop(GstBaseTransform *trans)
+gst_vaapipostproc_stop (GstBaseTransform * trans)
{
- GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans);
+ GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans);
- ds_reset(&postproc->deinterlace_state);
- gst_vaapi_plugin_base_close(GST_VAAPI_PLUGIN_BASE(postproc));
- return TRUE;
+ ds_reset (&postproc->deinterlace_state);
+ gst_vaapi_plugin_base_close (GST_VAAPI_PLUGIN_BASE (postproc));
+
+ postproc->field_duration = GST_CLOCK_TIME_NONE;
+ gst_video_info_init (&postproc->sinkpad_info);
+ gst_video_info_init (&postproc->srcpad_info);
+ gst_video_info_init (&postproc->filter_pool_info);
+
+ return TRUE;
}
static gboolean
-should_deinterlace_buffer(GstVaapiPostproc *postproc, GstBuffer *buf)
+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->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;
+ if (postproc->deinterlace_mode == GST_VAAPI_DEINTERLACE_MODE_INTERLACED)
+ return TRUE;
- g_assert(postproc->deinterlace_mode == GST_VAAPI_DEINTERLACE_MODE_AUTO);
+ 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;
-#else
- if (!GST_BUFFER_FLAG_IS_SET(buf, GST_VIDEO_BUFFER_PROGRESSIVE))
- return TRUE;
-#endif
- break;
+ if (GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_FLAG_INTERLACED))
+ return TRUE;
+ 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;
- /* 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;
+ GstBufferPool *const pool =
+ GST_VAAPI_PLUGIN_BASE (postproc)->srcpad_buffer_pool;
+ GstFlowReturn ret;
-#if !GST_CHECK_VERSION(1,0,0)
- gst_buffer_set_caps(outbuf, GST_VAAPI_PLUGIN_BASE_SRC_PAD_CAPS(postproc));
-#endif
- return outbuf;
+ g_return_val_if_fail (pool != NULL, NULL);
+
+ if (!gst_buffer_pool_set_active (pool, TRUE))
+ goto error_activate_pool;
+
+ outbuf = NULL;
+ ret = gst_buffer_pool_acquire_buffer (pool, &outbuf, NULL);
+ if (ret != GST_FLOW_OK || !outbuf)
+ goto error_create_buffer;
+ return outbuf;
- /* ERRORS */
+ /* ERRORS */
+error_activate_pool:
+ {
+ GST_ERROR ("failed to activate output video buffer pool");
+ return NULL;
+ }
error_create_buffer:
- {
- GST_ERROR("failed to create output video buffer");
- return NULL;
- }
+ {
+ GST_ERROR ("failed to create output video buffer");
+ return NULL;
+ }
}
-static inline void
-append_output_buffer_metadata(GstBuffer *outbuf, GstBuffer *inbuf, guint flags)
+static gboolean
+append_output_buffer_metadata (GstVaapiPostproc * postproc, GstBuffer * outbuf,
+ GstBuffer * inbuf, guint flags)
{
- gst_buffer_copy_into(outbuf, inbuf, flags |
- GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_META | GST_BUFFER_COPY_MEMORY,
- 0, -1);
+ GstVaapiVideoMeta *inbuf_meta, *outbuf_meta;
+ GstVaapiSurfaceProxy *proxy;
+
+ gst_buffer_copy_into (outbuf, inbuf, flags | GST_BUFFER_COPY_FLAGS, 0, -1);
+
+ /* GstVideoCropMeta */
+ 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;
+ }
+ }
+
+ /* 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;
+
+ 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;
-
- 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;
+ 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;
}
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;
- 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;
-#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;
-
- 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_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_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;
-
- 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;
- }
-#endif
- 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);
-
- /* 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);
- }
+ 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;
+ const GstVideoCropMeta *crop_meta;
+ GstVaapiRectangle *crop_rect = NULL;
+ GstVaapiRectangle tmp_rect;
+
+ /* 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_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_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_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_SKINTONE) &&
+ !gst_vaapi_filter_set_skintone (postproc->filter,
+ postproc->skintone_enhance))
+ 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);
+
+ 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;
+ }
+ 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);
+
+ /* 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);
}
+ }
- 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;
-
- outbuf_meta = gst_vaapi_video_meta_new_from_pool(postproc->filter_pool);
- if (!outbuf_meta)
- goto error_create_meta;
- outbuf_surface = gst_vaapi_video_meta_get_surface(outbuf_meta);
-
- 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;
- }
-
- 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_set_vaapi_video_meta(fieldbuf, outbuf_meta);
- gst_vaapi_video_meta_unref(outbuf_meta);
-
- 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;
+ /* First field */
+ if (postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE) {
+ fieldbuf = create_output_buffer (postproc);
+ if (!fieldbuf)
+ goto error_create_buffer;
- /* Second field */
- outbuf_meta = gst_vaapi_video_meta_new_from_pool(postproc->filter_pool);
+ outbuf_meta = gst_buffer_get_vaapi_video_meta (fieldbuf);
if (!outbuf_meta)
- goto error_create_meta;
- outbuf_surface = gst_vaapi_video_meta_get_surface(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 ? 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;
- 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_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;
}
- gst_buffer_set_vaapi_video_meta(outbuf, outbuf_meta);
- gst_vaapi_video_meta_unref(outbuf_meta);
- if (deint && deint_refs)
- ds_add_buffer(ds, inbuf);
- return GST_FLOW_OK;
+ 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;
- /* ERRORS */
+ 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);
+ 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 ? 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))
+ 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_ERROR;
- }
+ {
+ 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);
- gst_vaapi_video_meta_unref(outbuf_meta);
- return GST_FLOW_ERROR;
- }
+ {
+ 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);
- gst_vaapi_video_meta_unref(outbuf_meta);
- return GST_FLOW_NOT_SUPPORTED;
- }
+ {
+ 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);
- gst_vaapi_video_meta_unref(outbuf_meta);
- return GST_FLOW_ERROR;
- }
+ {
+ 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;
- }
+ {
+ 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)
+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(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(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 */
+ 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);
+ 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;
- }
+ {
+ 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;
- }
+ {
+ 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)
+gst_vaapipostproc_passthrough (GstBaseTransform * trans, GstBuffer * inbuf,
+ GstBuffer * outbuf)
{
- GstVaapiVideoMeta *meta;
+ GstVaapiVideoMeta *meta;
- /* No video processing needed, simply copy buffer metadata */
- meta = gst_buffer_get_vaapi_video_meta(inbuf);
- if (!meta)
- goto error_invalid_buffer;
+ /* 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(outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS);
- return GST_FLOW_OK;
+ append_output_buffer_metadata (GST_VAAPIPOSTPROC (trans), outbuf, inbuf,
+ GST_BUFFER_COPY_TIMESTAMPS);
+ return GST_FLOW_OK;
- /* ERRORS */
+ /* 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;
+ }
}
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;
- return FALSE;
+ 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)
+video_info_update (GstCaps * caps, GstVideoInfo * info,
+ gboolean * caps_changed_ptr)
{
- GstVideoInfo vi;
- gboolean deinterlace;
+ GstVideoInfo vi;
- 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 (!gst_video_info_from_caps (&vi, caps))
+ return FALSE;
- 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;
+ *caps_changed_ptr = FALSE;
+ if (video_info_changed (info, &vi)) {
+ *caps_changed_ptr = TRUE;
+ *info = vi;
+ }
- postproc->get_va_surfaces = gst_caps_has_vaapi_surface(caps);
- return TRUE;
+ return TRUE;
}
static gboolean
-gst_vaapipostproc_update_src_caps(GstVaapiPostproc *postproc, GstCaps *caps,
- gboolean *caps_changed_ptr)
+gst_vaapipostproc_update_sink_caps (GstVaapiPostproc * postproc, GstCaps * caps,
+ gboolean * caps_changed_ptr)
{
- GstVideoInfo vi;
+ GstVideoInfo vi;
+ gboolean deinterlace;
- if (!gst_video_info_from_caps(&vi, caps))
- return FALSE;
+ GST_INFO_OBJECT (postproc, "new sink caps = %" GST_PTR_FORMAT, caps);
- if (video_info_changed(&vi, &postproc->srcpad_info))
- postproc->srcpad_info = vi, *caps_changed_ptr = TRUE;
+ if (!video_info_update (caps, &postproc->sinkpad_info, caps_changed_ptr))
+ return FALSE;
- if (postproc->format != GST_VIDEO_INFO_FORMAT(&postproc->sinkpad_info) ||
- postproc->format != DEFAULT_FORMAT)
- postproc->flags |= GST_VAAPI_POSTPROC_FLAG_FORMAT;
+ vi = postproc->sinkpad_info;
+ 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->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;
+ postproc->get_va_surfaces = gst_caps_has_vaapi_surface (caps);
+ return TRUE;
}
static gboolean
-ensure_allowed_sinkpad_caps(GstVaapiPostproc *postproc)
+gst_vaapipostproc_update_src_caps (GstVaapiPostproc * postproc, GstCaps * caps,
+ gboolean * caps_changed_ptr)
{
- GstCaps *out_caps, *raw_caps;
+ GST_INFO_OBJECT (postproc, "new src caps = %" GST_PTR_FORMAT, caps);
- if (postproc->allowed_sinkpad_caps)
- return TRUE;
+ if (!video_info_update (caps, &postproc->srcpad_info, caps_changed_ptr))
+ return FALSE;
- /* 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->format != GST_VIDEO_INFO_FORMAT (&postproc->sinkpad_info) &&
+ postproc->format != DEFAULT_FORMAT)
+ postproc->flags |= GST_VAAPI_POSTPROC_FLAG_FORMAT;
- /* 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;
+ 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
+ensure_allowed_sinkpad_caps (GstVaapiPostproc * postproc)
+{
+ GstCaps *out_caps, *raw_caps;
- /* XXX: append VA/VPP filters */
+ if (postproc->allowed_sinkpad_caps)
return TRUE;
+
+ /* Create VA caps */
+ out_caps = gst_caps_from_string (GST_VAAPI_MAKE_SURFACE_CAPS ", "
+ GST_CAPS_INTERLACED_MODES);
+ if (!out_caps) {
+ GST_ERROR_OBJECT (postproc, "failed to create VA sink caps");
+ return FALSE;
+ }
+
+ /* Append raw video caps */
+ if (gst_vaapipostproc_ensure_display (postproc)) {
+ raw_caps =
+ gst_vaapi_plugin_base_get_allowed_raw_caps (GST_VAAPI_PLUGIN_BASE
+ (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_OBJECT (postproc, "failed to create YUV sink caps");
+ }
+ }
+ postproc->allowed_sinkpad_caps = out_caps;
+
+ /* 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;
-
- 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);
- }
-
- num_structures = gst_caps_get_size(caps);
- for (i = 0; i < num_structures; i++) {
- GstStructure * const structure = gst_caps_get_structure(caps, i);
- if (!structure)
- continue;
- gst_structure_set_value(structure, "format", &value);
- }
- g_value_unset(&value);
+ GValue value = G_VALUE_INIT, v_format = G_VALUE_INIT;
+ guint i, num_structures;
+
+ if (postproc->filter == NULL)
+ 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);
+ }
+
+ num_structures = gst_caps_get_size (caps);
+ for (i = 0; i < num_structures; i++) {
+ GstCapsFeatures *const features = gst_caps_get_features (caps, i);
+ GstStructure *structure;
+
+ if (gst_caps_features_contains (features,
+ GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META))
+ continue;
+
+ 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;
+ 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;
-
- 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;
- }
+ 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;
+ } 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;
- GstCaps *out_caps;
- 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 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;
-
- // 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;
- }
+ GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans);
+ GstVideoInfo vi;
+ GstVideoFormat out_format;
+ GstCaps *out_caps;
+ GstVaapiCapsFeature feature;
+ const gchar *feature_str;
+ 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 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;
- // Signal the other pad that we only generate progressive frames
- GST_VIDEO_INFO_INTERLACE_MODE(&vi) = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
+ // 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;
+
+ // Update size from user-specified parameters
+ find_best_size (postproc, &vi, &width, &height);
+
+ // Update format from user-specified parameters
+ /* 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) */
+ out_format = GST_VIDEO_FORMAT_UNKNOWN;
+ if (postproc->format != DEFAULT_FORMAT)
+ out_format = postproc->format;
+
+ feature =
+ gst_vaapi_find_preferred_caps_feature (GST_BASE_TRANSFORM_SRC_PAD (trans),
+ postproc->allowed_srcpad_caps,
+ (out_format == GST_VIDEO_FORMAT_UNKNOWN) ? &out_format : NULL);
+
+ if (feature == GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED)
+ return gst_pad_peer_query_caps (GST_BASE_TRANSFORM_SRC_PAD (trans),
+ postproc->allowed_srcpad_caps);
+
+ gst_video_info_change_format (&vi, out_format, width, height);
+ out_caps = gst_video_info_to_caps (&vi);
+ if (!out_caps)
+ return NULL;
- // Update size from user-specified parameters
-#if GST_CHECK_VERSION(1,1,0)
- format = postproc->format;
-#else
- format = GST_VIDEO_FORMAT_ENCODED;
-#endif
- find_best_size(postproc, &vi, &width, &height);
- gst_video_info_set_format(&vi, format, width, height);
-
-#if GST_CHECK_VERSION(1,1,0)
- out_caps = gst_video_info_to_caps(&vi);
- if (!out_caps)
- return NULL;
-
- gst_caps_set_features(out_caps, 0,
- gst_caps_features_new(GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, NULL));
-#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;
-
- 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);
-#endif
- return out_caps;
+ 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));
+ }
+
+ /* we don't need to do format conversion if GL_TEXTURE_UPLOAD_META
+ * is negotiated */
+ if (feature != GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META &&
+ postproc->format != out_format) {
+ postproc->format = out_format;
+ }
+ 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;
-
- 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 \
- gst_vaapipostproc_transform_caps_impl
-#endif
+ GstCaps *out_caps;
-#if GST_CHECK_VERSION(1,0,0)
-typedef gsize GstBaseTransformSizeType;
-#else
-typedef guint GstBaseTransformSizeType;
-#endif
+ 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;
+}
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, gsize size,
+ GstCaps * othercaps, gsize * 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_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");
+ }
- 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->use_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");
- postproc->use_vpp = FALSE;
- }
-
- /* 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;
- }
+ /* 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);
+ /* 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,
-#if !GST_CHECK_VERSION(1,0,0)
- gint size, GstCaps *caps,
-#endif
- GstBuffer **outbuf_ptr)
+gst_vaapipostproc_prepare_output_buffer (GstBaseTransform * trans,
+ GstBuffer * inbuf, 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_set_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;
+ if (postproc->filter_pool
+ && !video_info_changed (&postproc->filter_pool_info, &vi))
+ 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;
+ pool =
+ gst_vaapi_surface_pool_new_full (GST_VAAPI_PLUGIN_BASE_DISPLAY (postproc),
+ &postproc->filter_pool_info, 0);
+ if (!pool)
+ return FALSE;
- gst_vaapi_video_pool_replace(&postproc->filter_pool, pool);
- gst_vaapi_video_pool_unref(pool);
- return TRUE;
+ 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)
+is_native_video_format (GstVideoFormat format)
{
- 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 (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;
- return TRUE;
+ guint i = 0;
+ for (i = 0; i < G_N_ELEMENTS (native_formats); i++)
+ if (native_formats[i] == format)
+ return TRUE;
+ return FALSE;
}
static gboolean
-gst_vaapipostproc_query(GstBaseTransform *trans, GstPadDirection direction,
- GstQuery *query)
+gst_vaapipostproc_set_caps (GstBaseTransform * trans, GstCaps * caps,
+ GstCaps * out_caps)
{
- GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans);
+ GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans);
+ gboolean caps_changed = FALSE;
+ GstVideoInfo vinfo;
- GST_INFO_OBJECT(trans, "query type `%s'", GST_QUERY_TYPE_NAME(query));
+ if (!gst_vaapipostproc_update_sink_caps (postproc, caps, &caps_changed))
+ return FALSE;
+ /* HACK: This is a workaround to deal with the va-intel-driver for non-native
+ * formats while doing advanced deinterlacing. The format of reference surfaces must
+ * be same as the format used by the driver internally for motion adaptive
+ * deinterlacing and motion compensated deinterlacing */
+ gst_video_info_from_caps (&vinfo, caps);
+ if (deint_method_is_advanced (postproc->deinterlace_method)
+ && !is_native_video_format (GST_VIDEO_INFO_FORMAT (&vinfo))) {
+ GST_WARNING_OBJECT (postproc,
+ "Advanced deinterlacing requires the native video formats used by the driver internally");
+ return FALSE;
+ }
+ if (!gst_vaapipostproc_update_src_caps (postproc, out_caps, &caps_changed))
+ return FALSE;
- 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;
+ 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;
+ return TRUE;
+}
+
+static gboolean
+gst_vaapipostproc_query (GstBaseTransform * trans, GstPadDirection direction,
+ GstQuery * query)
+{
+ GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans);
+
+ if (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT) {
+ if (gst_vaapi_handle_context_query (query,
+ GST_VAAPI_PLUGIN_BASE_DISPLAY (postproc))) {
+ GST_DEBUG_OBJECT (postproc, "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);
-
- /* 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;
+ 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;
+}
+
+static gboolean
+gst_vaapipostproc_decide_allocation (GstBaseTransform * trans, GstQuery * query)
+{
+ return gst_vaapi_plugin_base_decide_allocation (GST_VAAPI_PLUGIN_BASE (trans),
+ query);
}
-#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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ case PROP_SKIN_TONE_ENHANCEMENT:
+ postproc->skintone_enhance = g_value_get_boolean (value);
+ postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SKINTONE;
+ 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_get_property(
- GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec
-)
+gst_vaapipostproc_get_property (GObject * object,
+ guint prop_id, 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:
- g_value_set_enum(value, postproc->format);
- break;
+ g_value_set_enum (value, postproc->format);
+ break;
case PROP_WIDTH:
- g_value_set_uint(value, postproc->width);
- break;
+ g_value_set_uint (value, postproc->width);
+ break;
case PROP_HEIGHT:
- g_value_set_uint(value, postproc->height);
- break;
+ g_value_set_uint (value, postproc->height);
+ break;
case PROP_FORCE_ASPECT_RATIO:
- g_value_set_boolean(value, postproc->keep_aspect);
- break;
+ g_value_set_boolean (value, postproc->keep_aspect);
+ break;
case PROP_DEINTERLACE_MODE:
- g_value_set_enum(value, postproc->deinterlace_mode);
- break;
+ g_value_set_enum (value, postproc->deinterlace_mode);
+ break;
case PROP_DEINTERLACE_METHOD:
- g_value_set_enum(value, postproc->deinterlace_method);
- break;
+ g_value_set_enum (value, postproc->deinterlace_method);
+ break;
case PROP_DENOISE:
- g_value_set_float(value, postproc->denoise_level);
- break;
+ g_value_set_float (value, postproc->denoise_level);
+ break;
case PROP_SHARPEN:
- g_value_set_float(value, postproc->sharpen_level);
- break;
+ g_value_set_float (value, postproc->sharpen_level);
+ break;
case PROP_HUE:
- g_value_set_float(value, postproc->hue);
- break;
+ g_value_set_float (value, postproc->hue);
+ break;
case PROP_SATURATION:
- g_value_set_float(value, postproc->saturation);
- break;
+ g_value_set_float (value, postproc->saturation);
+ break;
case PROP_BRIGHTNESS:
- g_value_set_float(value, postproc->brightness);
- break;
+ g_value_set_float (value, postproc->brightness);
+ break;
case PROP_CONTRAST:
- g_value_set_float(value, postproc->contrast);
- break;
+ g_value_set_float (value, postproc->contrast);
+ break;
+ case PROP_SCALE_METHOD:
+ g_value_set_enum (value, postproc->scale_method);
+ break;
+ case PROP_SKIN_TONE_ENHANCEMENT:
+ g_value_set_boolean (value, postproc->skintone_enhance);
+ 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_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;
-
- 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;
-#endif
+ 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;
+
+ 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;
+ trans_class->propose_allocation = gst_vaapipostproc_propose_allocation;
+ trans_class->decide_allocation = gst_vaapipostproc_decide_allocation;
+
+ 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 <gwenole.beauchesne@intel.com>");
+
+ /* 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);
+
+ /**
+ * 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));
+
+ 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: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: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: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: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: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:skin-tone-enhancement:
+ *
+ * Apply the skin tone enhancement algorithm.
+ */
+ filter_op = find_filter_op (filter_ops, GST_VAAPI_FILTER_OP_SKINTONE);
+ if (filter_op)
+ g_object_class_install_property (object_class,
+ PROP_SKIN_TONE_ENHANCEMENT, filter_op->pspec);
+
+ g_ptr_array_unref (filter_ops);
+}
+
+static float *
+find_value_ptr (GstVaapiPostproc * postproc, GstVaapiFilterOp op)
+{
+ switch (op) {
+ case GST_VAAPI_FILTER_OP_HUE:
+ return &postproc->hue;
+ case GST_VAAPI_FILTER_OP_SATURATION:
+ return &postproc->saturation;
+ case GST_VAAPI_FILTER_OP_BRIGHTNESS:
+ return &postproc->brightness;
+ case GST_VAAPI_FILTER_OP_CONTRAST:
+ return &postproc->contrast;
+ default:
+ return NULL;
+ }
+}
+
+static void
+cb_set_default_value (GstVaapiPostproc * postproc, GPtrArray * filter_ops,
+ GstVaapiFilterOp op)
+{
+ GstVaapiFilterOpInfo *filter_op;
+ GParamSpecFloat *pspec;
+ float *var;
+
+ filter_op = find_filter_op (filter_ops, op);
+ if (!filter_op)
+ return;
+ var = find_value_ptr (postproc, op);
+ if (!var)
+ return;
+ pspec = G_PARAM_SPEC_FLOAT (filter_op->pspec);
+ *var = pspec->default_value;
+}
+
+static void
+gst_vaapipostproc_init (GstVaapiPostproc * postproc)
+{
+ GPtrArray *filter_ops;
+ guint i;
+
+ 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;
+
+ filter_ops = gst_vaapi_filter_get_operations (NULL);
+ if (filter_ops) {
+ for (i = GST_VAAPI_FILTER_OP_HUE; i <= GST_VAAPI_FILTER_OP_CONTRAST; i++)
+ cb_set_default_value (postproc, filter_ops, i);
+ g_ptr_array_unref (filter_ops);
+ }
+
+ gst_video_info_init (&postproc->sinkpad_info);
+ gst_video_info_init (&postproc->srcpad_info);
+ gst_video_info_init (&postproc->filter_pool_info);
+}
+
+/* ------------------------------------------------------------------------ */
+/* --- GstColorBalance interface --- */
+/* ------------------------------------------------------------------------ */
+
+#define CB_CHANNEL_FACTOR 1000.0
+
+typedef struct
+{
+ GstVaapiFilterOp op;
+ const gchar *name;
+} ColorBalanceChannel;
+
+ColorBalanceChannel cb_channels[] = {
+ {GST_VAAPI_FILTER_OP_HUE, "VA_FILTER_HUE"},
+ {GST_VAAPI_FILTER_OP_SATURATION, "VA_FILTER_SATURATION"},
+ {GST_VAAPI_FILTER_OP_BRIGHTNESS, "VA_FILTER_BRIGHTNESS"},
+ {GST_VAAPI_FILTER_OP_CONTRAST, "VA_FILTER_CONTRAST"},
+};
+
+static void
+cb_channels_init (GstVaapiPostproc * postproc)
+{
+ GPtrArray *filter_ops;
+ GstVaapiFilterOpInfo *filter_op;
+ GParamSpecFloat *pspec;
+ GstColorBalanceChannel *channel;
+ guint i;
+
+ if (postproc->cb_channels)
+ return;
+
+ if (!gst_vaapipostproc_ensure_filter (postproc))
+ return;
+
+ filter_ops = postproc->filter_ops ? g_ptr_array_ref (postproc->filter_ops)
+ : gst_vaapi_filter_get_operations (postproc->filter);
+ if (!filter_ops)
+ return;
+
+ for (i = 0; i < G_N_ELEMENTS (cb_channels); i++) {
+ filter_op = find_filter_op (filter_ops, cb_channels[i].op);
+ if (!filter_op)
+ continue;
+
+ pspec = G_PARAM_SPEC_FLOAT (filter_op->pspec);
+ channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
+ channel->label = g_strdup (cb_channels[i].name);
+ channel->min_value = pspec->minimum * CB_CHANNEL_FACTOR;
+ channel->max_value = pspec->maximum * CB_CHANNEL_FACTOR;
+
+ postproc->cb_channels = g_list_prepend (postproc->cb_channels, channel);
+ }
+
+ g_ptr_array_unref (filter_ops);
+}
+
+static const GList *
+gst_vaapipostproc_colorbalance_list_channels (GstColorBalance * balance)
+{
+ GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (balance);
+
+ cb_channels_init (postproc);
+ return postproc->cb_channels;
+}
+
+static gfloat *
+cb_get_value_ptr (GstVaapiPostproc * postproc, GstColorBalanceChannel * channel,
+ GstVaapiPostprocFlags * flags)
+{
+ guint i;
+ gfloat *ret = NULL;
+
+ for (i = 0; i < G_N_ELEMENTS (cb_channels); i++) {
+ if (g_ascii_strcasecmp (cb_channels[i].name, channel->label) == 0)
+ break;
+ }
+ if (i >= G_N_ELEMENTS (cb_channels))
+ return NULL;
+
+ ret = find_value_ptr (postproc, cb_channels[i].op);
+ if (flags)
+ *flags = 1 << cb_channels[i].op;
+ return ret;
+}
+
+static void
+gst_vaapipostproc_colorbalance_set_value (GstColorBalance * balance,
+ GstColorBalanceChannel * channel, gint value)
+{
+ GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (balance);
+ GstVaapiPostprocFlags flags;
+ gfloat new_val, *var;
+
+ value = CLAMP (value, channel->min_value, channel->max_value);
+ new_val = (gfloat) value / CB_CHANNEL_FACTOR;
+
+ var = cb_get_value_ptr (postproc, channel, &flags);
+ if (var) {
+ *var = new_val;
+ postproc->flags |= flags;
+ gst_color_balance_value_changed (balance, channel, value);
+ return;
+ }
+
+ GST_WARNING_OBJECT (postproc, "unknown channel %s", channel->label);
+}
- 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",
- GST_PLUGIN_DESC,
- "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
-
- /* 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);
-
- /**
- * 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));
-
- 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: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: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: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: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: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);
-
- g_ptr_array_unref(filter_ops);
+static gint
+gst_vaapipostproc_colorbalance_get_value (GstColorBalance * balance,
+ GstColorBalanceChannel * channel)
+{
+ GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (balance);
+ gfloat *var;
+ gint new_val;
+
+ var = cb_get_value_ptr (postproc, channel, NULL);
+ if (var) {
+ new_val = (gint) ((*var) * CB_CHANNEL_FACTOR);
+ new_val = CLAMP (new_val, channel->min_value, channel->max_value);
+ return new_val;
+ }
+
+ GST_WARNING_OBJECT (postproc, "unknown channel %s", channel->label);
+ return G_MININT;
+}
+
+static GstColorBalanceType
+gst_vaapipostproc_colorbalance_get_balance_type (GstColorBalance * balance)
+{
+ return GST_COLOR_BALANCE_HARDWARE;
}
static void
-gst_vaapipostproc_init(GstVaapiPostproc *postproc)
+gst_vaapipostproc_colorbalance_init (gpointer iface, gpointer data)
{
- 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;
-
- gst_video_info_init(&postproc->sinkpad_info);
- gst_video_info_init(&postproc->srcpad_info);
- gst_video_info_init(&postproc->filter_pool_info);
+ GstColorBalanceInterface *cbface = iface;
+ cbface->list_channels = gst_vaapipostproc_colorbalance_list_channels;
+ cbface->set_value = gst_vaapipostproc_colorbalance_set_value;
+ cbface->get_value = gst_vaapipostproc_colorbalance_get_value;
+ cbface->get_balance_type = gst_vaapipostproc_colorbalance_get_balance_type;
}