va: allocator: add _set_format() and _get_format()
authorVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Wed, 7 Oct 2020 16:03:20 +0000 (18:03 +0200)
committerVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Fri, 9 Oct 2020 14:34:57 +0000 (16:34 +0200)
Since allocators keep an available memory queue to reuse, video format and usage
hint are now persistant while allocator's memories are around.

This patch adds _set_format() and _get_format() for both VA allocators.

_set_format() validates if given format can be used or reused. If no allocated
surface previously it creates a dummy one to fetch its offsets and
strides. Updated info is returned to callee.

GstVaPool uses _set_format() at config to verify the allocator capacity and to
get the surfaces offsets and strides, which are going to be used by the video
meta.

Allocator extracted caps are compared with caps from config and if they have
different strides or offsets, force_videometa is set.

A new bufferpool method gst_va_pool_requires_video_meta() is added return the
value of force_videometa. This value is checked in order to know if decoders
need to copy the surface if downstream doesn't announce video meta support.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1667>

sys/va/gstvaallocator.c
sys/va/gstvaallocator.h
sys/va/gstvah264dec.c
sys/va/gstvapool.c
sys/va/gstvapool.h
sys/va/gstvavp8dec.c
sys/va/gstvavpp.c

index f249913ac3754dee434bbebba7f81593c75a16df..7e68ba4332d7664fbe4e49767587b2f622868271 100644 (file)
@@ -400,6 +400,9 @@ struct _GstVaDmabufAllocator
   GstMemoryMapFunction parent_map;
 
   GCond buffer_cond;
+
+  GstVideoInfo info;
+  guint usage_hint;
 };
 
 #define gst_va_dmabuf_allocator_parent_class dmabuf_parent_class
@@ -514,11 +517,15 @@ gst_va_dmabuf_memory_release (GstMiniObject * mini_object)
   return FALSE;
 }
 
-/* creates an exported VASurface and adds it as @buffer's memories
- * qdata */
-gboolean
-gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator,
-    GstBuffer * buffer, GstVaAllocationParams * params)
+/* Creates an exported VASurface and adds it as @buffer's memories
+ * qdata
+ *
+ * If @info is not NULL, a dummy (non-pooled) buffer is created to
+ * update offsets and strides, and it has to be unrefed immediately.
+ */
+static gboolean
+gst_va_dmabuf_allocator_setup_buffer_full (GstAllocator * allocator,
+    GstBuffer * buffer, GstVideoInfo * info)
 {
   GstVaBufferSurface *buf;
   GstVaDmabufAllocator *self = GST_VA_DMABUF_ALLOCATOR (allocator);
@@ -528,20 +535,19 @@ gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator,
   guint32 i, fourcc, rt_format, export_flags;
 
   g_return_val_if_fail (GST_IS_VA_DMABUF_ALLOCATOR (allocator), FALSE);
-  g_return_val_if_fail (params, FALSE);
 
-  format = GST_VIDEO_INFO_FORMAT (&params->info);
+  format = GST_VIDEO_INFO_FORMAT (&self->info);
   fourcc = gst_va_fourcc_from_video_format (format);
   rt_format = gst_va_chroma_from_video_format (format);
   if (fourcc == 0 || rt_format == 0) {
     GST_ERROR_OBJECT (allocator, "Unsupported format: %s",
-        gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&params->info)));
+        gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&self->info)));
     return FALSE;
   }
 
   if (!_create_surfaces (self->display, rt_format, fourcc,
-          GST_VIDEO_INFO_WIDTH (&params->info),
-          GST_VIDEO_INFO_HEIGHT (&params->info), params->usage_hint, NULL,
+          GST_VIDEO_INFO_WIDTH (&self->info),
+          GST_VIDEO_INFO_HEIGHT (&self->info), self->usage_hint, NULL,
           &surface, 1))
     return FALSE;
 
@@ -561,7 +567,7 @@ gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator,
   if (!_export_surface_to_dmabuf (self->display, surface, export_flags, &desc))
     goto failed;
 
-  g_assert (GST_VIDEO_INFO_N_PLANES (&params->info) == desc.num_layers);
+  g_assert (GST_VIDEO_INFO_N_PLANES (&self->info) == desc.num_layers);
 
   if (fourcc != desc.fourcc) {
     GST_ERROR ("Unsupported fourcc: %" GST_FOURCC_FORMAT,
@@ -570,7 +576,10 @@ gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator,
   }
 
   buf = gst_va_buffer_surface_new (surface, format, desc.width, desc.height);
-  GST_VIDEO_INFO_SIZE (&params->info) = 0;
+  if (G_UNLIKELY (info)) {
+    *info = self->info;
+    GST_VIDEO_INFO_SIZE (info) = 0;
+  }
 
   for (i = 0; i < desc.num_objects; i++) {
     gint fd = desc.objects[i].fd;
@@ -581,7 +590,8 @@ gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator,
 
     gst_buffer_append_memory (buffer, mem);
 
-    GST_MINI_OBJECT (mem)->dispose = gst_va_dmabuf_memory_release;
+    if (G_LIKELY (!info))
+      GST_MINI_OBJECT (mem)->dispose = gst_va_dmabuf_memory_release;
 
     g_atomic_int_add (&buf->ref_count, 1);
     gst_mini_object_set_qdata (GST_MINI_OBJECT (mem),
@@ -591,21 +601,23 @@ gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator,
     gst_mini_object_set_qdata (GST_MINI_OBJECT (mem), gst_va_drm_mod_quark (),
         drm_mod, g_free);
 
-    GST_VIDEO_INFO_SIZE (&params->info) += size;
+    if (G_UNLIKELY (info))
+      GST_VIDEO_INFO_SIZE (info) += size;
   }
 
-  for (i = 0; i < desc.num_layers; i++) {
-    g_assert (desc.layers[i].num_planes == 1);
-    GST_VIDEO_INFO_PLANE_OFFSET (&params->info, i) = desc.layers[i].offset[0];
-    GST_VIDEO_INFO_PLANE_STRIDE (&params->info, i) = desc.layers[i].pitch[0];
+  if (G_UNLIKELY (info)) {
+    for (i = 0; i < desc.num_layers; i++) {
+      g_assert (desc.layers[i].num_planes == 1);
+      GST_VIDEO_INFO_PLANE_OFFSET (info, i) = desc.layers[i].offset[0];
+      GST_VIDEO_INFO_PLANE_STRIDE (info, i) = desc.layers[i].pitch[0];
+    }
+  } else {
+    g_atomic_int_inc (&self->surface_count);
   }
 
-  g_atomic_int_inc (&self->surface_count);
-
   GST_LOG_OBJECT (self, "Created surface %#x [%dx%d] size %" G_GSIZE_FORMAT,
-      buf->surface, GST_VIDEO_INFO_WIDTH (&params->info),
-      GST_VIDEO_INFO_HEIGHT (&params->info),
-      GST_VIDEO_INFO_SIZE (&params->info));
+      buf->surface, GST_VIDEO_INFO_WIDTH (&self->info),
+      GST_VIDEO_INFO_HEIGHT (&self->info), GST_VIDEO_INFO_SIZE (&self->info));
 
   return TRUE;
 
@@ -616,6 +628,13 @@ failed:
   }
 }
 
+gboolean
+gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator,
+    GstBuffer * buffer)
+{
+  return gst_va_dmabuf_allocator_setup_buffer_full (allocator, buffer, NULL);
+}
+
 gboolean
 gst_va_dmabuf_allocator_prepare_buffer (GstAllocator * allocator,
     GstBuffer * buffer)
@@ -669,27 +688,75 @@ gst_va_dmabuf_allocator_flush (GstAllocator * allocator)
   GST_OBJECT_UNLOCK (self);
 }
 
+static gboolean
+gst_va_dmabuf_allocator_try (GstAllocator * allocator)
+{
+  GstBuffer *buffer;
+  GstVaDmabufAllocator *self = GST_VA_DMABUF_ALLOCATOR (allocator);
+  GstVideoInfo info = self->info;
+  gboolean ret;
+
+  buffer = gst_buffer_new ();
+  ret = gst_va_dmabuf_allocator_setup_buffer_full (allocator, buffer, &info);
+  gst_buffer_unref (buffer);
+
+  if (ret)
+    self->info = info;
+
+  return ret;
+}
+
 gboolean
-gst_va_dmabuf_try (GstAllocator * allocator, GstVaAllocationParams * params)
+gst_va_dmabuf_allocator_set_format (GstAllocator * allocator,
+    GstVideoInfo * info, guint usage_hint)
 {
-  GstBuffer *buffer = gst_buffer_new ();
-  GstMapInfo map_info;
+  GstVaDmabufAllocator *self;
   gboolean ret;
 
-  ret = gst_va_dmabuf_allocator_setup_buffer (allocator, buffer, params);
-  if (ret) {
-    /* XXX: radeonsi for kadaveri cannot map dmabufs to user space */
-    if (!gst_buffer_map (buffer, &map_info, GST_MAP_READWRITE)) {
-      GST_WARNING_OBJECT (allocator,
-          "DMABuf backend cannot map frames to user space.");
+  g_return_val_if_fail (GST_IS_VA_DMABUF_ALLOCATOR (allocator), FALSE);
+  g_return_val_if_fail (info, FALSE);
+
+  self = GST_VA_DMABUF_ALLOCATOR (allocator);
+
+  if (self->surface_count != 0) {
+    if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_INFO_FORMAT (&self->info)
+        && GST_VIDEO_INFO_WIDTH (info) == GST_VIDEO_INFO_WIDTH (&self->info)
+        && GST_VIDEO_INFO_HEIGHT (info) == GST_VIDEO_INFO_HEIGHT (&self->info)
+        && usage_hint == self->usage_hint) {
+      *info = self->info;       /* update callee info (offset & stride) */
+      return TRUE;
     }
-    gst_buffer_unmap (buffer, &map_info);
+    return FALSE;
   }
-  gst_buffer_unref (buffer);
+
+  self->usage_hint = usage_hint;
+  self->info = *info;
+
+  ret = gst_va_dmabuf_allocator_try (allocator);
+
+  if (ret)
+    *info = self->info;
 
   return ret;
 }
 
+gboolean
+gst_va_dmabuf_allocator_get_format (GstAllocator * allocator,
+    GstVideoInfo * info, guint * usage_hint)
+{
+  GstVaDmabufAllocator *self = GST_VA_DMABUF_ALLOCATOR (allocator);
+
+  if (GST_VIDEO_INFO_FORMAT (&self->info) == GST_VIDEO_FORMAT_UNKNOWN)
+    return FALSE;
+
+  if (info)
+    *info = self->info;
+  if (usage_hint)
+    *usage_hint = self->usage_hint;
+
+  return TRUE;
+}
+
 /* XXX: use a surface pool to control the created surfaces */
 gboolean
 gst_va_dmabuf_memories_setup (GstVaDisplay * display, GstVideoInfo * info,
@@ -773,6 +840,9 @@ struct _GstVaAllocator
   GArray *surface_formats;
 
   GCond buffer_cond;
+
+  GstVideoInfo info;
+  guint usage_hint;
 };
 
 typedef struct _GstVaMemory GstVaMemory;
@@ -780,7 +850,6 @@ struct _GstVaMemory
 {
   GstMemory mem;
 
-  GstVideoInfo info;
   VASurfaceID surface;
   GstVideoFormat surface_format;
   VAImage image;
@@ -886,7 +955,7 @@ _reset_mem (GstVaMemory * mem, GstAllocator * allocator, gsize size)
 
 static inline gboolean
 _ensure_image (GstVaDisplay * display, VASurfaceID surface, GstVideoInfo * info,
-    VAImage * image, gboolean * derived)
+    VAImage * image, gboolean * derived, gboolean update_info)
 {
   gint i;
   gboolean try_derived;
@@ -909,12 +978,14 @@ _ensure_image (GstVaDisplay * display, VASurfaceID surface, GstVideoInfo * info,
     *derived = FALSE;
 
 bail:
-  for (i = 0; i < image->num_planes; i++) {
-    GST_VIDEO_INFO_PLANE_OFFSET (info, i) = image->offsets[i];
-    GST_VIDEO_INFO_PLANE_STRIDE (info, i) = image->pitches[i];
-  }
+  if (G_UNLIKELY (update_info)) {
+    for (i = 0; i < image->num_planes; i++) {
+      GST_VIDEO_INFO_PLANE_OFFSET (info, i) = image->offsets[i];
+      GST_VIDEO_INFO_PLANE_STRIDE (info, i) = image->pitches[i];
+    }
 
-  GST_VIDEO_INFO_SIZE (info) = image->data_size;
+    GST_VIDEO_INFO_SIZE (info) = image->data_size;
+  }
 
   return TRUE;
 }
@@ -945,7 +1016,7 @@ _va_map_unlocked (GstVaMemory * mem, GstMapFlags flags)
   } else {                      /* GST_MAP_READ only */
     mem->is_dirty = FALSE;
     mem->is_derived = va_allocator->use_derived &&
-        (GST_VIDEO_INFO_FORMAT (&mem->info) == mem->surface_format);
+        (GST_VIDEO_INFO_FORMAT (&va_allocator->info) == mem->surface_format);
   }
 
   if (flags & GST_MAP_VA) {
@@ -953,8 +1024,8 @@ _va_map_unlocked (GstVaMemory * mem, GstMapFlags flags)
     goto success;
   }
 
-  if (!_ensure_image (display, mem->surface, &mem->info, &mem->image,
-          &mem->is_derived))
+  if (!_ensure_image (display, mem->surface, &va_allocator->info, &mem->image,
+          &mem->is_derived, FALSE))
     return NULL;
 
   va_allocator->use_derived = mem->is_derived;
@@ -1063,7 +1134,6 @@ _va_share (GstMemory * mem, gssize offset, gssize size)
 
   sub->surface = vamem->surface;
   sub->surface_format = vamem->surface_format;
-  sub->info = vamem->info;
 
   _clean_mem (sub);
 
@@ -1110,14 +1180,16 @@ gst_va_memory_release (GstMiniObject * mini_object)
   return FALSE;
 }
 
-GstMemory *
-gst_va_allocator_alloc (GstAllocator * allocator,
-    GstVaAllocationParams * params)
+/* If @info is not NULL, a dummy (non-pooled) memory and its VAImage
+ * are created, to update offsets and strides. The memory has to be
+ * unrefed immediately.
+ */
+static GstMemory *
+gst_va_allocator_alloc_full (GstAllocator * allocator, GstVideoInfo * info)
 {
   GstVaAllocator *self;
   GstVaMemory *mem;
   GstVideoFormat format, img_format;
-  VAImage image = { 0, };
   VASurfaceID surface;
   guint32 fourcc, rt_format;
 
@@ -1125,7 +1197,7 @@ gst_va_allocator_alloc (GstAllocator * allocator,
 
   self = GST_VA_ALLOCATOR (allocator);
 
-  img_format = GST_VIDEO_INFO_FORMAT (&params->info);
+  img_format = GST_VIDEO_INFO_FORMAT (&self->info);
 
   format = gst_va_video_surface_format_from_image_format (img_format,
       self->surface_formats);
@@ -1145,35 +1217,43 @@ gst_va_allocator_alloc (GstAllocator * allocator,
   }
 
   if (!_create_surfaces (self->display, rt_format, fourcc,
-          GST_VIDEO_INFO_WIDTH (&params->info),
-          GST_VIDEO_INFO_HEIGHT (&params->info), params->usage_hint, NULL,
+          GST_VIDEO_INFO_WIDTH (&self->info),
+          GST_VIDEO_INFO_HEIGHT (&self->info), self->usage_hint, NULL,
           &surface, 1))
     return NULL;
 
-  image.image_id = VA_INVALID_ID;
-  if (!_ensure_image (self->display, surface, &params->info, &image, NULL))
-    return NULL;
-  _destroy_image (self->display, image.image_id);
+  if (G_UNLIKELY (info)) {
+    VAImage image = {.image_id = VA_INVALID_ID, };
+
+    if (!_ensure_image (self->display, surface, info, &image, NULL, TRUE))
+      return NULL;
+    _destroy_image (self->display, image.image_id);
+  }
 
   mem = g_slice_new (GstVaMemory);
 
   mem->surface = surface;
   mem->surface_format = format;
-  mem->info = params->info;
-
-  _reset_mem (mem, allocator, GST_VIDEO_INFO_SIZE (&params->info));
 
-  GST_MINI_OBJECT (mem)->dispose = gst_va_memory_release;
+  _reset_mem (mem, allocator, GST_VIDEO_INFO_SIZE (&self->info));
 
-  g_atomic_int_inc (&self->surface_count);
+  if (G_LIKELY (!info)) {
+    GST_MINI_OBJECT (mem)->dispose = gst_va_memory_release;
+    g_atomic_int_inc (&self->surface_count);
+  }
 
   GST_LOG_OBJECT (self, "Created surface %#x [%dx%d]", mem->surface,
-      GST_VIDEO_INFO_WIDTH (&params->info),
-      GST_VIDEO_INFO_HEIGHT (&params->info));
+      GST_VIDEO_INFO_WIDTH (&self->info), GST_VIDEO_INFO_HEIGHT (&self->info));
 
   return GST_MEMORY_CAST (mem);
 }
 
+GstMemory *
+gst_va_allocator_alloc (GstAllocator * allocator)
+{
+  return gst_va_allocator_alloc_full (allocator, NULL);
+}
+
 GstAllocator *
 gst_va_allocator_new (GstVaDisplay * display, GArray * surface_formats)
 {
@@ -1224,15 +1304,69 @@ gst_va_allocator_flush (GstAllocator * allocator)
   GST_OBJECT_UNLOCK (self);
 }
 
-gboolean
-gst_va_allocator_try (GstAllocator * allocator, GstVaAllocationParams * params)
+static gboolean
+gst_va_allocator_try (GstAllocator * allocator)
 {
   GstMemory *mem;
+  GstVaAllocator *self = GST_VA_ALLOCATOR (allocator);
+  GstVideoInfo info = self->info;
 
-  mem = gst_va_allocator_alloc (allocator, params);
+  mem = gst_va_allocator_alloc_full (allocator, &info);
   if (!mem)
     return FALSE;
   gst_memory_unref (mem);
+
+  self->info = info;
+  return TRUE;
+}
+
+gboolean
+gst_va_allocator_set_format (GstAllocator * allocator, GstVideoInfo * info,
+    guint usage_hint)
+{
+  GstVaAllocator *self;
+  gboolean ret;
+
+  g_return_val_if_fail (GST_IS_VA_ALLOCATOR (allocator), FALSE);
+  g_return_val_if_fail (info, FALSE);
+
+  self = GST_VA_ALLOCATOR (allocator);
+
+  if (self->surface_count != 0) {
+    if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_INFO_FORMAT (&self->info)
+        && GST_VIDEO_INFO_WIDTH (info) == GST_VIDEO_INFO_WIDTH (&self->info)
+        && GST_VIDEO_INFO_HEIGHT (info) == GST_VIDEO_INFO_HEIGHT (&self->info)
+        && usage_hint == self->usage_hint) {
+      *info = self->info;       /* update callee info (offset & stride) */
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  self->usage_hint = usage_hint;
+  self->info = *info;
+
+  ret = gst_va_allocator_try (allocator);
+  if (ret)
+    *info = self->info;
+
+  return ret;
+}
+
+gboolean
+gst_va_allocator_get_format (GstAllocator * allocator, GstVideoInfo * info,
+    guint * usage_hint)
+{
+  GstVaAllocator *self = GST_VA_ALLOCATOR (allocator);
+
+  if (GST_VIDEO_INFO_FORMAT (&self->info) == GST_VIDEO_FORMAT_UNKNOWN)
+    return FALSE;
+
+  if (info)
+    *info = self->info;
+  if (usage_hint)
+    *usage_hint = self->usage_hint;
+
   return TRUE;
 }
 
index 7040139b925e3a4673798a66410d8bebc48ebc1f..bbe364cb9414b221e54420bb97c3a2d5f8ed08b8 100644 (file)
 
 G_BEGIN_DECLS
 
-typedef struct _GstVaAllocationParams GstVaAllocationParams;
-struct _GstVaAllocationParams
-{
-  GstVideoInfo info;
-  guint32 usage_hint;
-};
-
 #define GST_TYPE_VA_DMABUF_ALLOCATOR (gst_va_dmabuf_allocator_get_type())
 G_DECLARE_FINAL_TYPE (GstVaDmabufAllocator, gst_va_dmabuf_allocator, GST,
     VA_DMABUF_ALLOCATOR, GstDmaBufAllocator);
 
 GstAllocator *        gst_va_dmabuf_allocator_new         (GstVaDisplay * display);
 gboolean              gst_va_dmabuf_allocator_setup_buffer (GstAllocator * allocator,
-                                                            GstBuffer * buffer,
-                                                            GstVaAllocationParams * params);
+                                                            GstBuffer * buffer);
 gboolean              gst_va_dmabuf_allocator_prepare_buffer (GstAllocator * allocator,
                                                               GstBuffer * buffer);
 void                  gst_va_dmabuf_allocator_flush       (GstAllocator * allocator);
-gboolean              gst_va_dmabuf_try                   (GstAllocator * allocator,
-                                                           GstVaAllocationParams * params);
+gboolean              gst_va_dmabuf_allocator_set_format  (GstAllocator * allocator,
+                                                           GstVideoInfo * info,
+                                                           guint usage_hint);
+gboolean              gst_va_dmabuf_allocator_get_format  (GstAllocator * allocator,
+                                                           GstVideoInfo * info,
+                                                           guint * usage_hint);
 
 gboolean              gst_va_dmabuf_memories_setup        (GstVaDisplay * display,
                                                            GstVideoInfo * info,
@@ -65,13 +61,16 @@ G_DECLARE_FINAL_TYPE (GstVaAllocator, gst_va_allocator, GST, VA_ALLOCATOR, GstAl
 
 GstAllocator *        gst_va_allocator_new                (GstVaDisplay * display,
                                                            GArray * surface_formats);
-GstMemory *           gst_va_allocator_alloc              (GstAllocator * allocator,
-                                                           GstVaAllocationParams * params);
+GstMemory *           gst_va_allocator_alloc              (GstAllocator * allocator);
 gboolean              gst_va_allocator_prepare_buffer     (GstAllocator * allocator,
                                                            GstBuffer * buffer);
 void                  gst_va_allocator_flush              (GstAllocator * allocator);
-gboolean              gst_va_allocator_try                (GstAllocator * allocator,
-                                                           GstVaAllocationParams * params);
+gboolean              gst_va_allocator_set_format         (GstAllocator * allocator,
+                                                           GstVideoInfo * info,
+                                                           guint usage_hint);
+gboolean              gst_va_allocator_get_format         (GstAllocator * allocator,
+                                                           GstVideoInfo * info,
+                                                           guint * usage_hint);
 
 VASurfaceID           gst_va_memory_get_surface           (GstMemory * mem);
 VASurfaceID           gst_va_buffer_get_surface           (GstBuffer * buffer);
index 88b7a9dc5fed48bbd9059c14337bfb3a459c3e20..102d716fb31f4b13921086fa7d193b185936379c 100644 (file)
@@ -745,6 +745,17 @@ gst_va_h264_dec_new_sequence (GstH264Decoder * decoder, const GstH264SPS * sps,
     }
   }
 
+  if (!self->has_videometa) {
+    GstBufferPool *pool;
+
+    pool = gst_video_decoder_get_buffer_pool (GST_VIDEO_DECODER (self));
+    self->copy_frames = gst_va_pool_requires_video_meta (pool);
+    gst_object_unref (pool);
+
+    if (self->copy_frames)
+      GST_INFO_OBJECT (self, "Raw frame copy enabled.");
+  }
+
   return TRUE;
 }
 
@@ -1048,81 +1059,19 @@ gst_va_h264_dec_negotiate (GstVideoDecoder * decoder)
   return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
 }
 
-static inline void
-_shall_copy_frames (GstVaH264Dec * self, GstVideoInfo * info)
-{
-  GstVideoInfo ref_info;
-  guint i;
-
-  self->copy_frames = FALSE;
-
-  if (self->has_videometa)
-    return;
-
-  gst_video_info_set_format (&ref_info, GST_VIDEO_INFO_FORMAT (info),
-      self->display_width, self->display_height);
-
-  for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
-    if (info->stride[i] != ref_info.stride[i] ||
-        info->offset[i] != ref_info.offset[i]) {
-      GST_WARNING_OBJECT (self,
-          "GstVideoMeta support required, copying frames.");
-      self->copy_frames = TRUE;
-      break;
-    }
-  }
-}
-
-static gboolean
-_try_allocator (GstVaH264Dec * self, GstAllocator * allocator, GstCaps * caps)
-{
-  GstVaAllocationParams params = {
-    .usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_DECODER,
-  };
-
-  if (!gst_video_info_from_caps (&params.info, caps))
-    return FALSE;
-  if (self->need_cropping) {
-    GST_VIDEO_INFO_WIDTH (&params.info) = self->coded_width;
-    GST_VIDEO_INFO_HEIGHT (&params.info) = self->coded_height;
-  }
-
-  if (GST_IS_VA_DMABUF_ALLOCATOR (allocator)) {
-    if (!gst_va_dmabuf_try (allocator, &params))
-      return FALSE;
-  } else if (GST_IS_VA_ALLOCATOR (allocator)) {
-    if (!gst_va_allocator_try (allocator, &params))
-      return FALSE;
-    if (!gst_caps_is_vamemory (caps))
-      _shall_copy_frames (self, &params.info);
-  } else {
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
 static GstAllocator *
 _create_allocator (GstVaH264Dec * self, GstCaps * caps)
 {
   GstAllocator *allocator = NULL;
-  GstVaDisplay *display = NULL;
-
-  g_object_get (self->decoder, "display", &display, NULL);
 
   if (gst_caps_is_dmabuf (caps))
-    allocator = gst_va_dmabuf_allocator_new (display);
+    allocator = gst_va_dmabuf_allocator_new (self->display);
   else {
     GArray *surface_formats =
         gst_va_decoder_get_surface_formats (self->decoder);
-    allocator = gst_va_allocator_new (display, surface_formats);
+    allocator = gst_va_allocator_new (self->display, surface_formats);
   }
 
-  gst_object_unref (display);
-
-  if (!_try_allocator (self, allocator, caps))
-    gst_clear_object (&allocator);
-
   return allocator;
 }
 
index b86a115a78d8e646bcae312e300acd0f0ef818fc..63257bdc8505c82bb8d6f1957fee771247b2c6ac 100644 (file)
@@ -25,6 +25,7 @@
 #include "gstvapool.h"
 
 #include "gstvaallocator.h"
+#include "gstvacaps.h"
 
 GST_DEBUG_CATEGORY_STATIC (gst_va_pool_debug);
 #define GST_CAT_DEFAULT gst_va_pool_debug
@@ -36,7 +37,7 @@ struct _GstVaPool
   GstVideoInfo alloc_info;
   GstVideoInfo caps_info;
   GstAllocator *allocator;
-  guint32 usage_hint;
+  gboolean force_videometa;
   gboolean add_videometa;
   gboolean need_alignment;
   GstVideoAlignment video_align;
@@ -74,9 +75,9 @@ gst_va_pool_set_config (GstBufferPool * pool, GstStructure * config)
   GstCaps *caps;
   GstVaPool *vpool = GST_VA_POOL (pool);
   GstVideoAlignment video_align = { 0, };
-  GstVideoInfo caps_info, alloc_info;
+  GstVideoInfo caps_info, alloc_info, orig_info;
   gint width, height;
-  guint min_buffers, max_buffers;
+  guint i, min_buffers, max_buffers;
   guint32 usage_hint;
 
   if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers,
@@ -99,14 +100,12 @@ gst_va_pool_set_config (GstBufferPool * pool, GstStructure * config)
   if (!gst_buffer_pool_config_get_va_allocation_params (config, &usage_hint))
     goto wrong_config;
 
+  orig_info = caps_info;
   width = GST_VIDEO_INFO_WIDTH (&caps_info);
   height = GST_VIDEO_INFO_HEIGHT (&caps_info);
 
   GST_LOG_OBJECT (vpool, "%dx%d | %" GST_PTR_FORMAT, width, height, caps);
 
-  gst_object_replace ((GstObject **) & vpool->allocator,
-      GST_OBJECT (allocator));
-
   /* enable metadata based on config of the pool */
   vpool->add_videometa = gst_buffer_pool_config_has_option (config,
       GST_BUFFER_POOL_OPTION_VIDEO_META);
@@ -128,15 +127,40 @@ gst_va_pool_set_config (GstBufferPool * pool, GstStructure * config)
     gst_buffer_pool_config_set_video_alignment (config, &video_align);
   }
 
+  /* update allocation info with aligned size */
   alloc_info = caps_info;
   GST_VIDEO_INFO_WIDTH (&alloc_info) = width;
   GST_VIDEO_INFO_HEIGHT (&alloc_info) = height;
 
+  if (GST_IS_VA_DMABUF_ALLOCATOR (allocator)) {
+    if (!gst_va_dmabuf_allocator_set_format (allocator, &alloc_info,
+            usage_hint))
+      goto failed_allocator;
+  } else if (GST_IS_VA_ALLOCATOR (allocator)) {
+    if (!gst_va_allocator_set_format (allocator, &alloc_info, usage_hint))
+      goto failed_allocator;
+  }
+
+  gst_object_replace ((GstObject **) & vpool->allocator,
+      GST_OBJECT (allocator));
+
   vpool->caps_info = caps_info;
   vpool->alloc_info = alloc_info;
-  vpool->usage_hint = usage_hint;
   vpool->video_align = video_align;
 
+  if (gst_caps_is_raw (caps)) {
+    for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&caps_info); i++) {
+      if (GST_VIDEO_INFO_PLANE_STRIDE (&orig_info, i) !=
+          GST_VIDEO_INFO_PLANE_STRIDE (&alloc_info, i) ||
+          GST_VIDEO_INFO_PLANE_OFFSET (&orig_info, i) !=
+          GST_VIDEO_INFO_PLANE_OFFSET (&alloc_info, i)) {
+        GST_INFO_OBJECT (vpool, "Video meta is required in buffer.");
+        vpool->force_videometa = TRUE;
+        break;
+      }
+    }
+  }
+
   /* with pooled allocators bufferpool->release_buffer() is cheated
    * because the memories are removed from the buffer at
    * reset_buffer(), then buffer is an empty holder with size 0 while
@@ -167,6 +191,11 @@ failed_to_align:
     GST_WARNING_OBJECT (vpool, "Failed to align");
     return FALSE;
   }
+failed_allocator:
+  {
+    GST_WARNING_OBJECT (vpool, "Failed to set format to allocator");
+    return FALSE;
+  }
 }
 
 static GstFlowReturn
@@ -176,19 +205,14 @@ gst_va_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
   GstBuffer *buf;
   GstVideoMeta *vmeta;
   GstVaPool *vpool = GST_VA_POOL (pool);
-  GstVaAllocationParams alloc_params = {
-    .info = vpool->alloc_info,
-    .usage_hint = vpool->usage_hint,
-  };
 
   buf = gst_buffer_new ();
 
   if (GST_IS_VA_DMABUF_ALLOCATOR (vpool->allocator)) {
-    if (!gst_va_dmabuf_allocator_setup_buffer (vpool->allocator, buf,
-            &alloc_params))
+    if (!gst_va_dmabuf_allocator_setup_buffer (vpool->allocator, buf))
       goto no_memory;
   } else if (GST_IS_VA_ALLOCATOR (vpool->allocator)) {
-    GstMemory *mem = gst_va_allocator_alloc (vpool->allocator, &alloc_params);
+    GstMemory *mem = gst_va_allocator_alloc (vpool->allocator);
     if (!mem)
       goto no_memory;
     gst_buffer_append_memory (buf, mem);
@@ -203,7 +227,7 @@ gst_va_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
         GST_VIDEO_INFO_WIDTH (&vpool->caps_info),
         GST_VIDEO_INFO_HEIGHT (&vpool->caps_info),
         GST_VIDEO_INFO_N_PLANES (&vpool->caps_info),
-        alloc_params.info.offset, alloc_params.info.stride);
+        vpool->alloc_info.offset, vpool->alloc_info.stride);
 
     if (vpool->need_alignment)
       gst_video_meta_set_alignment (vmeta, vpool->video_align);
@@ -342,3 +366,9 @@ gst_buffer_pool_config_set_va_allocation_params (GstStructure * config,
 {
   gst_structure_set (config, "usage-hint", G_TYPE_UINT, usage_hint, NULL);
 }
+
+gboolean
+gst_va_pool_requires_video_meta (GstBufferPool * pool)
+{
+  return GST_VA_POOL (pool)->force_videometa;
+}
index 38e73fe72eb30ea3b4b8638ba95f26993f098a6a..af8416965bc8604beeb8423037863a380e2953b5 100644 (file)
@@ -28,6 +28,7 @@ G_BEGIN_DECLS
 G_DECLARE_FINAL_TYPE (GstVaPool, gst_va_pool, GST, VA_POOL, GstBufferPool)
 
 GstBufferPool *      gst_va_pool_new                      (void);
+gboolean             gst_va_pool_requires_video_meta      (GstBufferPool * pool);
 void                 gst_buffer_pool_config_set_va_allocation_params (GstStructure * config,
                                                            guint usage_hint);
 G_END_DECLS
index e9f2d4033ed31d0e8dab55dd5c46ad3a5d938f91..dfcc71f7e878e671f018d5ddd33743a22e70e342 100644 (file)
@@ -367,77 +367,19 @@ gst_va_vp8_dec_negotiate (GstVideoDecoder * decoder)
   return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
 }
 
-static inline void
-_shall_copy_frames (GstVaVp8Dec * self, GstVideoInfo * info)
-{
-  GstVideoInfo ref_info;
-  guint i;
-
-  self->copy_frames = FALSE;
-
-  if (self->has_videometa)
-    return;
-
-  gst_video_info_set_format (&ref_info, GST_VIDEO_INFO_FORMAT (info),
-      self->width, self->height);
-
-  for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
-    if (info->stride[i] != ref_info.stride[i] ||
-        info->offset[i] != ref_info.offset[i]) {
-      GST_WARNING_OBJECT (self,
-          "GstVideoMeta support required, copying frames.");
-      self->copy_frames = TRUE;
-      break;
-    }
-  }
-}
-
-static gboolean
-_try_allocator (GstVaVp8Dec * self, GstAllocator * allocator, GstCaps * caps)
-{
-  GstVaAllocationParams params = {
-    .usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_DECODER,
-  };
-
-  if (!gst_video_info_from_caps (&params.info, caps))
-    return FALSE;
-
-  if (GST_IS_VA_DMABUF_ALLOCATOR (allocator)) {
-    if (!gst_va_dmabuf_try (allocator, &params))
-      return FALSE;
-  } else if (GST_IS_VA_ALLOCATOR (allocator)) {
-    if (!gst_va_allocator_try (allocator, &params))
-      return FALSE;
-    if (!gst_caps_is_vamemory (caps))
-      _shall_copy_frames (self, &params.info);
-  } else {
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
 static GstAllocator *
 _create_allocator (GstVaVp8Dec * self, GstCaps * caps)
 {
   GstAllocator *allocator = NULL;
-  GstVaDisplay *display = NULL;
-
-  g_object_get (self->decoder, "display", &display, NULL);
 
-  if (gst_caps_is_dmabuf (caps))
-    allocator = gst_va_dmabuf_allocator_new (display);
-  else {
+  if (gst_caps_is_dmabuf (caps)) {
+    allocator = gst_va_dmabuf_allocator_new (self->display);
+  else {
     GArray *surface_formats =
         gst_va_decoder_get_surface_formats (self->decoder);
-    allocator = gst_va_allocator_new (display, surface_formats);
+    allocator = gst_va_allocator_new (self->display, surface_formats);
   }
 
-  gst_object_unref (display);
-
-  if (!_try_allocator (self, allocator, caps))
-    gst_clear_object (&allocator);
-
   return allocator;
 }
 
@@ -657,6 +599,14 @@ gst_va_vp8_dec_new_sequence (GstVp8Decoder * decoder,
     }
   }
 
+  if (!self->has_videometa) {
+    GstBufferPool *pool;
+
+    pool = gst_video_decoder_get_buffer_pool (GST_VIDEO_DECODER (self));
+    self->copy_frames = gst_va_pool_requires_video_meta (pool);
+    gst_object_unref (pool);
+  }
+
   return TRUE;
 }
 
index 022c33f99b805626f860785ef55f25977d2f82eb..b5f944c6704313b10c155b458404d320e07400f0 100644 (file)
@@ -395,29 +395,6 @@ gst_va_vpp_set_context (GstElement * element, GstContext * context)
   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
 }
 
-static gboolean
-_try_allocator (GstVaVpp * self, GstAllocator * allocator, GstCaps * caps,
-    guint usage_hint)
-{
-  GstVaAllocationParams params = {
-    .usage_hint = usage_hint,
-  };
-
-  if (!gst_video_info_from_caps (&params.info, caps))
-    return FALSE;
-  if (GST_IS_VA_DMABUF_ALLOCATOR (allocator)) {
-    if (!gst_va_dmabuf_try (allocator, &params))
-      return FALSE;
-  } else if (GST_IS_VA_ALLOCATOR (allocator)) {
-    if (!gst_va_allocator_try (allocator, &params))
-      return FALSE;
-  } else {
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
 static GstAllocator *
 _create_allocator (GstVaVpp * self, GstCaps * caps, guint usage_hint)
 {
@@ -430,9 +407,6 @@ _create_allocator (GstVaVpp * self, GstCaps * caps, guint usage_hint)
     allocator = gst_va_allocator_new (self->display, surface_formats);
   }
 
-  if (!_try_allocator (self, allocator, caps, usage_hint))
-    gst_clear_object (&allocator);
-
   return allocator;
 }