xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 1 | /* 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 | |
| 33 | struct _GstAmlV4l2GUdevIterator |
| 34 | { |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 35 | GstAmlV4l2Iterator parent; |
| 36 | GList *devices; |
| 37 | GUdevDevice *device; |
| 38 | GUdevClient *client; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 39 | }; |
| 40 | |
| 41 | GstAmlV4l2Iterator * |
| 42 | gst_aml_v4l2_iterator_new(void) |
| 43 | { |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 44 | static const gchar *subsystems[] = { "video4linux", NULL }; |
| 45 | struct _GstAmlV4l2GUdevIterator *it; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 46 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 47 | it = g_slice_new0(struct _GstAmlV4l2GUdevIterator); |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 48 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 49 | it->client = g_udev_client_new (subsystems); |
| 50 | it->devices = g_udev_client_query_by_subsystem (it->client, "video4linux"); |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 51 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 52 | return (GstAmlV4l2Iterator *)it; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 53 | } |
| 54 | |
| 55 | gboolean |
| 56 | gst_aml_v4l2_iterator_next(GstAmlV4l2Iterator *_it) |
| 57 | { |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 58 | struct _GstAmlV4l2GUdevIterator *it = (struct _GstAmlV4l2GUdevIterator *)_it; |
| 59 | const gchar *device_name; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 60 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 61 | if (it->device) |
| 62 | g_object_unref (it->device); |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 63 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 64 | it->device = NULL; |
| 65 | it->parent.device_path = NULL; |
| 66 | it->parent.device_name = NULL; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 67 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 68 | if (it->devices == NULL) |
| 69 | return FALSE; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 70 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 71 | it->device = it->devices->data; |
| 72 | it->devices = g_list_delete_link (it->devices, it->devices); |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 73 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 74 | 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.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 79 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 80 | 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.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 83 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 84 | return TRUE; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 85 | } |
| 86 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 87 | void |
| 88 | gst_aml_v4l2_iterator_free (GstAmlV4l2Iterator *_it) |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 89 | { |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 90 | 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.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 94 | } |
| 95 | |
| 96 | #else /* No GUDEV */ |
| 97 | |
| 98 | struct _GstAmlV4l2FsIterator |
| 99 | { |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 100 | GstAmlV4l2Iterator parent; |
| 101 | gint base_idx; |
| 102 | gint video_idx; |
| 103 | gchar *device; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 104 | }; |
| 105 | |
| 106 | GstAmlV4l2Iterator * |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 107 | gst_aml_v4l2_iterator_new (void) |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 108 | { |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 109 | struct _GstAmlV4l2FsIterator *it; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 110 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 111 | 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.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 116 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 117 | return (GstAmlV4l2Iterator *) it; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | gboolean |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 121 | gst_aml_v4l2_iterator_next (GstAmlV4l2Iterator * _it) |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 122 | { |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 123 | struct _GstAmlV4l2FsIterator *it = (struct _GstAmlV4l2FsIterator *)_it; |
| 124 | static const gchar *dev_base[] = { "/dev/video", "/dev/v4l2/video", NULL }; |
| 125 | gchar *device = NULL; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 126 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 127 | if (it->parent.device_path) { |
| 128 | g_free((gchar *)it->parent.device_path); |
| 129 | it->parent.device_path = NULL; |
| 130 | } |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 131 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 132 | while (device == NULL) |
| 133 | { |
| 134 | it->video_idx++; |
| 135 | |
| 136 | if (it->video_idx >= 64) |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 137 | { |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 138 | it->video_idx = 0; |
| 139 | it->base_idx++; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 140 | } |
| 141 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 142 | 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.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 161 | } |
| 162 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 163 | void |
| 164 | gst_aml_v4l2_iterator_free (GstAmlV4l2Iterator * _it) |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 165 | { |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 166 | struct _GstAmlV4l2FsIterator *it = (struct _GstAmlV4l2FsIterator *)_it; |
| 167 | g_free ((gchar *) it->parent.device_path); |
| 168 | g_slice_free (struct _GstAmlV4l2FsIterator, it); |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 169 | } |
| 170 | |
| 171 | #endif |
| 172 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 173 | void |
| 174 | gst_aml_v4l2_clear_error (GstAmlV4l2Error * v4l2err) |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 175 | { |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 176 | if (v4l2err) |
| 177 | { |
| 178 | g_clear_error (&v4l2err->error); |
| 179 | g_free (v4l2err->dbg_message); |
| 180 | v4l2err->dbg_message = NULL; |
| 181 | } |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 182 | } |
| 183 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 184 | void |
| 185 | gst_aml_v4l2_error (gpointer element, GstAmlV4l2Error * v4l2err) |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 186 | { |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 187 | GError *error; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 188 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 189 | if (!v4l2err || !v4l2err->error) |
| 190 | return; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 191 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 192 | error = v4l2err->error; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 193 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 194 | if (error->message) |
| 195 | GST_WARNING_OBJECT (element, "error: %s", error->message); |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 196 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 197 | if (v4l2err->dbg_message) |
| 198 | GST_WARNING_OBJECT (element, "error: %s", v4l2err->dbg_message); |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 199 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 200 | 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.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 203 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 204 | error->message = NULL; |
| 205 | v4l2err->dbg_message = NULL; |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 206 | |
bo.xiao | 857b868 | 2024-09-12 16:40:32 +0800 | [diff] [blame^] | 207 | gst_aml_v4l2_clear_error (v4l2err); |
xuesong.jiang | ae1548e | 2022-05-06 16:38:46 +0800 | [diff] [blame] | 208 | } |