2 * Copyright (C) 2020 Nicolas Dufresne <nicolas.dufresne@collabora.com>
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.
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.
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.
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"
32 #include <sys/ioctl.h>
34 #include <sys/types.h>
37 #include <gst/base/base.h>
39 #define IMAGE_MINSZ (256*1024) /* 256kB */
41 GST_DEBUG_CATEGORY (v4l2_decoder_debug);
42 #define GST_CAT_DEFAULT v4l2_decoder_debug
51 struct _GstV4l2Request
56 GstV4l2Decoder *decoder;
67 gboolean hold_pic_buf;
71 struct _GstV4l2Decoder
78 GstQueueArray *request_pool;
79 GstQueueArray *pending_requests;
82 enum v4l2_buf_type src_buf_type;
83 enum v4l2_buf_type sink_buf_type;
91 /* detected features */
92 gboolean supports_holding_capture;
95 G_DEFINE_TYPE_WITH_CODE (GstV4l2Decoder, gst_v4l2_decoder, GST_TYPE_OBJECT,
96 GST_DEBUG_CATEGORY_INIT (v4l2_decoder_debug, "v4l2codecs-decoder", 0,
97 "V4L2 stateless decoder helper"));
99 static void gst_v4l2_request_free (GstV4l2Request * request);
102 direction_to_buffer_type (GstV4l2Decoder * self, GstPadDirection direction)
104 if (direction == GST_PAD_SRC)
105 return self->src_buf_type;
107 return self->sink_buf_type;
111 gst_v4l2_decoder_finalize (GObject * obj)
113 GstV4l2Decoder *self = GST_V4L2_DECODER (obj);
115 gst_v4l2_decoder_close (self);
117 g_free (self->media_device);
118 g_free (self->video_device);
119 gst_queue_array_free (self->request_pool);
120 gst_queue_array_free (self->pending_requests);
122 G_OBJECT_CLASS (gst_v4l2_decoder_parent_class)->finalize (obj);
126 gst_v4l2_decoder_init (GstV4l2Decoder * self)
128 self->request_pool = gst_queue_array_new (16);
129 self->pending_requests = gst_queue_array_new (16);
133 gst_v4l2_decoder_class_init (GstV4l2DecoderClass * klass)
135 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
137 gobject_class->finalize = gst_v4l2_decoder_finalize;
138 gobject_class->get_property = gst_v4l2_decoder_get_property;
139 gobject_class->set_property = gst_v4l2_decoder_set_property;
141 gst_v4l2_decoder_install_properties (gobject_class, 0, NULL);
145 gst_v4l2_decoder_new (GstV4l2CodecDevice * device)
147 GstV4l2Decoder *decoder;
149 g_return_val_if_fail (device->function == MEDIA_ENT_F_PROC_VIDEO_DECODER,
152 decoder = g_object_new (GST_TYPE_V4L2_DECODER,
153 "media-device", device->media_device_path,
154 "video-device", device->video_device_path, NULL);
156 return gst_object_ref_sink (decoder);
160 gst_v4l2_decoder_get_version (GstV4l2Decoder * self)
162 return self->version;
166 gst_v4l2_decoder_open (GstV4l2Decoder * self)
169 struct v4l2_capability querycap;
170 guint32 capabilities;
172 self->media_fd = open (self->media_device, 0);
173 if (self->media_fd < 0) {
174 GST_ERROR_OBJECT (self, "Failed to open '%s': %s",
175 self->media_device, g_strerror (errno));
179 self->video_fd = open (self->video_device, O_NONBLOCK);
180 if (self->video_fd < 0) {
181 GST_ERROR_OBJECT (self, "Failed to open '%s': %s",
182 self->video_device, g_strerror (errno));
186 ret = ioctl (self->video_fd, VIDIOC_QUERYCAP, &querycap);
188 GST_ERROR_OBJECT (self, "VIDIOC_QUERYCAP failed: %s", g_strerror (errno));
189 gst_v4l2_decoder_close (self);
193 self->version = querycap.version;
195 if (querycap.capabilities & V4L2_CAP_DEVICE_CAPS)
196 capabilities = querycap.device_caps;
198 capabilities = querycap.capabilities;
200 if (capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) {
201 self->sink_buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
202 self->src_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
204 } else if (capabilities & V4L2_CAP_VIDEO_M2M) {
205 self->sink_buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
206 self->src_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
207 self->mplane = FALSE;
209 GST_ERROR_OBJECT (self, "Unsupported memory-2-memory device.");
210 gst_v4l2_decoder_close (self);
220 gst_v4l2_decoder_close (GstV4l2Decoder * self)
222 GstV4l2Request *request;
224 while ((request = gst_queue_array_pop_head (self->pending_requests)))
225 gst_v4l2_request_unref (request);
227 while ((request = gst_queue_array_pop_head (self->request_pool)))
228 gst_v4l2_request_free (request);
231 close (self->media_fd);
233 close (self->video_fd);
237 self->opened = FALSE;
243 gst_v4l2_decoder_streamon (GstV4l2Decoder * self, GstPadDirection direction)
246 guint32 type = direction_to_buffer_type (self, direction);
248 ret = ioctl (self->video_fd, VIDIOC_STREAMON, &type);
250 GST_ERROR_OBJECT (self, "VIDIOC_STREAMON failed: %s", g_strerror (errno));
258 gst_v4l2_decoder_streamoff (GstV4l2Decoder * self, GstPadDirection direction)
260 guint32 type = direction_to_buffer_type (self, direction);
263 if (direction == GST_PAD_SRC) {
264 GstV4l2Request *pending_req;
266 /* STREAMOFF have the effect of cancelling all requests and unqueuing all
267 * buffers, so clear the pending request list */
268 while ((pending_req = gst_queue_array_pop_head (self->pending_requests))) {
269 g_clear_pointer (&pending_req->bitstream, gst_memory_unref);
270 pending_req->pending = FALSE;
271 gst_v4l2_request_unref (pending_req);
275 ret = ioctl (self->video_fd, VIDIOC_STREAMOFF, &type);
277 GST_ERROR_OBJECT (self, "VIDIOC_STREAMOFF failed: %s", g_strerror (errno));
285 gst_v4l2_decoder_flush (GstV4l2Decoder * self)
287 /* We ignore streamoff failure as it's not relevant, if we manage to
288 * streamon again, we are good. */
289 gst_v4l2_decoder_streamoff (self, GST_PAD_SINK);
290 gst_v4l2_decoder_streamoff (self, GST_PAD_SRC);
292 return gst_v4l2_decoder_streamon (self, GST_PAD_SINK) &&
293 gst_v4l2_decoder_streamon (self, GST_PAD_SRC);
297 gst_v4l2_decoder_enum_sink_fmt (GstV4l2Decoder * self, gint i,
300 struct v4l2_fmtdesc fmtdesc = { i, self->sink_buf_type, };
303 g_return_val_if_fail (self->opened, FALSE);
305 ret = ioctl (self->video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
308 GST_ERROR_OBJECT (self, "VIDIOC_ENUM_FMT failed: %s", g_strerror (errno));
312 GST_DEBUG_OBJECT (self, "Found format %" GST_FOURCC_FORMAT " (%s)",
313 GST_FOURCC_ARGS (fmtdesc.pixelformat), fmtdesc.description);
314 *out_fmt = fmtdesc.pixelformat;
320 gst_v4l2_decoder_set_sink_fmt (GstV4l2Decoder * self, guint32 pix_fmt,
321 gint width, gint height, gint pixel_bitdepth)
323 struct v4l2_format format = (struct v4l2_format) {
324 .type = self->sink_buf_type,
325 /* Compatible with .fmt.pix for these field */
326 .fmt.pix_mp = (struct v4l2_pix_format_mplane) {
327 .pixelformat = pix_fmt,
334 /* Using raw image size for now, it is guarantied to be large enough */
335 gsize sizeimage = MAX (IMAGE_MINSZ, (width * height * pixel_bitdepth) / 8);
338 format.fmt.pix_mp.plane_fmt[0].sizeimage = sizeimage;
340 format.fmt.pix.sizeimage = sizeimage;
342 ret = ioctl (self->video_fd, VIDIOC_S_FMT, &format);
344 GST_ERROR_OBJECT (self, "VIDIOC_S_FMT failed: %s", g_strerror (errno));
348 if (format.fmt.pix_mp.pixelformat != pix_fmt
349 || format.fmt.pix_mp.width < width || format.fmt.pix_mp.height < height) {
350 GST_WARNING_OBJECT (self, "Failed to set sink format to %"
351 GST_FOURCC_FORMAT " %ix%i", GST_FOURCC_ARGS (pix_fmt), width, height);
360 gst_v4l2_decoder_enum_size_for_format (GstV4l2Decoder * self,
361 guint32 pixelformat, gint index, gint unscaled_width, gint unscaled_height)
363 struct v4l2_frmsizeenum size;
364 GstVideoFormat format;
368 memset (&size, 0, sizeof (struct v4l2_frmsizeenum));
370 size.pixel_format = pixelformat;
372 GST_DEBUG_OBJECT (self, "enumerate size index %d for %" GST_FOURCC_FORMAT,
373 index, GST_FOURCC_ARGS (pixelformat));
375 ret = ioctl (self->video_fd, VIDIOC_ENUM_FRAMESIZES, &size);
380 if (size.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
381 GST_WARNING_OBJECT (self, "V4L2_FRMSIZE type not supported");
385 if (gst_util_fraction_compare (unscaled_width, unscaled_height,
386 size.discrete.width, size.discrete.height)) {
387 GST_DEBUG_OBJECT (self,
388 "Pixel ratio modification not supported %dx%d %dx%d (%d)",
389 unscaled_width, unscaled_height, size.discrete.width,
390 size.discrete.height, ret);
394 res = gst_v4l2_format_to_video_format (pixelformat, &format);
397 GST_DEBUG_OBJECT (self, "get size (%d x %d) index %d for %" GST_FOURCC_FORMAT,
398 size.discrete.width, size.discrete.height, index,
399 GST_FOURCC_ARGS (pixelformat));
401 return gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
402 gst_video_format_to_string (format),
403 "width", G_TYPE_INT, size.discrete.width,
404 "height", G_TYPE_INT, size.discrete.height, NULL);
408 gst_v4l2_decoder_probe_caps_for_format (GstV4l2Decoder * self,
409 guint32 pixelformat, gint unscaled_width, gint unscaled_height)
413 GstVideoFormat format;
415 GST_DEBUG_OBJECT (self, "enumerate size for %" GST_FOURCC_FORMAT,
416 GST_FOURCC_ARGS (pixelformat));
418 if (!gst_v4l2_format_to_video_format (pixelformat, &format))
419 return gst_caps_new_empty ();
421 caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
422 gst_video_format_to_string (format), NULL);
424 while ((tmp = gst_v4l2_decoder_enum_size_for_format (self, pixelformat,
425 index++, unscaled_width, unscaled_height))) {
426 caps = gst_caps_merge (caps, tmp);
433 gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self)
436 struct v4l2_format fmt = {
437 .type = self->src_buf_type,
442 g_return_val_if_fail (self->opened, FALSE);
444 ret = ioctl (self->video_fd, VIDIOC_G_FMT, &fmt);
446 GST_ERROR_OBJECT (self, "VIDIOC_G_FMT failed: %s", g_strerror (errno));
451 gst_v4l2_decoder_probe_caps_for_format (self,
452 fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height);
454 /* And then enumerate other possible formats and place that as a second
455 * structure in the caps */
456 for (i = 0; ret >= 0; i++) {
457 struct v4l2_fmtdesc fmtdesc = { i, self->src_buf_type, };
460 ret = ioctl (self->video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
463 GST_ERROR_OBJECT (self, "VIDIOC_ENUM_FMT failed: %s",
468 tmp = gst_v4l2_decoder_probe_caps_for_format (self, fmtdesc.pixelformat,
469 fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height);
470 caps = gst_caps_merge (caps, tmp);
477 gst_v4l2_decoder_select_src_format (GstV4l2Decoder * self, GstCaps * caps,
481 struct v4l2_format fmt = {
482 .type = self->src_buf_type,
485 const gchar *format_str;
486 GstVideoFormat format;
489 if (gst_caps_is_empty (caps))
492 ret = ioctl (self->video_fd, VIDIOC_G_FMT, &fmt);
494 GST_ERROR_OBJECT (self, "VIDIOC_G_FMT failed: %s", g_strerror (errno));
498 caps = gst_caps_make_writable (caps);
499 str = gst_caps_get_structure (caps, 0);
500 gst_structure_fixate_field (str, "format");
502 format_str = gst_structure_get_string (str, "format");
503 format = gst_video_format_from_string (format_str);
505 if (gst_v4l2_format_from_video_format (format, &pix_fmt) &&
506 pix_fmt != fmt.fmt.pix_mp.pixelformat) {
507 GST_DEBUG_OBJECT (self, "Trying to use peer format: %s ", format_str);
508 fmt.fmt.pix_mp.pixelformat = pix_fmt;
510 ret = ioctl (self->video_fd, VIDIOC_S_FMT, &fmt);
512 GST_ERROR_OBJECT (self, "VIDIOC_S_FMT failed: %s", g_strerror (errno));
517 if (!gst_v4l2_format_to_video_info (&fmt, info)) {
518 GST_ERROR_OBJECT (self, "Unsupported V4L2 pixelformat %" GST_FOURCC_FORMAT,
519 GST_FOURCC_ARGS (fmt.fmt.pix_mp.pixelformat));
523 GST_INFO_OBJECT (self, "Selected format %s %ix%i",
524 gst_video_format_to_string (info->finfo->format),
525 info->width, info->height);
531 gst_v4l2_decoder_request_buffers (GstV4l2Decoder * self,
532 GstPadDirection direction, guint num_buffers)
535 struct v4l2_requestbuffers reqbufs = {
536 .count = num_buffers,
537 .memory = V4L2_MEMORY_MMAP,
538 .type = direction_to_buffer_type (self, direction),
541 GST_DEBUG_OBJECT (self, "Requesting %u buffers", num_buffers);
543 ret = ioctl (self->video_fd, VIDIOC_REQBUFS, &reqbufs);
545 GST_ERROR_OBJECT (self, "VIDIOC_REQBUFS failed: %s", g_strerror (errno));
549 if (direction == GST_PAD_SINK) {
550 if (reqbufs.capabilities & V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF)
551 self->supports_holding_capture = TRUE;
553 self->supports_holding_capture = FALSE;
556 return reqbufs.count;
560 gst_v4l2_decoder_export_buffer (GstV4l2Decoder * self,
561 GstPadDirection direction, gint index, gint * fds, gsize * sizes,
562 gsize * offsets, guint * num_fds)
565 struct v4l2_plane planes[GST_VIDEO_MAX_PLANES] = { {0} };
566 struct v4l2_buffer v4l2_buf = {
568 .type = direction_to_buffer_type (self, direction),
572 v4l2_buf.length = GST_VIDEO_MAX_PLANES;
573 v4l2_buf.m.planes = planes;
576 ret = ioctl (self->video_fd, VIDIOC_QUERYBUF, &v4l2_buf);
578 GST_ERROR_OBJECT (self, "VIDIOC_QUERYBUF failed: %s", g_strerror (errno));
583 for (i = 0; i < v4l2_buf.length; i++) {
584 struct v4l2_plane *plane = v4l2_buf.m.planes + i;
585 struct v4l2_exportbuffer expbuf = {
586 .type = direction_to_buffer_type (self, direction),
589 .flags = O_CLOEXEC | O_RDWR,
592 ret = ioctl (self->video_fd, VIDIOC_EXPBUF, &expbuf);
595 GST_ERROR_OBJECT (self, "VIDIOC_EXPBUF failed: %s", g_strerror (errno));
597 for (j = i - 1; j >= 0; j--)
603 *num_fds = v4l2_buf.length;
605 sizes[i] = plane->length;
606 offsets[i] = plane->data_offset;
609 struct v4l2_exportbuffer expbuf = {
610 .type = direction_to_buffer_type (self, direction),
612 .flags = O_CLOEXEC | O_RDWR,
615 ret = ioctl (self->video_fd, VIDIOC_EXPBUF, &expbuf);
617 GST_ERROR_OBJECT (self, "VIDIOC_EXPBUF failed: %s", g_strerror (errno));
623 sizes[0] = v4l2_buf.length;
631 gst_v4l2_decoder_queue_sink_mem (GstV4l2Decoder * self,
632 GstV4l2Request * request, GstMemory * mem, guint32 frame_num, guint flags)
635 gsize bytesused = gst_memory_get_sizes (mem, NULL, NULL);
636 struct v4l2_plane plane = {
637 .bytesused = bytesused,
639 struct v4l2_buffer buf = {
640 .type = self->sink_buf_type,
641 .memory = V4L2_MEMORY_MMAP,
642 .index = gst_v4l2_codec_memory_get_index (mem),
643 .timestamp.tv_sec = frame_num / 1000000,
644 .timestamp.tv_usec = frame_num % 1000000,
645 .request_fd = request->fd,
646 .flags = V4L2_BUF_FLAG_REQUEST_FD | flags,
649 GST_TRACE_OBJECT (self, "Queueing bitstream buffer %i", buf.index);
653 buf.m.planes = &plane;
655 buf.bytesused = bytesused;
658 ret = ioctl (self->video_fd, VIDIOC_QBUF, &buf);
660 GST_ERROR_OBJECT (self, "VIDIOC_QBUF failed: %s", g_strerror (errno));
668 gst_v4l2_decoder_queue_src_buffer (GstV4l2Decoder * self, GstBuffer * buffer)
671 struct v4l2_plane planes[GST_VIDEO_MAX_PLANES];
672 struct v4l2_buffer buf = {
673 .type = self->src_buf_type,
674 .memory = V4L2_MEMORY_MMAP,
675 .index = gst_v4l2_codec_buffer_get_index (buffer),
678 GST_TRACE_OBJECT (self, "Queuing picture buffer %i", buf.index);
681 buf.length = gst_buffer_n_memory (buffer);
682 buf.m.planes = planes;
683 for (i = 0; i < buf.length; i++) {
684 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
686 planes[i] = (struct v4l2_plane) {
687 .bytesused = gst_memory_get_sizes (mem, NULL, NULL),
692 buf.bytesused = gst_buffer_get_size (buffer);
695 ret = ioctl (self->video_fd, VIDIOC_QBUF, &buf);
697 GST_ERROR_OBJECT (self, "VIDIOC_QBUF failed: %s", g_strerror (errno));
705 gst_v4l2_decoder_dequeue_sink (GstV4l2Decoder * self)
708 struct v4l2_plane planes[GST_VIDEO_MAX_PLANES] = { {0} };
709 struct v4l2_buffer buf = {
710 .type = self->sink_buf_type,
711 .memory = V4L2_MEMORY_MMAP,
715 buf.length = GST_VIDEO_MAX_PLANES;
716 buf.m.planes = planes;
719 ret = ioctl (self->video_fd, VIDIOC_DQBUF, &buf);
721 GST_ERROR_OBJECT (self, "VIDIOC_DQBUF failed: %s", g_strerror (errno));
725 GST_TRACE_OBJECT (self, "Dequeued bitstream buffer %i", buf.index);
731 gst_v4l2_decoder_dequeue_src (GstV4l2Decoder * self, guint32 * out_frame_num)
734 struct v4l2_plane planes[GST_VIDEO_MAX_PLANES] = { {0} };
735 struct v4l2_buffer buf = {
736 .type = self->src_buf_type,
737 .memory = V4L2_MEMORY_MMAP,
741 buf.length = GST_VIDEO_MAX_PLANES;
742 buf.m.planes = planes;
745 ret = ioctl (self->video_fd, VIDIOC_DQBUF, &buf);
747 GST_ERROR_OBJECT (self, "VIDIOC_DQBUF failed: %s", g_strerror (errno));
751 *out_frame_num = buf.timestamp.tv_usec + buf.timestamp.tv_sec * 1000000;
753 GST_TRACE_OBJECT (self, "Dequeued picture buffer %i", buf.index);
759 gst_v4l2_decoder_set_controls (GstV4l2Decoder * self, GstV4l2Request * request,
760 struct v4l2_ext_control * control, guint count)
763 struct v4l2_ext_controls controls = {
766 .request_fd = request ? request->fd : 0,
767 .which = request ? V4L2_CTRL_WHICH_REQUEST_VAL : 0,
770 ret = ioctl (self->video_fd, VIDIOC_S_EXT_CTRLS, &controls);
772 GST_ERROR_OBJECT (self, "VIDIOC_S_EXT_CTRLS failed: %s",
781 gst_v4l2_decoder_get_controls (GstV4l2Decoder * self,
782 struct v4l2_ext_control * control, guint count)
785 struct v4l2_ext_controls controls = {
790 ret = ioctl (self->video_fd, VIDIOC_G_EXT_CTRLS, &controls);
792 GST_ERROR_OBJECT (self, "VIDIOC_G_EXT_CTRLS failed: %s",
801 gst_v4l2_decoder_query_control_size (GstV4l2Decoder * self,
802 unsigned int control_id, unsigned int *control_size)
805 struct v4l2_query_ext_ctrl control = {
812 ret = ioctl (self->video_fd, VIDIOC_QUERY_EXT_CTRL, &control);
815 * It's not an error if a control is not supported by this driver.
816 * Return false but don't print any error.
821 *control_size = control.elem_size;
826 gst_v4l2_decoder_install_properties (GObjectClass * gobject_class,
827 gint prop_offset, GstV4l2CodecDevice * device)
829 const gchar *media_device_path = NULL;
830 const gchar *video_device_path = NULL;
833 media_device_path = device->media_device_path;
834 video_device_path = device->video_device_path;
837 g_object_class_install_property (gobject_class, PROP_MEDIA_DEVICE,
838 g_param_spec_string ("media-device", "Media Device Path",
839 "Path to the media device node", media_device_path,
840 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
842 g_object_class_install_property (gobject_class, PROP_VIDEO_DEVICE,
843 g_param_spec_string ("video-device", "Video Device Path",
844 "Path to the video device node", video_device_path,
845 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
849 gst_v4l2_decoder_set_property (GObject * object, guint prop_id,
850 const GValue * value, GParamSpec * pspec)
852 GstV4l2Decoder *self = GST_V4L2_DECODER (object);
855 case PROP_MEDIA_DEVICE:
856 g_free (self->media_device);
857 self->media_device = g_value_dup_string (value);
859 case PROP_VIDEO_DEVICE:
860 g_free (self->video_device);
861 self->video_device = g_value_dup_string (value);
864 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
870 gst_v4l2_decoder_get_property (GObject * object, guint prop_id,
871 GValue * value, GParamSpec * pspec)
873 GstV4l2Decoder *self = GST_V4L2_DECODER (object);
876 case PROP_MEDIA_DEVICE:
877 g_value_set_string (value, self->media_device);
879 case PROP_VIDEO_DEVICE:
880 g_value_set_string (value, self->video_device);
883 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
889 * gst_v4l2_decoder_register:
890 * @plugin: a #GstPlugin
891 * @dec_type: A #GType for the codec
892 * @class_init: The #GClassInitFunc for #dec_type
893 * @instance_init: The #GInstanceInitFunc for #dec_type
894 * @element_name_tmpl: A string to use for the first codec found and as a template for the next ones.
895 * @device: (transfer full) A #GstV4l2CodecDevice
896 * @rank: The rank to use for the element
897 * @class_data: (nullable) (transfer full) A #gpointer to pass as class_data, set to @device if null
898 * @element_name (nullable) (out) Sets the pointer to the new element name
900 * Registers a decoder element as a subtype of @dec_type for @plugin.
901 * Will create a different sub_types for each subsequent @decoder of the
905 gst_v4l2_decoder_register (GstPlugin * plugin,
906 GType dec_type, GClassInitFunc class_init, gconstpointer class_data,
907 GInstanceInitFunc instance_init, const gchar * element_name_tmpl,
908 GstV4l2CodecDevice * device, guint rank, gchar ** element_name)
910 GTypeQuery type_query;
911 GTypeInfo type_info = { 0, };
915 g_type_query (dec_type, &type_query);
916 memset (&type_info, 0, sizeof (type_info));
917 type_info.class_size = type_query.class_size;
918 type_info.instance_size = type_query.instance_size;
919 type_info.class_init = class_init;
920 type_info.class_data = class_data;
921 type_info.instance_init = instance_init;
923 if (class_data == device)
924 GST_MINI_OBJECT_FLAG_SET (device, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
926 /* The first decoder to be registered should use a constant name, like
927 * v4l2slvp8dec, for any additional decoders, we create unique names. Decoder
928 * names may change between boots, so this should help gain stable names for
929 * the most common use cases. SL stands for state-less, we differentiate
930 * with v4l2vp8dec as this element may not have the same properties */
931 type_name = g_strdup_printf (element_name_tmpl, "");
933 if (g_type_from_name (type_name) != 0) {
934 gchar *basename = g_path_get_basename (device->video_device_path);
936 type_name = g_strdup_printf (element_name_tmpl, basename);
940 subtype = g_type_register_static (dec_type, type_name, &type_info, 0);
942 if (!gst_element_register (plugin, type_name, rank, subtype)) {
943 GST_WARNING ("Failed to register plugin '%s'", type_name);
949 *element_name = type_name;
955 * gst_v4l2_decoder_alloc_request:
956 * @self a #GstV4l2Decoder pointer
957 * @frame_num: Used as a timestamp to identify references
958 * @bitstream the #GstMemory that holds the bitstream data
959 * @pic_buf the #GstBuffer holding the decoded picture
961 * Allocate a Linux media request file descriptor. This request wrapper will
962 * hold a reference to the requested bitstream memory to decoded and the
963 * picture buffer this request will decode to. This will be used for
964 * transparent management of the V4L2 queues.
966 * Returns: a new #GstV4l2Request
969 gst_v4l2_decoder_alloc_request (GstV4l2Decoder * self, guint32 frame_num,
970 GstMemory * bitstream, GstBuffer * pic_buf)
972 GstV4l2Request *request = gst_queue_array_pop_head (self->request_pool);
976 request = g_new0 (GstV4l2Request, 1);
978 ret = ioctl (self->media_fd, MEDIA_IOC_REQUEST_ALLOC, &request->fd);
980 GST_ERROR_OBJECT (self, "MEDIA_IOC_REQUEST_ALLOC failed: %s",
985 request->poll = gst_poll_new (FALSE);
986 gst_poll_fd_init (&request->pollfd);
987 request->pollfd.fd = request->fd;
988 gst_poll_add_fd (request->poll, &request->pollfd);
989 gst_poll_fd_ctl_pri (request->poll, &request->pollfd, TRUE);
992 request->decoder = g_object_ref (self);
993 request->bitstream = gst_memory_ref (bitstream);
994 request->pic_buf = gst_buffer_ref (pic_buf);
995 request->frame_num = frame_num;
996 request->ref_count = 1;
1002 * gst_v4l2_decoder_alloc_sub_request:
1003 * @self a #GstV4l2Decoder pointer
1004 * @prev_request the #GstV4l2Request this request continue
1005 * @bitstream the #GstMemory that holds the bitstream data
1007 * Allocate a Linux media request file descriptor. Similar to
1008 * gst_v4l2_decoder_alloc_request(), but used when a request is the
1009 * continuation of the decoding of the same picture. This is notably the case
1010 * for subsequent slices or for second field of a frame.
1012 * Returns: a new #GstV4l2Request
1015 gst_v4l2_decoder_alloc_sub_request (GstV4l2Decoder * self,
1016 GstV4l2Request * prev_request, GstMemory * bitstream)
1018 GstV4l2Request *request = gst_queue_array_pop_head (self->request_pool);
1022 request = g_new0 (GstV4l2Request, 1);
1024 ret = ioctl (self->media_fd, MEDIA_IOC_REQUEST_ALLOC, &request->fd);
1026 GST_ERROR_OBJECT (self, "MEDIA_IOC_REQUEST_ALLOC failed: %s",
1027 g_strerror (errno));
1031 request->poll = gst_poll_new (FALSE);
1032 gst_poll_fd_init (&request->pollfd);
1033 request->pollfd.fd = request->fd;
1034 gst_poll_add_fd (request->poll, &request->pollfd);
1035 gst_poll_fd_ctl_pri (request->poll, &request->pollfd, TRUE);
1038 request->decoder = g_object_ref (self);
1039 request->bitstream = gst_memory_ref (bitstream);
1040 request->pic_buf = gst_buffer_ref (prev_request->pic_buf);
1041 request->frame_num = prev_request->frame_num;
1042 request->sub_request = TRUE;
1043 request->ref_count = 1;
1049 * gst_v4l2_decoder_set_render_delay:
1050 * @self: a #GstV4l2Decoder pointer
1051 * @delay: The expected render delay
1053 * The decoder will adjust the number of allowed concurrent request in order
1054 * to allow this delay. The same number of concurrent bitstream buffer will be
1055 * used, so make sure to adjust the number of bitstream buffer.
1057 * For per-slice decoder, this is the maximum number of pending slice, so the
1058 * render backlog in frame may be less then the render delay.
1061 gst_v4l2_decoder_set_render_delay (GstV4l2Decoder * self, guint delay)
1063 self->render_delay = delay;
1067 * gst_v4l2_decoder_get_render_delay:
1068 * @self: a #GstV4l2Decoder pointer
1070 * This function is used to avoid storing the render delay in multiple places.
1072 * Returns: The currently configured render delay.
1075 gst_v4l2_decoder_get_render_delay (GstV4l2Decoder * self)
1077 return self->render_delay;
1081 gst_v4l2_request_ref (GstV4l2Request * request)
1083 request->ref_count++;
1088 gst_v4l2_request_free (GstV4l2Request * request)
1090 GstV4l2Decoder *decoder = request->decoder;
1092 request->decoder = NULL;
1093 close (request->fd);
1094 gst_poll_free (request->poll);
1098 g_object_unref (decoder);
1102 gst_v4l2_request_unref (GstV4l2Request * request)
1104 GstV4l2Decoder *decoder = request->decoder;
1107 g_return_if_fail (request->ref_count > 0);
1109 if (--request->ref_count > 0)
1112 g_clear_pointer (&request->bitstream, gst_memory_unref);
1113 g_clear_pointer (&request->pic_buf, gst_buffer_unref);
1114 request->frame_num = G_MAXUINT32;
1115 request->failed = FALSE;
1116 request->hold_pic_buf = FALSE;
1117 request->sub_request = FALSE;
1119 if (request->pending) {
1122 GST_DEBUG_OBJECT (decoder, "Freeing pending request %i.", request->fd);
1124 idx = gst_queue_array_find (decoder->pending_requests, NULL, request);
1126 gst_queue_array_drop_element (decoder->pending_requests, idx);
1128 gst_v4l2_request_free (request);
1132 GST_TRACE_OBJECT (decoder, "Recycling request %i.", request->fd);
1134 ret = ioctl (request->fd, MEDIA_REQUEST_IOC_REINIT, NULL);
1136 GST_ERROR_OBJECT (request->decoder, "MEDIA_REQUEST_IOC_REINIT failed: %s",
1137 g_strerror (errno));
1138 gst_v4l2_request_free (request);
1142 gst_queue_array_push_tail (decoder->request_pool, request);
1143 g_clear_object (&request->decoder);
1147 gst_v4l2_request_queue (GstV4l2Request * request, guint flags)
1149 GstV4l2Decoder *decoder = request->decoder;
1153 GST_TRACE_OBJECT (decoder, "Queuing request %i.", request->fd);
1155 /* this would lead to stalls if we tried to use this feature and it wasn't
1157 if ((flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF)
1158 && !decoder->supports_holding_capture) {
1159 GST_ERROR_OBJECT (decoder,
1160 "Driver does not support holding capture buffer.");
1164 if (!gst_v4l2_decoder_queue_sink_mem (decoder, request,
1165 request->bitstream, request->frame_num, flags)) {
1166 GST_ERROR_OBJECT (decoder, "Driver did not accept the bitstream data.");
1170 if (!request->sub_request &&
1171 !gst_v4l2_decoder_queue_src_buffer (decoder, request->pic_buf)) {
1172 GST_ERROR_OBJECT (decoder, "Driver did not accept the picture buffer.");
1176 ret = ioctl (request->fd, MEDIA_REQUEST_IOC_QUEUE, NULL);
1178 GST_ERROR_OBJECT (decoder, "MEDIA_REQUEST_IOC_QUEUE, failed: %s",
1179 g_strerror (errno));
1183 if (flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF)
1184 request->hold_pic_buf = TRUE;
1186 request->pending = TRUE;
1187 gst_queue_array_push_tail (decoder->pending_requests,
1188 gst_v4l2_request_ref (request));
1190 max_pending = MAX (1, decoder->render_delay);
1192 if (gst_queue_array_get_length (decoder->pending_requests) > max_pending) {
1193 GstV4l2Request *pending_req;
1195 pending_req = gst_queue_array_peek_head (decoder->pending_requests);
1196 gst_v4l2_request_set_done (pending_req);
1203 gst_v4l2_request_set_done (GstV4l2Request * request)
1205 GstV4l2Decoder *decoder = request->decoder;
1206 GstV4l2Request *pending_req = NULL;
1209 if (!request->pending)
1212 GST_DEBUG_OBJECT (decoder, "Waiting for request %i to complete.",
1215 ret = gst_poll_wait (request->poll, GST_SECOND);
1217 GST_WARNING_OBJECT (decoder, "Request %i took too long.", request->fd);
1222 GST_WARNING_OBJECT (decoder, "Request %i error: %s (%i)",
1223 request->fd, g_strerror (errno), errno);
1227 while ((pending_req = gst_queue_array_pop_head (decoder->pending_requests))) {
1228 gst_v4l2_decoder_dequeue_sink (decoder);
1229 g_clear_pointer (&pending_req->bitstream, gst_memory_unref);
1231 if (!pending_req->hold_pic_buf) {
1232 guint32 frame_num = G_MAXUINT32;
1234 if (!gst_v4l2_decoder_dequeue_src (decoder, &frame_num)) {
1235 pending_req->failed = TRUE;
1236 } else if (frame_num != pending_req->frame_num) {
1237 GST_WARNING_OBJECT (decoder,
1238 "Requested frame %u, but driver returned frame %u.",
1239 pending_req->frame_num, frame_num);
1240 pending_req->failed = TRUE;
1244 pending_req->pending = FALSE;
1245 gst_v4l2_request_unref (pending_req);
1247 if (pending_req == request)
1251 /* Pending request must be in the pending request list */
1252 g_assert (pending_req == request);
1258 gst_v4l2_request_failed (GstV4l2Request * request)
1260 return request->failed;
1264 gst_v4l2_request_dup_pic_buf (GstV4l2Request * request)
1266 return gst_buffer_ref (request->pic_buf);
1270 gst_v4l2_request_get_fd (GstV4l2Request * request)