beb2e56dbbab93fc39dd901d18681cfa7efb6592
[platform/upstream/gstreamer.git] / sys / v4l2codecs / gstv4l2decoder.c
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/stat.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35
36 GST_DEBUG_CATEGORY (v4l2_decoder_debug);
37 #define GST_CAT_DEFAULT v4l2_decoder_debug
38
39 enum
40 {
41   PROP_0,
42   PROP_MEDIA_DEVICE,
43   PROP_VIDEO_DEVICE,
44 };
45
46 struct _GstV4l2Request
47 {
48   GstV4l2Decoder *decoder;
49   gint fd;
50   GstMemory *bitstream;
51   GstPoll *poll;
52   GstPollFD pollfd;
53   gboolean pending;
54 };
55
56 struct _GstV4l2Decoder
57 {
58   GstObject parent;
59
60   gboolean opened;
61   gint media_fd;
62   gint video_fd;
63   GstAtomicQueue *request_pool;
64
65   /* properties */
66   gchar *media_device;
67   gchar *video_device;
68 };
69
70 G_DEFINE_TYPE_WITH_CODE (GstV4l2Decoder, gst_v4l2_decoder, GST_TYPE_OBJECT,
71     GST_DEBUG_CATEGORY_INIT (v4l2_decoder_debug, "v4l2codecs-decoder", 0,
72         "V4L2 stateless decoder helper"));
73
74 static guint32
75 direction_to_buffer_type (GstPadDirection direction)
76 {
77   if (direction == GST_PAD_SRC)
78     return V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
79   else
80     return V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
81 }
82
83 static void
84 gst_v4l2_decoder_finalize (GObject * obj)
85 {
86   GstV4l2Decoder *self = GST_V4L2_DECODER (obj);
87
88   gst_v4l2_decoder_close (self);
89
90   g_free (self->media_device);
91   g_free (self->video_device);
92   gst_atomic_queue_unref (self->request_pool);
93
94   G_OBJECT_CLASS (gst_v4l2_decoder_parent_class)->finalize (obj);
95 }
96
97 static void
98 gst_v4l2_decoder_init (GstV4l2Decoder * self)
99 {
100   self->request_pool = gst_atomic_queue_new (16);
101 }
102
103 static void
104 gst_v4l2_decoder_class_init (GstV4l2DecoderClass * klass)
105 {
106   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
107
108   gobject_class->finalize = gst_v4l2_decoder_finalize;
109   gobject_class->get_property = gst_v4l2_decoder_get_property;
110   gobject_class->set_property = gst_v4l2_decoder_set_property;
111
112   gst_v4l2_decoder_install_properties (gobject_class, 0, NULL);
113 }
114
115 GstV4l2Decoder *
116 gst_v4l2_decoder_new (GstV4l2CodecDevice * device)
117 {
118   GstV4l2Decoder *decoder;
119
120   g_return_val_if_fail (device->function == MEDIA_ENT_F_PROC_VIDEO_DECODER,
121       NULL);
122
123   decoder = g_object_new (GST_TYPE_V4L2_DECODER,
124       "media-device", device->media_device_path,
125       "video-device", device->video_device_path, NULL);
126
127   return gst_object_ref_sink (decoder);
128 }
129
130 gboolean
131 gst_v4l2_decoder_open (GstV4l2Decoder * self)
132 {
133   self->media_fd = open (self->media_device, 0);
134   if (self->media_fd < 0) {
135     GST_ERROR_OBJECT (self, "Failed to open '%s': %s",
136         self->media_device, g_strerror (errno));
137     return FALSE;
138   }
139
140   self->video_fd = open (self->video_device, O_NONBLOCK);
141   if (self->video_fd < 0) {
142     GST_ERROR_OBJECT (self, "Failed to open '%s': %s",
143         self->video_device, g_strerror (errno));
144     return FALSE;
145   }
146
147   self->opened = TRUE;
148
149   return TRUE;
150 }
151
152 gboolean
153 gst_v4l2_decoder_close (GstV4l2Decoder * self)
154 {
155   GstV4l2Request *request;
156
157   while ((request = gst_atomic_queue_pop (self->request_pool)))
158     gst_v4l2_request_free (request);
159
160   if (self->media_fd)
161     close (self->media_fd);
162   if (self->video_fd)
163     close (self->media_fd);
164
165   self->media_fd = 0;
166   self->video_fd = 0;
167   self->opened = FALSE;
168
169   return TRUE;
170 }
171
172 gboolean
173 gst_v4l2_decoder_streamon (GstV4l2Decoder * self, GstPadDirection direction)
174 {
175   gint ret;
176   guint32 type = direction_to_buffer_type (direction);
177
178   ret = ioctl (self->video_fd, VIDIOC_STREAMON, &type);
179   if (ret < 0) {
180     GST_ERROR_OBJECT (self, "VIDIOC_STREAMON failed: %s", g_strerror (errno));
181     return FALSE;
182   }
183
184   return TRUE;
185 }
186
187 gboolean
188 gst_v4l2_decoder_streamoff (GstV4l2Decoder * self, GstPadDirection direction)
189 {
190   gint ret;
191   guint32 type = direction_to_buffer_type (direction);
192
193   ret = ioctl (self->video_fd, VIDIOC_STREAMOFF, &type);
194   if (ret < 0) {
195     GST_ERROR_OBJECT (self, "VIDIOC_STREAMOFF failed: %s", g_strerror (errno));
196     return FALSE;
197   }
198
199   return TRUE;
200 }
201
202 gboolean
203 gst_v4l2_decoder_flush (GstV4l2Decoder * self)
204 {
205   /* We ignore streamoff failure as it's not relevant, if we manage to
206    * streamon again, we are good. */
207   gst_v4l2_decoder_streamoff (self, GST_PAD_SINK);
208   gst_v4l2_decoder_streamoff (self, GST_PAD_SRC);
209
210   return gst_v4l2_decoder_streamon (self, GST_PAD_SINK) &&
211       gst_v4l2_decoder_streamon (self, GST_PAD_SRC);
212 }
213
214 gboolean
215 gst_v4l2_decoder_enum_sink_fmt (GstV4l2Decoder * self, gint i,
216     guint32 * out_fmt)
217 {
218   struct v4l2_fmtdesc fmtdesc = { i, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, };
219   gint ret;
220
221   g_return_val_if_fail (self->opened, FALSE);
222
223   ret = ioctl (self->video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
224   if (ret < 0) {
225     if (errno != EINVAL)
226       GST_ERROR_OBJECT (self, "VIDIOC_ENUM_FMT failed: %s", g_strerror (errno));
227     return FALSE;
228   }
229
230   GST_DEBUG_OBJECT (self, "Found format %" GST_FOURCC_FORMAT " (%s)",
231       GST_FOURCC_ARGS (fmtdesc.pixelformat), fmtdesc.description);
232   *out_fmt = fmtdesc.pixelformat;
233
234   return TRUE;
235 }
236
237 gboolean
238 gst_v4l2_decoder_set_sink_fmt (GstV4l2Decoder * self, guint32 pix_fmt,
239     gint width, gint height)
240 {
241   struct v4l2_format format = (struct v4l2_format) {
242     .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
243     .fmt.pix_mp = (struct v4l2_pix_format_mplane) {
244           .pixelformat = pix_fmt,
245           .width = width,
246           .height = height,
247         },
248   };
249   gint ret;
250
251   ret = ioctl (self->video_fd, VIDIOC_S_FMT, &format);
252   if (ret < 0) {
253     GST_ERROR_OBJECT (self, "VIDIOC_S_FMT failed: %s", g_strerror (errno));
254     return FALSE;
255   }
256
257   if (format.fmt.pix_mp.pixelformat != pix_fmt
258       || format.fmt.pix_mp.width != width
259       || format.fmt.pix_mp.height != height) {
260     GST_WARNING_OBJECT (self, "Failed to set sink format to %"
261         GST_FOURCC_FORMAT " %ix%i", GST_FOURCC_ARGS (pix_fmt), width, height);
262     errno = EINVAL;
263     return FALSE;
264   }
265
266   return TRUE;
267 }
268
269 GstCaps *
270 gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self)
271 {
272   gint ret;
273   struct v4l2_format fmt = {
274     .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
275   };
276   GstVideoFormat format;
277   GstCaps *caps;
278   GValue list = G_VALUE_INIT;
279   GValue value = G_VALUE_INIT;
280   gint i;
281
282   g_return_val_if_fail (self->opened, FALSE);
283
284   ret = ioctl (self->video_fd, VIDIOC_G_FMT, &fmt);
285   if (ret < 0) {
286     GST_ERROR_OBJECT (self, "VIDIOC_G_FMT failed: %s", g_strerror (errno));
287     return FALSE;
288   }
289
290   /* We first place a structure with the default pixel format */
291   if (gst_v4l2_format_to_video_format (fmt.fmt.pix_mp.pixelformat, &format))
292     caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
293         gst_video_format_to_string (format), NULL);
294   else
295     caps = gst_caps_new_empty ();
296
297   /* And then enumerate other possible formats and place that as a second
298    * structure in the caps */
299   g_value_init (&list, GST_TYPE_LIST);
300   g_value_init (&value, G_TYPE_STRING);
301
302   for (i = 0; ret >= 0; i++) {
303     struct v4l2_fmtdesc fmtdesc = { i, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, };
304
305     ret = ioctl (self->video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
306     if (ret < 0) {
307       if (errno != EINVAL)
308         GST_ERROR_OBJECT (self, "VIDIOC_ENUM_FMT failed: %s",
309             g_strerror (errno));
310       continue;
311     }
312
313     if (gst_v4l2_format_to_video_format (fmtdesc.pixelformat, &format)) {
314       g_value_set_static_string (&value, gst_video_format_to_string (format));
315       gst_value_list_append_value (&list, &value);
316     }
317   }
318   g_value_reset (&value);
319
320   if (gst_value_list_get_size (&list) > 0) {
321     GstStructure *str = gst_structure_new_empty ("video/x-raw");
322     gst_structure_take_value (str, "format", &list);
323     gst_caps_append_structure (caps, str);
324   } else {
325     g_value_reset (&list);
326   }
327
328   return caps;
329 }
330
331 gboolean
332 gst_v4l2_decoder_select_src_format (GstV4l2Decoder * self, GstCaps * caps,
333     GstVideoInfo * info)
334 {
335   gint ret;
336   struct v4l2_format fmt = {
337     .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
338   };
339   GstStructure *str;
340   const gchar *format_str;
341   GstVideoFormat format;
342   guint32 pix_fmt;
343
344   if (gst_caps_is_empty (caps))
345     return FALSE;
346
347   ret = ioctl (self->video_fd, VIDIOC_G_FMT, &fmt);
348   if (ret < 0) {
349     GST_ERROR_OBJECT (self, "VIDIOC_G_FMT failed: %s", g_strerror (errno));
350     return FALSE;
351   }
352
353   caps = gst_caps_make_writable (caps);
354   str = gst_caps_get_structure (caps, 0);
355   gst_structure_fixate_field (str, "format");
356
357   format_str = gst_structure_get_string (str, "format");
358   format = gst_video_format_from_string (format_str);
359
360   if (gst_v4l2_format_from_video_format (format, &pix_fmt) &&
361       pix_fmt != fmt.fmt.pix_mp.pixelformat) {
362     GST_DEBUG_OBJECT (self, "Trying to use peer format: %s ", format_str);
363     fmt.fmt.pix_mp.pixelformat = pix_fmt;
364
365     ret = ioctl (self->video_fd, VIDIOC_S_FMT, &fmt);
366     if (ret < 0) {
367       GST_ERROR_OBJECT (self, "VIDIOC_S_FMT failed: %s", g_strerror (errno));
368       return FALSE;
369     }
370   }
371
372   if (!gst_v4l2_format_to_video_info (&fmt, info)) {
373     GST_ERROR_OBJECT (self, "Unsupported V4L2 pixelformat %" GST_FOURCC_FORMAT,
374         GST_FOURCC_ARGS (fmt.fmt.pix_mp.pixelformat));
375     return FALSE;
376   }
377
378   GST_INFO_OBJECT (self, "Selected format %s %ix%i",
379       gst_video_format_to_string (info->finfo->format),
380       info->width, info->height);
381
382   return TRUE;
383 }
384
385 gint
386 gst_v4l2_decoder_request_buffers (GstV4l2Decoder * self,
387     GstPadDirection direction, guint num_buffers)
388 {
389   gint ret;
390   struct v4l2_requestbuffers reqbufs = {
391     .count = num_buffers,
392     .memory = V4L2_MEMORY_MMAP,
393     .type = direction_to_buffer_type (direction),
394   };
395
396   GST_DEBUG_OBJECT (self, "Requesting %u buffers", num_buffers);
397
398   ret = ioctl (self->video_fd, VIDIOC_REQBUFS, &reqbufs);
399   if (ret < 0) {
400     GST_ERROR_OBJECT (self, "VIDIOC_REQBUFS failed: %s", g_strerror (errno));
401     return ret;
402   }
403
404   return reqbufs.count;
405 }
406
407 gboolean
408 gst_v4l2_decoder_export_buffer (GstV4l2Decoder * self,
409     GstPadDirection direction, gint index, gint * fds, gsize * sizes,
410     gsize * offsets, guint * num_fds)
411 {
412   gint i, ret;
413   struct v4l2_plane planes[GST_VIDEO_MAX_PLANES] = { {0} };
414   struct v4l2_buffer v4l2_buf = {
415     .index = 0,
416     .type = direction_to_buffer_type (direction),
417     .length = GST_VIDEO_MAX_PLANES,
418     .m.planes = planes,
419   };
420
421   ret = ioctl (self->video_fd, VIDIOC_QUERYBUF, &v4l2_buf);
422   if (ret < 0) {
423     GST_ERROR_OBJECT (self, "VIDIOC_QUERYBUF failed: %s", g_strerror (errno));
424     return FALSE;
425   }
426
427   *num_fds = v4l2_buf.length;
428   for (i = 0; i < v4l2_buf.length; i++) {
429     struct v4l2_plane *plane = v4l2_buf.m.planes + i;
430     struct v4l2_exportbuffer expbuf = {
431       .type = direction_to_buffer_type (direction),
432       .index = index,
433       .plane = i,
434       .flags = O_CLOEXEC | O_RDWR,
435     };
436
437     ret = ioctl (self->video_fd, VIDIOC_EXPBUF, &expbuf);
438     if (ret < 0) {
439       gint j;
440       GST_ERROR_OBJECT (self, "VIDIOC_EXPBUF failed: %s", g_strerror (errno));
441
442       for (j = i - 1; j >= 0; j--)
443         close (fds[j]);
444
445       return FALSE;
446     }
447
448     fds[i] = expbuf.fd;
449     sizes[i] = plane->length;
450     offsets[i] = plane->data_offset;
451   }
452
453   return TRUE;
454 }
455
456 gboolean
457 gst_v4l2_decoder_queue_sink_mem (GstV4l2Decoder * self,
458     GstV4l2Request * request, GstMemory * mem, guint32 frame_num,
459     gsize bytesused)
460 {
461   gint ret;
462   struct v4l2_plane plane = {
463     .bytesused = bytesused,
464   };
465   struct v4l2_buffer buf = {
466     .type = direction_to_buffer_type (GST_PAD_SINK),
467     .memory = V4L2_MEMORY_MMAP,
468     .index = gst_v4l2_codec_memory_get_index (mem),
469     .timestamp.tv_usec = frame_num,
470     .request_fd = request->fd,
471     .flags = V4L2_BUF_FLAG_REQUEST_FD,
472     .length = 1,
473     .m.planes = &plane,
474   };
475
476   ret = ioctl (self->video_fd, VIDIOC_QBUF, &buf);
477   if (ret < 0) {
478     GST_ERROR_OBJECT (self, "VIDIOC_QBUF failed: %s", g_strerror (errno));
479     return FALSE;
480   }
481
482   request->bitstream = gst_memory_ref (mem);
483
484   return TRUE;
485 }
486
487 gboolean
488 gst_v4l2_decoder_queue_src_buffer (GstV4l2Decoder * self, GstBuffer * buffer,
489     guint32 frame_num)
490 {
491   gint i, ret;
492   struct v4l2_plane plane[GST_VIDEO_MAX_PLANES];
493   struct v4l2_buffer buf = {
494     .type = direction_to_buffer_type (GST_PAD_SRC),
495     .memory = V4L2_MEMORY_MMAP,
496     .index = gst_v4l2_codec_buffer_get_index (buffer),
497     .length = gst_buffer_n_memory (buffer),
498     .m.planes = plane,
499   };
500
501   for (i = 0; i < buf.length; i++) {
502     GstMemory *mem = gst_buffer_peek_memory (buffer, i);
503     /* *INDENT-OFF* */
504     plane[i] = (struct v4l2_plane) {
505       .bytesused = gst_memory_get_sizes (mem, NULL, NULL),
506     };
507     /* *INDENT-ON* */
508   }
509
510   ret = ioctl (self->video_fd, VIDIOC_QBUF, &buf);
511   if (ret < 0) {
512     GST_ERROR_OBJECT (self, "VIDIOC_QBUF failed: %s", g_strerror (errno));
513     return FALSE;
514   }
515
516   return TRUE;
517 }
518
519 gboolean
520 gst_v4l2_decoder_dequeue_sink (GstV4l2Decoder * self)
521 {
522   gint ret;
523   struct v4l2_plane plane[GST_VIDEO_MAX_PLANES] = { {0} };
524   struct v4l2_buffer buf = {
525     .type = direction_to_buffer_type (GST_PAD_SINK),
526     .memory = V4L2_MEMORY_MMAP,
527     .length = GST_VIDEO_MAX_PLANES,
528     .m.planes = plane,
529   };
530
531   ret = ioctl (self->video_fd, VIDIOC_DQBUF, &buf);
532   if (ret < 0) {
533     GST_ERROR_OBJECT (self, "VIDIOC_DQBUF failed: %s", g_strerror (errno));
534     return FALSE;
535   }
536
537   return TRUE;
538 }
539
540 gboolean
541 gst_v4l2_decoder_dequeue_src (GstV4l2Decoder * self, guint32 * out_frame_num)
542 {
543   gint ret;
544   struct v4l2_plane plane[GST_VIDEO_MAX_PLANES] = { {0} };
545   struct v4l2_buffer buf = {
546     .type = direction_to_buffer_type (GST_PAD_SRC),
547     .memory = V4L2_MEMORY_MMAP,
548     .length = GST_VIDEO_MAX_PLANES,
549     .m.planes = plane,
550   };
551
552   ret = ioctl (self->video_fd, VIDIOC_DQBUF, &buf);
553   if (ret < 0) {
554     GST_ERROR_OBJECT (self, "VIDIOC_DQBUF failed: %s", g_strerror (errno));
555     return FALSE;
556   }
557
558   *out_frame_num = buf.timestamp.tv_usec;
559   return TRUE;
560 }
561
562 gboolean
563 gst_v4l2_decoder_set_controls (GstV4l2Decoder * self, GstV4l2Request * request,
564     struct v4l2_ext_control * control, guint count)
565 {
566   gint ret;
567   struct v4l2_ext_controls controls = {
568     .controls = control,
569     .count = count,
570     .request_fd = request ? request->fd : 0,
571     .which = request ? V4L2_CTRL_WHICH_REQUEST_VAL : 0,
572   };
573
574   ret = ioctl (self->video_fd, VIDIOC_S_EXT_CTRLS, &controls);
575   if (ret < 0) {
576     GST_ERROR_OBJECT (self, "VIDIOC_S_EXT_CTRLS failed: %s",
577         g_strerror (errno));
578     return FALSE;
579   }
580
581   return TRUE;
582 }
583
584 void
585 gst_v4l2_decoder_install_properties (GObjectClass * gobject_class,
586     gint prop_offset, GstV4l2CodecDevice * device)
587 {
588   const gchar *media_device_path = NULL;
589   const gchar *video_device_path = NULL;
590
591   if (device) {
592     media_device_path = device->media_device_path;
593     video_device_path = device->video_device_path;
594   }
595
596   g_object_class_install_property (gobject_class, PROP_MEDIA_DEVICE,
597       g_param_spec_string ("media-device", "Media Device Path",
598           "Path to the media device node", media_device_path,
599           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
600
601   g_object_class_install_property (gobject_class, PROP_VIDEO_DEVICE,
602       g_param_spec_string ("video-device", "Video Device Path",
603           "Path to the video device node", video_device_path,
604           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
605 }
606
607 void
608 gst_v4l2_decoder_set_property (GObject * object, guint prop_id,
609     const GValue * value, GParamSpec * pspec)
610 {
611   GstV4l2Decoder *self = GST_V4L2_DECODER (object);
612
613   switch (prop_id) {
614     case PROP_MEDIA_DEVICE:
615       g_free (self->media_device);
616       self->media_device = g_value_dup_string (value);
617       break;
618     case PROP_VIDEO_DEVICE:
619       g_free (self->video_device);
620       self->video_device = g_value_dup_string (value);
621       break;
622     default:
623       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
624       break;
625   }
626 }
627
628 void
629 gst_v4l2_decoder_get_property (GObject * object, guint prop_id,
630     GValue * value, GParamSpec * pspec)
631 {
632   GstV4l2Decoder *self = GST_V4L2_DECODER (object);
633
634   switch (prop_id) {
635     case PROP_MEDIA_DEVICE:
636       g_value_set_string (value, self->media_device);
637       break;
638     case PROP_VIDEO_DEVICE:
639       g_value_set_string (value, self->video_device);
640       break;
641     default:
642       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
643       break;
644   }
645 }
646
647 GstV4l2Request *
648 gst_v4l2_decoder_alloc_request (GstV4l2Decoder * self)
649 {
650   GstV4l2Request *request = gst_atomic_queue_pop (self->request_pool);
651   gint ret;
652
653   if (!request) {
654     request = g_new0 (GstV4l2Request, 1);
655
656     ret = ioctl (self->media_fd, MEDIA_IOC_REQUEST_ALLOC, &request->fd);
657     if (ret < 0) {
658       GST_ERROR_OBJECT (self, "MEDIA_IOC_REQUEST_ALLOC failed: %s",
659           g_strerror (errno));
660       return NULL;
661     }
662
663     request->poll = gst_poll_new (FALSE);
664     gst_poll_fd_init (&request->pollfd);
665     request->pollfd.fd = request->fd;
666     gst_poll_add_fd (request->poll, &request->pollfd);
667     gst_poll_fd_ctl_pri (request->poll, &request->pollfd, TRUE);
668   }
669
670   request->decoder = g_object_ref (self);
671   return request;
672 }
673
674 void
675 gst_v4l2_request_free (GstV4l2Request * request)
676 {
677   GstV4l2Decoder *decoder = request->decoder;
678   gint ret;
679
680   if (!decoder) {
681     close (request->fd);
682     gst_poll_free (request->poll);
683     g_free (request);
684     return;
685   }
686
687   g_clear_pointer (&request->bitstream, gst_memory_unref);
688   request->decoder = NULL;
689
690   if (request->pending) {
691     gst_v4l2_request_free (request);
692     g_object_unref (decoder);
693     return;
694   }
695
696   ret = ioctl (request->fd, MEDIA_REQUEST_IOC_REINIT, NULL);
697   if (ret < 0) {
698     GST_ERROR_OBJECT (request->decoder, "MEDIA_REQUEST_IOC_REINIT failed: %s",
699         g_strerror (errno));
700     gst_v4l2_request_free (request);
701     g_object_unref (decoder);
702     return;
703   }
704
705   gst_atomic_queue_push (decoder->request_pool, request);
706   g_object_unref (decoder);
707 }
708
709 gboolean
710 gst_v4l2_request_queue (GstV4l2Request * request)
711 {
712   gint ret;
713
714   ret = ioctl (request->fd, MEDIA_REQUEST_IOC_QUEUE, NULL);
715   if (ret < 0) {
716     GST_ERROR_OBJECT (request->decoder, "MEDIA_REQUEST_IOC_QUEUE, failed: %s",
717         g_strerror (errno));
718     return FALSE;
719   }
720
721   request->pending = TRUE;
722
723   return TRUE;
724 }
725
726 gint
727 gst_v4l2_request_poll (GstV4l2Request * request, GstClockTime timeout)
728 {
729   return gst_poll_wait (request->poll, timeout);
730 }
731
732 void
733 gst_v4l2_request_set_done (GstV4l2Request * request)
734 {
735   if (request->bitstream) {
736     gst_v4l2_decoder_dequeue_sink (request->decoder);
737     g_clear_pointer (&request->bitstream, gst_memory_unref);
738   }
739
740   request->pending = FALSE;
741 }
742
743 gboolean
744 gst_v4l2_request_is_done (GstV4l2Request * request)
745 {
746   return !request->pending;
747 }