• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 2020 Igalia, S.L.
3  *     Author: Víctor Jáquez <vjaquez@igalia.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 /**
22  * SECTION:gstvadisplaydrm
23  * @title: GstVaDisplayDrm
24  * @short_description: VADisplay from a DRM device
25  * @sources:
26  * - gstvadisplay_drm.h
27  *
28  * This is a #GstVaDisplay subclass to instantiate with DRM devices.
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #include "gstvadisplay_drm.h"
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <va/va_drm.h>
41 
42 #if HAVE_LIBDRM
43 #include <xf86drm.h>
44 #endif
45 
46 /**
47  * GstVaDisplayDrm:
48  * @parent: parent #GstVaDisplay
49  *
50  * Since: 1.20
51  */
52 struct _GstVaDisplayDrm
53 {
54   GstVaDisplay parent;
55 
56   /* <private> */
57   gchar *path;
58   gint fd;
59 };
60 
61 /**
62  * GstVaDisplayDrmClass:
63  * @parent_class: parent #GstVaDisplayClass
64  *
65  * Since: 1.20
66  */
67 struct _GstVaDisplayDrmClass
68 {
69   GstVaDisplayClass parent_class;
70 };
71 
72 GST_DEBUG_CATEGORY_EXTERN (gst_va_display_debug);
73 #define GST_CAT_DEFAULT gst_va_display_debug
74 
75 #define gst_va_display_drm_parent_class parent_class
76 G_DEFINE_TYPE (GstVaDisplayDrm, gst_va_display_drm, GST_TYPE_VA_DISPLAY);
77 
78 enum
79 {
80   PROP_PATH = 1,
81   N_PROPERTIES
82 };
83 
84 static GParamSpec *g_properties[N_PROPERTIES];
85 
86 #define MAX_DEVICES 8
87 
88 static void
gst_va_display_drm_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)89 gst_va_display_drm_set_property (GObject * object, guint prop_id,
90     const GValue * value, GParamSpec * pspec)
91 {
92   GstVaDisplayDrm *self = GST_VA_DISPLAY_DRM (object);
93 
94   switch (prop_id) {
95     case PROP_PATH:
96       self->path = g_value_dup_string (value);
97       break;
98     default:
99       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
100       break;
101   }
102 }
103 
104 static void
gst_va_display_drm_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)105 gst_va_display_drm_get_property (GObject * object, guint prop_id,
106     GValue * value, GParamSpec * pspec)
107 {
108   GstVaDisplayDrm *self = GST_VA_DISPLAY_DRM (object);
109 
110   switch (prop_id) {
111     case PROP_PATH:
112       g_value_set_string (value, self->path);
113       break;
114     default:
115       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
116       break;
117   }
118 }
119 
120 static void
gst_va_display_drm_finalize(GObject * object)121 gst_va_display_drm_finalize (GObject * object)
122 {
123   GstVaDisplayDrm *self = GST_VA_DISPLAY_DRM (object);
124 
125   g_free (self->path);
126   if (self->fd > -1)
127     close (self->fd);
128 
129   G_OBJECT_CLASS (parent_class)->finalize (object);
130 }
131 
132 static gpointer
gst_va_display_drm_create_va_display(GstVaDisplay * display)133 gst_va_display_drm_create_va_display (GstVaDisplay * display)
134 {
135   int fd, saved_errno = 0;
136   GstVaDisplayDrm *self = GST_VA_DISPLAY_DRM (display);
137 
138   fd = open (self->path, O_CLOEXEC | O_RDWR);
139   saved_errno = errno;
140   if (fd < 0) {
141     GST_WARNING_OBJECT (self, "Failed to open %s: %s", self->path,
142         g_strerror (saved_errno));
143     return 0;
144   }
145 #if HAVE_LIBDRM
146   {
147     drmVersion *version;
148 
149     version = drmGetVersion (fd);
150     if (!version) {
151       GST_ERROR_OBJECT (self, "Device %s is not a DRM render node", self->path);
152       return 0;
153     }
154     GST_INFO_OBJECT (self, "DRM render node with kernel driver %s",
155         version->name);
156     drmFreeVersion (version);
157   }
158 #endif
159 
160   self->fd = fd;
161   return vaGetDisplayDRM (self->fd);
162 }
163 
164 static void
gst_va_display_drm_class_init(GstVaDisplayDrmClass * klass)165 gst_va_display_drm_class_init (GstVaDisplayDrmClass * klass)
166 {
167   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
168   GstVaDisplayClass *vadisplay_class = GST_VA_DISPLAY_CLASS (klass);
169 
170   gobject_class->set_property = gst_va_display_drm_set_property;
171   gobject_class->get_property = gst_va_display_drm_get_property;
172   gobject_class->finalize = gst_va_display_drm_finalize;
173 
174   vadisplay_class->create_va_display = gst_va_display_drm_create_va_display;
175 
176   g_properties[PROP_PATH] =
177       g_param_spec_string ("path", "render-path", "The path of DRM device",
178       "/dev/dri/renderD128",
179       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
180 
181   g_object_class_install_properties (gobject_class, N_PROPERTIES, g_properties);
182 }
183 
184 static void
gst_va_display_drm_init(GstVaDisplayDrm * self)185 gst_va_display_drm_init (GstVaDisplayDrm * self)
186 {
187   self->fd = -1;
188 }
189 
190 /**
191  * gst_va_display_drm_new_from_path:
192  * @path: the path to the DRM device
193  *
194  * Creates a new #GstVaDisplay from a DRM device . It will try to open
195  * and operate the device in @path.
196  *
197  * Returns: (transfer full): a newly allocated #GstVaDisplay if the
198  *     specified DRM render device could be opened and initialized;
199  *     otherwise %NULL is returned.
200  *
201  * Since: 1.20
202  **/
203 GstVaDisplay *
gst_va_display_drm_new_from_path(const gchar * path)204 gst_va_display_drm_new_from_path (const gchar * path)
205 {
206   GstVaDisplay *dpy;
207 
208   g_return_val_if_fail (path, NULL);
209 
210   dpy = g_object_new (GST_TYPE_VA_DISPLAY_DRM, "path", path, NULL);
211   if (!gst_va_display_initialize (dpy)) {
212     gst_object_unref (dpy);
213     return NULL;
214   }
215 
216   return gst_object_ref_sink (dpy);
217 }
218