plugins: allow download capability to vaapidecode element.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Tue, 22 Jul 2014 16:54:29 +0000 (18:54 +0200)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Tue, 22 Jul 2014 17:06:52 +0000 (19:06 +0200)
Fix support for VA surface download capability in vaapidecode element
for GStreamer >= 1.2. This is a fix to supporting libva-vdpau-driver,
but also the libva-intel-driver while performing hardware accelerated
conversions from the native VA surface format (NV12) to the desired
output VA image format.

For instance, this fixes pipelines involving vaapidecode ! xvimagesink.

https://bugzilla.gnome.org/show_bug.cgi?id=733243

gst/vaapi/gstvaapidecode.c
gst/vaapi/gstvaapivideomemory.c

index 1d97c62..1e94561 100644 (file)
@@ -155,6 +155,7 @@ gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
     GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
     GstVideoCodecState *state;
     GstVideoInfo *vi, vis;
+    GstVideoFormat format, out_format;
 #if GST_CHECK_VERSION(1,1,0)
     GstCapsFeatures *features = NULL;
     GstVaapiCapsFeature feature;
@@ -164,17 +165,28 @@ gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
         GST_VIDEO_INFO_FORMAT(&ref_state->info));
 #endif
 
-    state = gst_video_decoder_set_output_state(vdec,
-        GST_VIDEO_INFO_FORMAT(&ref_state->info),
+    format = GST_VIDEO_INFO_FORMAT(&ref_state->info);
+
+    state = gst_video_decoder_set_output_state(vdec, format,
         ref_state->info.width, ref_state->info.height,
         (GstVideoCodecState *)ref_state);
     if (!state)
         return FALSE;
 
     vi = &state->info;
-    if (GST_VIDEO_INFO_FORMAT(vi) == GST_VIDEO_FORMAT_ENCODED) {
+    out_format = format;
+    if (format == GST_VIDEO_FORMAT_ENCODED) {
+#if GST_CHECK_VERSION(1,1,0)
+        out_format = GST_VIDEO_FORMAT_NV12;
+        if (feature == GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY) {
+            /* XXX: intercept with the preferred output format.
+               Anyway, I420 is the minimum format that drivers
+               should support to be useful */
+            out_format = GST_VIDEO_FORMAT_I420;
+        }
+#endif
         gst_video_info_init(&vis);
-        gst_video_info_set_format(&vis, GST_VIDEO_FORMAT_NV12,
+        gst_video_info_set_format(&vis, out_format,
             GST_VIDEO_INFO_WIDTH(vi), GST_VIDEO_INFO_HEIGHT(vi));
         vi->size = vis.size;
     }
@@ -190,12 +202,12 @@ gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
             GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, NULL);
         break;
     default:
-        if (GST_VIDEO_INFO_FORMAT(vi) == GST_VIDEO_FORMAT_ENCODED) {
+        if (format == GST_VIDEO_FORMAT_ENCODED) {
             /* XXX: this is a workaround until auto-plugging is fixed when
             format=ENCODED + memory:VASurface caps feature are provided.
             Meanwhile, providing a random format here works but this is
             a terribly wrong thing per se. */
-            gst_vaapidecode_video_info_change_format(&vis, GST_VIDEO_FORMAT_NV12,
+            gst_vaapidecode_video_info_change_format(&vis, out_format,
                 GST_VIDEO_INFO_WIDTH(vi), GST_VIDEO_INFO_HEIGHT(vi));
 #if GST_CHECK_VERSION(1,3,0)
             if (feature == GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE)
index cb953c1..38049b0 100644 (file)
@@ -51,6 +51,11 @@ ensure_image(GstVaapiVideoMemory *mem)
             GST_WARNING("failed to derive image, fallbacking to copy");
             mem->use_direct_rendering = FALSE;
         }
+        else if (gst_vaapi_surface_get_format(mem->surface) !=
+                 GST_VIDEO_INFO_FORMAT(mem->image_info)) {
+            gst_vaapi_object_replace(&mem->image, NULL);
+            mem->use_direct_rendering = FALSE;
+        }
     }
 
     if (!mem->image) {
@@ -142,10 +147,14 @@ gst_video_meta_map_vaapi_memory(GstVideoMeta *meta, guint plane,
             goto error_ensure_image;
 
         // Check that we can actually map the surface, or image
-        if ((flags & GST_MAP_READWRITE) != GST_MAP_WRITE &&
+        if ((flags & GST_MAP_READWRITE) == GST_MAP_WRITE &&
             !mem->use_direct_rendering)
             goto error_unsupported_map;
 
+        // Load VA image from surface
+        if ((flags & GST_MAP_READ) && !mem->use_direct_rendering)
+            gst_vaapi_surface_get_image(mem->surface, mem->image);
+
         if (!gst_vaapi_image_map(mem->image))
             goto error_map_image;
         mem->map_type = GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR;