vaapipostproc: advertise crop meta is handled
authorU. Artie Eoff <ullysses.a.eoff@intel.com>
Tue, 20 Aug 2019 21:22:57 +0000 (14:22 -0700)
committerVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Fri, 30 Aug 2019 17:01:55 +0000 (17:01 +0000)
Advertise to upstream that vaapipostproc can handle
crop meta.

When used in conjunction with videocrop plugin, the
videocrop plugin will only do in-place transform on the
crop meta when vaapipostproc advertises the ability to
handle it.  This allows vaapipostproc to apply the crop
meta on the output buffer using vaapi acceleration.
Without this advertisement, the videocrop plugin will
crop the output buffer directly via software methods,
which is not what we desire.

vaapipostproc will not apply the crop meta if downstream
advertises crop meta handling; vaapipostproc will just
forward the crop meta to downstream.  If crop meta is
not advertised by downstream, then vaapipostproc will
apply the crop meta.

Examples:

1. vaapipostproc will forward crop meta to vaapisink
 gst-launch-1.0 videotestsrc \
  ! videocrop left=10 \
  ! vaapipostproc \
  ! vaapisink

2. vaapipostproc will do the cropping
 gst-launch-1.0 videotestsrc \
  ! videocrop left=10 \
  ! vaapipostproc \
  ! identity drop-allocation=1 \
  ! vaapisink

gst/vaapi/gstvaapipostproc.c
gst/vaapi/gstvaapipostproc.h

index 6e53dc2..a90738e 100644 (file)
@@ -672,6 +672,12 @@ replace_to_dumb_buffer_if_required (GstVaapiPostproc * postproc,
   return TRUE;
 }
 
+static gboolean
+use_vpp_crop (GstVaapiPostproc * postproc)
+{
+  return !postproc->forward_crop;
+}
+
 static GstFlowReturn
 gst_vaapipostproc_process_vpp (GstBaseTransform * trans, GstBuffer * inbuf,
     GstBuffer * outbuf)
@@ -698,7 +704,9 @@ gst_vaapipostproc_process_vpp (GstBaseTransform * trans, GstBuffer * inbuf,
   inbuf_surface = gst_vaapi_video_meta_get_surface (inbuf_meta);
 
   crop_meta = gst_buffer_get_video_crop_meta (inbuf);
-  if (crop_meta) {
+  if (crop_meta && use_vpp_crop (postproc)) {
+    GST_DEBUG_OBJECT (postproc, "cropping x=%d,y=%d,w=%d,h=%d",
+        crop_meta->x, crop_meta->y, crop_meta->width, crop_meta->height);
     crop_rect = &tmp_rect;
     crop_rect->x = crop_meta->x;
     crop_rect->y = crop_meta->y;
@@ -860,6 +868,7 @@ gst_vaapipostproc_process_vpp (GstBaseTransform * trans, GstBuffer * inbuf,
       discont = FALSE;
     }
   }
+
   copy_metadata (postproc, outbuf, inbuf);
 
   if (deint && deint_refs)
@@ -1332,8 +1341,9 @@ gst_vaapipostproc_transform_meta (GstBaseTransform * trans, GstBuffer * outbuf,
 {
   GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans);
 
-  /* dont' GstVideoCropMeta if use_vpp */
-  if (meta->info->api == GST_VIDEO_CROP_META_API_TYPE && postproc->use_vpp)
+  /* don't copy GstVideoCropMeta if we are using vpp crop */
+  if (meta->info->api == GST_VIDEO_CROP_META_API_TYPE
+      && use_vpp_crop (postproc))
     return FALSE;
 
   /* don't copy GstParentBufferMeta if use_vpp */
@@ -1401,17 +1411,56 @@ done:
   return ret;
 }
 
+static gboolean
+ensure_buffer_pool (GstVaapiPostproc * postproc, GstVideoInfo * vi)
+{
+  GstVaapiVideoPool *pool;
+
+  if (!vi)
+    return FALSE;
+
+  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 (&postproc->filter_pool_info, vi))
+    return TRUE;
+  postproc->filter_pool_info = *vi;
+
+  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;
+}
+
 static GstFlowReturn
 gst_vaapipostproc_prepare_output_buffer (GstBaseTransform * trans,
     GstBuffer * inbuf, GstBuffer ** outbuf_ptr)
 {
   GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans);
+  const GstVideoCropMeta *crop_meta;
+  GstVideoInfo info;
 
   if (gst_base_transform_is_passthrough (trans)) {
     *outbuf_ptr = inbuf;
     return GST_FLOW_OK;
   }
 
+  /* If we are not using vpp crop (i.e. forwarding crop meta to downstream)
+   * then, ensure our output buffer pool is sized for uncropped output */
+  crop_meta = gst_buffer_get_video_crop_meta (inbuf);
+  if (crop_meta && !use_vpp_crop (postproc)) {
+    info = postproc->srcpad_info;
+    info.width += crop_meta->x;
+    info.height += crop_meta->y;
+    ensure_buffer_pool (postproc, &info);
+  }
+
   if (GST_VAAPI_PLUGIN_BASE_COPY_OUTPUT_FRAME (trans)) {
     *outbuf_ptr = create_output_dump_buffer (postproc);
   } else {
@@ -1428,27 +1477,11 @@ static gboolean
 ensure_srcpad_buffer_pool (GstVaapiPostproc * postproc, GstCaps * caps)
 {
   GstVideoInfo vi;
-  GstVaapiVideoPool *pool;
 
   if (!gst_video_info_from_caps (&vi, caps))
     return FALSE;
-  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 (&postproc->filter_pool_info, &vi))
-    return TRUE;
-  postproc->filter_pool_info = vi;
-
-  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;
+  return ensure_buffer_pool (postproc, &vi);
 }
 
 static gboolean
@@ -1552,6 +1585,10 @@ gst_vaapipostproc_propose_allocation (GstBaseTransform * trans,
   gint allocation_width, allocation_height;
   gint negotiated_width, negotiated_height;
 
+  /* advertise to upstream that we can handle crop meta */
+  if (decide_query)
+    gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL);
+
   negotiated_width = GST_VIDEO_INFO_WIDTH (&postproc->sinkpad_info);
   negotiated_height = GST_VIDEO_INFO_HEIGHT (&postproc->sinkpad_info);
 
@@ -1588,6 +1625,16 @@ bail:
 static gboolean
 gst_vaapipostproc_decide_allocation (GstBaseTransform * trans, GstQuery * query)
 {
+  GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (trans);
+
+  g_mutex_lock (&postproc->postproc_lock);
+  /* Let downstream handle the crop meta if they support it */
+  postproc->forward_crop = (gst_query_find_allocation_meta (query,
+          GST_VIDEO_CROP_META_API_TYPE, NULL) &&
+      gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL));
+  GST_DEBUG_OBJECT (postproc, "use_vpp_crop=%d", use_vpp_crop (postproc));
+  g_mutex_unlock (&postproc->postproc_lock);
+
   return gst_vaapi_plugin_base_decide_allocation (GST_VAAPI_PLUGIN_BASE (trans),
       query);
 }
@@ -2172,6 +2219,7 @@ gst_vaapipostproc_init (GstVaapiPostproc * postproc)
   postproc->field_duration = GST_CLOCK_TIME_NONE;
   postproc->keep_aspect = TRUE;
   postproc->get_va_surfaces = TRUE;
+  postproc->forward_crop = FALSE;
 
   /* AUTO is not valid for tag_video_direction, this is just to
    * ensure we setup the method as sink event tag */
index 0d98923..6acc599 100644 (file)
@@ -175,6 +175,7 @@ struct _GstVaapiPostproc
   gfloat contrast;
 
   gboolean skintone_enhance;
+  gboolean forward_crop;
 
   guint get_va_surfaces:1;
   guint has_vpp:1;