d3d11colorconverter: Add support cropping

Vertex buffer will be updated if input texture resolution is different
from GstVideoInfo or when an user requests specific crop area.
This commit is contained in:
Seungha Yang 2020-03-07 18:29:20 +09:00 committed by Seungha Yang
parent c6c83ca493
commit 5074cecc82
2 changed files with 141 additions and 0 deletions

View file

@ -291,6 +291,12 @@ struct _GstD3D11ColorConverter
D3D11_VIEWPORT viewport[GST_VIDEO_MAX_PLANES];
RECT crop_rect;
gint input_texture_width;
gint input_texture_height;
ID3D11Buffer *vertex_buffer;
gboolean update_vertex;
ConvertInfo convert_info;
};
@ -1048,6 +1054,18 @@ gst_d3d11_color_convert_setup_shader (GstD3D11ColorConverter * self,
self->num_input_view = GST_VIDEO_INFO_N_PLANES (in_info);
self->num_output_view = GST_VIDEO_INFO_N_PLANES (out_info);
/* holds vertex buffer for crop rect update */
self->vertex_buffer = vertex_buffer;
ID3D11Buffer_AddRef (vertex_buffer);
self->crop_rect.left = 0;
self->crop_rect.top = 0;
self->crop_rect.right = GST_VIDEO_INFO_WIDTH (in_info);
self->crop_rect.bottom = GST_VIDEO_INFO_HEIGHT (in_info);
self->input_texture_width = GST_VIDEO_INFO_WIDTH (in_info);
self->input_texture_height = GST_VIDEO_INFO_HEIGHT (in_info);
clear:
for (i = 0; i < CONVERTER_MAX_QUADS; i++) {
if (ps[i])
@ -1203,10 +1221,88 @@ gst_d3d11_color_converter_free (GstD3D11ColorConverter * converter)
g_free (converter->convert_info.ps_body[i]);
}
if (converter->vertex_buffer)
ID3D11Buffer_Release (converter->vertex_buffer);
gst_clear_object (&converter->device);
g_free (converter);
}
/* must be called with gst_d3d11_device_lock since ID3D11DeviceContext is not
* thread-safe */
static gboolean
gst_d3d11_color_converter_update_vertex_buffer (GstD3D11ColorConverter * self)
{
D3D11_MAPPED_SUBRESOURCE map;
VertexData *vertex_data;
ID3D11DeviceContext *context_handle;
HRESULT hr;
FLOAT u, v;
const RECT *crop_rect = &self->crop_rect;
gint texture_width = self->input_texture_width;
gint texture_height = self->input_texture_height;
context_handle = gst_d3d11_device_get_device_context_handle (self->device);
hr = ID3D11DeviceContext_Map (context_handle,
(ID3D11Resource *) self->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD,
0, &map);
if (!gst_d3d11_result (hr, self->device)) {
GST_ERROR ("Couldn't map vertex buffer, hr: 0x%x", (guint) hr);
return FALSE;
}
vertex_data = (VertexData *) map.pData;
/* bottom left */
u = (crop_rect->left / (gfloat) texture_width) - 0.5f / texture_width;
v = (crop_rect->bottom / (gfloat) texture_height) - 0.5f / texture_height;
vertex_data[0].position.x = -1.0f;
vertex_data[0].position.y = -1.0f;
vertex_data[0].position.z = 0.0f;
vertex_data[0].texture.x = u;
vertex_data[0].texture.y = v;
/* top left */
u = (crop_rect->left / (gfloat) texture_width) - 0.5f / texture_width;
v = (crop_rect->top / (gfloat) texture_height) - 0.5f / texture_height;
vertex_data[1].position.x = -1.0f;
vertex_data[1].position.y = 1.0f;
vertex_data[1].position.z = 0.0f;
vertex_data[1].texture.x = u;
vertex_data[1].texture.y = v;
/* top right */
u = (crop_rect->right / (gfloat) texture_width) - 0.5f / texture_width;
v = (crop_rect->top / (gfloat) texture_height) - 0.5f / texture_height;
vertex_data[2].position.x = 1.0f;
vertex_data[2].position.y = 1.0f;
vertex_data[2].position.z = 0.0f;
vertex_data[2].texture.x = u;
vertex_data[2].texture.y = v;
/* bottom right */
u = (crop_rect->right / (gfloat) texture_width) - 0.5f / texture_width;
v = (crop_rect->bottom / (gfloat) texture_height) - 0.5f / texture_height;
vertex_data[3].position.x = 1.0f;
vertex_data[3].position.y = -1.0f;
vertex_data[3].position.z = 0.0f;
vertex_data[3].texture.x = u;
vertex_data[3].texture.y = v;
ID3D11DeviceContext_Unmap (context_handle,
(ID3D11Resource *) self->vertex_buffer, 0);
self->update_vertex = FALSE;
return TRUE;
}
gboolean
gst_d3d11_color_converter_convert (GstD3D11ColorConverter * converter,
ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES],
@ -1231,11 +1327,33 @@ gst_d3d11_color_converter_convert_unlocked (GstD3D11ColorConverter * converter,
ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES])
{
gboolean ret;
ID3D11Resource *resource;
D3D11_TEXTURE2D_DESC desc;
g_return_val_if_fail (converter != NULL, FALSE);
g_return_val_if_fail (srv != NULL, FALSE);
g_return_val_if_fail (rtv != NULL, FALSE);
/* check texture resolution and update crop area */
ID3D11ShaderResourceView_GetResource (srv[0], &resource);
ID3D11Texture2D_GetDesc ((ID3D11Texture2D *) resource, &desc);
ID3D11Resource_Release (resource);
if (converter->update_vertex ||
desc.Width != converter->input_texture_width ||
desc.Height != converter->input_texture_height) {
GST_DEBUG ("Update vertext buffer, texture resolution: %dx%d",
desc.Width, desc.Height);
converter->input_texture_width = desc.Width;
converter->input_texture_height = desc.Height;
if (!gst_d3d11_color_converter_update_vertex_buffer (converter)) {
GST_ERROR ("Cannot update vertex buffer");
return FALSE;
}
}
ret = gst_d3d11_draw_quad_unlocked (converter->quad[0], converter->viewport,
1, srv, converter->num_input_view, rtv, 1, NULL);
@ -1292,3 +1410,23 @@ gst_d3d11_color_converter_update_rect (GstD3D11ColorConverter * converter,
return TRUE;
}
gboolean
gst_d3d11_color_converter_update_crop_rect (GstD3D11ColorConverter * converter,
RECT * crop_rect)
{
g_return_val_if_fail (converter != NULL, FALSE);
g_return_val_if_fail (crop_rect != NULL, FALSE);
if (converter->crop_rect.left != crop_rect->left ||
converter->crop_rect.top != crop_rect->top ||
converter->crop_rect.right != crop_rect->right ||
converter->crop_rect.bottom != crop_rect->bottom) {
converter->crop_rect = *crop_rect;
/* vertex buffer will be updated on next convert() call */
converter->update_vertex = TRUE;
}
return TRUE;
}

View file

@ -45,6 +45,9 @@ gboolean gst_d3d11_color_converter_convert_unlocked (GstD3D11Col
gboolean gst_d3d11_color_converter_update_rect (GstD3D11ColorConverter * converter,
RECT *rect);
gboolean gst_d3d11_color_converter_update_crop_rect (GstD3D11ColorConverter * converter,
RECT *crop_rect);
G_END_DECLS
#endif /* __GST_D3D11_COLOR_CONVERTER_H__ */