blob: 5562ef11eb6de1322470b12b65fd787cdfd556c8 [file] [log] [blame]
xuesong.jiangae1548e2022-05-06 16:38:46 +08001/* GStreamer
2 * Copyright (C) 2022 <xuesong.jiang@amlogic.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
17 * Boston, MA 02110-1335, USA.
18 */
19
20#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include "aml-v4l2-utils.h"
25
26/**************************/
27/* Common device iterator */
28/**************************/
29
30#ifdef HAVE_GUDEV
31#include <gudev/gudev.h>
32
33struct _GstAmlV4l2GUdevIterator
34{
bo.xiao857b8682024-09-12 16:40:32 +080035 GstAmlV4l2Iterator parent;
36 GList *devices;
37 GUdevDevice *device;
38 GUdevClient *client;
xuesong.jiangae1548e2022-05-06 16:38:46 +080039};
40
41GstAmlV4l2Iterator *
42gst_aml_v4l2_iterator_new(void)
43{
bo.xiao857b8682024-09-12 16:40:32 +080044 static const gchar *subsystems[] = { "video4linux", NULL };
45 struct _GstAmlV4l2GUdevIterator *it;
xuesong.jiangae1548e2022-05-06 16:38:46 +080046
bo.xiao857b8682024-09-12 16:40:32 +080047 it = g_slice_new0(struct _GstAmlV4l2GUdevIterator);
xuesong.jiangae1548e2022-05-06 16:38:46 +080048
bo.xiao857b8682024-09-12 16:40:32 +080049 it->client = g_udev_client_new (subsystems);
50 it->devices = g_udev_client_query_by_subsystem (it->client, "video4linux");
xuesong.jiangae1548e2022-05-06 16:38:46 +080051
bo.xiao857b8682024-09-12 16:40:32 +080052 return (GstAmlV4l2Iterator *)it;
xuesong.jiangae1548e2022-05-06 16:38:46 +080053}
54
55gboolean
56gst_aml_v4l2_iterator_next(GstAmlV4l2Iterator *_it)
57{
bo.xiao857b8682024-09-12 16:40:32 +080058 struct _GstAmlV4l2GUdevIterator *it = (struct _GstAmlV4l2GUdevIterator *)_it;
59 const gchar *device_name;
xuesong.jiangae1548e2022-05-06 16:38:46 +080060
bo.xiao857b8682024-09-12 16:40:32 +080061 if (it->device)
62 g_object_unref (it->device);
xuesong.jiangae1548e2022-05-06 16:38:46 +080063
bo.xiao857b8682024-09-12 16:40:32 +080064 it->device = NULL;
65 it->parent.device_path = NULL;
66 it->parent.device_name = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +080067
bo.xiao857b8682024-09-12 16:40:32 +080068 if (it->devices == NULL)
69 return FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +080070
bo.xiao857b8682024-09-12 16:40:32 +080071 it->device = it->devices->data;
72 it->devices = g_list_delete_link (it->devices, it->devices);
xuesong.jiangae1548e2022-05-06 16:38:46 +080073
bo.xiao857b8682024-09-12 16:40:32 +080074 device_name = g_udev_device_get_property (it->device, "ID_V4L_PRODUCT");
75 if (!device_name)
76 device_name = g_udev_device_get_property (it->device, "ID_MODEL_ENC");
77 if (!device_name)
78 device_name = g_udev_device_get_property (it->device, "ID_MODEL");
xuesong.jiangae1548e2022-05-06 16:38:46 +080079
bo.xiao857b8682024-09-12 16:40:32 +080080 it->parent.device_path = g_udev_device_get_device_file (it->device);
81 it->parent.device_name = device_name;
82 it->parent.sys_path = g_udev_device_get_sysfs_path (it->device);
xuesong.jiangae1548e2022-05-06 16:38:46 +080083
bo.xiao857b8682024-09-12 16:40:32 +080084 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +080085}
86
bo.xiao857b8682024-09-12 16:40:32 +080087void
88gst_aml_v4l2_iterator_free (GstAmlV4l2Iterator *_it)
xuesong.jiangae1548e2022-05-06 16:38:46 +080089{
bo.xiao857b8682024-09-12 16:40:32 +080090 struct _GstAmlV4l2GUdevIterator *it = (struct _GstAmlV4l2GUdevIterator *) _it;
91 g_list_free_full (it->devices, g_object_unref);
92 gst_object_unref (it->client);
93 g_slice_free(struct _GstAmlV4l2GUdevIterator, it);
xuesong.jiangae1548e2022-05-06 16:38:46 +080094}
95
96#else /* No GUDEV */
97
98struct _GstAmlV4l2FsIterator
99{
bo.xiao857b8682024-09-12 16:40:32 +0800100 GstAmlV4l2Iterator parent;
101 gint base_idx;
102 gint video_idx;
103 gchar *device;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800104};
105
106GstAmlV4l2Iterator *
bo.xiao857b8682024-09-12 16:40:32 +0800107gst_aml_v4l2_iterator_new (void)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800108{
bo.xiao857b8682024-09-12 16:40:32 +0800109 struct _GstAmlV4l2FsIterator *it;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800110
bo.xiao857b8682024-09-12 16:40:32 +0800111 it = g_slice_new0(struct _GstAmlV4l2FsIterator);
112 it->base_idx = 0;
113 it->video_idx = -1;
114 it->device = NULL;
115 it->parent.device_path = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800116
bo.xiao857b8682024-09-12 16:40:32 +0800117 return (GstAmlV4l2Iterator *) it;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800118}
119
120gboolean
bo.xiao857b8682024-09-12 16:40:32 +0800121gst_aml_v4l2_iterator_next (GstAmlV4l2Iterator * _it)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800122{
bo.xiao857b8682024-09-12 16:40:32 +0800123 struct _GstAmlV4l2FsIterator *it = (struct _GstAmlV4l2FsIterator *)_it;
124 static const gchar *dev_base[] = { "/dev/video", "/dev/v4l2/video", NULL };
125 gchar *device = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800126
bo.xiao857b8682024-09-12 16:40:32 +0800127 if (it->parent.device_path) {
128 g_free((gchar *)it->parent.device_path);
129 it->parent.device_path = NULL;
130 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800131
bo.xiao857b8682024-09-12 16:40:32 +0800132 while (device == NULL)
133 {
134 it->video_idx++;
135
136 if (it->video_idx >= 64)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800137 {
bo.xiao857b8682024-09-12 16:40:32 +0800138 it->video_idx = 0;
139 it->base_idx++;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800140 }
141
bo.xiao857b8682024-09-12 16:40:32 +0800142 if (dev_base[it->base_idx] == NULL)
143 {
144 it->video_idx = 0;
145 break;
146 }
147
148 device = g_strdup_printf ("%s%d", dev_base[it->base_idx], it->video_idx);
149
150 if (g_file_test(device, G_FILE_TEST_EXISTS))
151 {
152 it->parent.device_path = device;
153 break;
154 }
155
156 g_free (device);
157 device = NULL;
158 }
159
160 return it->parent.device_path != NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800161}
162
bo.xiao857b8682024-09-12 16:40:32 +0800163void
164gst_aml_v4l2_iterator_free (GstAmlV4l2Iterator * _it)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800165{
bo.xiao857b8682024-09-12 16:40:32 +0800166 struct _GstAmlV4l2FsIterator *it = (struct _GstAmlV4l2FsIterator *)_it;
167 g_free ((gchar *) it->parent.device_path);
168 g_slice_free (struct _GstAmlV4l2FsIterator, it);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800169}
170
171#endif
172
bo.xiao857b8682024-09-12 16:40:32 +0800173void
174gst_aml_v4l2_clear_error (GstAmlV4l2Error * v4l2err)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800175{
bo.xiao857b8682024-09-12 16:40:32 +0800176 if (v4l2err)
177 {
178 g_clear_error (&v4l2err->error);
179 g_free (v4l2err->dbg_message);
180 v4l2err->dbg_message = NULL;
181 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800182}
183
bo.xiao857b8682024-09-12 16:40:32 +0800184void
185gst_aml_v4l2_error (gpointer element, GstAmlV4l2Error * v4l2err)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800186{
bo.xiao857b8682024-09-12 16:40:32 +0800187 GError *error;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800188
bo.xiao857b8682024-09-12 16:40:32 +0800189 if (!v4l2err || !v4l2err->error)
190 return;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800191
bo.xiao857b8682024-09-12 16:40:32 +0800192 error = v4l2err->error;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800193
bo.xiao857b8682024-09-12 16:40:32 +0800194 if (error->message)
195 GST_WARNING_OBJECT (element, "error: %s", error->message);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800196
bo.xiao857b8682024-09-12 16:40:32 +0800197 if (v4l2err->dbg_message)
198 GST_WARNING_OBJECT (element, "error: %s", v4l2err->dbg_message);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800199
bo.xiao857b8682024-09-12 16:40:32 +0800200 gst_element_message_full (GST_ELEMENT (element), GST_MESSAGE_ERROR,
201 error->domain, error->code, error->message, v4l2err->dbg_message,
202 v4l2err->file, v4l2err->func, v4l2err->line);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800203
bo.xiao857b8682024-09-12 16:40:32 +0800204 error->message = NULL;
205 v4l2err->dbg_message = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800206
bo.xiao857b8682024-09-12 16:40:32 +0800207 gst_aml_v4l2_clear_error (v4l2err);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800208}