d3d11overlaycompositor: Objectify overlay render implementation
Be consistent with other implementations Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2697>
This commit is contained in:
parent
b2d09de899
commit
fdbb9041a2
@ -77,10 +77,9 @@ static const gchar templ_vertex_shader[] =
|
|||||||
"}\n";
|
"}\n";
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
struct _GstD3D11OverlayCompositor
|
struct _GstD3D11OverlayCompositorPrivate
|
||||||
{
|
{
|
||||||
GstD3D11Device *device;
|
GstVideoInfo info;
|
||||||
GstVideoInfo out_info;
|
|
||||||
|
|
||||||
D3D11_VIEWPORT viewport;
|
D3D11_VIEWPORT viewport;
|
||||||
|
|
||||||
@ -103,11 +102,55 @@ typedef struct
|
|||||||
ID3D11Buffer *vertex_buffer;
|
ID3D11Buffer *vertex_buffer;
|
||||||
} GstD3D11CompositionOverlay;
|
} GstD3D11CompositionOverlay;
|
||||||
|
|
||||||
|
static void gst_d3d11_overlay_compositor_dispose (GObject * object);
|
||||||
|
static void
|
||||||
|
gst_d3d11_overlay_compositor_free_overlays (GstD3D11OverlayCompositor * self);
|
||||||
|
|
||||||
|
#define gst_d3d11_overlay_compositor_parent_class parent_class
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE (GstD3D11OverlayCompositor,
|
||||||
|
gst_d3d11_overlay_compositor, GST_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_d3d11_overlay_compositor_class_init (GstD3D11OverlayCompositorClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->dispose = gst_d3d11_overlay_compositor_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_d3d11_overlay_compositor_init (GstD3D11OverlayCompositor * self)
|
||||||
|
{
|
||||||
|
self->priv = (GstD3D11OverlayCompositorPrivate *)
|
||||||
|
gst_d3d11_overlay_compositor_get_instance_private (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_d3d11_overlay_compositor_dispose (GObject * object)
|
||||||
|
{
|
||||||
|
GstD3D11OverlayCompositor *self = GST_D3D11_OVERLAY_COMPOSITOR (object);
|
||||||
|
GstD3D11OverlayCompositorPrivate *priv = self->priv;
|
||||||
|
|
||||||
|
gst_d3d11_overlay_compositor_free_overlays (self);
|
||||||
|
|
||||||
|
GST_D3D11_CLEAR_COM (priv->ps);
|
||||||
|
GST_D3D11_CLEAR_COM (priv->vs);
|
||||||
|
GST_D3D11_CLEAR_COM (priv->layout);
|
||||||
|
GST_D3D11_CLEAR_COM (priv->sampler);
|
||||||
|
GST_D3D11_CLEAR_COM (priv->blend);
|
||||||
|
GST_D3D11_CLEAR_COM (priv->index_buffer);
|
||||||
|
|
||||||
|
gst_clear_object (&self->device);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
static GstD3D11CompositionOverlay *
|
static GstD3D11CompositionOverlay *
|
||||||
gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
||||||
GstVideoOverlayRectangle * overlay_rect)
|
GstVideoOverlayRectangle * overlay_rect)
|
||||||
{
|
{
|
||||||
GstD3D11CompositionOverlay *overlay = NULL;
|
GstD3D11OverlayCompositorPrivate *priv = self->priv;
|
||||||
|
GstD3D11CompositionOverlay *overlay = nullptr;
|
||||||
gint x, y;
|
gint x, y;
|
||||||
guint width, height;
|
guint width, height;
|
||||||
D3D11_SUBRESOURCE_DATA subresource_data;
|
D3D11_SUBRESOURCE_DATA subresource_data;
|
||||||
@ -131,8 +174,6 @@ gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
|||||||
ComPtr < ID3D11ShaderResourceView > srv;
|
ComPtr < ID3D11ShaderResourceView > srv;
|
||||||
ComPtr < ID3D11Buffer > vertex_buffer;
|
ComPtr < ID3D11Buffer > vertex_buffer;
|
||||||
|
|
||||||
g_return_val_if_fail (overlay_rect != NULL, NULL);
|
|
||||||
|
|
||||||
memset (&subresource_data, 0, sizeof (subresource_data));
|
memset (&subresource_data, 0, sizeof (subresource_data));
|
||||||
memset (&texture_desc, 0, sizeof (texture_desc));
|
memset (&texture_desc, 0, sizeof (texture_desc));
|
||||||
memset (&srv_desc, 0, sizeof (srv_desc));
|
memset (&srv_desc, 0, sizeof (srv_desc));
|
||||||
@ -143,27 +184,27 @@ gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
|||||||
|
|
||||||
if (!gst_video_overlay_rectangle_get_render_rectangle (overlay_rect, &x, &y,
|
if (!gst_video_overlay_rectangle_get_render_rectangle (overlay_rect, &x, &y,
|
||||||
&width, &height)) {
|
&width, &height)) {
|
||||||
GST_ERROR ("Failed to get render rectangle");
|
GST_ERROR_OBJECT (self, "Failed to get render rectangle");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = gst_video_overlay_rectangle_get_pixels_unscaled_argb (overlay_rect,
|
buf = gst_video_overlay_rectangle_get_pixels_unscaled_argb (overlay_rect,
|
||||||
GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
|
GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
GST_ERROR ("Failed to get overlay buffer");
|
GST_ERROR_OBJECT (self, "Failed to get overlay buffer");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
vmeta = gst_buffer_get_video_meta (buf);
|
vmeta = gst_buffer_get_video_meta (buf);
|
||||||
if (!vmeta) {
|
if (!vmeta) {
|
||||||
GST_ERROR ("Failed to get video meta");
|
GST_ERROR_OBJECT (self, "Failed to get video meta");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_video_meta_map (vmeta,
|
if (!gst_video_meta_map (vmeta,
|
||||||
0, &info, (gpointer *) & data, &stride, GST_MAP_READ)) {
|
0, &info, (gpointer *) & data, &stride, GST_MAP_READ)) {
|
||||||
GST_ERROR ("Failed to map");
|
GST_ERROR_OBJECT (self, "Failed to map");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do create texture and upload data at once, for create immutable texture */
|
/* Do create texture and upload data at once, for create immutable texture */
|
||||||
@ -175,7 +216,6 @@ gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
|||||||
texture_desc.Height = height;
|
texture_desc.Height = height;
|
||||||
texture_desc.MipLevels = 1;
|
texture_desc.MipLevels = 1;
|
||||||
texture_desc.ArraySize = 1;
|
texture_desc.ArraySize = 1;
|
||||||
/* FIXME: need to consider non-BGRA ? */
|
|
||||||
texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
texture_desc.SampleDesc.Count = 1;
|
texture_desc.SampleDesc.Count = 1;
|
||||||
texture_desc.SampleDesc.Quality = 0;
|
texture_desc.SampleDesc.Quality = 0;
|
||||||
@ -188,8 +228,8 @@ gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
|||||||
gst_video_meta_unmap (vmeta, 0, &info);
|
gst_video_meta_unmap (vmeta, 0, &info);
|
||||||
|
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
if (!gst_d3d11_result (hr, device)) {
|
||||||
GST_ERROR ("Failed to create texture");
|
GST_ERROR_OBJECT (self, "Failed to create texture");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||||
@ -198,8 +238,8 @@ gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
|||||||
hr = device_handle->CreateShaderResourceView (texture.Get (), &srv_desc,
|
hr = device_handle->CreateShaderResourceView (texture.Get (), &srv_desc,
|
||||||
&srv);
|
&srv);
|
||||||
if (!gst_d3d11_result (hr, device) || !srv) {
|
if (!gst_d3d11_result (hr, device) || !srv) {
|
||||||
GST_ERROR ("Failed to create shader resource view");
|
GST_ERROR_OBJECT (self, "Failed to create shader resource view");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
|
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
@ -207,10 +247,11 @@ gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
|||||||
buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||||
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||||
|
|
||||||
hr = device_handle->CreateBuffer (&buffer_desc, NULL, &vertex_buffer);
|
hr = device_handle->CreateBuffer (&buffer_desc, nullptr, &vertex_buffer);
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
if (!gst_d3d11_result (hr, device)) {
|
||||||
GST_ERROR ("Couldn't create vertex buffer, hr: 0x%x", (guint) hr);
|
GST_ERROR_OBJECT (self,
|
||||||
return NULL;
|
"Couldn't create vertex buffer, hr: 0x%x", (guint) hr);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_d3d11_device_lock (device);
|
gst_d3d11_device_lock (device);
|
||||||
@ -218,27 +259,26 @@ gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
|
|||||||
0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||||
|
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
if (!gst_d3d11_result (hr, device)) {
|
||||||
GST_ERROR ("Couldn't map vertex buffer, hr: 0x%x", (guint) hr);
|
GST_ERROR_OBJECT (self, "Couldn't map vertex buffer, hr: 0x%x", (guint) hr);
|
||||||
gst_d3d11_device_unlock (device);
|
gst_d3d11_device_unlock (device);
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
vertex_data = (VertexData *) map.pData;
|
vertex_data = (VertexData *) map.pData;
|
||||||
/* bottom left */
|
/* bottom left */
|
||||||
gst_util_fraction_to_double (x, GST_VIDEO_INFO_WIDTH (&self->out_info), &val);
|
gst_util_fraction_to_double (x, GST_VIDEO_INFO_WIDTH (&priv->info), &val);
|
||||||
x1 = (val * 2.0f) - 1.0f;
|
x1 = (val * 2.0f) - 1.0f;
|
||||||
|
|
||||||
gst_util_fraction_to_double (y + height,
|
gst_util_fraction_to_double (y + height,
|
||||||
GST_VIDEO_INFO_HEIGHT (&self->out_info), &val);
|
GST_VIDEO_INFO_HEIGHT (&priv->info), &val);
|
||||||
y1 = (val * -2.0f) + 1.0f;
|
y1 = (val * -2.0f) + 1.0f;
|
||||||
|
|
||||||
/* top right */
|
/* top right */
|
||||||
gst_util_fraction_to_double (x + width,
|
gst_util_fraction_to_double (x + width,
|
||||||
GST_VIDEO_INFO_WIDTH (&self->out_info), &val);
|
GST_VIDEO_INFO_WIDTH (&priv->info), &val);
|
||||||
x2 = (val * 2.0f) - 1.0f;
|
x2 = (val * 2.0f) - 1.0f;
|
||||||
|
|
||||||
gst_util_fraction_to_double (y,
|
gst_util_fraction_to_double (y, GST_VIDEO_INFO_HEIGHT (&priv->info), &val);
|
||||||
GST_VIDEO_INFO_HEIGHT (&self->out_info), &val);
|
|
||||||
y2 = (val * -2.0f) + 1.0f;
|
y2 = (val * -2.0f) + 1.0f;
|
||||||
|
|
||||||
/* bottom left */
|
/* bottom left */
|
||||||
@ -298,9 +338,11 @@ gst_d3d11_composition_overlay_free (GstD3D11CompositionOverlay * overlay)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self,
|
gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self)
|
||||||
GstD3D11Device * device)
|
|
||||||
{
|
{
|
||||||
|
GstD3D11OverlayCompositorPrivate *priv = self->priv;
|
||||||
|
GstVideoInfo *info = &priv->info;
|
||||||
|
GstD3D11Device *device = self->device;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
D3D11_SAMPLER_DESC sampler_desc;
|
D3D11_SAMPLER_DESC sampler_desc;
|
||||||
D3D11_INPUT_ELEMENT_DESC input_desc[2];
|
D3D11_INPUT_ELEMENT_DESC input_desc[2];
|
||||||
@ -336,14 +378,13 @@ gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self,
|
|||||||
|
|
||||||
hr = device_handle->CreateSamplerState (&sampler_desc, &sampler);
|
hr = device_handle->CreateSamplerState (&sampler_desc, &sampler);
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
if (!gst_d3d11_result (hr, device)) {
|
||||||
GST_ERROR ("Couldn't create sampler state, hr: 0x%x", (guint) hr);
|
GST_ERROR_OBJECT (self, "Couldn't create sampler state, hr: 0x%x",
|
||||||
|
(guint) hr);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG ("Create Pixel Shader \n%s", templ_pixel_shader);
|
|
||||||
|
|
||||||
if (!gst_d3d11_create_pixel_shader (device, templ_pixel_shader, &ps)) {
|
if (!gst_d3d11_create_pixel_shader (device, templ_pixel_shader, &ps)) {
|
||||||
GST_ERROR ("Couldn't create pixel shader");
|
GST_ERROR_OBJECT (self, "Couldn't create pixel shader");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,7 +406,7 @@ gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self,
|
|||||||
|
|
||||||
if (!gst_d3d11_create_vertex_shader (device, templ_vertex_shader,
|
if (!gst_d3d11_create_vertex_shader (device, templ_vertex_shader,
|
||||||
input_desc, G_N_ELEMENTS (input_desc), &vs, &layout)) {
|
input_desc, G_N_ELEMENTS (input_desc), &vs, &layout)) {
|
||||||
GST_ERROR ("Couldn't vertex pixel shader");
|
GST_ERROR_OBJECT (self, "Couldn't vertex pixel shader");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +424,8 @@ gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self,
|
|||||||
|
|
||||||
hr = device_handle->CreateBlendState (&blend_desc, &blend);
|
hr = device_handle->CreateBlendState (&blend_desc, &blend);
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
if (!gst_d3d11_result (hr, device)) {
|
||||||
GST_ERROR ("Couldn't create blend staten, hr: 0x%x", (guint) hr);
|
GST_ERROR_OBJECT (self,
|
||||||
|
"Couldn't create blend staten, hr: 0x%x", (guint) hr);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,9 +434,10 @@ gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self,
|
|||||||
buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||||
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||||
|
|
||||||
hr = device_handle->CreateBuffer (&buffer_desc, NULL, &index_buffer);
|
hr = device_handle->CreateBuffer (&buffer_desc, nullptr, &index_buffer);
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
if (!gst_d3d11_result (hr, device)) {
|
||||||
GST_ERROR ("Couldn't create index buffer, hr: 0x%x", (guint) hr);
|
GST_ERROR_OBJECT (self,
|
||||||
|
"Couldn't create index buffer, hr: 0x%x", (guint) hr);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +446,7 @@ gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self,
|
|||||||
0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||||
|
|
||||||
if (!gst_d3d11_result (hr, device)) {
|
if (!gst_d3d11_result (hr, device)) {
|
||||||
GST_ERROR ("Couldn't map index buffer, hr: 0x%x", (guint) hr);
|
GST_ERROR_OBJECT (self, "Couldn't map index buffer, hr: 0x%x", (guint) hr);
|
||||||
gst_d3d11_device_unlock (device);
|
gst_d3d11_device_unlock (device);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -422,61 +465,60 @@ gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self,
|
|||||||
context_handle->Unmap (index_buffer.Get (), 0);
|
context_handle->Unmap (index_buffer.Get (), 0);
|
||||||
gst_d3d11_device_unlock (device);
|
gst_d3d11_device_unlock (device);
|
||||||
|
|
||||||
self->ps = ps.Detach ();
|
priv->ps = ps.Detach ();
|
||||||
self->vs = vs.Detach ();
|
priv->vs = vs.Detach ();
|
||||||
self->layout = layout.Detach ();
|
priv->layout = layout.Detach ();
|
||||||
self->sampler = sampler.Detach ();
|
priv->sampler = sampler.Detach ();
|
||||||
self->blend = blend.Detach ();
|
priv->blend = blend.Detach ();
|
||||||
self->index_buffer = index_buffer.Detach ();
|
priv->index_buffer = index_buffer.Detach ();
|
||||||
|
|
||||||
|
priv->viewport.TopLeftX = 0;
|
||||||
|
priv->viewport.TopLeftY = 0;
|
||||||
|
priv->viewport.Width = GST_VIDEO_INFO_WIDTH (info);
|
||||||
|
priv->viewport.Height = GST_VIDEO_INFO_HEIGHT (info);
|
||||||
|
priv->viewport.MinDepth = 0.0f;
|
||||||
|
priv->viewport.MaxDepth = 1.0f;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GstD3D11OverlayCompositor *
|
GstD3D11OverlayCompositor *
|
||||||
gst_d3d11_overlay_compositor_new (GstD3D11Device * device,
|
gst_d3d11_overlay_compositor_new (GstD3D11Device * device,
|
||||||
GstVideoInfo * out_info)
|
const GstVideoInfo * info)
|
||||||
{
|
{
|
||||||
GstD3D11OverlayCompositor *compositor = NULL;
|
GstD3D11OverlayCompositor *self = nullptr;
|
||||||
|
GstD3D11OverlayCompositorPrivate *priv;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
|
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), nullptr);
|
||||||
g_return_val_if_fail (out_info != NULL, NULL);
|
g_return_val_if_fail (info != nullptr, nullptr);
|
||||||
|
|
||||||
compositor = g_new0 (GstD3D11OverlayCompositor, 1);
|
self = (GstD3D11OverlayCompositor *)
|
||||||
|
g_object_new (GST_TYPE_D3D11_OVERLAY_COMPOSITOR, nullptr);
|
||||||
|
gst_object_ref_sink (self);
|
||||||
|
priv = self->priv;
|
||||||
|
|
||||||
if (!gst_d3d11_overlay_compositor_setup_shader (compositor, device)) {
|
self->device = (GstD3D11Device *) gst_object_ref (device);
|
||||||
gst_d3d11_overlay_compositor_free (compositor);
|
priv->info = *info;
|
||||||
return NULL;
|
|
||||||
|
if (!gst_d3d11_overlay_compositor_setup_shader (self)) {
|
||||||
|
gst_object_unref (self);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
compositor->device = (GstD3D11Device *) gst_object_ref (device);
|
return self;
|
||||||
compositor->out_info = *out_info;
|
|
||||||
|
|
||||||
compositor->viewport.TopLeftX = 0;
|
|
||||||
compositor->viewport.TopLeftY = 0;
|
|
||||||
compositor->viewport.Width = GST_VIDEO_INFO_WIDTH (out_info);
|
|
||||||
compositor->viewport.Height = GST_VIDEO_INFO_HEIGHT (out_info);
|
|
||||||
compositor->viewport.MinDepth = 0.0f;
|
|
||||||
compositor->viewport.MaxDepth = 1.0f;
|
|
||||||
|
|
||||||
return compositor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
gst_d3d11_overlay_compositor_free (GstD3D11OverlayCompositor * compositor)
|
gst_d3d11_overlay_compositor_free_overlays (GstD3D11OverlayCompositor * self)
|
||||||
{
|
{
|
||||||
g_return_if_fail (compositor != NULL);
|
GstD3D11OverlayCompositorPrivate *priv = self->priv;
|
||||||
|
|
||||||
gst_d3d11_overlay_compositor_free_overlays (compositor);
|
if (priv->overlays) {
|
||||||
|
g_list_free_full (priv->overlays,
|
||||||
|
(GDestroyNotify) gst_d3d11_composition_overlay_free);
|
||||||
|
|
||||||
GST_D3D11_CLEAR_COM (compositor->ps);
|
priv->overlays = nullptr;
|
||||||
GST_D3D11_CLEAR_COM (compositor->vs);
|
}
|
||||||
GST_D3D11_CLEAR_COM (compositor->layout);
|
|
||||||
GST_D3D11_CLEAR_COM (compositor->sampler);
|
|
||||||
GST_D3D11_CLEAR_COM (compositor->blend);
|
|
||||||
GST_D3D11_CLEAR_COM (compositor->index_buffer);
|
|
||||||
|
|
||||||
gst_clear_object (&compositor->device);
|
|
||||||
g_free (compositor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
@ -505,15 +547,17 @@ gboolean
|
|||||||
gst_d3d11_overlay_compositor_upload (GstD3D11OverlayCompositor * compositor,
|
gst_d3d11_overlay_compositor_upload (GstD3D11OverlayCompositor * compositor,
|
||||||
GstBuffer * buf)
|
GstBuffer * buf)
|
||||||
{
|
{
|
||||||
|
GstD3D11OverlayCompositorPrivate *priv;
|
||||||
GstVideoOverlayCompositionMeta *meta;
|
GstVideoOverlayCompositionMeta *meta;
|
||||||
gint i, num_overlays;
|
gint i, num_overlays;
|
||||||
GList *iter;
|
GList *iter;
|
||||||
|
|
||||||
g_return_val_if_fail (compositor != NULL, FALSE);
|
g_return_val_if_fail (compositor != nullptr, FALSE);
|
||||||
g_return_val_if_fail (GST_IS_BUFFER (buf), FALSE);
|
g_return_val_if_fail (GST_IS_BUFFER (buf), FALSE);
|
||||||
|
|
||||||
meta = gst_buffer_get_video_overlay_composition_meta (buf);
|
priv = compositor->priv;
|
||||||
|
|
||||||
|
meta = gst_buffer_get_video_overlay_composition_meta (buf);
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
gst_d3d11_overlay_compositor_free_overlays (compositor);
|
gst_d3d11_overlay_compositor_free_overlays (compositor);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -525,35 +569,35 @@ gst_d3d11_overlay_compositor_upload (GstD3D11OverlayCompositor * compositor,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG ("Upload %d overlay rectangles", num_overlays);
|
GST_LOG_OBJECT (compositor, "Upload %d overlay rectangles", num_overlays);
|
||||||
|
|
||||||
/* Upload new overlay */
|
/* Upload new overlay */
|
||||||
for (i = 0; i < num_overlays; i++) {
|
for (i = 0; i < num_overlays; i++) {
|
||||||
GstVideoOverlayRectangle *rectangle =
|
GstVideoOverlayRectangle *rectangle =
|
||||||
gst_video_overlay_composition_get_rectangle (meta->overlay, i);
|
gst_video_overlay_composition_get_rectangle (meta->overlay, i);
|
||||||
|
|
||||||
if (!g_list_find_custom (compositor->overlays,
|
if (!g_list_find_custom (priv->overlays,
|
||||||
rectangle, (GCompareFunc) find_in_compositor)) {
|
rectangle, (GCompareFunc) find_in_compositor)) {
|
||||||
GstD3D11CompositionOverlay *overlay = NULL;
|
GstD3D11CompositionOverlay *overlay = nullptr;
|
||||||
|
|
||||||
overlay = gst_d3d11_composition_overlay_new (compositor, rectangle);
|
overlay = gst_d3d11_composition_overlay_new (compositor, rectangle);
|
||||||
|
|
||||||
if (!overlay)
|
if (!overlay)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
compositor->overlays = g_list_append (compositor->overlays, overlay);
|
priv->overlays = g_list_append (priv->overlays, overlay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove old overlay */
|
/* Remove old overlay */
|
||||||
iter = compositor->overlays;
|
iter = priv->overlays;
|
||||||
while (iter) {
|
while (iter) {
|
||||||
GstD3D11CompositionOverlay *overlay =
|
GstD3D11CompositionOverlay *overlay =
|
||||||
(GstD3D11CompositionOverlay *) iter->data;
|
(GstD3D11CompositionOverlay *) iter->data;
|
||||||
GList *next = iter->next;
|
GList *next = iter->next;
|
||||||
|
|
||||||
if (!is_in_video_overlay_composition (meta->overlay, overlay)) {
|
if (!is_in_video_overlay_composition (meta->overlay, overlay)) {
|
||||||
compositor->overlays = g_list_delete_link (compositor->overlays, iter);
|
priv->overlays = g_list_delete_link (priv->overlays, iter);
|
||||||
gst_d3d11_composition_overlay_free (overlay);
|
gst_d3d11_composition_overlay_free (overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,28 +607,14 @@ gst_d3d11_overlay_compositor_upload (GstD3D11OverlayCompositor * compositor,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
gst_d3d11_overlay_compositor_free_overlays (GstD3D11OverlayCompositor *
|
|
||||||
compositor)
|
|
||||||
{
|
|
||||||
g_return_if_fail (compositor != NULL);
|
|
||||||
|
|
||||||
if (compositor->overlays) {
|
|
||||||
g_list_free_full (compositor->overlays,
|
|
||||||
(GDestroyNotify) gst_d3d11_composition_overlay_free);
|
|
||||||
|
|
||||||
compositor->overlays = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_d3d11_overlay_compositor_update_viewport (GstD3D11OverlayCompositor *
|
gst_d3d11_overlay_compositor_update_viewport (GstD3D11OverlayCompositor *
|
||||||
compositor, D3D11_VIEWPORT * viewport)
|
compositor, D3D11_VIEWPORT * viewport)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (compositor != NULL, FALSE);
|
g_return_val_if_fail (GST_IS_D3D11_OVERLAY_COMPOSITOR (compositor), FALSE);
|
||||||
g_return_val_if_fail (viewport != NULL, FALSE);
|
g_return_val_if_fail (viewport != nullptr, FALSE);
|
||||||
|
|
||||||
compositor->viewport = *viewport;
|
compositor->priv->viewport = *viewport;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -595,8 +625,8 @@ gst_d3d11_overlay_compositor_draw (GstD3D11OverlayCompositor * compositor,
|
|||||||
{
|
{
|
||||||
gboolean ret = TRUE;
|
gboolean ret = TRUE;
|
||||||
|
|
||||||
g_return_val_if_fail (compositor != NULL, FALSE);
|
g_return_val_if_fail (compositor != nullptr, FALSE);
|
||||||
g_return_val_if_fail (rtv != NULL, FALSE);
|
g_return_val_if_fail (rtv != nullptr, FALSE);
|
||||||
|
|
||||||
gst_d3d11_device_lock (compositor->device);
|
gst_d3d11_device_lock (compositor->device);
|
||||||
ret = gst_d3d11_overlay_compositor_draw_unlocked (compositor, rtv);
|
ret = gst_d3d11_overlay_compositor_draw_unlocked (compositor, rtv);
|
||||||
@ -609,27 +639,33 @@ gboolean
|
|||||||
gst_d3d11_overlay_compositor_draw_unlocked (GstD3D11OverlayCompositor *
|
gst_d3d11_overlay_compositor_draw_unlocked (GstD3D11OverlayCompositor *
|
||||||
compositor, ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES])
|
compositor, ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES])
|
||||||
{
|
{
|
||||||
|
GstD3D11OverlayCompositorPrivate *priv;
|
||||||
GList *iter;
|
GList *iter;
|
||||||
ID3D11DeviceContext *context;
|
ID3D11DeviceContext *context;
|
||||||
ID3D11ShaderResourceView *clear_view[GST_VIDEO_MAX_PLANES] = { nullptr, };
|
ID3D11ShaderResourceView *clear_view[GST_VIDEO_MAX_PLANES] = { nullptr, };
|
||||||
UINT strides = sizeof (VertexData);
|
UINT strides = sizeof (VertexData);
|
||||||
UINT offsets = 0;
|
UINT offsets = 0;
|
||||||
|
|
||||||
g_return_val_if_fail (compositor != NULL, FALSE);
|
g_return_val_if_fail (compositor != nullptr, FALSE);
|
||||||
g_return_val_if_fail (rtv != NULL, FALSE);
|
g_return_val_if_fail (rtv != nullptr, FALSE);
|
||||||
|
|
||||||
|
priv = compositor->priv;
|
||||||
|
|
||||||
|
if (!priv->overlays)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
context = gst_d3d11_device_get_device_context_handle (compositor->device);
|
context = gst_d3d11_device_get_device_context_handle (compositor->device);
|
||||||
context->IASetPrimitiveTopology (D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
context->IASetPrimitiveTopology (D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
context->IASetInputLayout (compositor->layout);
|
context->IASetInputLayout (priv->layout);
|
||||||
context->IASetIndexBuffer (compositor->index_buffer, DXGI_FORMAT_R16_UINT, 0);
|
context->IASetIndexBuffer (priv->index_buffer, DXGI_FORMAT_R16_UINT, 0);
|
||||||
context->PSSetSamplers (0, 1, &compositor->sampler);
|
context->PSSetSamplers (0, 1, &priv->sampler);
|
||||||
context->VSSetShader (compositor->vs, nullptr, 0);
|
context->VSSetShader (priv->vs, nullptr, 0);
|
||||||
context->PSSetShader (compositor->ps, nullptr, 0);
|
context->PSSetShader (priv->ps, nullptr, 0);
|
||||||
context->RSSetViewports (1, &compositor->viewport);
|
context->RSSetViewports (1, &priv->viewport);
|
||||||
context->OMSetRenderTargets (1, rtv, nullptr);
|
context->OMSetRenderTargets (1, rtv, nullptr);
|
||||||
context->OMSetBlendState (compositor->blend, nullptr, 0xffffffff);
|
context->OMSetBlendState (priv->blend, nullptr, 0xffffffff);
|
||||||
|
|
||||||
for (iter = compositor->overlays; iter; iter = g_list_next (iter)) {
|
for (iter = priv->overlays; iter; iter = g_list_next (iter)) {
|
||||||
GstD3D11CompositionOverlay *overlay =
|
GstD3D11CompositionOverlay *overlay =
|
||||||
(GstD3D11CompositionOverlay *) iter->data;
|
(GstD3D11CompositionOverlay *) iter->data;
|
||||||
|
|
||||||
|
@ -26,18 +26,45 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_D3D11_OVERLAY_COMPOSITOR (gst_d3d11_overlay_compositor_get_type())
|
||||||
|
#define GST_D3D11_OVERLAY_COMPOSITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_D3D11_OVERLAY_COMPOSITOR,GstD3D11OverlayCompositor))
|
||||||
|
#define GST_D3D11_OVERLAY_COMPOSITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_D3D11_OVERLAY_COMPOSITOR,GstD3D11OverlayCompositorClass))
|
||||||
|
#define GST_D3D11_OVERLAY_COMPOSITOR_GET_CLASS(obj) (GST_D3D11_OVERLAY_COMPOSITOR_CLASS(G_OBJECT_GET_CLASS(obj)))
|
||||||
|
#define GST_IS_D3D11_OVERLAY_COMPOSITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_D3D11_OVERLAY_COMPOSITOR))
|
||||||
|
#define GST_IS_D3D11_OVERLAY_COMPOSITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_D3D11_OVERLAY_COMPOSITOR))
|
||||||
|
#define GST_D3D11_OVERLAY_COMPOSITOR_CAST(obj) ((GstD3D11OverlayCompositor*)(obj))
|
||||||
|
|
||||||
typedef struct _GstD3D11OverlayCompositor GstD3D11OverlayCompositor;
|
typedef struct _GstD3D11OverlayCompositor GstD3D11OverlayCompositor;
|
||||||
|
typedef struct _GstD3D11OverlayCompositorClass GstD3D11OverlayCompositorClass;
|
||||||
|
typedef struct _GstD3D11OverlayCompositorPrivate GstD3D11OverlayCompositorPrivate;
|
||||||
|
|
||||||
|
struct _GstD3D11OverlayCompositor
|
||||||
|
{
|
||||||
|
GstObject parent;
|
||||||
|
|
||||||
|
GstD3D11Device *device;
|
||||||
|
|
||||||
|
/*< private >*/
|
||||||
|
GstD3D11OverlayCompositorPrivate *priv;
|
||||||
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstD3D11OverlayCompositorClass
|
||||||
|
{
|
||||||
|
GstObjectClass parent_class;
|
||||||
|
|
||||||
|
/*< private >*/
|
||||||
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_d3d11_overlay_compositor_get_type (void);
|
||||||
|
|
||||||
GstD3D11OverlayCompositor * gst_d3d11_overlay_compositor_new (GstD3D11Device * device,
|
GstD3D11OverlayCompositor * gst_d3d11_overlay_compositor_new (GstD3D11Device * device,
|
||||||
GstVideoInfo * out_info);
|
const GstVideoInfo * info);
|
||||||
|
|
||||||
void gst_d3d11_overlay_compositor_free (GstD3D11OverlayCompositor * compositor);
|
|
||||||
|
|
||||||
gboolean gst_d3d11_overlay_compositor_upload (GstD3D11OverlayCompositor * compositor,
|
gboolean gst_d3d11_overlay_compositor_upload (GstD3D11OverlayCompositor * compositor,
|
||||||
GstBuffer * buf);
|
GstBuffer * buf);
|
||||||
|
|
||||||
void gst_d3d11_overlay_compositor_free_overlays (GstD3D11OverlayCompositor * compositor);
|
|
||||||
|
|
||||||
gboolean gst_d3d11_overlay_compositor_update_viewport (GstD3D11OverlayCompositor * compositor,
|
gboolean gst_d3d11_overlay_compositor_update_viewport (GstD3D11OverlayCompositor * compositor,
|
||||||
D3D11_VIEWPORT * viewport);
|
D3D11_VIEWPORT * viewport);
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ gst_d3d11_window_dispose (GObject * object)
|
|||||||
gst_d3d11_window_release_resources (self->device, self);
|
gst_d3d11_window_release_resources (self->device, self);
|
||||||
|
|
||||||
g_clear_pointer (&self->processor, gst_d3d11_video_processor_free);
|
g_clear_pointer (&self->processor, gst_d3d11_video_processor_free);
|
||||||
g_clear_pointer (&self->compositor, gst_d3d11_overlay_compositor_free);
|
gst_clear_object (&self->compositor);
|
||||||
gst_clear_object (&self->converter);
|
gst_clear_object (&self->converter);
|
||||||
|
|
||||||
gst_clear_buffer (&self->cached_buffer);
|
gst_clear_buffer (&self->cached_buffer);
|
||||||
@ -461,7 +461,7 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
|
|||||||
/* Step 1: Clear old resources and objects */
|
/* Step 1: Clear old resources and objects */
|
||||||
gst_clear_buffer (&window->cached_buffer);
|
gst_clear_buffer (&window->cached_buffer);
|
||||||
g_clear_pointer (&window->processor, gst_d3d11_video_processor_free);
|
g_clear_pointer (&window->processor, gst_d3d11_video_processor_free);
|
||||||
g_clear_pointer (&window->compositor, gst_d3d11_overlay_compositor_free);
|
gst_clear_object (&window->compositor);
|
||||||
gst_clear_object (&window->converter);
|
gst_clear_object (&window->converter);
|
||||||
|
|
||||||
window->processor_in_use = FALSE;
|
window->processor_in_use = FALSE;
|
||||||
|
@ -88,7 +88,7 @@ gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
|
|||||||
GstDxgiColorSpace in_space;
|
GstDxgiColorSpace in_space;
|
||||||
|
|
||||||
g_clear_pointer (&window->processor, gst_d3d11_video_processor_free);
|
g_clear_pointer (&window->processor, gst_d3d11_video_processor_free);
|
||||||
g_clear_pointer (&window->compositor, gst_d3d11_overlay_compositor_free);
|
gst_clear_object (&window->compositor);
|
||||||
gst_clear_object (&window->converter);
|
gst_clear_object (&window->converter);
|
||||||
|
|
||||||
/* We are supporting only RGBA, BGRA or RGB10A2_LE formats but we don't know
|
/* We are supporting only RGBA, BGRA or RGB10A2_LE formats but we don't know
|
||||||
|
Loading…
x
Reference in New Issue
Block a user