2 * V4L2 mem2mem encoders
4 * Copyright (C) 2017 Alexis Ballier <aballier@gentoo.org>
5 * Copyright (C) 2017 Jorge Ramirez <jorge.ramirez-ortiz@linaro.org>
7 * This file is part of FFmpeg.
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.
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.
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
24 #include <linux/videodev2.h>
25 #include <sys/ioctl.h>
27 #include "libavcodec/avcodec.h"
28 #include "libavcodec/internal.h"
29 #include "libavutil/pixdesc.h"
30 #include "libavutil/pixfmt.h"
31 #include "libavutil/opt.h"
32 #include "v4l2_context.h"
36 #define MPEG_CID(x) V4L2_CID_MPEG_VIDEO_##x
37 #define MPEG_VIDEO(x) V4L2_MPEG_VIDEO_##x
39 static inline void v4l2_set_timeperframe(V4L2m2mContext *s, unsigned int num, unsigned int den)
41 struct v4l2_streamparm parm = { 0 };
43 parm.type = V4L2_TYPE_IS_MULTIPLANAR(s->output.type) ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : V4L2_BUF_TYPE_VIDEO_OUTPUT;
44 parm.parm.output.timeperframe.denominator = den;
45 parm.parm.output.timeperframe.numerator = num;
47 if (ioctl(s->fd, VIDIOC_S_PARM, &parm) < 0)
48 av_log(s->avctx, AV_LOG_WARNING, "Failed to set timeperframe");
51 static inline void v4l2_set_ext_ctrl(V4L2m2mContext *s, unsigned int id, signed int value, const char *name, int log_warning)
53 struct v4l2_ext_controls ctrls = { { 0 } };
54 struct v4l2_ext_control ctrl = { 0 };
57 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
58 ctrls.controls = &ctrl;
65 if (ioctl(s->fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
66 av_log(s->avctx, log_warning || errno != EINVAL ? AV_LOG_WARNING : AV_LOG_DEBUG,
67 "Failed to set %s: %s\n", name, strerror(errno));
69 av_log(s->avctx, AV_LOG_DEBUG, "Encoder: %s = %d\n", name, value);
72 static inline int v4l2_get_ext_ctrl(V4L2m2mContext *s, unsigned int id, signed int *value, const char *name, int log_warning)
74 struct v4l2_ext_controls ctrls = { { 0 } };
75 struct v4l2_ext_control ctrl = { 0 };
79 ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
80 ctrls.controls = &ctrl;
86 ret = ioctl(s->fd, VIDIOC_G_EXT_CTRLS, &ctrls);
88 av_log(s->avctx, log_warning || errno != EINVAL ? AV_LOG_WARNING : AV_LOG_DEBUG,
89 "Failed to get %s\n", name);
98 static inline unsigned int v4l2_h264_profile_from_ff(int p)
100 static const struct h264_profile {
101 unsigned int ffmpeg_val;
102 unsigned int v4l2_val;
104 { FF_PROFILE_H264_CONSTRAINED_BASELINE, MPEG_VIDEO(H264_PROFILE_CONSTRAINED_BASELINE) },
105 { FF_PROFILE_H264_HIGH_444_PREDICTIVE, MPEG_VIDEO(H264_PROFILE_HIGH_444_PREDICTIVE) },
106 { FF_PROFILE_H264_HIGH_422_INTRA, MPEG_VIDEO(H264_PROFILE_HIGH_422_INTRA) },
107 { FF_PROFILE_H264_HIGH_444_INTRA, MPEG_VIDEO(H264_PROFILE_HIGH_444_INTRA) },
108 { FF_PROFILE_H264_HIGH_10_INTRA, MPEG_VIDEO(H264_PROFILE_HIGH_10_INTRA) },
109 { FF_PROFILE_H264_HIGH_422, MPEG_VIDEO(H264_PROFILE_HIGH_422) },
110 { FF_PROFILE_H264_BASELINE, MPEG_VIDEO(H264_PROFILE_BASELINE) },
111 { FF_PROFILE_H264_EXTENDED, MPEG_VIDEO(H264_PROFILE_EXTENDED) },
112 { FF_PROFILE_H264_HIGH_10, MPEG_VIDEO(H264_PROFILE_HIGH_10) },
113 { FF_PROFILE_H264_MAIN, MPEG_VIDEO(H264_PROFILE_MAIN) },
114 { FF_PROFILE_H264_HIGH, MPEG_VIDEO(H264_PROFILE_HIGH) },
118 for (i = 0; i < FF_ARRAY_ELEMS(profile); i++) {
119 if (profile[i].ffmpeg_val == p)
120 return profile[i].v4l2_val;
122 return AVERROR(ENOENT);
125 static inline int v4l2_mpeg4_profile_from_ff(int p)
127 static const struct mpeg4_profile {
128 unsigned int ffmpeg_val;
129 unsigned int v4l2_val;
131 { FF_PROFILE_MPEG4_ADVANCED_CODING, MPEG_VIDEO(MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY) },
132 { FF_PROFILE_MPEG4_ADVANCED_SIMPLE, MPEG_VIDEO(MPEG4_PROFILE_ADVANCED_SIMPLE) },
133 { FF_PROFILE_MPEG4_SIMPLE_SCALABLE, MPEG_VIDEO(MPEG4_PROFILE_SIMPLE_SCALABLE) },
134 { FF_PROFILE_MPEG4_SIMPLE, MPEG_VIDEO(MPEG4_PROFILE_SIMPLE) },
135 { FF_PROFILE_MPEG4_CORE, MPEG_VIDEO(MPEG4_PROFILE_CORE) },
139 for (i = 0; i < FF_ARRAY_ELEMS(profile); i++) {
140 if (profile[i].ffmpeg_val == p)
141 return profile[i].v4l2_val;
143 return AVERROR(ENOENT);
146 static int v4l2_check_b_frame_support(V4L2m2mContext *s)
148 if (s->avctx->max_b_frames)
149 av_log(s->avctx, AV_LOG_WARNING, "Encoder does not support b-frames yet\n");
151 v4l2_set_ext_ctrl(s, MPEG_CID(B_FRAMES), 0, "number of B-frames", 0);
152 v4l2_get_ext_ctrl(s, MPEG_CID(B_FRAMES), &s->avctx->max_b_frames, "number of B-frames", 0);
153 if (s->avctx->max_b_frames == 0)
156 avpriv_report_missing_feature(s->avctx, "DTS/PTS calculation for V4L2 encoding");
158 return AVERROR_PATCHWELCOME;
161 static inline void v4l2_subscribe_eos_event(V4L2m2mContext *s)
163 struct v4l2_event_subscription sub;
165 memset(&sub, 0, sizeof(sub));
166 sub.type = V4L2_EVENT_EOS;
167 if (ioctl(s->fd, VIDIOC_SUBSCRIBE_EVENT, &sub) < 0)
168 av_log(s->avctx, AV_LOG_WARNING,
169 "the v4l2 driver does not support end of stream VIDIOC_SUBSCRIBE_EVENT\n");
172 static int v4l2_prepare_encoder(V4L2m2mContext *s)
174 AVCodecContext *avctx = s->avctx;
175 int qmin_cid, qmax_cid, qmin, qmax;
181 v4l2_subscribe_eos_event(s);
183 ret = v4l2_check_b_frame_support(s);
190 if (avctx->framerate.num || avctx->framerate.den)
191 v4l2_set_timeperframe(s, avctx->framerate.den, avctx->framerate.num);
194 v4l2_set_ext_ctrl(s, MPEG_CID(HEADER_MODE), MPEG_VIDEO(HEADER_MODE_SEPARATE), "header mode", 0);
195 v4l2_set_ext_ctrl(s, MPEG_CID(BITRATE) , avctx->bit_rate, "bit rate", 1);
196 v4l2_set_ext_ctrl(s, MPEG_CID(FRAME_RC_ENABLE), 1, "frame level rate control", 0);
197 v4l2_set_ext_ctrl(s, MPEG_CID(GOP_SIZE), avctx->gop_size,"gop size", 1);
199 av_log(avctx, AV_LOG_DEBUG,
200 "Encoder Context: id (%d), profile (%d), frame rate(%d/%d), number b-frames (%d), "
201 "gop size (%d), bit rate (%"PRId64"), qmin (%d), qmax (%d)\n",
202 avctx->codec_id, avctx->profile, avctx->framerate.num, avctx->framerate.den,
203 avctx->max_b_frames, avctx->gop_size, avctx->bit_rate, avctx->qmin, avctx->qmax);
205 switch (avctx->codec_id) {
206 case AV_CODEC_ID_H264:
207 if (avctx->profile != FF_PROFILE_UNKNOWN) {
208 val = v4l2_h264_profile_from_ff(avctx->profile);
210 av_log(avctx, AV_LOG_WARNING, "h264 profile not found\n");
212 v4l2_set_ext_ctrl(s, MPEG_CID(H264_PROFILE), val, "h264 profile", 1);
214 qmin_cid = MPEG_CID(H264_MIN_QP);
215 qmax_cid = MPEG_CID(H264_MAX_QP);
219 case AV_CODEC_ID_MPEG4:
220 if (avctx->profile != FF_PROFILE_UNKNOWN) {
221 val = v4l2_mpeg4_profile_from_ff(avctx->profile);
223 av_log(avctx, AV_LOG_WARNING, "mpeg4 profile not found\n");
225 v4l2_set_ext_ctrl(s, MPEG_CID(MPEG4_PROFILE), val, "mpeg4 profile", 1);
227 qmin_cid = MPEG_CID(MPEG4_MIN_QP);
228 qmax_cid = MPEG_CID(MPEG4_MAX_QP);
229 if (avctx->flags & AV_CODEC_FLAG_QPEL)
230 v4l2_set_ext_ctrl(s, MPEG_CID(MPEG4_QPEL), 1, "qpel", 1);
234 case AV_CODEC_ID_H263:
235 qmin_cid = MPEG_CID(H263_MIN_QP);
236 qmax_cid = MPEG_CID(H263_MAX_QP);
240 case AV_CODEC_ID_VP8:
241 qmin_cid = MPEG_CID(VPX_MIN_QP);
242 qmax_cid = MPEG_CID(VPX_MAX_QP);
246 case AV_CODEC_ID_VP9:
247 qmin_cid = MPEG_CID(VPX_MIN_QP);
248 qmax_cid = MPEG_CID(VPX_MAX_QP);
256 if (avctx->qmin >= 0 && avctx->qmax >= 0 && avctx->qmin > avctx->qmax) {
257 av_log(avctx, AV_LOG_WARNING, "Invalid qmin:%d qmax:%d. qmin should not "
258 "exceed qmax\n", avctx->qmin, avctx->qmax);
260 qmin = avctx->qmin >= 0 ? avctx->qmin : qmin;
261 qmax = avctx->qmax >= 0 ? avctx->qmax : qmax;
264 v4l2_set_ext_ctrl(s, qmin_cid, qmin, "minimum video quantizer scale",
266 v4l2_set_ext_ctrl(s, qmax_cid, qmax, "maximum video quantizer scale",
272 static int v4l2_send_frame(AVCodecContext *avctx, const AVFrame *frame)
274 V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context;
275 V4L2Context *const output = &s->output;
277 #ifdef V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME
278 if (frame && frame->pict_type == AV_PICTURE_TYPE_I)
279 v4l2_set_ext_ctrl(s, MPEG_CID(FORCE_KEY_FRAME), 0, "force key frame", 1);
282 return ff_v4l2_context_enqueue_frame(output, frame);
285 static int v4l2_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
287 V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context;
288 V4L2Context *const capture = &s->capture;
289 V4L2Context *const output = &s->output;
295 if (!output->streamon) {
296 ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMON);
298 av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMON failed on output context\n");
303 if (!capture->streamon) {
304 ret = ff_v4l2_context_set_status(capture, VIDIOC_STREAMON);
306 av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMON failed on capture context\n");
312 return ff_v4l2_context_dequeue_packet(capture, avpkt);
315 static av_cold int v4l2_encode_init(AVCodecContext *avctx)
317 V4L2Context *capture, *output;
319 V4L2m2mPriv *priv = avctx->priv_data;
320 enum AVPixelFormat pix_fmt_output;
321 uint32_t v4l2_fmt_output;
324 ret = ff_v4l2_m2m_create_context(priv, &s);
328 capture = &s->capture;
331 /* common settings output/capture */
332 output->height = capture->height = avctx->height;
333 output->width = capture->width = avctx->width;
336 output->av_codec_id = AV_CODEC_ID_RAWVIDEO;
337 output->av_pix_fmt = avctx->pix_fmt;
339 /* capture context */
340 capture->av_codec_id = avctx->codec_id;
341 capture->av_pix_fmt = AV_PIX_FMT_NONE;
344 ret = ff_v4l2_m2m_codec_init(priv);
346 av_log(avctx, AV_LOG_ERROR, "can't configure encoder\n");
350 if (V4L2_TYPE_IS_MULTIPLANAR(output->type))
351 v4l2_fmt_output = output->format.fmt.pix_mp.pixelformat;
353 v4l2_fmt_output = output->format.fmt.pix.pixelformat;
355 pix_fmt_output = ff_v4l2_format_v4l2_to_avfmt(v4l2_fmt_output, AV_CODEC_ID_RAWVIDEO);
356 if (pix_fmt_output != avctx->pix_fmt) {
357 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt_output);
358 av_log(avctx, AV_LOG_ERROR, "Encoder requires %s pixel format.\n", desc->name);
359 return AVERROR(EINVAL);
362 return v4l2_prepare_encoder(s);
365 static av_cold int v4l2_encode_close(AVCodecContext *avctx)
367 return ff_v4l2_m2m_codec_end(avctx->priv_data);
370 #define OFFSET(x) offsetof(V4L2m2mPriv, x)
371 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
373 static const AVOption options[] = {
374 V4L_M2M_DEFAULT_OPTS,
375 { "num_capture_buffers", "Number of buffers in the capture context",
376 OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 4 }, 4, INT_MAX, FLAGS },
380 static const AVCodecDefault v4l2_m2m_defaults[] = {
386 #define M2MENC_CLASS(NAME) \
387 static const AVClass v4l2_m2m_ ## NAME ## _enc_class = { \
388 .class_name = #NAME "_v4l2m2m_encoder", \
389 .item_name = av_default_item_name, \
391 .version = LIBAVUTIL_VERSION_INT, \
394 #define M2MENC(NAME, LONGNAME, CODEC) \
396 AVCodec ff_ ## NAME ## _v4l2m2m_encoder = { \
397 .name = #NAME "_v4l2m2m" , \
398 .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " encoder wrapper"), \
399 .type = AVMEDIA_TYPE_VIDEO, \
401 .priv_data_size = sizeof(V4L2m2mPriv), \
402 .priv_class = &v4l2_m2m_ ## NAME ##_enc_class, \
403 .init = v4l2_encode_init, \
404 .send_frame = v4l2_send_frame, \
405 .receive_packet = v4l2_receive_packet, \
406 .close = v4l2_encode_close, \
407 .defaults = v4l2_m2m_defaults, \
408 .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \
409 .wrapper_name = "v4l2m2m", \
412 M2MENC(mpeg4,"MPEG4", AV_CODEC_ID_MPEG4);
413 M2MENC(h263, "H.263", AV_CODEC_ID_H263);
414 M2MENC(h264, "H.264", AV_CODEC_ID_H264);
415 M2MENC(hevc, "HEVC", AV_CODEC_ID_HEVC);
416 M2MENC(vp8, "VP8", AV_CODEC_ID_VP8);