{
GstPad *sinkpad, *srcpad;
- upload->display = NULL;
- upload->images = NULL;
- upload->images_reset = FALSE;
- upload->image_width = 0;
- upload->image_height = 0;
- upload->surfaces = NULL;
- upload->surfaces_reset = FALSE;
- upload->surface_width = 0;
- upload->surface_height = 0;
- upload->direct_rendering_caps = 0;
- upload->direct_rendering = G_MAXUINT32;
+ upload->display = NULL;
+ upload->images = NULL;
+ upload->images_reset = FALSE;
+ upload->image_width = 0;
+ upload->image_height = 0;
+ upload->surfaces = NULL;
+ upload->surfaces_reset = FALSE;
+ upload->surface_width = 0;
+ upload->surface_height = 0;
+ upload->direct_rendering_caps = 0;
+ upload->direct_rendering = G_MAXUINT32;
+ upload->need_manual_upload = FALSE;
/* Override buffer allocator on sink pad */
sinkpad = gst_element_get_static_pad(GST_ELEMENT(upload), "sink");
GstVaapiVideoBuffer *vbuffer;
GstVaapiSurface *surface;
GstVaapiImage *image;
- GstCaps *buffer_caps;
gboolean success;
- GstVaapiImageFormat buffer_format;
- gboolean format_changed;
vbuffer = GST_VAAPI_VIDEO_BUFFER(outbuf);
surface = gst_vaapi_video_buffer_get_surface(vbuffer);
image = gst_vaapi_video_pool_get_object(upload->images);
if (!image)
- return GST_FLOW_UNEXPECTED;
+ goto error_put_image;
+
+ if (!upload->need_manual_upload) {
+ gst_vaapi_image_update_from_buffer(image, inbuf, NULL);
+ } else { /* manually copy data to image*/
+ success = gst_vaapi_upload_buffer_to_image(image, inbuf);
+ if (!success)
+ goto error_put_image;
+ }
- gst_vaapi_image_update_from_buffer(image, inbuf, NULL);
success = gst_vaapi_surface_put_image(surface, image);
gst_vaapi_video_pool_put_object(upload->images, image);
if (!success)
goto error_put_image;
flow_ok:
- FPS_CALCULATION(vaapiconvert);
+ FPS_CALCULATION(vaapiupload);
return GST_FLOW_OK;
error_put_image:
}
}
+typedef enum YUV_TYPE {
+ YUV_UNKOWN = 0,
+ YUV_411 = 1,
+ YUV_422 = 2,
+ YUV_444 = 4
+} YUV_TYPE;
+
+static YUV_TYPE
+_image_format_to_yuv_type(guint32 fourcc)
+{
+ switch (fourcc) {
+ case GST_MAKE_FOURCC('N','V','1','2'):
+ case GST_MAKE_FOURCC('Y','V','1','2'):
+ case GST_MAKE_FOURCC('I','4','2','0'):
+ case GST_MAKE_FOURCC('N','V','2','1'):
+ return YUV_411;
+
+ case GST_MAKE_FOURCC('Y','U','Y','2'):
+ case GST_MAKE_FOURCC('Y','V','Y','U'):
+ return YUV_422;
+
+ case GST_MAKE_FOURCC('A','Y','U','V'):
+ return YUV_UNKOWN;
+
+ default:
+ return YUV_UNKOWN;
+ }
+}
+
+static GstCaps *
+_get_nearest_caps(GstCaps *caps_list, GstCaps *src_caps)
+{
+ GstCaps *ret = NULL;
+ GstStructure *cur_struct, *tmp_struct;
+ guint32 cur_format, dest_format, tmp_format;
+ YUV_TYPE cur_type, tmp_type;
+ const GValue*tmp_val;
+ guint n_caps;
+ guint i;
+ guint min_diff, tmp_diff;
+
+ cur_struct = gst_caps_get_structure(src_caps, 0);
+ tmp_val = gst_structure_get_value (cur_struct, "format");
+ if (!tmp_val)
+ return NULL;
+
+ cur_format = gst_value_get_fourcc(tmp_val);
+ if((cur_type = _image_format_to_yuv_type(cur_format)) == YUV_UNKOWN)
+ return NULL;
+
+ n_caps = gst_caps_get_size(caps_list);
+ min_diff = 100;
+ dest_format = 0;
+ for (i = 0; i < n_caps; ++i) {
+ tmp_struct = gst_caps_get_structure(caps_list, i);
+ tmp_val = gst_structure_get_value (tmp_struct, "format");
+ if (!tmp_val)
+ continue;
+ tmp_format = gst_value_get_fourcc(tmp_val);
+ if ((tmp_type = _image_format_to_yuv_type(tmp_format)) == YUV_UNKOWN)
+ continue;
+ tmp_diff = abs(tmp_type - cur_type);
+ if (tmp_diff < min_diff) {
+ min_diff = tmp_diff;
+ dest_format = tmp_format;
+ }
+ }
+
+ if (dest_format == 0)
+ return NULL;
+
+ ret = gst_caps_copy(src_caps);
+ tmp_struct = gst_caps_get_structure(ret, 0);
+ gst_structure_set(tmp_struct, "format", GST_TYPE_FOURCC, dest_format, NULL);
+ return ret;
+}
+
static gboolean
gst_vaapiupload_negotiate_buffers(
GstVaapiUpload *upload,
)
{
guint dr;
+ gboolean ret = TRUE;
+ GstCaps *image_allowed_caps = NULL;
+ GstCaps *image_caps = NULL;
+
+ image_allowed_caps = gst_vaapi_display_get_image_caps(upload->display);
+ if (gst_caps_can_intersect(incaps, image_allowed_caps)) {
+ image_caps = gst_caps_ref(incaps);
+ upload->need_manual_upload = FALSE;
+ } else {
+ image_caps = _get_nearest_caps(image_allowed_caps, incaps);
+ upload->need_manual_upload = TRUE;
+ }
- if (!gst_vaapiupload_ensure_image_pool(upload, incaps))
- return FALSE;
+ if (!gst_vaapiupload_ensure_image_pool(upload, image_caps))
+ goto failed;
if (!gst_vaapiupload_ensure_surface_pool(upload, outcaps))
- return FALSE;
+ goto failed;
- if (upload->direct_rendering)
- gst_vaapiupload_ensure_direct_rendering_caps(upload, incaps);
+ if (upload->direct_rendering && !upload->need_manual_upload)
+ gst_vaapiupload_ensure_direct_rendering_caps(upload, incaps);
dr = MIN(upload->direct_rendering, upload->direct_rendering_caps);
if (upload->direct_rendering != dr) {
upload->direct_rendering = dr;
- return TRUE;
+ GST_DEBUG("direct-rendering level: %d", dr);
+ }
+ ret = TRUE;
+ goto end;
+
+ failed:
+ ret = FALSE;
+
+ end:
+ gst_caps_unref(image_caps);
+ gst_caps_unref(image_allowed_caps);
+ return ret;
}
static gboolean
GstVaapiSurface *surface = NULL;
GstVaapiVideoBuffer *vbuffer;
+ /* already checked */
+ if (!upload->direct_rendering)
+ return GST_FLOW_OK;
+
/* Check if we can use direct-rendering */
if (!gst_vaapiupload_negotiate_buffers(upload, caps, caps))
goto error;