]> git.sesse.net Git - ffmpeg/blob - libavcodec/v4l2_context.c
avcodec/v4l2_m2m: Use consistent logging context
[ffmpeg] / libavcodec / v4l2_context.c
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 "libavcodec/internal.h"
32 #include "v4l2_buffers.h"
33 #include "v4l2_fmt.h"
34 #include "v4l2_m2m.h"
35
36 struct v4l2_format_update {
37     uint32_t v4l2_fmt;
38     int update_v4l2;
39
40     enum AVPixelFormat av_fmt;
41     int update_avfmt;
42 };
43
44 static inline V4L2m2mContext *ctx_to_m2mctx(V4L2Context *ctx)
45 {
46     return V4L2_TYPE_IS_OUTPUT(ctx->type) ?
47         container_of(ctx, V4L2m2mContext, output) :
48         container_of(ctx, V4L2m2mContext, capture);
49 }
50
51 static inline AVClass *logger(V4L2Context *ctx)
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
66 static AVRational v4l2_get_sar(V4L2Context *ctx)
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
103 static inline int v4l2_type_supported(V4L2Context *ctx)
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
111 static inline int v4l2_get_framesize_compressed(V4L2Context* ctx, int width, int height)
112 {
113     V4L2m2mContext *s = ctx_to_m2mctx(ctx);
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
156 /**
157  * returns 1 if reinit was successful, negative if it failed
158  * returns 0 if reinit was not executed
159  */
160 static int v4l2_handle_event(V4L2Context *ctx)
161 {
162     V4L2m2mContext *s = ctx_to_m2mctx(ctx);
163     struct v4l2_format cap_fmt = s->capture.format;
164     struct v4l2_format out_fmt = s->output.format;
165     struct v4l2_event evt = { 0 };
166     int full_reinit, reinit, ret;
167
168     ret = ioctl(s->fd, VIDIOC_DQEVENT, &evt);
169     if (ret < 0) {
170         av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQEVENT\n", ctx->name);
171         return 0;
172     }
173
174     if (evt.type != V4L2_EVENT_SOURCE_CHANGE)
175         return 0;
176
177     ret = ioctl(s->fd, VIDIOC_G_FMT, &out_fmt);
178     if (ret) {
179         av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT\n", s->output.name);
180         return 0;
181     }
182
183     ret = ioctl(s->fd, VIDIOC_G_FMT, &cap_fmt);
184     if (ret) {
185         av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT\n", s->capture.name);
186         return 0;
187     }
188
189     full_reinit = v4l2_resolution_changed(&s->output, &out_fmt);
190     if (full_reinit) {
191         s->output.height = v4l2_get_height(&out_fmt);
192         s->output.width = v4l2_get_width(&out_fmt);
193         s->output.sample_aspect_ratio = v4l2_get_sar(&s->output);
194     }
195
196     reinit = v4l2_resolution_changed(&s->capture, &cap_fmt);
197     if (reinit) {
198         s->capture.height = v4l2_get_height(&cap_fmt);
199         s->capture.width = v4l2_get_width(&cap_fmt);
200         s->capture.sample_aspect_ratio = v4l2_get_sar(&s->capture);
201     }
202
203     if (full_reinit || reinit)
204         s->reinit = 1;
205
206     if (full_reinit) {
207         ret = ff_v4l2_m2m_codec_full_reinit(s);
208         if (ret) {
209             av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_full_reinit\n");
210             return AVERROR(EINVAL);
211         }
212         goto reinit_run;
213     }
214
215     if (reinit) {
216         if (s->avctx)
217             ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height);
218         if (ret < 0)
219             av_log(logger(ctx), AV_LOG_WARNING, "update avcodec height and width\n");
220
221         ret = ff_v4l2_m2m_codec_reinit(s);
222         if (ret) {
223             av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_reinit\n");
224             return AVERROR(EINVAL);
225         }
226         goto reinit_run;
227     }
228
229     /* dummy event received */
230     return 0;
231
232     /* reinit executed */
233 reinit_run:
234     return 1;
235 }
236
237 static int v4l2_stop_decode(V4L2Context *ctx)
238 {
239     struct v4l2_decoder_cmd cmd = {
240         .cmd = V4L2_DEC_CMD_STOP,
241         .flags = 0,
242     };
243     int ret;
244
245     ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DECODER_CMD, &cmd);
246     if (ret) {
247         /* DECODER_CMD is optional */
248         if (errno == ENOTTY)
249             return ff_v4l2_context_set_status(ctx, VIDIOC_STREAMOFF);
250         else
251             return AVERROR(errno);
252     }
253
254     return 0;
255 }
256
257 static int v4l2_stop_encode(V4L2Context *ctx)
258 {
259     struct v4l2_encoder_cmd cmd = {
260         .cmd = V4L2_ENC_CMD_STOP,
261         .flags = 0,
262     };
263     int ret;
264
265     ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_ENCODER_CMD, &cmd);
266     if (ret) {
267         /* ENCODER_CMD is optional */
268         if (errno == ENOTTY)
269             return ff_v4l2_context_set_status(ctx, VIDIOC_STREAMOFF);
270         else
271             return AVERROR(errno);
272     }
273
274     return 0;
275 }
276
277 static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout)
278 {
279     struct v4l2_plane planes[VIDEO_MAX_PLANES];
280     struct v4l2_buffer buf = { 0 };
281     V4L2Buffer *avbuf;
282     struct pollfd pfd = {
283         .events =  POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM, /* default blocking capture */
284         .fd = ctx_to_m2mctx(ctx)->fd,
285     };
286     int i, ret;
287
288     /* if we are draining and there are no more capture buffers queued in the driver we are done */
289     if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) {
290         for (i = 0; i < ctx->num_buffers; i++) {
291             /* capture buffer initialization happens during decode hence
292              * detection happens at runtime
293              */
294             if (!ctx->buffers)
295                 break;
296
297             if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER)
298                 goto start;
299         }
300         ctx->done = 1;
301         return NULL;
302     }
303
304 start:
305     if (V4L2_TYPE_IS_OUTPUT(ctx->type))
306         pfd.events =  POLLOUT | POLLWRNORM;
307     else {
308         /* no need to listen to requests for more input while draining */
309         if (ctx_to_m2mctx(ctx)->draining)
310             pfd.events =  POLLIN | POLLRDNORM | POLLPRI;
311     }
312
313     for (;;) {
314         ret = poll(&pfd, 1, timeout);
315         if (ret > 0)
316             break;
317         if (errno == EINTR)
318             continue;
319         return NULL;
320     }
321
322     /* 0. handle errors */
323     if (pfd.revents & POLLERR) {
324         /* if we are trying to get free buffers but none have been queued yet
325            no need to raise a warning */
326         if (timeout == 0) {
327             for (i = 0; i < ctx->num_buffers; i++) {
328                 if (ctx->buffers[i].status != V4L2BUF_AVAILABLE)
329                     av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name);
330             }
331         }
332         else
333             av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name);
334
335         return NULL;
336     }
337
338     /* 1. handle resolution changes */
339     if (pfd.revents & POLLPRI) {
340         ret = v4l2_handle_event(ctx);
341         if (ret < 0) {
342             /* if re-init failed, abort */
343             ctx->done = 1;
344             return NULL;
345         }
346         if (ret) {
347             /* if re-init was successful drop the buffer (if there was one)
348              * since we had to reconfigure capture (unmap all buffers)
349              */
350             return NULL;
351         }
352     }
353
354     /* 2. dequeue the buffer */
355     if (pfd.revents & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM)) {
356
357         if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) {
358             /* there is a capture buffer ready */
359             if (pfd.revents & (POLLIN | POLLRDNORM))
360                 goto dequeue;
361
362             /* the driver is ready to accept more input; instead of waiting for the capture
363              * buffer to complete we return NULL so input can proceed (we are single threaded)
364              */
365             if (pfd.revents & (POLLOUT | POLLWRNORM))
366                 return NULL;
367         }
368
369 dequeue:
370         memset(&buf, 0, sizeof(buf));
371         buf.memory = V4L2_MEMORY_MMAP;
372         buf.type = ctx->type;
373         if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
374             memset(planes, 0, sizeof(planes));
375             buf.length = VIDEO_MAX_PLANES;
376             buf.m.planes = planes;
377         }
378
379         ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DQBUF, &buf);
380         if (ret) {
381             if (errno != EAGAIN) {
382                 ctx->done = 1;
383                 if (errno != EPIPE)
384                     av_log(logger(ctx), AV_LOG_DEBUG, "%s VIDIOC_DQBUF, errno (%s)\n",
385                         ctx->name, av_err2str(AVERROR(errno)));
386             }
387             return NULL;
388         }
389
390         avbuf = &ctx->buffers[buf.index];
391         avbuf->status = V4L2BUF_AVAILABLE;
392         avbuf->buf = buf;
393         if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
394             memcpy(avbuf->planes, planes, sizeof(planes));
395             avbuf->buf.m.planes = avbuf->planes;
396         }
397         return avbuf;
398     }
399
400     return NULL;
401 }
402
403 static V4L2Buffer* v4l2_getfree_v4l2buf(V4L2Context *ctx)
404 {
405     int timeout = 0; /* return when no more buffers to dequeue */
406     int i;
407
408     /* get back as many output buffers as possible */
409     if (V4L2_TYPE_IS_OUTPUT(ctx->type)) {
410           do {
411           } while (v4l2_dequeue_v4l2buf(ctx, timeout));
412     }
413
414     for (i = 0; i < ctx->num_buffers; i++) {
415         if (ctx->buffers[i].status == V4L2BUF_AVAILABLE)
416             return &ctx->buffers[i];
417     }
418
419     return NULL;
420 }
421
422 static int v4l2_release_buffers(V4L2Context* ctx)
423 {
424     struct v4l2_requestbuffers req = {
425         .memory = V4L2_MEMORY_MMAP,
426         .type = ctx->type,
427         .count = 0, /* 0 -> unmaps buffers from the driver */
428     };
429     int i, j;
430
431     for (i = 0; i < ctx->num_buffers; i++) {
432         V4L2Buffer *buffer = &ctx->buffers[i];
433
434         for (j = 0; j < buffer->num_planes; j++) {
435             struct V4L2Plane_info *p = &buffer->plane_info[j];
436             if (p->mm_addr && p->length)
437                 if (munmap(p->mm_addr, p->length) < 0)
438                     av_log(logger(ctx), AV_LOG_ERROR, "%s unmap plane (%s))\n", ctx->name, av_err2str(AVERROR(errno)));
439         }
440     }
441
442     return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req);
443 }
444
445 static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfmt)
446 {
447     struct v4l2_format *fmt = &ctx->format;
448     uint32_t v4l2_fmt;
449     int ret;
450
451     v4l2_fmt = ff_v4l2_format_avfmt_to_v4l2(pixfmt);
452     if (!v4l2_fmt)
453         return AVERROR(EINVAL);
454
455     if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type))
456         fmt->fmt.pix_mp.pixelformat = v4l2_fmt;
457     else
458         fmt->fmt.pix.pixelformat = v4l2_fmt;
459
460     fmt->type = ctx->type;
461
462     ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_TRY_FMT, fmt);
463     if (ret)
464         return AVERROR(EINVAL);
465
466     return 0;
467 }
468
469 static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p)
470 {
471     enum AVPixelFormat pixfmt = ctx->av_pix_fmt;
472     struct v4l2_fmtdesc fdesc;
473     int ret;
474
475     memset(&fdesc, 0, sizeof(fdesc));
476     fdesc.type = ctx->type;
477
478     if (pixfmt != AV_PIX_FMT_NONE) {
479         ret = v4l2_try_raw_format(ctx, pixfmt);
480         if (!ret)
481             return 0;
482     }
483
484     for (;;) {
485         ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_ENUM_FMT, &fdesc);
486         if (ret)
487             return AVERROR(EINVAL);
488
489         pixfmt = ff_v4l2_format_v4l2_to_avfmt(fdesc.pixelformat, AV_CODEC_ID_RAWVIDEO);
490         ret = v4l2_try_raw_format(ctx, pixfmt);
491         if (ret){
492             fdesc.index++;
493             continue;
494         }
495
496         *p = pixfmt;
497
498         return 0;
499     }
500
501     return AVERROR(EINVAL);
502 }
503
504 static int v4l2_get_coded_format(V4L2Context* ctx, uint32_t *p)
505 {
506     struct v4l2_fmtdesc fdesc;
507     uint32_t v4l2_fmt;
508     int ret;
509
510     /* translate to a valid v4l2 format */
511     v4l2_fmt = ff_v4l2_format_avcodec_to_v4l2(ctx->av_codec_id);
512     if (!v4l2_fmt)
513         return AVERROR(EINVAL);
514
515     /* check if the driver supports this format */
516     memset(&fdesc, 0, sizeof(fdesc));
517     fdesc.type = ctx->type;
518
519     for (;;) {
520         ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_ENUM_FMT, &fdesc);
521         if (ret)
522             return AVERROR(EINVAL);
523
524         if (fdesc.pixelformat == v4l2_fmt)
525             break;
526
527         fdesc.index++;
528     }
529
530     *p = v4l2_fmt;
531
532     return 0;
533 }
534
535  /*****************************************************************************
536   *
537   *             V4L2 Context Interface
538   *
539   *****************************************************************************/
540
541 int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd)
542 {
543     int type = ctx->type;
544     int ret;
545
546     ret = ioctl(ctx_to_m2mctx(ctx)->fd, cmd, &type);
547     if (ret < 0)
548         return AVERROR(errno);
549
550     ctx->streamon = (cmd == VIDIOC_STREAMON);
551
552     return 0;
553 }
554
555 int ff_v4l2_context_enqueue_frame(V4L2Context* ctx, const AVFrame* frame)
556 {
557     V4L2m2mContext *s = ctx_to_m2mctx(ctx);
558     V4L2Buffer* avbuf;
559     int ret;
560
561     if (!frame) {
562         ret = v4l2_stop_encode(ctx);
563         if (ret)
564             av_log(logger(ctx), AV_LOG_ERROR, "%s stop_encode\n", ctx->name);
565         s->draining= 1;
566         return 0;
567     }
568
569     avbuf = v4l2_getfree_v4l2buf(ctx);
570     if (!avbuf)
571         return AVERROR(ENOMEM);
572
573     ret = ff_v4l2_buffer_avframe_to_buf(frame, avbuf);
574     if (ret)
575         return ret;
576
577     return ff_v4l2_buffer_enqueue(avbuf);
578 }
579
580 int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt)
581 {
582     V4L2m2mContext *s = ctx_to_m2mctx(ctx);
583     V4L2Buffer* avbuf;
584     int ret;
585
586     if (!pkt->size) {
587         ret = v4l2_stop_decode(ctx);
588         if (ret)
589             av_log(logger(ctx), AV_LOG_ERROR, "%s stop_decode\n", ctx->name);
590         s->draining = 1;
591         return 0;
592     }
593
594     avbuf = v4l2_getfree_v4l2buf(ctx);
595     if (!avbuf)
596         return AVERROR(EAGAIN);
597
598     ret = ff_v4l2_buffer_avpkt_to_buf(pkt, avbuf);
599     if (ret)
600         return ret;
601
602     return ff_v4l2_buffer_enqueue(avbuf);
603 }
604
605 int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame, int timeout)
606 {
607     V4L2Buffer *avbuf;
608
609     /*
610      * timeout=-1 blocks until:
611      *  1. decoded frame available
612      *  2. an input buffer is ready to be dequeued
613      */
614     avbuf = v4l2_dequeue_v4l2buf(ctx, timeout);
615     if (!avbuf) {
616         if (ctx->done)
617             return AVERROR_EOF;
618
619         return AVERROR(EAGAIN);
620     }
621
622     return ff_v4l2_buffer_buf_to_avframe(frame, avbuf);
623 }
624
625 int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt)
626 {
627     V4L2Buffer *avbuf;
628
629     /*
630      * blocks until:
631      *  1. encoded packet available
632      *  2. an input buffer ready to be dequeued
633      */
634     avbuf = v4l2_dequeue_v4l2buf(ctx, -1);
635     if (!avbuf) {
636         if (ctx->done)
637             return AVERROR_EOF;
638
639         return AVERROR(EAGAIN);
640     }
641
642     return ff_v4l2_buffer_buf_to_avpkt(pkt, avbuf);
643 }
644
645 int ff_v4l2_context_get_format(V4L2Context* ctx, int probe)
646 {
647     struct v4l2_format_update fmt = { 0 };
648     int ret;
649
650     if  (ctx->av_codec_id == AV_CODEC_ID_RAWVIDEO) {
651         ret = v4l2_get_raw_format(ctx, &fmt.av_fmt);
652         if (ret)
653             return ret;
654
655         fmt.update_avfmt = !probe;
656         v4l2_save_to_context(ctx, &fmt);
657
658         /* format has been tried already */
659         return ret;
660     }
661
662     ret = v4l2_get_coded_format(ctx, &fmt.v4l2_fmt);
663     if (ret)
664         return ret;
665
666     fmt.update_v4l2 = 1;
667     v4l2_save_to_context(ctx, &fmt);
668
669     return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_TRY_FMT, &ctx->format);
670 }
671
672 int ff_v4l2_context_set_format(V4L2Context* ctx)
673 {
674     return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_S_FMT, &ctx->format);
675 }
676
677 void ff_v4l2_context_release(V4L2Context* ctx)
678 {
679     int ret;
680
681     if (!ctx->buffers)
682         return;
683
684     ret = v4l2_release_buffers(ctx);
685     if (ret)
686         av_log(logger(ctx), AV_LOG_WARNING, "V4L2 failed to unmap the %s buffers\n", ctx->name);
687
688     av_free(ctx->buffers);
689     ctx->buffers = NULL;
690 }
691
692 int ff_v4l2_context_init(V4L2Context* ctx)
693 {
694     V4L2m2mContext *s = ctx_to_m2mctx(ctx);
695     struct v4l2_requestbuffers req;
696     int ret, i;
697
698     if (!v4l2_type_supported(ctx)) {
699         av_log(logger(ctx), AV_LOG_ERROR, "type %i not supported\n", ctx->type);
700         return AVERROR_PATCHWELCOME;
701     }
702
703     ret = ioctl(s->fd, VIDIOC_G_FMT, &ctx->format);
704     if (ret)
705         av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT failed\n", ctx->name);
706
707     memset(&req, 0, sizeof(req));
708     req.count = ctx->num_buffers;
709     req.memory = V4L2_MEMORY_MMAP;
710     req.type = ctx->type;
711     ret = ioctl(s->fd, VIDIOC_REQBUFS, &req);
712     if (ret < 0) {
713         av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_REQBUFS failed: %s\n", ctx->name, strerror(errno));
714         return AVERROR(errno);
715     }
716
717     ctx->num_buffers = req.count;
718     ctx->buffers = av_mallocz(ctx->num_buffers * sizeof(V4L2Buffer));
719     if (!ctx->buffers) {
720         av_log(logger(ctx), AV_LOG_ERROR, "%s malloc enomem\n", ctx->name);
721         return AVERROR(ENOMEM);
722     }
723
724     for (i = 0; i < req.count; i++) {
725         ctx->buffers[i].context = ctx;
726         ret = ff_v4l2_buffer_initialize(&ctx->buffers[i], i);
727         if (ret < 0) {
728             av_log(logger(ctx), AV_LOG_ERROR, "%s buffer[%d] initialization (%s)\n", ctx->name, i, av_err2str(ret));
729             goto error;
730         }
731     }
732
733     av_log(logger(ctx), AV_LOG_DEBUG, "%s: %s %02d buffers initialized: %04ux%04u, sizeimage %08u, bytesperline %08u\n", ctx->name,
734         V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? av_fourcc2str(ctx->format.fmt.pix_mp.pixelformat) : av_fourcc2str(ctx->format.fmt.pix.pixelformat),
735         req.count,
736         v4l2_get_width(&ctx->format),
737         v4l2_get_height(&ctx->format),
738         V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].sizeimage : ctx->format.fmt.pix.sizeimage,
739         V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].bytesperline : ctx->format.fmt.pix.bytesperline);
740
741     return 0;
742
743 error:
744     v4l2_release_buffers(ctx);
745
746     av_free(ctx->buffers);
747     ctx->buffers = NULL;
748
749     return ret;
750 }