"}\n";
/* *INDENT-ON* */
-struct _GstD3D11OverlayCompositor
+struct _GstD3D11OverlayCompositorPrivate
{
- GstD3D11Device *device;
- GstVideoInfo out_info;
+ GstVideoInfo info;
D3D11_VIEWPORT viewport;
ID3D11Buffer *vertex_buffer;
} 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 *
gst_d3d11_composition_overlay_new (GstD3D11OverlayCompositor * self,
GstVideoOverlayRectangle * overlay_rect)
{
- GstD3D11CompositionOverlay *overlay = NULL;
+ GstD3D11OverlayCompositorPrivate *priv = self->priv;
+ GstD3D11CompositionOverlay *overlay = nullptr;
gint x, y;
guint width, height;
D3D11_SUBRESOURCE_DATA subresource_data;
ComPtr < ID3D11ShaderResourceView > srv;
ComPtr < ID3D11Buffer > vertex_buffer;
- g_return_val_if_fail (overlay_rect != NULL, NULL);
-
memset (&subresource_data, 0, sizeof (subresource_data));
memset (&texture_desc, 0, sizeof (texture_desc));
memset (&srv_desc, 0, sizeof (srv_desc));
if (!gst_video_overlay_rectangle_get_render_rectangle (overlay_rect, &x, &y,
&width, &height)) {
- GST_ERROR ("Failed to get render rectangle");
- return NULL;
+ GST_ERROR_OBJECT (self, "Failed to get render rectangle");
+ return nullptr;
}
buf = gst_video_overlay_rectangle_get_pixels_unscaled_argb (overlay_rect,
GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
if (!buf) {
- GST_ERROR ("Failed to get overlay buffer");
- return NULL;
+ GST_ERROR_OBJECT (self, "Failed to get overlay buffer");
+ return nullptr;
}
vmeta = gst_buffer_get_video_meta (buf);
if (!vmeta) {
- GST_ERROR ("Failed to get video meta");
- return NULL;
+ GST_ERROR_OBJECT (self, "Failed to get video meta");
+ return nullptr;
}
if (!gst_video_meta_map (vmeta,
0, &info, (gpointer *) & data, &stride, GST_MAP_READ)) {
- GST_ERROR ("Failed to map");
- return NULL;
+ GST_ERROR_OBJECT (self, "Failed to map");
+ return nullptr;
}
/* Do create texture and upload data at once, for create immutable texture */
texture_desc.Height = height;
texture_desc.MipLevels = 1;
texture_desc.ArraySize = 1;
- /* FIXME: need to consider non-BGRA ? */
texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
texture_desc.SampleDesc.Count = 1;
texture_desc.SampleDesc.Quality = 0;
gst_video_meta_unmap (vmeta, 0, &info);
if (!gst_d3d11_result (hr, device)) {
- GST_ERROR ("Failed to create texture");
- return NULL;
+ GST_ERROR_OBJECT (self, "Failed to create texture");
+ return nullptr;
}
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
hr = device_handle->CreateShaderResourceView (texture.Get (), &srv_desc,
&srv);
if (!gst_d3d11_result (hr, device) || !srv) {
- GST_ERROR ("Failed to create shader resource view");
- return NULL;
+ GST_ERROR_OBJECT (self, "Failed to create shader resource view");
+ return nullptr;
}
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
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)) {
- GST_ERROR ("Couldn't create vertex buffer, hr: 0x%x", (guint) hr);
- return NULL;
+ GST_ERROR_OBJECT (self,
+ "Couldn't create vertex buffer, hr: 0x%x", (guint) hr);
+ return nullptr;
}
gst_d3d11_device_lock (device);
0, D3D11_MAP_WRITE_DISCARD, 0, &map);
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);
- return NULL;
+ return nullptr;
}
vertex_data = (VertexData *) map.pData;
/* 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;
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;
/* top right */
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;
- gst_util_fraction_to_double (y,
- GST_VIDEO_INFO_HEIGHT (&self->out_info), &val);
+ gst_util_fraction_to_double (y, GST_VIDEO_INFO_HEIGHT (&priv->info), &val);
y2 = (val * -2.0f) + 1.0f;
/* bottom left */
}
static gboolean
-gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self,
- GstD3D11Device * device)
+gst_d3d11_overlay_compositor_setup_shader (GstD3D11OverlayCompositor * self)
{
+ GstD3D11OverlayCompositorPrivate *priv = self->priv;
+ GstVideoInfo *info = &priv->info;
+ GstD3D11Device *device = self->device;
HRESULT hr;
D3D11_SAMPLER_DESC sampler_desc;
D3D11_INPUT_ELEMENT_DESC input_desc[2];
hr = device_handle->CreateSamplerState (&sampler_desc, &sampler);
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;
}
- GST_LOG ("Create Pixel Shader \n%s", templ_pixel_shader);
-
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;
}
if (!gst_d3d11_create_vertex_shader (device, templ_vertex_shader,
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;
}
hr = device_handle->CreateBlendState (&blend_desc, &blend);
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;
}
buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
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)) {
- 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;
}
0, D3D11_MAP_WRITE_DISCARD, 0, &map);
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);
return FALSE;
}
context_handle->Unmap (index_buffer.Get (), 0);
gst_d3d11_device_unlock (device);
- self->ps = ps.Detach ();
- self->vs = vs.Detach ();
- self->layout = layout.Detach ();
- self->sampler = sampler.Detach ();
- self->blend = blend.Detach ();
- self->index_buffer = index_buffer.Detach ();
+ priv->ps = ps.Detach ();
+ priv->vs = vs.Detach ();
+ priv->layout = layout.Detach ();
+ priv->sampler = sampler.Detach ();
+ priv->blend = blend.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;
}
GstD3D11OverlayCompositor *
gst_d3d11_overlay_compositor_new (GstD3D11Device * device,
- GstVideoInfo * out_info)
+ const GstVideoInfo * info)
{
- GstD3D11OverlayCompositor *compositor = NULL;
-
- g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
- g_return_val_if_fail (out_info != NULL, NULL);
+ GstD3D11OverlayCompositor *self = nullptr;
+ GstD3D11OverlayCompositorPrivate *priv;
- compositor = g_new0 (GstD3D11OverlayCompositor, 1);
+ g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), nullptr);
+ g_return_val_if_fail (info != nullptr, nullptr);
- if (!gst_d3d11_overlay_compositor_setup_shader (compositor, device)) {
- gst_d3d11_overlay_compositor_free (compositor);
- return NULL;
- }
+ self = (GstD3D11OverlayCompositor *)
+ g_object_new (GST_TYPE_D3D11_OVERLAY_COMPOSITOR, nullptr);
+ gst_object_ref_sink (self);
+ priv = self->priv;
- compositor->device = (GstD3D11Device *) gst_object_ref (device);
- compositor->out_info = *out_info;
+ self->device = (GstD3D11Device *) gst_object_ref (device);
+ priv->info = *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;
+ if (!gst_d3d11_overlay_compositor_setup_shader (self)) {
+ gst_object_unref (self);
+ return nullptr;
+ }
- return compositor;
+ return self;
}
-void
-gst_d3d11_overlay_compositor_free (GstD3D11OverlayCompositor * compositor)
+static void
+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);
-
- GST_D3D11_CLEAR_COM (compositor->ps);
- 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);
+ if (priv->overlays) {
+ g_list_free_full (priv->overlays,
+ (GDestroyNotify) gst_d3d11_composition_overlay_free);
- gst_clear_object (&compositor->device);
- g_free (compositor);
+ priv->overlays = nullptr;
+ }
}
static gint
gst_d3d11_overlay_compositor_upload (GstD3D11OverlayCompositor * compositor,
GstBuffer * buf)
{
+ GstD3D11OverlayCompositorPrivate *priv;
GstVideoOverlayCompositionMeta *meta;
gint i, num_overlays;
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);
- meta = gst_buffer_get_video_overlay_composition_meta (buf);
+ priv = compositor->priv;
+ meta = gst_buffer_get_video_overlay_composition_meta (buf);
if (!meta) {
gst_d3d11_overlay_compositor_free_overlays (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 */
for (i = 0; i < num_overlays; i++) {
GstVideoOverlayRectangle *rectangle =
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)) {
- GstD3D11CompositionOverlay *overlay = NULL;
+ GstD3D11CompositionOverlay *overlay = nullptr;
overlay = gst_d3d11_composition_overlay_new (compositor, rectangle);
if (!overlay)
return FALSE;
- compositor->overlays = g_list_append (compositor->overlays, overlay);
+ priv->overlays = g_list_append (priv->overlays, overlay);
}
}
/* Remove old overlay */
- iter = compositor->overlays;
+ iter = priv->overlays;
while (iter) {
GstD3D11CompositionOverlay *overlay =
(GstD3D11CompositionOverlay *) iter->data;
GList *next = iter->next;
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);
}
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
gst_d3d11_overlay_compositor_update_viewport (GstD3D11OverlayCompositor *
compositor, D3D11_VIEWPORT * viewport)
{
- g_return_val_if_fail (compositor != NULL, FALSE);
- g_return_val_if_fail (viewport != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_D3D11_OVERLAY_COMPOSITOR (compositor), FALSE);
+ g_return_val_if_fail (viewport != nullptr, FALSE);
- compositor->viewport = *viewport;
+ compositor->priv->viewport = *viewport;
return TRUE;
}
{
gboolean ret = TRUE;
- g_return_val_if_fail (compositor != NULL, FALSE);
- g_return_val_if_fail (rtv != NULL, FALSE);
+ g_return_val_if_fail (compositor != nullptr, FALSE);
+ g_return_val_if_fail (rtv != nullptr, FALSE);
gst_d3d11_device_lock (compositor->device);
ret = gst_d3d11_overlay_compositor_draw_unlocked (compositor, rtv);
gst_d3d11_overlay_compositor_draw_unlocked (GstD3D11OverlayCompositor *
compositor, ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES])
{
+ GstD3D11OverlayCompositorPrivate *priv;
GList *iter;
ID3D11DeviceContext *context;
ID3D11ShaderResourceView *clear_view[GST_VIDEO_MAX_PLANES] = { nullptr, };
UINT strides = sizeof (VertexData);
UINT offsets = 0;
- g_return_val_if_fail (compositor != NULL, FALSE);
- g_return_val_if_fail (rtv != NULL, FALSE);
+ g_return_val_if_fail (compositor != nullptr, 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->IASetPrimitiveTopology (D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
- context->IASetInputLayout (compositor->layout);
- context->IASetIndexBuffer (compositor->index_buffer, DXGI_FORMAT_R16_UINT, 0);
- context->PSSetSamplers (0, 1, &compositor->sampler);
- context->VSSetShader (compositor->vs, nullptr, 0);
- context->PSSetShader (compositor->ps, nullptr, 0);
- context->RSSetViewports (1, &compositor->viewport);
+ context->IASetInputLayout (priv->layout);
+ context->IASetIndexBuffer (priv->index_buffer, DXGI_FORMAT_R16_UINT, 0);
+ context->PSSetSamplers (0, 1, &priv->sampler);
+ context->VSSetShader (priv->vs, nullptr, 0);
+ context->PSSetShader (priv->ps, nullptr, 0);
+ context->RSSetViewports (1, &priv->viewport);
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 *) iter->data;