FFmpeg
v4l2_context.c
Go to the documentation of this file.
1 /*
2  * V4L2 context helper functions.
3  *
4  * Copyright (C) 2017 Alexis Ballier <aballier@gentoo.org>
5  * Copyright (C) 2017 Jorge Ramirez <jorge.ramirez-ortiz@linaro.org>
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 #include <linux/videodev2.h>
25 #include <sys/ioctl.h>
26 #include <sys/mman.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <poll.h>
30 #include "libavcodec/avcodec.h"
31 #include "decode.h"
32 #include "v4l2_buffers.h"
33 #include "v4l2_fmt.h"
34 #include "v4l2_m2m.h"
35 
37  uint32_t v4l2_fmt;
39 
42 };
43 
45 {
46  return V4L2_TYPE_IS_OUTPUT(ctx->type) ?
48  container_of(ctx, V4L2m2mContext, capture);
49 }
50 
52 {
53  return ctx_to_m2mctx(ctx)->avctx;
54 }
55 
56 static inline unsigned int v4l2_get_width(struct v4l2_format *fmt)
57 {
58  return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.width : fmt->fmt.pix.width;
59 }
60 
61 static inline unsigned int v4l2_get_height(struct v4l2_format *fmt)
62 {
63  return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.height : fmt->fmt.pix.height;
64 }
65 
67 {
68  struct AVRational sar = { 0, 1 };
69  struct v4l2_cropcap cropcap;
70  int ret;
71 
72  memset(&cropcap, 0, sizeof(cropcap));
73  cropcap.type = ctx->type;
74 
75  ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_CROPCAP, &cropcap);
76  if (ret)
77  return sar;
78 
79  sar.num = cropcap.pixelaspect.numerator;
80  sar.den = cropcap.pixelaspect.denominator;
81  return sar;
82 }
83 
84 static inline unsigned int v4l2_resolution_changed(V4L2Context *ctx, struct v4l2_format *fmt2)
85 {
86  struct v4l2_format *fmt1 = &ctx->format;
87  int ret = V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ?
88  fmt1->fmt.pix_mp.width != fmt2->fmt.pix_mp.width ||
89  fmt1->fmt.pix_mp.height != fmt2->fmt.pix_mp.height
90  :
91  fmt1->fmt.pix.width != fmt2->fmt.pix.width ||
92  fmt1->fmt.pix.height != fmt2->fmt.pix.height;
93 
94  if (ret)
95  av_log(logger(ctx), AV_LOG_DEBUG, "%s changed (%dx%d) -> (%dx%d)\n",
96  ctx->name,
97  v4l2_get_width(fmt1), v4l2_get_height(fmt1),
98  v4l2_get_width(fmt2), v4l2_get_height(fmt2));
99 
100  return ret;
101 }
102 
104 {
105  return ctx->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
106  ctx->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ||
107  ctx->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
108  ctx->type == V4L2_BUF_TYPE_VIDEO_OUTPUT;
109 }
110 
112 {
114  const int SZ_4K = 0x1000;
115  int size;
116 
117  if (s->avctx && av_codec_is_decoder(s->avctx->codec))
118  return ((width * height * 3 / 2) / 2) + 128;
119 
120  /* encoder */
121  size = FFALIGN(height, 32) * FFALIGN(width, 32) * 3 / 2 / 2;
122  return FFALIGN(size, SZ_4K);
123 }
124 
125 static inline void v4l2_save_to_context(V4L2Context* ctx, struct v4l2_format_update *fmt)
126 {
127  ctx->format.type = ctx->type;
128 
129  if (fmt->update_avfmt)
130  ctx->av_pix_fmt = fmt->av_fmt;
131 
132  if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
133  /* update the sizes to handle the reconfiguration of the capture stream at runtime */
134  ctx->format.fmt.pix_mp.height = ctx->height;
135  ctx->format.fmt.pix_mp.width = ctx->width;
136  if (fmt->update_v4l2) {
137  ctx->format.fmt.pix_mp.pixelformat = fmt->v4l2_fmt;
138 
139  /* s5p-mfc requires the user to specify a buffer size */
140  ctx->format.fmt.pix_mp.plane_fmt[0].sizeimage =
141  v4l2_get_framesize_compressed(ctx, ctx->width, ctx->height);
142  }
143  } else {
144  ctx->format.fmt.pix.height = ctx->height;
145  ctx->format.fmt.pix.width = ctx->width;
146  if (fmt->update_v4l2) {
147  ctx->format.fmt.pix.pixelformat = fmt->v4l2_fmt;
148 
149  /* s5p-mfc requires the user to specify a buffer size */
150  ctx->format.fmt.pix.sizeimage =
151  v4l2_get_framesize_compressed(ctx, ctx->width, ctx->height);
152  }
153  }
154 }
155 
157 {
158  struct v4l2_decoder_cmd cmd = {
159  .cmd = V4L2_DEC_CMD_START,
160  .flags = 0,
161  };
162  int ret;
163 
164  ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DECODER_CMD, &cmd);
165  if (ret)
166  return AVERROR(errno);
167 
168  return 0;
169 }
170 
171 /**
172  * handle resolution change event and end of stream event
173  * returns 1 if reinit was successful, negative if it failed
174  * returns 0 if reinit was not executed
175  */
177 {
179  struct v4l2_format cap_fmt = s->capture.format;
180  struct v4l2_event evt = { 0 };
181  int ret;
182 
183  ret = ioctl(s->fd, VIDIOC_DQEVENT, &evt);
184  if (ret < 0) {
185  av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQEVENT\n", ctx->name);
186  return 0;
187  }
188 
189  if (evt.type == V4L2_EVENT_EOS) {
190  ctx->done = 1;
191  return 0;
192  }
193 
194  if (evt.type != V4L2_EVENT_SOURCE_CHANGE)
195  return 0;
196 
197  ret = ioctl(s->fd, VIDIOC_G_FMT, &cap_fmt);
198  if (ret) {
199  av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT\n", s->capture.name);
200  return 0;
201  }
202 
203  if (v4l2_resolution_changed(&s->capture, &cap_fmt)) {
204  s->capture.height = v4l2_get_height(&cap_fmt);
205  s->capture.width = v4l2_get_width(&cap_fmt);
206  s->capture.sample_aspect_ratio = v4l2_get_sar(&s->capture);
207  } else {
209  return 0;
210  }
211 
212  s->reinit = 1;
213 
214  if (s->avctx)
215  ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height);
216  if (ret < 0)
217  av_log(logger(ctx), AV_LOG_WARNING, "update avcodec height and width\n");
218 
220  if (ret) {
221  av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_reinit\n");
222  return AVERROR(EINVAL);
223  }
224 
225  /* reinit executed */
226  return 1;
227 }
228 
230 {
231  struct v4l2_decoder_cmd cmd = {
232  .cmd = V4L2_DEC_CMD_STOP,
233  .flags = 0,
234  };
235  int ret;
236 
237  ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DECODER_CMD, &cmd);
238  if (ret) {
239  /* DECODER_CMD is optional */
240  if (errno == ENOTTY)
241  return ff_v4l2_context_set_status(ctx, VIDIOC_STREAMOFF);
242  else
243  return AVERROR(errno);
244  }
245 
246  return 0;
247 }
248 
250 {
251  struct v4l2_encoder_cmd cmd = {
252  .cmd = V4L2_ENC_CMD_STOP,
253  .flags = 0,
254  };
255  int ret;
256 
257  ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_ENCODER_CMD, &cmd);
258  if (ret) {
259  /* ENCODER_CMD is optional */
260  if (errno == ENOTTY)
261  return ff_v4l2_context_set_status(ctx, VIDIOC_STREAMOFF);
262  else
263  return AVERROR(errno);
264  }
265 
266  return 0;
267 }
268 
270 {
271  struct v4l2_plane planes[VIDEO_MAX_PLANES];
272  struct v4l2_buffer buf = { 0 };
273  V4L2Buffer *avbuf;
274  struct pollfd pfd = {
275  .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM, /* default blocking capture */
276  .fd = ctx_to_m2mctx(ctx)->fd,
277  };
278  int i, ret;
279 
280  if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx->buffers) {
281  for (i = 0; i < ctx->num_buffers; i++) {
282  if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER)
283  break;
284  }
285  if (i == ctx->num_buffers)
286  av_log(logger(ctx), AV_LOG_WARNING, "All capture buffers returned to "
287  "userspace. Increase num_capture_buffers "
288  "to prevent device deadlock or dropped "
289  "packets/frames.\n");
290  }
291 
292  /* if we are draining and there are no more capture buffers queued in the driver we are done */
293  if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) {
294  for (i = 0; i < ctx->num_buffers; i++) {
295  /* capture buffer initialization happens during decode hence
296  * detection happens at runtime
297  */
298  if (!ctx->buffers)
299  break;
300 
301  if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER)
302  goto start;
303  }
304  ctx->done = 1;
305  return NULL;
306  }
307 
308 start:
309  if (V4L2_TYPE_IS_OUTPUT(ctx->type))
310  pfd.events = POLLOUT | POLLWRNORM;
311  else {
312  /* no need to listen to requests for more input while draining */
313  if (ctx_to_m2mctx(ctx)->draining)
314  pfd.events = POLLIN | POLLRDNORM | POLLPRI;
315  }
316 
317  for (;;) {
318  ret = poll(&pfd, 1, timeout);
319  if (ret > 0)
320  break;
321  if (errno == EINTR)
322  continue;
323  return NULL;
324  }
325 
326  /* 0. handle errors */
327  if (pfd.revents & POLLERR) {
328  /* if we are trying to get free buffers but none have been queued yet,
329  * or if no buffers have been allocated yet, no need to raise a warning
330  */
331  if (timeout == 0) {
332  if (!ctx->buffers)
333  return NULL;
334 
335  for (i = 0; i < ctx->num_buffers; i++) {
336  if (ctx->buffers[i].status != V4L2BUF_AVAILABLE)
337  av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name);
338  }
339  }
340  else
341  av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name);
342 
343  return NULL;
344  }
345 
346  /* 1. handle resolution changes */
347  if (pfd.revents & POLLPRI) {
349  if (ret < 0) {
350  /* if re-init failed, abort */
351  ctx->done = 1;
352  return NULL;
353  }
354  if (ret) {
355  /* if re-init was successful drop the buffer (if there was one)
356  * since we had to reconfigure capture (unmap all buffers)
357  */
358  return NULL;
359  }
360  }
361 
362  /* 2. dequeue the buffer */
363  if (pfd.revents & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM)) {
364 
365  if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) {
366  /* there is a capture buffer ready */
367  if (pfd.revents & (POLLIN | POLLRDNORM))
368  goto dequeue;
369 
370  /* the driver is ready to accept more input; instead of waiting for the capture
371  * buffer to complete we return NULL so input can proceed (we are single threaded)
372  */
373  if (pfd.revents & (POLLOUT | POLLWRNORM))
374  return NULL;
375  }
376 
377 dequeue:
378  memset(&buf, 0, sizeof(buf));
379  buf.memory = V4L2_MEMORY_MMAP;
380  buf.type = ctx->type;
381  if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
382  memset(planes, 0, sizeof(planes));
383  buf.length = VIDEO_MAX_PLANES;
384  buf.m.planes = planes;
385  }
386 
387  ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DQBUF, &buf);
388  if (ret) {
389  if (errno != EAGAIN) {
390  ctx->done = 1;
391  if (errno != EPIPE)
392  av_log(logger(ctx), AV_LOG_DEBUG, "%s VIDIOC_DQBUF, errno (%s)\n",
393  ctx->name, av_err2str(AVERROR(errno)));
394  }
395  return NULL;
396  }
397 
398  if (ctx_to_m2mctx(ctx)->draining && !V4L2_TYPE_IS_OUTPUT(ctx->type)) {
399  int bytesused = V4L2_TYPE_IS_MULTIPLANAR(buf.type) ?
400  buf.m.planes[0].bytesused : buf.bytesused;
401  if (bytesused == 0) {
402  ctx->done = 1;
403  return NULL;
404  }
405 #ifdef V4L2_BUF_FLAG_LAST
406  if (buf.flags & V4L2_BUF_FLAG_LAST)
407  ctx->done = 1;
408 #endif
409  }
410 
411  avbuf = &ctx->buffers[buf.index];
412  avbuf->status = V4L2BUF_AVAILABLE;
413  avbuf->buf = buf;
414  if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
415  memcpy(avbuf->planes, planes, sizeof(planes));
416  avbuf->buf.m.planes = avbuf->planes;
417  }
418  return avbuf;
419  }
420 
421  return NULL;
422 }
423 
425 {
426  int timeout = 0; /* return when no more buffers to dequeue */
427  int i;
428 
429  /* get back as many output buffers as possible */
430  if (V4L2_TYPE_IS_OUTPUT(ctx->type)) {
431  do {
432  } while (v4l2_dequeue_v4l2buf(ctx, timeout));
433  }
434 
435  for (i = 0; i < ctx->num_buffers; i++) {
436  if (ctx->buffers[i].status == V4L2BUF_AVAILABLE)
437  return &ctx->buffers[i];
438  }
439 
440  return NULL;
441 }
442 
444 {
445  struct v4l2_requestbuffers req = {
446  .memory = V4L2_MEMORY_MMAP,
447  .type = ctx->type,
448  .count = 0, /* 0 -> unmaps buffers from the driver */
449  };
450  int i, j;
451 
452  for (i = 0; i < ctx->num_buffers; i++) {
453  V4L2Buffer *buffer = &ctx->buffers[i];
454 
455  for (j = 0; j < buffer->num_planes; j++) {
456  struct V4L2Plane_info *p = &buffer->plane_info[j];
457  if (p->mm_addr && p->length)
458  if (munmap(p->mm_addr, p->length) < 0)
459  av_log(logger(ctx), AV_LOG_ERROR, "%s unmap plane (%s))\n", ctx->name, av_err2str(AVERROR(errno)));
460  }
461  }
462 
463  return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req);
464 }
465 
467 {
468  struct v4l2_format *fmt = &ctx->format;
469  uint32_t v4l2_fmt;
470  int ret;
471 
473  if (!v4l2_fmt)
474  return AVERROR(EINVAL);
475 
476  if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type))
477  fmt->fmt.pix_mp.pixelformat = v4l2_fmt;
478  else
479  fmt->fmt.pix.pixelformat = v4l2_fmt;
480 
481  fmt->type = ctx->type;
482 
483  ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_TRY_FMT, fmt);
484  if (ret)
485  return AVERROR(EINVAL);
486 
487  return 0;
488 }
489 
491 {
492  enum AVPixelFormat pixfmt = ctx->av_pix_fmt;
493  struct v4l2_fmtdesc fdesc;
494  int ret;
495 
496  memset(&fdesc, 0, sizeof(fdesc));
497  fdesc.type = ctx->type;
498 
499  if (pixfmt != AV_PIX_FMT_NONE) {
501  if (!ret)
502  return 0;
503  }
504 
505  for (;;) {
506  ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_ENUM_FMT, &fdesc);
507  if (ret)
508  return AVERROR(EINVAL);
509 
512  if (ret){
513  fdesc.index++;
514  continue;
515  }
516 
517  *p = pixfmt;
518 
519  return 0;
520  }
521 
522  return AVERROR(EINVAL);
523 }
524 
525 static int v4l2_get_coded_format(V4L2Context* ctx, uint32_t *p)
526 {
527  struct v4l2_fmtdesc fdesc;
528  uint32_t v4l2_fmt;
529  int ret;
530 
531  /* translate to a valid v4l2 format */
532  v4l2_fmt = ff_v4l2_format_avcodec_to_v4l2(ctx->av_codec_id);
533  if (!v4l2_fmt)
534  return AVERROR(EINVAL);
535 
536  /* check if the driver supports this format */
537  memset(&fdesc, 0, sizeof(fdesc));
538  fdesc.type = ctx->type;
539 
540  for (;;) {
541  ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_ENUM_FMT, &fdesc);
542  if (ret)
543  return AVERROR(EINVAL);
544 
545  if (fdesc.pixelformat == v4l2_fmt)
546  break;
547 
548  fdesc.index++;
549  }
550 
551  *p = v4l2_fmt;
552 
553  return 0;
554 }
555 
556  /*****************************************************************************
557  *
558  * V4L2 Context Interface
559  *
560  *****************************************************************************/
561 
563 {
564  int type = ctx->type;
565  int ret;
566 
567  ret = ioctl(ctx_to_m2mctx(ctx)->fd, cmd, &type);
568  if (ret < 0)
569  return AVERROR(errno);
570 
571  ctx->streamon = (cmd == VIDIOC_STREAMON);
572 
573  return 0;
574 }
575 
577 {
579  V4L2Buffer* avbuf;
580  int ret;
581 
582  if (!frame) {
584  if (ret)
585  av_log(logger(ctx), AV_LOG_ERROR, "%s stop_encode\n", ctx->name);
586  s->draining= 1;
587  return 0;
588  }
589 
590  avbuf = v4l2_getfree_v4l2buf(ctx);
591  if (!avbuf)
592  return AVERROR(EAGAIN);
593 
595  if (ret)
596  return ret;
597 
598  return ff_v4l2_buffer_enqueue(avbuf);
599 }
600 
602 {
604  V4L2Buffer* avbuf;
605  int ret;
606 
607  if (!pkt->size) {
609  if (ret)
610  av_log(logger(ctx), AV_LOG_ERROR, "%s stop_decode\n", ctx->name);
611  s->draining = 1;
612  return 0;
613  }
614 
615  avbuf = v4l2_getfree_v4l2buf(ctx);
616  if (!avbuf)
617  return AVERROR(EAGAIN);
618 
620  if (ret)
621  return ret;
622 
623  return ff_v4l2_buffer_enqueue(avbuf);
624 }
625 
627 {
628  V4L2Buffer *avbuf;
629 
630  /*
631  * timeout=-1 blocks until:
632  * 1. decoded frame available
633  * 2. an input buffer is ready to be dequeued
634  */
635  avbuf = v4l2_dequeue_v4l2buf(ctx, timeout);
636  if (!avbuf) {
637  if (ctx->done)
638  return AVERROR_EOF;
639 
640  return AVERROR(EAGAIN);
641  }
642 
643  return ff_v4l2_buffer_buf_to_avframe(frame, avbuf);
644 }
645 
647 {
648  V4L2Buffer *avbuf;
649 
650  /*
651  * blocks until:
652  * 1. encoded packet available
653  * 2. an input buffer ready to be dequeued
654  */
655  avbuf = v4l2_dequeue_v4l2buf(ctx, -1);
656  if (!avbuf) {
657  if (ctx->done)
658  return AVERROR_EOF;
659 
660  return AVERROR(EAGAIN);
661  }
662 
663  return ff_v4l2_buffer_buf_to_avpkt(pkt, avbuf);
664 }
665 
667 {
668  struct v4l2_format_update fmt = { 0 };
669  int ret;
670 
671  if (ctx->av_codec_id == AV_CODEC_ID_RAWVIDEO) {
673  if (ret)
674  return ret;
675 
676  fmt.update_avfmt = !probe;
677  v4l2_save_to_context(ctx, &fmt);
678 
679  /* format has been tried already */
680  return ret;
681  }
682 
684  if (ret)
685  return ret;
686 
687  fmt.update_v4l2 = 1;
688  v4l2_save_to_context(ctx, &fmt);
689 
690  return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_TRY_FMT, &ctx->format);
691 }
692 
694 {
695  return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_S_FMT, &ctx->format);
696 }
697 
699 {
700  int ret;
701 
702  if (!ctx->buffers)
703  return;
704 
706  if (ret)
707  av_log(logger(ctx), AV_LOG_WARNING, "V4L2 failed to unmap the %s buffers\n", ctx->name);
708 
709  av_freep(&ctx->buffers);
710 }
711 
713 {
715  struct v4l2_requestbuffers req;
716  int ret, i;
717 
718  if (!v4l2_type_supported(ctx)) {
719  av_log(logger(ctx), AV_LOG_ERROR, "type %i not supported\n", ctx->type);
720  return AVERROR_PATCHWELCOME;
721  }
722 
723  ret = ioctl(s->fd, VIDIOC_G_FMT, &ctx->format);
724  if (ret)
725  av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT failed\n", ctx->name);
726 
727  memset(&req, 0, sizeof(req));
728  req.count = ctx->num_buffers;
729  req.memory = V4L2_MEMORY_MMAP;
730  req.type = ctx->type;
731  ret = ioctl(s->fd, VIDIOC_REQBUFS, &req);
732  if (ret < 0) {
733  av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_REQBUFS failed: %s\n", ctx->name, strerror(errno));
734  return AVERROR(errno);
735  }
736 
737  ctx->num_buffers = req.count;
738  ctx->buffers = av_mallocz(ctx->num_buffers * sizeof(V4L2Buffer));
739  if (!ctx->buffers) {
740  av_log(logger(ctx), AV_LOG_ERROR, "%s malloc enomem\n", ctx->name);
741  return AVERROR(ENOMEM);
742  }
743 
744  for (i = 0; i < req.count; i++) {
745  ctx->buffers[i].context = ctx;
746  ret = ff_v4l2_buffer_initialize(&ctx->buffers[i], i);
747  if (ret < 0) {
748  av_log(logger(ctx), AV_LOG_ERROR, "%s buffer[%d] initialization (%s)\n", ctx->name, i, av_err2str(ret));
749  goto error;
750  }
751  }
752 
753  av_log(logger(ctx), AV_LOG_DEBUG, "%s: %s %02d buffers initialized: %04ux%04u, sizeimage %08u, bytesperline %08u\n", ctx->name,
754  V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? av_fourcc2str(ctx->format.fmt.pix_mp.pixelformat) : av_fourcc2str(ctx->format.fmt.pix.pixelformat),
755  req.count,
756  v4l2_get_width(&ctx->format),
757  v4l2_get_height(&ctx->format),
758  V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].sizeimage : ctx->format.fmt.pix.sizeimage,
759  V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].bytesperline : ctx->format.fmt.pix.bytesperline);
760 
761  return 0;
762 
763 error:
765 
766  av_freep(&ctx->buffers);
767 
768  return ret;
769 }
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:31
ff_v4l2_context_init
int ff_v4l2_context_init(V4L2Context *ctx)
Initializes a V4L2Context.
Definition: v4l2_context.c:712
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
v4l2_get_width
static unsigned int v4l2_get_width(struct v4l2_format *fmt)
Definition: v4l2_context.c:56
v4l2_buffers.h
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
ff_v4l2_m2m_codec_reinit
int ff_v4l2_m2m_codec_reinit(V4L2m2mContext *s)
Reinitializes the V4L2m2mContext when the driver cannot continue processing with the capture paramete...
Definition: v4l2_m2m.c:206
output
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
Definition: filter_design.txt:225
ff_v4l2_buffer_buf_to_avpkt
int ff_v4l2_buffer_buf_to_avpkt(AVPacket *pkt, V4L2Buffer *avbuf)
Extracts the data from a V4L2Buffer to an AVPacket.
Definition: v4l2_buffers.c:453
V4L2m2mContext
Definition: v4l2_m2m.h:43
AV_CODEC_ID_RAWVIDEO
@ AV_CODEC_ID_RAWVIDEO
Definition: codec_id.h:65
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
ff_v4l2_context_dequeue_packet
int ff_v4l2_context_dequeue_packet(V4L2Context *ctx, AVPacket *pkt)
Dequeues a buffer from a V4L2Context to an AVPacket.
Definition: v4l2_context.c:646
ff_v4l2_context_release
void ff_v4l2_context_release(V4L2Context *ctx)
Releases a V4L2Context.
Definition: v4l2_context.c:698
v4l2_stop_encode
static int v4l2_stop_encode(V4L2Context *ctx)
Definition: v4l2_context.c:249
v4l2_format_update::v4l2_fmt
uint32_t v4l2_fmt
Definition: v4l2_context.c:37
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:94
ctx_to_m2mctx
static V4L2m2mContext * ctx_to_m2mctx(V4L2Context *ctx)
Definition: v4l2_context.c:44
v4l2_handle_event
static int v4l2_handle_event(V4L2Context *ctx)
handle resolution change event and end of stream event returns 1 if reinit was successful,...
Definition: v4l2_context.c:176
v4l2_start_decode
static int v4l2_start_decode(V4L2Context *ctx)
Definition: v4l2_context.c:156
v4l2_get_framesize_compressed
static int v4l2_get_framesize_compressed(V4L2Context *ctx, int width, int height)
Definition: v4l2_context.c:111
V4L2Buffer::buf
struct v4l2_buffer buf
Definition: v4l2_buffers.h:63
ff_v4l2_buffer_buf_to_avframe
int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf)
Extracts the data from a V4L2Buffer to an AVFrame.
Definition: v4l2_buffers.c:418
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
AVRational::num
int num
Numerator.
Definition: rational.h:59
v4l2_save_to_context
static void v4l2_save_to_context(V4L2Context *ctx, struct v4l2_format_update *fmt)
Definition: v4l2_context.c:125
v4l2_release_buffers
static int v4l2_release_buffers(V4L2Context *ctx)
Definition: v4l2_context.c:443
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
ff_v4l2_buffer_avframe_to_buf
int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out)
Extracts the data from an AVFrame to a V4L2Buffer.
Definition: v4l2_buffers.c:411
ff_v4l2_context_set_format
int ff_v4l2_context_set_format(V4L2Context *ctx)
Sets the V4L2Context format in the v4l2 driver.
Definition: v4l2_context.c:693
V4L2Buffer
V4L2Buffer (wrapper for v4l2_buffer management)
Definition: v4l2_buffers.h:44
ff_v4l2_context_get_format
int ff_v4l2_context_get_format(V4L2Context *ctx, int probe)
Queries the driver for a valid v4l2 format and copies it to the context.
Definition: v4l2_context.c:666
v4l2_getfree_v4l2buf
static V4L2Buffer * v4l2_getfree_v4l2buf(V4L2Context *ctx)
Definition: v4l2_context.c:424
v4l2_fmt.h
width
#define width
s
#define s(width, name)
Definition: cbs_vp9.c:198
ff_v4l2_format_v4l2_to_avfmt
enum AVPixelFormat ff_v4l2_format_v4l2_to_avfmt(uint32_t v4l2_fmt, enum AVCodecID avcodec)
Definition: v4l2_fmt.c:132
logger
static AVCodecContext * logger(V4L2Context *ctx)
Definition: v4l2_context.c:51
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
decode.h
frame
static AVFrame * frame
Definition: demux_decode.c:54
ff_v4l2_buffer_enqueue
int ff_v4l2_buffer_enqueue(V4L2Buffer *avbuf)
Enqueues a V4L2Buffer.
Definition: v4l2_buffers.c:561
v4l2_stop_decode
static int v4l2_stop_decode(V4L2Context *ctx)
Definition: v4l2_context.c:229
V4L2Context
Definition: v4l2_context.h:37
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
container_of
#define container_of(ptr, type, member)
Definition: v4l2_m2m.h:35
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
ff_v4l2_context_enqueue_packet
int ff_v4l2_context_enqueue_packet(V4L2Context *ctx, const AVPacket *pkt)
Enqueues a buffer to a V4L2Context from an AVPacket.
Definition: v4l2_context.c:601
v4l2_dequeue_v4l2buf
static V4L2Buffer * v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout)
Definition: v4l2_context.c:269
ff_v4l2_buffer_avpkt_to_buf
int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out)
Extracts the data from an AVPacket to a V4L2Buffer.
Definition: v4l2_buffers.c:478
V4L2BUF_AVAILABLE
@ V4L2BUF_AVAILABLE
Definition: v4l2_buffers.h:36
av_codec_is_decoder
int av_codec_is_decoder(const AVCodec *codec)
Definition: utils.c:86
AVPacket::size
int size
Definition: packet.h:492
v4l2_get_raw_format
static int v4l2_get_raw_format(V4L2Context *ctx, enum AVPixelFormat *p)
Definition: v4l2_context.c:490
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:121
V4L2BUF_IN_DRIVER
@ V4L2BUF_IN_DRIVER
Definition: v4l2_buffers.h:37
size
int size
Definition: twinvq_data.h:10344
v4l2_get_sar
static AVRational v4l2_get_sar(V4L2Context *ctx)
Definition: v4l2_context.c:66
height
#define height
ff_v4l2_context_dequeue_frame
int ff_v4l2_context_dequeue_frame(V4L2Context *ctx, AVFrame *frame, int timeout)
Dequeues a buffer from a V4L2Context to an AVFrame.
Definition: v4l2_context.c:626
ff_v4l2_context_set_status
int ff_v4l2_context_set_status(V4L2Context *ctx, uint32_t cmd)
Sets the status of a V4L2Context.
Definition: v4l2_context.c:562
ff_v4l2_format_avcodec_to_v4l2
uint32_t ff_v4l2_format_avcodec_to_v4l2(enum AVCodecID avcodec)
Definition: v4l2_fmt.c:112
V4L2m2mContext::avctx
AVCodecContext * avctx
Definition: v4l2_m2m.h:52
v4l2_try_raw_format
static int v4l2_try_raw_format(V4L2Context *ctx, enum AVPixelFormat pixfmt)
Definition: v4l2_context.c:466
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
V4L2Buffer::planes
struct v4l2_plane planes[VIDEO_MAX_PLANES]
Definition: v4l2_buffers.h:64
planes
static const struct @363 planes[]
v4l2_format_update::update_avfmt
int update_avfmt
Definition: v4l2_context.c:41
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
v4l2_get_coded_format
static int v4l2_get_coded_format(V4L2Context *ctx, uint32_t *p)
Definition: v4l2_context.c:525
ff_v4l2_context_enqueue_frame
int ff_v4l2_context_enqueue_frame(V4L2Context *ctx, const AVFrame *frame)
Enqueues a buffer to a V4L2Context from an AVFrame.
Definition: v4l2_context.c:576
avcodec.h
ret
ret
Definition: filter_design.txt:187
pixfmt
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:365
v4l2_format_update::av_fmt
enum AVPixelFormat av_fmt
Definition: v4l2_context.c:40
v4l2_format_update::update_v4l2
int update_v4l2
Definition: v4l2_context.c:38
AVCodecContext
main external API structure.
Definition: avcodec.h:441
probe
static int probe(const AVProbeData *p)
Definition: act.c:38
v4l2_get_height
static unsigned int v4l2_get_height(struct v4l2_format *fmt)
Definition: v4l2_context.c:61
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
AVRational::den
int den
Denominator.
Definition: rational.h:60
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
V4L2m2mContext::fd
int fd
Definition: v4l2_m2m.h:45
v4l2_format_update
Definition: v4l2_context.c:36
v4l2_resolution_changed
static unsigned int v4l2_resolution_changed(V4L2Context *ctx, struct v4l2_format *fmt2)
Definition: v4l2_context.c:84
ff_v4l2_format_avfmt_to_v4l2
uint32_t ff_v4l2_format_avfmt_to_v4l2(enum AVPixelFormat avfmt)
Definition: v4l2_fmt.c:122
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVPacket
This structure stores compressed data.
Definition: packet.h:468
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
v4l2_m2m.h
ff_v4l2_buffer_initialize
int ff_v4l2_buffer_initialize(V4L2Buffer *avbuf, int index)
Initializes a V4L2Buffer.
Definition: v4l2_buffers.c:494
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
av_fourcc2str
#define av_fourcc2str(fourcc)
Definition: avutil.h:358
v4l2_type_supported
static int v4l2_type_supported(V4L2Context *ctx)
Definition: v4l2_context.c:103
V4L2Buffer::status
enum V4L2Buffer_status status
Definition: v4l2_buffers.h:67