• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 2020 Nicolas Dufresne <nicolas.dufresne@collabora.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 St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 #include "gstv4l2codecallocator.h"
25 #include "gstv4l2codecpool.h"
26 #include "gstv4l2decoder.h"
27 #include "gstv4l2format.h"
28 #include "linux/media.h"
29 #include "linux/videodev2.h"
30 
31 #include <fcntl.h>
32 #include <sys/ioctl.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36 
37 #include <gst/base/base.h>
38 
39 #define IMAGE_MINSZ 4096
40 
41 GST_DEBUG_CATEGORY (v4l2_decoder_debug);
42 #define GST_CAT_DEFAULT v4l2_decoder_debug
43 
44 enum
45 {
46   PROP_0,
47   PROP_MEDIA_DEVICE,
48   PROP_VIDEO_DEVICE,
49 };
50 
51 struct _GstV4l2Request
52 {
53   /* non-thread safe */
54   gint ref_count;
55 
56   GstV4l2Decoder *decoder;
57   gint fd;
58   guint32 frame_num;
59   GstMemory *bitstream;
60   GstBuffer *pic_buf;
61   GstPoll *poll;
62   GstPollFD pollfd;
63 
64   /* request state */
65   gboolean pending;
66   gboolean failed;
67   gboolean hold_pic_buf;
68   gboolean sub_request;
69 };
70 
71 struct _GstV4l2Decoder
72 {
73   GstObject parent;
74 
75   gboolean opened;
76   gint media_fd;
77   gint video_fd;
78   GstQueueArray *request_pool;
79   GstQueueArray *pending_requests;
80   guint version;
81 
82   enum v4l2_buf_type src_buf_type;
83   enum v4l2_buf_type sink_buf_type;
84   gboolean mplane;
85 
86   /* properties */
87   gchar *media_device;
88   gchar *video_device;
89   guint render_delay;
90 };
91 
92 G_DEFINE_TYPE_WITH_CODE (GstV4l2Decoder, gst_v4l2_decoder, GST_TYPE_OBJECT,
93     GST_DEBUG_CATEGORY_INIT (v4l2_decoder_debug, "v4l2codecs-decoder", 0,
94         "V4L2 stateless decoder helper"));
95 
96 static void gst_v4l2_request_free (GstV4l2Request * request);
97 
98 static guint32
direction_to_buffer_type(GstV4l2Decoder * self,GstPadDirection direction)99 direction_to_buffer_type (GstV4l2Decoder * self, GstPadDirection direction)
100 {
101   if (direction == GST_PAD_SRC)
102     return self->src_buf_type;
103   else
104     return self->sink_buf_type;
105 }
106 
107 static void
gst_v4l2_decoder_finalize(GObject * obj)108 gst_v4l2_decoder_finalize (GObject * obj)
109 {
110   GstV4l2Decoder *self = GST_V4L2_DECODER (obj);
111 
112   gst_v4l2_decoder_close (self);
113 
114   g_free (self->media_device);
115   g_free (self->video_device);
116   gst_queue_array_free (self->request_pool);
117   gst_queue_array_free (self->pending_requests);
118 
119   G_OBJECT_CLASS (gst_v4l2_decoder_parent_class)->finalize (obj);
120 }
121 
122 static void
gst_v4l2_decoder_init(GstV4l2Decoder * self)123 gst_v4l2_decoder_init (GstV4l2Decoder * self)
124 {
125   self->request_pool = gst_queue_array_new (16);
126   self->pending_requests = gst_queue_array_new (16);
127 }
128 
129 static void
gst_v4l2_decoder_class_init(GstV4l2DecoderClass * klass)130 gst_v4l2_decoder_class_init (GstV4l2DecoderClass * klass)
131 {
132   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
133 
134   gobject_class->finalize = gst_v4l2_decoder_finalize;
135   gobject_class->get_property = gst_v4l2_decoder_get_property;
136   gobject_class->set_property = gst_v4l2_decoder_set_property;
137 
138   gst_v4l2_decoder_install_properties (gobject_class, 0, NULL);
139 }
140 
141 GstV4l2Decoder *
gst_v4l2_decoder_new(GstV4l2CodecDevice * device)142 gst_v4l2_decoder_new (GstV4l2CodecDevice * device)
143 {
144   GstV4l2Decoder *decoder;
145 
146   g_return_val_if_fail (device->function == MEDIA_ENT_F_PROC_VIDEO_DECODER,
147       NULL);
148 
149   decoder = g_object_new (GST_TYPE_V4L2_DECODER,
150       "media-device", device->media_device_path,
151       "video-device", device->video_device_path, NULL);
152 
153   return gst_object_ref_sink (decoder);
154 }
155 
156 guint
gst_v4l2_decoder_get_version(GstV4l2Decoder * self)157 gst_v4l2_decoder_get_version (GstV4l2Decoder * self)
158 {
159   return self->version;
160 }
161 
162 gboolean
gst_v4l2_decoder_open(GstV4l2Decoder * self)163 gst_v4l2_decoder_open (GstV4l2Decoder * self)
164 {
165   gint ret;
166   struct v4l2_capability querycap;
167   guint32 capabilities;
168 
169   self->media_fd = open (self->media_device, 0);
170   if (self->media_fd < 0) {
171     GST_ERROR_OBJECT (self, "Failed to open '%s': %s",
172         self->media_device, g_strerror (errno));
173     return FALSE;
174   }
175 
176   self->video_fd = open (self->video_device, O_NONBLOCK);
177   if (self->video_fd < 0) {
178     GST_ERROR_OBJECT (self, "Failed to open '%s': %s",
179         self->video_device, g_strerror (errno));
180     return FALSE;
181   }
182 
183   ret = ioctl (self->video_fd, VIDIOC_QUERYCAP, &querycap);
184   if (ret < 0) {
185     GST_ERROR_OBJECT (self, "VIDIOC_QUERYCAP failed: %s", g_strerror (errno));
186     gst_v4l2_decoder_close (self);
187     return FALSE;
188   }
189 
190   self->version = querycap.version;
191 
192   if (querycap.capabilities & V4L2_CAP_DEVICE_CAPS)
193     capabilities = querycap.device_caps;
194   else
195     capabilities = querycap.capabilities;
196 
197   if (capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) {
198     self->sink_buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
199     self->src_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
200     self->mplane = TRUE;
201   } else if (capabilities & V4L2_CAP_VIDEO_M2M) {
202     self->sink_buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
203     self->src_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
204     self->mplane = FALSE;
205   } else {
206     GST_ERROR_OBJECT (self, "Unsupported memory-2-memory device.");
207     gst_v4l2_decoder_close (self);
208     return FALSE;
209   }
210 
211   self->opened = TRUE;
212 
213   return TRUE;
214 }
215 
216 gboolean
gst_v4l2_decoder_close(GstV4l2Decoder * self)217 gst_v4l2_decoder_close (GstV4l2Decoder * self)
218 {
219   GstV4l2Request *request;
220 
221   while ((request = gst_queue_array_pop_head (self->pending_requests)))
222     gst_v4l2_request_unref (request);
223 
224   while ((request = gst_queue_array_pop_head (self->request_pool)))
225     gst_v4l2_request_free (request);
226 
227   if (self->media_fd)
228     close (self->media_fd);
229   if (self->video_fd)
230     close (self->video_fd);
231 
232   self->media_fd = 0;
233   self->video_fd = 0;
234   self->opened = FALSE;
235 
236   return TRUE;
237 }
238 
239 gboolean
gst_v4l2_decoder_streamon(GstV4l2Decoder * self,GstPadDirection direction)240 gst_v4l2_decoder_streamon (GstV4l2Decoder * self, GstPadDirection direction)
241 {
242   gint ret;
243   guint32 type = direction_to_buffer_type (self, direction);
244 
245   ret = ioctl (self->video_fd, VIDIOC_STREAMON, &type);
246   if (ret < 0) {
247     GST_ERROR_OBJECT (self, "VIDIOC_STREAMON failed: %s", g_strerror (errno));
248     return FALSE;
249   }
250 
251   return TRUE;
252 }
253 
254 gboolean
gst_v4l2_decoder_streamoff(GstV4l2Decoder * self,GstPadDirection direction)255 gst_v4l2_decoder_streamoff (GstV4l2Decoder * self, GstPadDirection direction)
256 {
257   guint32 type = direction_to_buffer_type (self, direction);
258   gint ret;
259 
260   if (direction == GST_PAD_SRC) {
261     GstV4l2Request *pending_req;
262 
263     /* STREAMOFF have the effect of cancelling all requests and unqueuing all
264      * buffers, so clear the pending request list */
265     while ((pending_req = gst_queue_array_pop_head (self->pending_requests))) {
266       g_clear_pointer (&pending_req->bitstream, gst_memory_unref);
267       pending_req->pending = FALSE;
268       gst_v4l2_request_unref (pending_req);
269     }
270   }
271 
272   ret = ioctl (self->video_fd, VIDIOC_STREAMOFF, &type);
273   if (ret < 0) {
274     GST_ERROR_OBJECT (self, "VIDIOC_STREAMOFF failed: %s", g_strerror (errno));
275     return FALSE;
276   }
277 
278   return TRUE;
279 }
280 
281 gboolean
gst_v4l2_decoder_flush(GstV4l2Decoder * self)282 gst_v4l2_decoder_flush (GstV4l2Decoder * self)
283 {
284   /* We ignore streamoff failure as it's not relevant, if we manage to
285    * streamon again, we are good. */
286   gst_v4l2_decoder_streamoff (self, GST_PAD_SINK);
287   gst_v4l2_decoder_streamoff (self, GST_PAD_SRC);
288 
289   return gst_v4l2_decoder_streamon (self, GST_PAD_SINK) &&
290       gst_v4l2_decoder_streamon (self, GST_PAD_SRC);
291 }
292 
293 gboolean
gst_v4l2_decoder_enum_sink_fmt(GstV4l2Decoder * self,gint i,guint32 * out_fmt)294 gst_v4l2_decoder_enum_sink_fmt (GstV4l2Decoder * self, gint i,
295     guint32 * out_fmt)
296 {
297   struct v4l2_fmtdesc fmtdesc = { i, self->sink_buf_type, };
298   gint ret;
299 
300   g_return_val_if_fail (self->opened, FALSE);
301 
302   ret = ioctl (self->video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
303   if (ret < 0) {
304     if (errno != EINVAL)
305       GST_ERROR_OBJECT (self, "VIDIOC_ENUM_FMT failed: %s", g_strerror (errno));
306     return FALSE;
307   }
308 
309   GST_DEBUG_OBJECT (self, "Found format %" GST_FOURCC_FORMAT " (%s)",
310       GST_FOURCC_ARGS (fmtdesc.pixelformat), fmtdesc.description);
311   *out_fmt = fmtdesc.pixelformat;
312 
313   return TRUE;
314 }
315 
316 gboolean
gst_v4l2_decoder_set_sink_fmt(GstV4l2Decoder * self,guint32 pix_fmt,gint width,gint height,gint pixel_bitdepth)317 gst_v4l2_decoder_set_sink_fmt (GstV4l2Decoder * self, guint32 pix_fmt,
318     gint width, gint height, gint pixel_bitdepth)
319 {
320   struct v4l2_format format = (struct v4l2_format) {
321     .type = self->sink_buf_type,
322     /* Compatible with .fmt.pix for these field */
323     .fmt.pix_mp = (struct v4l2_pix_format_mplane) {
324           .pixelformat = pix_fmt,
325           .width = width,
326           .height = height,
327         },
328   };
329   gint ret;
330 
331   /* Using raw image size for now, it is guarantied to be large enough */
332   gsize sizeimage = MAX (IMAGE_MINSZ, (width * height * pixel_bitdepth) / 8);
333 
334   if (self->mplane)
335     format.fmt.pix_mp.plane_fmt[0].sizeimage = sizeimage;
336   else
337     format.fmt.pix.sizeimage = sizeimage;
338 
339   ret = ioctl (self->video_fd, VIDIOC_S_FMT, &format);
340   if (ret < 0) {
341     GST_ERROR_OBJECT (self, "VIDIOC_S_FMT failed: %s", g_strerror (errno));
342     return FALSE;
343   }
344 
345   if (format.fmt.pix_mp.pixelformat != pix_fmt
346       || format.fmt.pix_mp.width < width || format.fmt.pix_mp.height < height) {
347     GST_WARNING_OBJECT (self, "Failed to set sink format to %"
348         GST_FOURCC_FORMAT " %ix%i", GST_FOURCC_ARGS (pix_fmt), width, height);
349     errno = EINVAL;
350     return FALSE;
351   }
352 
353   return TRUE;
354 }
355 
356 GstCaps *
gst_v4l2_decoder_enum_src_formats(GstV4l2Decoder * self)357 gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self)
358 {
359   gint ret;
360   struct v4l2_format fmt = {
361     .type = self->src_buf_type,
362   };
363   GstVideoFormat format;
364   GstCaps *caps;
365   GValue list = G_VALUE_INIT;
366   GValue value = G_VALUE_INIT;
367   gint i;
368 
369   g_return_val_if_fail (self->opened, FALSE);
370 
371   ret = ioctl (self->video_fd, VIDIOC_G_FMT, &fmt);
372   if (ret < 0) {
373     GST_ERROR_OBJECT (self, "VIDIOC_G_FMT failed: %s", g_strerror (errno));
374     return FALSE;
375   }
376 
377   /* We first place a structure with the default pixel format */
378   if (gst_v4l2_format_to_video_format (fmt.fmt.pix_mp.pixelformat, &format))
379     caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
380         gst_video_format_to_string (format), NULL);
381   else
382     caps = gst_caps_new_empty ();
383 
384   /* And then enumerate other possible formats and place that as a second
385    * structure in the caps */
386   g_value_init (&list, GST_TYPE_LIST);
387   g_value_init (&value, G_TYPE_STRING);
388 
389   for (i = 0; ret >= 0; i++) {
390     struct v4l2_fmtdesc fmtdesc = { i, self->src_buf_type, };
391 
392     ret = ioctl (self->video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
393     if (ret < 0) {
394       if (errno != EINVAL)
395         GST_ERROR_OBJECT (self, "VIDIOC_ENUM_FMT failed: %s",
396             g_strerror (errno));
397       continue;
398     }
399 
400     if (gst_v4l2_format_to_video_format (fmtdesc.pixelformat, &format)) {
401       g_value_set_static_string (&value, gst_video_format_to_string (format));
402       gst_value_list_append_value (&list, &value);
403     }
404   }
405   g_value_reset (&value);
406 
407   if (gst_value_list_get_size (&list) > 0) {
408     GstStructure *str = gst_structure_new_empty ("video/x-raw");
409     gst_structure_take_value (str, "format", &list);
410     gst_caps_append_structure (caps, str);
411   } else {
412     g_value_reset (&list);
413   }
414 
415   return caps;
416 }
417 
418 gboolean
gst_v4l2_decoder_select_src_format(GstV4l2Decoder * self,GstCaps * caps,GstVideoInfo * info)419 gst_v4l2_decoder_select_src_format (GstV4l2Decoder * self, GstCaps * caps,
420     GstVideoInfo * info)
421 {
422   gint ret;
423   struct v4l2_format fmt = {
424     .type = self->src_buf_type,
425   };
426   GstStructure *str;
427   const gchar *format_str;
428   GstVideoFormat format;
429   guint32 pix_fmt;
430 
431   if (gst_caps_is_empty (caps))
432     return FALSE;
433 
434   ret = ioctl (self->video_fd, VIDIOC_G_FMT, &fmt);
435   if (ret < 0) {
436     GST_ERROR_OBJECT (self, "VIDIOC_G_FMT failed: %s", g_strerror (errno));
437     return FALSE;
438   }
439 
440   caps = gst_caps_make_writable (caps);
441   str = gst_caps_get_structure (caps, 0);
442   gst_structure_fixate_field (str, "format");
443 
444   format_str = gst_structure_get_string (str, "format");
445   format = gst_video_format_from_string (format_str);
446 
447   if (gst_v4l2_format_from_video_format (format, &pix_fmt) &&
448       pix_fmt != fmt.fmt.pix_mp.pixelformat) {
449     GST_DEBUG_OBJECT (self, "Trying to use peer format: %s ", format_str);
450     fmt.fmt.pix_mp.pixelformat = pix_fmt;
451 
452     ret = ioctl (self->video_fd, VIDIOC_S_FMT, &fmt);
453     if (ret < 0) {
454       GST_ERROR_OBJECT (self, "VIDIOC_S_FMT failed: %s", g_strerror (errno));
455       return FALSE;
456     }
457   }
458 
459   if (!gst_v4l2_format_to_video_info (&fmt, info)) {
460     GST_ERROR_OBJECT (self, "Unsupported V4L2 pixelformat %" GST_FOURCC_FORMAT,
461         GST_FOURCC_ARGS (fmt.fmt.pix_mp.pixelformat));
462     return FALSE;
463   }
464 
465   GST_INFO_OBJECT (self, "Selected format %s %ix%i",
466       gst_video_format_to_string (info->finfo->format),
467       info->width, info->height);
468 
469   return TRUE;
470 }
471 
472 gint
gst_v4l2_decoder_request_buffers(GstV4l2Decoder * self,GstPadDirection direction,guint num_buffers)473 gst_v4l2_decoder_request_buffers (GstV4l2Decoder * self,
474     GstPadDirection direction, guint num_buffers)
475 {
476   gint ret;
477   struct v4l2_requestbuffers reqbufs = {
478     .count = num_buffers,
479     .memory = V4L2_MEMORY_MMAP,
480     .type = direction_to_buffer_type (self, direction),
481   };
482 
483   GST_DEBUG_OBJECT (self, "Requesting %u buffers", num_buffers);
484 
485   ret = ioctl (self->video_fd, VIDIOC_REQBUFS, &reqbufs);
486   if (ret < 0) {
487     GST_ERROR_OBJECT (self, "VIDIOC_REQBUFS failed: %s", g_strerror (errno));
488     return ret;
489   }
490 
491   return reqbufs.count;
492 }
493 
494 gboolean
gst_v4l2_decoder_export_buffer(GstV4l2Decoder * self,GstPadDirection direction,gint index,gint * fds,gsize * sizes,gsize * offsets,guint * num_fds)495 gst_v4l2_decoder_export_buffer (GstV4l2Decoder * self,
496     GstPadDirection direction, gint index, gint * fds, gsize * sizes,
497     gsize * offsets, guint * num_fds)
498 {
499   gint i, ret;
500   struct v4l2_plane planes[GST_VIDEO_MAX_PLANES] = { {0} };
501   struct v4l2_buffer v4l2_buf = {
502     .index = 0,
503     .type = direction_to_buffer_type (self, direction),
504   };
505 
506   if (self->mplane) {
507     v4l2_buf.length = GST_VIDEO_MAX_PLANES;
508     v4l2_buf.m.planes = planes;
509   }
510 
511   ret = ioctl (self->video_fd, VIDIOC_QUERYBUF, &v4l2_buf);
512   if (ret < 0) {
513     GST_ERROR_OBJECT (self, "VIDIOC_QUERYBUF failed: %s", g_strerror (errno));
514     return FALSE;
515   }
516 
517   if (self->mplane) {
518     for (i = 0; i < v4l2_buf.length; i++) {
519       struct v4l2_plane *plane = v4l2_buf.m.planes + i;
520       struct v4l2_exportbuffer expbuf = {
521         .type = direction_to_buffer_type (self, direction),
522         .index = index,
523         .plane = i,
524         .flags = O_CLOEXEC | O_RDWR,
525       };
526 
527       ret = ioctl (self->video_fd, VIDIOC_EXPBUF, &expbuf);
528       if (ret < 0) {
529         gint j;
530         GST_ERROR_OBJECT (self, "VIDIOC_EXPBUF failed: %s", g_strerror (errno));
531 
532         for (j = i - 1; j >= 0; j--)
533           close (fds[j]);
534 
535         return FALSE;
536       }
537 
538       *num_fds = v4l2_buf.length;
539       fds[i] = expbuf.fd;
540       sizes[i] = plane->length;
541       offsets[i] = plane->data_offset;
542     }
543   } else {
544     struct v4l2_exportbuffer expbuf = {
545       .type = direction_to_buffer_type (self, direction),
546       .index = index,
547       .flags = O_CLOEXEC | O_RDWR,
548     };
549 
550     ret = ioctl (self->video_fd, VIDIOC_EXPBUF, &expbuf);
551     if (ret < 0) {
552       GST_ERROR_OBJECT (self, "VIDIOC_EXPBUF failed: %s", g_strerror (errno));
553       return FALSE;
554     }
555 
556     *num_fds = 1;
557     fds[0] = expbuf.fd;
558     sizes[0] = v4l2_buf.length;
559     offsets[0] = 0;
560   }
561 
562   return TRUE;
563 }
564 
565 static gboolean
gst_v4l2_decoder_queue_sink_mem(GstV4l2Decoder * self,GstV4l2Request * request,GstMemory * mem,guint32 frame_num,guint flags)566 gst_v4l2_decoder_queue_sink_mem (GstV4l2Decoder * self,
567     GstV4l2Request * request, GstMemory * mem, guint32 frame_num, guint flags)
568 {
569   gint ret;
570   gsize bytesused = gst_memory_get_sizes (mem, NULL, NULL);
571   struct v4l2_plane plane = {
572     .bytesused = bytesused,
573   };
574   struct v4l2_buffer buf = {
575     .type = self->sink_buf_type,
576     .memory = V4L2_MEMORY_MMAP,
577     .index = gst_v4l2_codec_memory_get_index (mem),
578     .timestamp.tv_usec = frame_num,
579     .request_fd = request->fd,
580     .flags = V4L2_BUF_FLAG_REQUEST_FD | flags,
581   };
582 
583   GST_TRACE_OBJECT (self, "Queueing bitstream buffer %i", buf.index);
584 
585   if (self->mplane) {
586     buf.length = 1;
587     buf.m.planes = &plane;
588   } else {
589     buf.bytesused = bytesused;
590   }
591 
592   ret = ioctl (self->video_fd, VIDIOC_QBUF, &buf);
593   if (ret < 0) {
594     GST_ERROR_OBJECT (self, "VIDIOC_QBUF failed: %s", g_strerror (errno));
595     return FALSE;
596   }
597 
598   return TRUE;
599 }
600 
601 static gboolean
gst_v4l2_decoder_queue_src_buffer(GstV4l2Decoder * self,GstBuffer * buffer)602 gst_v4l2_decoder_queue_src_buffer (GstV4l2Decoder * self, GstBuffer * buffer)
603 {
604   gint i, ret;
605   struct v4l2_plane planes[GST_VIDEO_MAX_PLANES];
606   struct v4l2_buffer buf = {
607     .type = self->src_buf_type,
608     .memory = V4L2_MEMORY_MMAP,
609     .index = gst_v4l2_codec_buffer_get_index (buffer),
610   };
611 
612   GST_TRACE_OBJECT (self, "Queuing picture buffer %i", buf.index);
613 
614   if (self->mplane) {
615     buf.length = gst_buffer_n_memory (buffer);
616     buf.m.planes = planes;
617     for (i = 0; i < buf.length; i++) {
618       GstMemory *mem = gst_buffer_peek_memory (buffer, i);
619       /* *INDENT-OFF* */
620       planes[i] = (struct v4l2_plane) {
621         .bytesused = gst_memory_get_sizes (mem, NULL, NULL),
622       };
623       /* *INDENT-ON* */
624     }
625   } else {
626     buf.bytesused = gst_buffer_get_size (buffer);
627   }
628 
629   ret = ioctl (self->video_fd, VIDIOC_QBUF, &buf);
630   if (ret < 0) {
631     GST_ERROR_OBJECT (self, "VIDIOC_QBUF failed: %s", g_strerror (errno));
632     return FALSE;
633   }
634 
635   return TRUE;
636 }
637 
638 static gboolean
gst_v4l2_decoder_dequeue_sink(GstV4l2Decoder * self)639 gst_v4l2_decoder_dequeue_sink (GstV4l2Decoder * self)
640 {
641   gint ret;
642   struct v4l2_plane planes[GST_VIDEO_MAX_PLANES] = { {0} };
643   struct v4l2_buffer buf = {
644     .type = self->sink_buf_type,
645     .memory = V4L2_MEMORY_MMAP,
646   };
647 
648   if (self->mplane) {
649     buf.length = GST_VIDEO_MAX_PLANES;
650     buf.m.planes = planes;
651   }
652 
653   ret = ioctl (self->video_fd, VIDIOC_DQBUF, &buf);
654   if (ret < 0) {
655     GST_ERROR_OBJECT (self, "VIDIOC_DQBUF failed: %s", g_strerror (errno));
656     return FALSE;
657   }
658 
659   GST_TRACE_OBJECT (self, "Dequeued bitstream buffer %i", buf.index);
660 
661   return TRUE;
662 }
663 
664 static gboolean
gst_v4l2_decoder_dequeue_src(GstV4l2Decoder * self,guint32 * out_frame_num)665 gst_v4l2_decoder_dequeue_src (GstV4l2Decoder * self, guint32 * out_frame_num)
666 {
667   gint ret;
668   struct v4l2_plane planes[GST_VIDEO_MAX_PLANES] = { {0} };
669   struct v4l2_buffer buf = {
670     .type = self->src_buf_type,
671     .memory = V4L2_MEMORY_MMAP,
672   };
673 
674   if (self->mplane) {
675     buf.length = GST_VIDEO_MAX_PLANES;
676     buf.m.planes = planes;
677   }
678 
679   ret = ioctl (self->video_fd, VIDIOC_DQBUF, &buf);
680   if (ret < 0) {
681     GST_ERROR_OBJECT (self, "VIDIOC_DQBUF failed: %s", g_strerror (errno));
682     return FALSE;
683   }
684 
685   *out_frame_num = buf.timestamp.tv_usec;
686 
687   GST_TRACE_OBJECT (self, "Dequeued picture buffer %i", buf.index);
688 
689   return TRUE;
690 }
691 
692 gboolean
gst_v4l2_decoder_set_controls(GstV4l2Decoder * self,GstV4l2Request * request,struct v4l2_ext_control * control,guint count)693 gst_v4l2_decoder_set_controls (GstV4l2Decoder * self, GstV4l2Request * request,
694     struct v4l2_ext_control * control, guint count)
695 {
696   gint ret;
697   struct v4l2_ext_controls controls = {
698     .controls = control,
699     .count = count,
700     .request_fd = request ? request->fd : 0,
701     .which = request ? V4L2_CTRL_WHICH_REQUEST_VAL : 0,
702   };
703 
704   ret = ioctl (self->video_fd, VIDIOC_S_EXT_CTRLS, &controls);
705   if (ret < 0) {
706     GST_ERROR_OBJECT (self, "VIDIOC_S_EXT_CTRLS failed: %s",
707         g_strerror (errno));
708     return FALSE;
709   }
710 
711   return TRUE;
712 }
713 
714 gboolean
gst_v4l2_decoder_get_controls(GstV4l2Decoder * self,struct v4l2_ext_control * control,guint count)715 gst_v4l2_decoder_get_controls (GstV4l2Decoder * self,
716     struct v4l2_ext_control * control, guint count)
717 {
718   gint ret;
719   struct v4l2_ext_controls controls = {
720     .controls = control,
721     .count = count,
722   };
723 
724   ret = ioctl (self->video_fd, VIDIOC_G_EXT_CTRLS, &controls);
725   if (ret < 0) {
726     GST_ERROR_OBJECT (self, "VIDIOC_G_EXT_CTRLS failed: %s",
727         g_strerror (errno));
728     return FALSE;
729   }
730 
731   return TRUE;
732 }
733 
734 gboolean
gst_v4l2_decoder_query_control_size(GstV4l2Decoder * self,unsigned int control_id,unsigned int * control_size)735 gst_v4l2_decoder_query_control_size (GstV4l2Decoder * self,
736     unsigned int control_id, unsigned int *control_size)
737 {
738   gint ret;
739   struct v4l2_query_ext_ctrl control = {
740     .id = control_id,
741   };
742 
743   *control_size = 0;
744 
745   ret = ioctl (self->video_fd, VIDIOC_QUERY_EXT_CTRL, &control);
746   if (ret < 0)
747     /*
748      * It's not an error if a control is not supported by this driver.
749      * Return false but don't print any error.
750      */
751     return FALSE;
752 
753   *control_size = control.elem_size;
754   return TRUE;
755 }
756 
757 void
gst_v4l2_decoder_install_properties(GObjectClass * gobject_class,gint prop_offset,GstV4l2CodecDevice * device)758 gst_v4l2_decoder_install_properties (GObjectClass * gobject_class,
759     gint prop_offset, GstV4l2CodecDevice * device)
760 {
761   const gchar *media_device_path = NULL;
762   const gchar *video_device_path = NULL;
763 
764   if (device) {
765     media_device_path = device->media_device_path;
766     video_device_path = device->video_device_path;
767   }
768 
769   g_object_class_install_property (gobject_class, PROP_MEDIA_DEVICE,
770       g_param_spec_string ("media-device", "Media Device Path",
771           "Path to the media device node", media_device_path,
772           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
773 
774   g_object_class_install_property (gobject_class, PROP_VIDEO_DEVICE,
775       g_param_spec_string ("video-device", "Video Device Path",
776           "Path to the video device node", video_device_path,
777           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
778 }
779 
780 void
gst_v4l2_decoder_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)781 gst_v4l2_decoder_set_property (GObject * object, guint prop_id,
782     const GValue * value, GParamSpec * pspec)
783 {
784   GstV4l2Decoder *self = GST_V4L2_DECODER (object);
785 
786   switch (prop_id) {
787     case PROP_MEDIA_DEVICE:
788       g_free (self->media_device);
789       self->media_device = g_value_dup_string (value);
790       break;
791     case PROP_VIDEO_DEVICE:
792       g_free (self->video_device);
793       self->video_device = g_value_dup_string (value);
794       break;
795     default:
796       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
797       break;
798   }
799 }
800 
801 void
gst_v4l2_decoder_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)802 gst_v4l2_decoder_get_property (GObject * object, guint prop_id,
803     GValue * value, GParamSpec * pspec)
804 {
805   GstV4l2Decoder *self = GST_V4L2_DECODER (object);
806 
807   switch (prop_id) {
808     case PROP_MEDIA_DEVICE:
809       g_value_set_string (value, self->media_device);
810       break;
811     case PROP_VIDEO_DEVICE:
812       g_value_set_string (value, self->video_device);
813       break;
814     default:
815       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
816       break;
817   }
818 }
819 
820 /**
821  * gst_v4l2_decoder_register:
822  * @plugin: a #GstPlugin
823  * @dec_type: A #GType for the codec
824  * @class_init: The #GClassInitFunc for #dec_type
825  * @instance_init: The #GInstanceInitFunc for #dec_type
826  * @element_name_tmpl: A string to use for the first codec found and as a template for the next ones.
827  * @device: (transfer full) A #GstV4l2CodecDevice
828  * @rank: The rank to use for the element
829  * @class_data: (nullable) (transfer full) A #gpointer to pass as class_data, set to @device if null
830  * @element_name (nullable) (out) Sets the pointer to the new element name
831  *
832  * Registers a decoder element as a subtype of @dec_type for @plugin.
833  * Will create a different sub_types for each subsequent @decoder of the
834  * same type.
835  */
836 void
gst_v4l2_decoder_register(GstPlugin * plugin,GType dec_type,GClassInitFunc class_init,gconstpointer class_data,GInstanceInitFunc instance_init,const gchar * element_name_tmpl,GstV4l2CodecDevice * device,guint rank,gchar ** element_name)837 gst_v4l2_decoder_register (GstPlugin * plugin,
838     GType dec_type, GClassInitFunc class_init, gconstpointer class_data,
839     GInstanceInitFunc instance_init, const gchar * element_name_tmpl,
840     GstV4l2CodecDevice * device, guint rank, gchar ** element_name)
841 {
842   GTypeQuery type_query;
843   GTypeInfo type_info = { 0, };
844   GType subtype;
845   gchar *type_name;
846 
847   g_type_query (dec_type, &type_query);
848   memset (&type_info, 0, sizeof (type_info));
849   type_info.class_size = type_query.class_size;
850   type_info.instance_size = type_query.instance_size;
851   type_info.class_init = class_init;
852   type_info.class_data = class_data;
853   type_info.instance_init = instance_init;
854 
855   if (class_data == device)
856     GST_MINI_OBJECT_FLAG_SET (device, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
857 
858   /* The first decoder to be registered should use a constant name, like
859    * v4l2slvp8dec, for any additional decoders, we create unique names. Decoder
860    * names may change between boots, so this should help gain stable names for
861    * the most common use cases. SL stands for state-less, we differentiate
862    * with v4l2vp8dec as this element may not have the same properties */
863   type_name = g_strdup_printf (element_name_tmpl, "");
864 
865   if (g_type_from_name (type_name) != 0) {
866     gchar *basename = g_path_get_basename (device->video_device_path);
867     g_free (type_name);
868     type_name = g_strdup_printf (element_name_tmpl, basename);
869     g_free (basename);
870   }
871 
872   subtype = g_type_register_static (dec_type, type_name, &type_info, 0);
873 
874   if (!gst_element_register (plugin, type_name, rank, subtype)) {
875     GST_WARNING ("Failed to register plugin '%s'", type_name);
876     g_free (type_name);
877     type_name = NULL;
878   }
879 
880   if (element_name)
881     *element_name = type_name;
882   else
883     g_free (type_name);
884 }
885 
886 /*
887  * gst_v4l2_decoder_alloc_request:
888  * @self a #GstV4l2Decoder pointer
889  * @frame_num: Used as a timestamp to identify references
890  * @bitstream the #GstMemory that holds the bitstream data
891  * @pic_buf the #GstBuffer holding the decoded picture
892  *
893  * Allocate a Linux media request file descriptor. This request wrapper will
894  * hold a reference to the requested bitstream memory to decoded and the
895  * picture buffer this request will decode to. This will be used for
896  * transparent management of the V4L2 queues.
897  *
898  * Returns: a new #GstV4l2Request
899  */
900 GstV4l2Request *
gst_v4l2_decoder_alloc_request(GstV4l2Decoder * self,guint32 frame_num,GstMemory * bitstream,GstBuffer * pic_buf)901 gst_v4l2_decoder_alloc_request (GstV4l2Decoder * self, guint32 frame_num,
902     GstMemory * bitstream, GstBuffer * pic_buf)
903 {
904   GstV4l2Request *request = gst_queue_array_pop_head (self->request_pool);
905   gint ret;
906 
907   if (!request) {
908     request = g_new0 (GstV4l2Request, 1);
909 
910     ret = ioctl (self->media_fd, MEDIA_IOC_REQUEST_ALLOC, &request->fd);
911     if (ret < 0) {
912       GST_ERROR_OBJECT (self, "MEDIA_IOC_REQUEST_ALLOC failed: %s",
913           g_strerror (errno));
914       return NULL;
915     }
916 
917     request->poll = gst_poll_new (FALSE);
918     gst_poll_fd_init (&request->pollfd);
919     request->pollfd.fd = request->fd;
920     gst_poll_add_fd (request->poll, &request->pollfd);
921     gst_poll_fd_ctl_pri (request->poll, &request->pollfd, TRUE);
922   }
923 
924   request->decoder = g_object_ref (self);
925   request->bitstream = gst_memory_ref (bitstream);
926   request->pic_buf = gst_buffer_ref (pic_buf);
927   request->frame_num = frame_num;
928   request->ref_count = 1;
929 
930   return request;
931 }
932 
933 /*
934  * gst_v4l2_decoder_alloc_sub_request:
935  * @self a #GstV4l2Decoder pointer
936  * @prev_request the #GstV4l2Request this request continue
937  * @bitstream the #GstMemory that holds the bitstream data
938  *
939  * Allocate a Linux media request file descriptor. Similar to
940  * gst_v4l2_decoder_alloc_request(), but used when a request is the
941  * continuation of the decoding of the same picture. This is notably the case
942  * for subsequent slices or for second field of a frame.
943  *
944  * Returns: a new #GstV4l2Request
945  */
946 GstV4l2Request *
gst_v4l2_decoder_alloc_sub_request(GstV4l2Decoder * self,GstV4l2Request * prev_request,GstMemory * bitstream)947 gst_v4l2_decoder_alloc_sub_request (GstV4l2Decoder * self,
948     GstV4l2Request * prev_request, GstMemory * bitstream)
949 {
950   GstV4l2Request *request = gst_queue_array_pop_head (self->request_pool);
951   gint ret;
952 
953   if (!request) {
954     request = g_new0 (GstV4l2Request, 1);
955 
956     ret = ioctl (self->media_fd, MEDIA_IOC_REQUEST_ALLOC, &request->fd);
957     if (ret < 0) {
958       GST_ERROR_OBJECT (self, "MEDIA_IOC_REQUEST_ALLOC failed: %s",
959           g_strerror (errno));
960       return NULL;
961     }
962 
963     request->poll = gst_poll_new (FALSE);
964     gst_poll_fd_init (&request->pollfd);
965     request->pollfd.fd = request->fd;
966     gst_poll_add_fd (request->poll, &request->pollfd);
967     gst_poll_fd_ctl_pri (request->poll, &request->pollfd, TRUE);
968   }
969 
970   request->decoder = g_object_ref (self);
971   request->bitstream = gst_memory_ref (bitstream);
972   request->pic_buf = gst_buffer_ref (prev_request->pic_buf);
973   request->frame_num = prev_request->frame_num;
974   request->sub_request = TRUE;
975   request->ref_count = 1;
976 
977   return request;
978 }
979 
980 /**
981  * gst_v4l2_decoder_set_render_delay:
982  * @self: a #GstV4l2Decoder pointer
983  * @delay: The expected render delay
984  *
985  * The decoder will adjust the number of allowed concurrent request in order
986  * to allow this delay. The same number of concurrent bitstream buffer will be
987  * used, so make sure to adjust the number of bitstream buffer.
988  *
989  * For per-slice decoder, this is the maximum number of pending slice, so the
990  * render backlog in frame may be less then the render delay.
991  */
992 void
gst_v4l2_decoder_set_render_delay(GstV4l2Decoder * self,guint delay)993 gst_v4l2_decoder_set_render_delay (GstV4l2Decoder * self, guint delay)
994 {
995   self->render_delay = delay;
996 }
997 
998 /**
999  * gst_v4l2_decoder_get_render_delay:
1000  * @self: a #GstV4l2Decoder pointer
1001  *
1002  * This function is used to avoid storing the render delay in multiple places.
1003  *
1004  * Returns: The currently configured render delay.
1005  */
1006 guint
gst_v4l2_decoder_get_render_delay(GstV4l2Decoder * self)1007 gst_v4l2_decoder_get_render_delay (GstV4l2Decoder * self)
1008 {
1009   return self->render_delay;
1010 }
1011 
1012 GstV4l2Request *
gst_v4l2_request_ref(GstV4l2Request * request)1013 gst_v4l2_request_ref (GstV4l2Request * request)
1014 {
1015   request->ref_count++;
1016   return request;
1017 }
1018 
1019 static void
gst_v4l2_request_free(GstV4l2Request * request)1020 gst_v4l2_request_free (GstV4l2Request * request)
1021 {
1022   GstV4l2Decoder *decoder = request->decoder;
1023 
1024   request->decoder = NULL;
1025   close (request->fd);
1026   gst_poll_free (request->poll);
1027   g_free (request);
1028 
1029   if (decoder)
1030     g_object_unref (decoder);
1031 }
1032 
1033 void
gst_v4l2_request_unref(GstV4l2Request * request)1034 gst_v4l2_request_unref (GstV4l2Request * request)
1035 {
1036   GstV4l2Decoder *decoder = request->decoder;
1037   gint ret;
1038 
1039   g_return_if_fail (request->ref_count > 0);
1040 
1041   if (--request->ref_count > 0)
1042     return;
1043 
1044   g_clear_pointer (&request->bitstream, gst_memory_unref);
1045   g_clear_pointer (&request->pic_buf, gst_buffer_unref);
1046   request->frame_num = G_MAXUINT32;
1047   request->failed = FALSE;
1048   request->hold_pic_buf = FALSE;
1049   request->sub_request = FALSE;
1050 
1051   if (request->pending) {
1052     gint idx;
1053 
1054     GST_DEBUG_OBJECT (decoder, "Freeing pending request %p.", request);
1055 
1056     idx = gst_queue_array_find (decoder->pending_requests, NULL, request);
1057     if (idx >= 0)
1058       gst_queue_array_drop_element (decoder->pending_requests, idx);
1059 
1060     gst_v4l2_request_free (request);
1061     return;
1062   }
1063 
1064   GST_TRACE_OBJECT (decoder, "Recycling request %p.", request);
1065 
1066   ret = ioctl (request->fd, MEDIA_REQUEST_IOC_REINIT, NULL);
1067   if (ret < 0) {
1068     GST_ERROR_OBJECT (request->decoder, "MEDIA_REQUEST_IOC_REINIT failed: %s",
1069         g_strerror (errno));
1070     gst_v4l2_request_free (request);
1071     return;
1072   }
1073 
1074   gst_queue_array_push_tail (decoder->request_pool, request);
1075   g_clear_object (&request->decoder);
1076 }
1077 
1078 gboolean
gst_v4l2_request_queue(GstV4l2Request * request,guint flags)1079 gst_v4l2_request_queue (GstV4l2Request * request, guint flags)
1080 {
1081   GstV4l2Decoder *decoder = request->decoder;
1082   gint ret;
1083   guint max_pending;
1084 
1085   GST_TRACE_OBJECT (decoder, "Queuing request %p.", request);
1086 
1087   if (!gst_v4l2_decoder_queue_sink_mem (decoder, request,
1088           request->bitstream, request->frame_num, flags)) {
1089     GST_ERROR_OBJECT (decoder, "Driver did not accept the bitstream data.");
1090     return FALSE;
1091   }
1092 
1093   if (!request->sub_request &&
1094       !gst_v4l2_decoder_queue_src_buffer (decoder, request->pic_buf)) {
1095     GST_ERROR_OBJECT (decoder, "Driver did not accept the picture buffer.");
1096     return FALSE;
1097   }
1098 
1099   ret = ioctl (request->fd, MEDIA_REQUEST_IOC_QUEUE, NULL);
1100   if (ret < 0) {
1101     GST_ERROR_OBJECT (decoder, "MEDIA_REQUEST_IOC_QUEUE, failed: %s",
1102         g_strerror (errno));
1103     return FALSE;
1104   }
1105 
1106   if (flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF)
1107     request->hold_pic_buf = TRUE;
1108 
1109   request->pending = TRUE;
1110   gst_queue_array_push_tail (decoder->pending_requests,
1111       gst_v4l2_request_ref (request));
1112 
1113   max_pending = MAX (1, decoder->render_delay);
1114 
1115   if (gst_queue_array_get_length (decoder->pending_requests) > max_pending) {
1116     GstV4l2Request *pending_req;
1117 
1118     pending_req = gst_queue_array_peek_head (decoder->pending_requests);
1119     gst_v4l2_request_set_done (pending_req);
1120   }
1121 
1122   return TRUE;
1123 }
1124 
1125 gint
gst_v4l2_request_set_done(GstV4l2Request * request)1126 gst_v4l2_request_set_done (GstV4l2Request * request)
1127 {
1128   GstV4l2Decoder *decoder = request->decoder;
1129   GstV4l2Request *pending_req = NULL;
1130   gint ret;
1131 
1132   if (!request->pending)
1133     return 1;
1134 
1135   ret = gst_poll_wait (request->poll, GST_SECOND);
1136   if (ret == 0) {
1137     GST_WARNING_OBJECT (decoder, "Request %p took too long.", request);
1138     return 0;
1139   }
1140 
1141   if (ret < 0) {
1142     GST_WARNING_OBJECT (decoder, "Request %p error: %s (%i)",
1143         request, g_strerror (errno), errno);
1144     return ret;
1145   }
1146 
1147   while ((pending_req = gst_queue_array_pop_head (decoder->pending_requests))) {
1148     gst_v4l2_decoder_dequeue_sink (decoder);
1149     g_clear_pointer (&pending_req->bitstream, gst_memory_unref);
1150 
1151     if (!pending_req->hold_pic_buf) {
1152       guint32 frame_num = G_MAXUINT32;
1153 
1154       if (!gst_v4l2_decoder_dequeue_src (decoder, &frame_num)) {
1155         pending_req->failed = TRUE;
1156       } else if (frame_num != pending_req->frame_num) {
1157         GST_WARNING_OBJECT (decoder,
1158             "Requested frame %u, but driver returned frame %u.",
1159             pending_req->frame_num, frame_num);
1160         pending_req->failed = TRUE;
1161       }
1162     }
1163 
1164     pending_req->pending = FALSE;
1165     gst_v4l2_request_unref (pending_req);
1166 
1167     if (pending_req == request)
1168       break;
1169   }
1170 
1171   /* Pending request must be in the pending request list */
1172   g_assert (pending_req == request);
1173 
1174   return ret;
1175 }
1176 
1177 gboolean
gst_v4l2_request_failed(GstV4l2Request * request)1178 gst_v4l2_request_failed (GstV4l2Request * request)
1179 {
1180   return request->failed;
1181 }
1182 
1183 GstBuffer *
gst_v4l2_request_dup_pic_buf(GstV4l2Request * request)1184 gst_v4l2_request_dup_pic_buf (GstV4l2Request * request)
1185 {
1186   return gst_buffer_ref (request->pic_buf);
1187 }
1188