FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
v4l2_m2m_enc.c
Go to the documentation of this file.
1 /*
2  * V4L2 mem2mem encoders
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 <search.h>
27 #include "libavcodec/avcodec.h"
28 #include "libavutil/pixdesc.h"
29 #include "libavutil/pixfmt.h"
30 #include "libavutil/opt.h"
31 #include "v4l2_context.h"
32 #include "v4l2_m2m.h"
33 
34 #define MPEG_CID(x) V4L2_CID_MPEG_VIDEO_##x
35 #define MPEG_VIDEO(x) V4L2_MPEG_VIDEO_##x
36 
37 static inline void v4l2_set_timeperframe(V4L2m2mContext *s, unsigned int num, unsigned int den)
38 {
39  struct v4l2_streamparm parm = { 0 };
40 
41  parm.type = V4L2_TYPE_IS_MULTIPLANAR(s->output.type) ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : V4L2_BUF_TYPE_VIDEO_OUTPUT;
42  parm.parm.output.timeperframe.denominator = den;
43  parm.parm.output.timeperframe.numerator = num;
44 
45  if (ioctl(s->fd, VIDIOC_S_PARM, &parm) < 0)
46  av_log(s->avctx, AV_LOG_WARNING, "Failed to set timeperframe");
47 }
48 
49 static inline void v4l2_set_ext_ctrl(V4L2m2mContext *s, unsigned int id, signed int value, const char *name)
50 {
51  struct v4l2_ext_controls ctrls = { 0 };
52  struct v4l2_ext_control ctrl = { 0 };
53 
54  /* set ctrls */
55  ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
56  ctrls.controls = &ctrl;
57  ctrls.count = 1;
58 
59  /* set ctrl*/
60  ctrl.value = value;
61  ctrl.id = id ;
62 
63  if (ioctl(s->fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
64  av_log(s->avctx, AV_LOG_WARNING, "Failed to set %s\n", name);
65  else
66  av_log(s->avctx, AV_LOG_DEBUG, "Encoder: %s = %d\n", name, value);
67 }
68 
69 static inline int v4l2_get_ext_ctrl(V4L2m2mContext *s, unsigned int id, signed int *value, const char *name)
70 {
71  struct v4l2_ext_controls ctrls = { 0 };
72  struct v4l2_ext_control ctrl = { 0 };
73  int ret;
74 
75  /* set ctrls */
76  ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
77  ctrls.controls = &ctrl;
78  ctrls.count = 1;
79 
80  /* set ctrl*/
81  ctrl.id = id ;
82 
83  ret = ioctl(s->fd, VIDIOC_G_EXT_CTRLS, &ctrls);
84  if (ret < 0) {
85  av_log(s->avctx, AV_LOG_WARNING, "Failed to set %s\n", name);
86  return ret;
87  }
88 
89  *value = ctrl.value;
90 
91  return 0;
92 }
93 
94 static inline unsigned int v4l2_h264_profile_from_ff(int p)
95 {
96  static const struct h264_profile {
97  unsigned int ffmpeg_val;
98  unsigned int v4l2_val;
99  } profile[] = {
100  { FF_PROFILE_H264_CONSTRAINED_BASELINE, MPEG_VIDEO(H264_PROFILE_CONSTRAINED_BASELINE) },
101  { FF_PROFILE_H264_HIGH_444_PREDICTIVE, MPEG_VIDEO(H264_PROFILE_HIGH_444_PREDICTIVE) },
102  { FF_PROFILE_H264_HIGH_422_INTRA, MPEG_VIDEO(H264_PROFILE_HIGH_422_INTRA) },
103  { FF_PROFILE_H264_HIGH_444_INTRA, MPEG_VIDEO(H264_PROFILE_HIGH_444_INTRA) },
104  { FF_PROFILE_H264_HIGH_10_INTRA, MPEG_VIDEO(H264_PROFILE_HIGH_10_INTRA) },
105  { FF_PROFILE_H264_HIGH_422, MPEG_VIDEO(H264_PROFILE_HIGH_422) },
106  { FF_PROFILE_H264_BASELINE, MPEG_VIDEO(H264_PROFILE_BASELINE) },
107  { FF_PROFILE_H264_EXTENDED, MPEG_VIDEO(H264_PROFILE_EXTENDED) },
108  { FF_PROFILE_H264_HIGH_10, MPEG_VIDEO(H264_PROFILE_HIGH_10) },
109  { FF_PROFILE_H264_MAIN, MPEG_VIDEO(H264_PROFILE_MAIN) },
110  { FF_PROFILE_H264_HIGH, MPEG_VIDEO(H264_PROFILE_HIGH) },
111  };
112  int i;
113 
114  for (i = 0; i < FF_ARRAY_ELEMS(profile); i++) {
115  if (profile[i].ffmpeg_val == p)
116  return profile[i].v4l2_val;
117  }
118  return AVERROR(ENOENT);
119 }
120 
121 static inline int v4l2_mpeg4_profile_from_ff(int p)
122 {
123  static const struct mpeg4_profile {
124  unsigned int ffmpeg_val;
125  unsigned int v4l2_val;
126  } profile[] = {
127  { FF_PROFILE_MPEG4_ADVANCED_CODING, MPEG_VIDEO(MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY) },
128  { FF_PROFILE_MPEG4_ADVANCED_SIMPLE, MPEG_VIDEO(MPEG4_PROFILE_ADVANCED_SIMPLE) },
129  { FF_PROFILE_MPEG4_SIMPLE_SCALABLE, MPEG_VIDEO(MPEG4_PROFILE_SIMPLE_SCALABLE) },
130  { FF_PROFILE_MPEG4_SIMPLE, MPEG_VIDEO(MPEG4_PROFILE_SIMPLE) },
131  { FF_PROFILE_MPEG4_CORE, MPEG_VIDEO(MPEG4_PROFILE_CORE) },
132  };
133  int i;
134 
135  for (i = 0; i < FF_ARRAY_ELEMS(profile); i++) {
136  if (profile[i].ffmpeg_val == p)
137  return profile[i].v4l2_val;
138  }
139  return AVERROR(ENOENT);
140 }
141 
143 {
144  if (s->avctx->max_b_frames)
145  av_log(s->avctx, AV_LOG_WARNING, "Encoder does not support b-frames yet\n");
146 
147  v4l2_set_ext_ctrl(s, MPEG_CID(B_FRAMES), 0, "number of B-frames");
148  v4l2_get_ext_ctrl(s, MPEG_CID(B_FRAMES), &s->avctx->max_b_frames, "number of B-frames");
149  if (s->avctx->max_b_frames == 0)
150  return 0;
151 
152  avpriv_report_missing_feature(s->avctx, "DTS/PTS calculation for V4L2 encoding");
153 
154  return AVERROR_PATCHWELCOME;
155 }
156 
158 {
159  AVCodecContext *avctx = s->avctx;
160  int qmin_cid, qmax_cid, qmin, qmax;
161  int ret, val;
162 
163  /**
164  * requirements
165  */
167  if (ret)
168  return ret;
169 
170  /**
171  * settingss
172  */
173  if (avctx->framerate.num || avctx->framerate.den)
174  v4l2_set_timeperframe(s, avctx->framerate.num, avctx->framerate.den);
175 
176  /* set ext ctrls */
177  v4l2_set_ext_ctrl(s, MPEG_CID(HEADER_MODE), MPEG_VIDEO(HEADER_MODE_SEPARATE), "header mode");
178  v4l2_set_ext_ctrl(s, MPEG_CID(BITRATE) , avctx->bit_rate, "bit rate");
179  v4l2_set_ext_ctrl(s, MPEG_CID(GOP_SIZE), avctx->gop_size,"gop size");
180 
181  av_log(avctx, AV_LOG_DEBUG,
182  "Encoder Context: id (%d), profile (%d), frame rate(%d/%d), number b-frames (%d), "
183  "gop size (%d), bit rate (%"PRId64"), qmin (%d), qmax (%d)\n",
184  avctx->codec_id, avctx->profile, avctx->framerate.num, avctx->framerate.den,
185  avctx->max_b_frames, avctx->gop_size, avctx->bit_rate, avctx->qmin, avctx->qmax);
186 
187  switch (avctx->codec_id) {
188  case AV_CODEC_ID_H264:
189  val = v4l2_h264_profile_from_ff(avctx->profile);
190  if (val < 0)
191  av_log(avctx, AV_LOG_WARNING, "h264 profile not found\n");
192  else
193  v4l2_set_ext_ctrl(s, MPEG_CID(H264_PROFILE), val, "h264 profile");
194  qmin_cid = MPEG_CID(H264_MIN_QP);
195  qmax_cid = MPEG_CID(H264_MAX_QP);
196  qmin = 0;
197  qmax = 51;
198  break;
199  case AV_CODEC_ID_MPEG4:
200  val = v4l2_mpeg4_profile_from_ff(avctx->profile);
201  if (val < 0)
202  av_log(avctx, AV_LOG_WARNING, "mpeg4 profile not found\n");
203  else
204  v4l2_set_ext_ctrl(s, MPEG_CID(MPEG4_PROFILE), val, "mpeg4 profile");
205  qmin_cid = MPEG_CID(MPEG4_MIN_QP);
206  qmax_cid = MPEG_CID(MPEG4_MAX_QP);
207  if (avctx->flags & AV_CODEC_FLAG_QPEL)
208  v4l2_set_ext_ctrl(s, MPEG_CID(MPEG4_QPEL), 1, "qpel");
209  qmin = 1;
210  qmax = 31;
211  break;
212  case AV_CODEC_ID_H263:
213  qmin_cid = MPEG_CID(H263_MIN_QP);
214  qmax_cid = MPEG_CID(H263_MAX_QP);
215  qmin = 1;
216  qmax = 31;
217  break;
218  case AV_CODEC_ID_VP8:
219  qmin_cid = MPEG_CID(VPX_MIN_QP);
220  qmax_cid = MPEG_CID(VPX_MAX_QP);
221  qmin = 0;
222  qmax = 127;
223  break;
224  case AV_CODEC_ID_VP9:
225  qmin_cid = MPEG_CID(VPX_MIN_QP);
226  qmax_cid = MPEG_CID(VPX_MAX_QP);
227  qmin = 0;
228  qmax = 255;
229  break;
230  default:
231  return 0;
232  }
233 
234  if (qmin != avctx->qmin || qmax != avctx->qmax)
235  av_log(avctx, AV_LOG_WARNING, "Encoder adjusted: qmin (%d), qmax (%d)\n", qmin, qmax);
236 
237  v4l2_set_ext_ctrl(s, qmin_cid, qmin, "minimum video quantizer scale");
238  v4l2_set_ext_ctrl(s, qmax_cid, qmax, "maximum video quantizer scale");
239 
240  return 0;
241 }
242 
243 static int v4l2_send_frame(AVCodecContext *avctx, const AVFrame *frame)
244 {
245  V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context;
246  V4L2Context *const output = &s->output;
247 
248  return ff_v4l2_context_enqueue_frame(output, frame);
249 }
250 
251 static int v4l2_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
252 {
253  V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context;
254  V4L2Context *const capture = &s->capture;
255  V4L2Context *const output = &s->output;
256  int ret;
257 
258  if (s->draining)
259  goto dequeue;
260 
261  if (!output->streamon) {
262  ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMON);
263  if (ret) {
264  av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF failed on output context\n");
265  return ret;
266  }
267  }
268 
269  if (!capture->streamon) {
270  ret = ff_v4l2_context_set_status(capture, VIDIOC_STREAMON);
271  if (ret) {
272  av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMON failed on capture context\n");
273  return ret;
274  }
275  }
276 
277 dequeue:
278  return ff_v4l2_context_dequeue_packet(capture, avpkt);
279 }
280 
282 {
283  V4L2Context *capture, *output;
284  V4L2m2mContext *s;
285  int ret;
286 
287  ret = ff_v4l2_m2m_create_context(avctx, &s);
288  if (ret < 0)
289  return ret;
290 
291  capture = &s->capture;
292  output = &s->output;
293 
294  /* common settings output/capture */
295  output->height = capture->height = avctx->height;
296  output->width = capture->width = avctx->width;
297 
298  /* output context */
300  output->av_pix_fmt = avctx->pix_fmt;
301 
302  /* capture context */
303  capture->av_codec_id = avctx->codec_id;
304  capture->av_pix_fmt = AV_PIX_FMT_NONE;
305 
306  ret = ff_v4l2_m2m_codec_init(avctx);
307  if (ret) {
308  av_log(avctx, AV_LOG_ERROR, "can't configure encoder\n");
309  return ret;
310  }
311 
312  return v4l2_prepare_encoder(s);
313 }
314 
315 #define OFFSET(x) offsetof(V4L2m2mPriv, x)
316 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
317 
318 static const AVOption options[] = {
320  { "num_capture_buffers", "Number of buffers in the capture context",
321  OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 4 }, 4, INT_MAX, FLAGS },
322  { NULL },
323 };
324 
325 #define M2MENC(NAME, LONGNAME, CODEC) \
326 static const AVClass v4l2_m2m_ ## NAME ## _enc_class = {\
327  .class_name = #NAME "_v4l2_m2m_encoder",\
328  .item_name = av_default_item_name,\
329  .option = options,\
330  .version = LIBAVUTIL_VERSION_INT,\
331 };\
332 \
333 AVCodec ff_ ## NAME ## _v4l2m2m_encoder = { \
334  .name = #NAME "_v4l2m2m" ,\
335  .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " encoder wrapper"),\
336  .type = AVMEDIA_TYPE_VIDEO,\
337  .id = CODEC ,\
338  .priv_data_size = sizeof(V4L2m2mPriv),\
339  .priv_class = &v4l2_m2m_ ## NAME ##_enc_class,\
340  .init = v4l2_encode_init,\
341  .send_frame = v4l2_send_frame,\
342  .receive_packet = v4l2_receive_packet,\
343  .close = ff_v4l2_m2m_codec_end,\
344  .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \
345  .wrapper_name = "v4l2m2m", \
346 };
347 
348 M2MENC(mpeg4,"MPEG4", AV_CODEC_ID_MPEG4);
349 M2MENC(h263, "H.263", AV_CODEC_ID_H263);
350 M2MENC(h264, "H.264", AV_CODEC_ID_H264);
351 M2MENC(hevc, "HEVC", AV_CODEC_ID_HEVC);
352 M2MENC(vp8, "VP8", AV_CODEC_ID_VP8);
#define FF_PROFILE_H264_MAIN
Definition: avcodec.h:2884
#define FF_PROFILE_MPEG4_SIMPLE
Definition: avcodec.h:2903
#define NULL
Definition: coverity.c:32
AVRational framerate
Definition: avcodec.h:3040
const char const char void * val
Definition: avisynth_c.h:771
static const AVOption options[]
Definition: v4l2_m2m_enc.c:318
const char * s
Definition: avisynth_c.h:768
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
AVOption.
Definition: opt.h:246
AVCodecContext * avctx
Definition: v4l2_m2m.h:52
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
int64_t bit_rate
the average bitrate
Definition: avcodec.h:1568
int max_b_frames
maximum number of B-frames between non-B-frames Note: The output will be delayed by max_b_frames+1 re...
Definition: avcodec.h:1777
static int v4l2_mpeg4_profile_from_ff(int p)
Definition: v4l2_m2m_enc.c:121
int num
Numerator.
Definition: rational.h:59
#define FLAGS
Definition: v4l2_m2m_enc.c:316
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1727
int width
Width and height of the frames it produces (in case of a capture context, e.g.
Definition: v4l2_context.h:71
#define MPEG_VIDEO(x)
Definition: v4l2_m2m_enc.c:35
#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE
Definition: avcodec.h:2904
int ff_v4l2_context_dequeue_packet(V4L2Context *ctx, AVPacket *pkt)
Dequeues a buffer from a V4L2Context to an AVPacket.
Definition: v4l2_context.c:594
int profile
profile
Definition: avcodec.h:2843
int ff_v4l2_m2m_codec_init(AVCodecContext *avctx)
Probes the video nodes looking for the required codec capabilities.
Definition: v4l2_m2m.c:341
static int v4l2_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
Definition: v4l2_m2m_enc.c:251
static av_cold int v4l2_encode_init(AVCodecContext *avctx)
Definition: v4l2_m2m_enc.c:281
#define FF_PROFILE_H264_HIGH_444_PREDICTIVE
Definition: avcodec.h:2894
enum AVCodecID av_codec_id
AVCodecID corresponding to this buffer context.
Definition: v4l2_context.h:59
#define FF_PROFILE_H264_BASELINE
Definition: avcodec.h:2882
#define av_cold
Definition: attributes.h:82
#define FF_PROFILE_MPEG4_CORE
Definition: avcodec.h:2905
AVOptions.
#define OFFSET(x)
Definition: v4l2_m2m_enc.c:315
static AVFrame * frame
static int v4l2_send_frame(AVCodecContext *avctx, const AVFrame *frame)
Definition: v4l2_m2m_enc.c:243
static void v4l2_set_timeperframe(V4L2m2mContext *s, unsigned int num, unsigned int den)
Definition: v4l2_m2m_enc.c:37
#define FF_PROFILE_H264_EXTENDED
Definition: avcodec.h:2885
#define av_log(a,...)
int ff_v4l2_m2m_create_context(AVCodecContext *avctx, V4L2m2mContext **s)
Allocate a new context and references for a V4L2 M2M instance.
Definition: v4l2_m2m.c:382
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define AVERROR(e)
Definition: error.h:43
int qmax
maximum quantizer
Definition: avcodec.h:2362
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
#define FF_PROFILE_H264_HIGH_422
Definition: avcodec.h:2890
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:1598
#define FF_PROFILE_H264_HIGH
Definition: avcodec.h:2886
enum AVPixelFormat av_pix_fmt
AVPixelFormat corresponding to this buffer context.
Definition: v4l2_context.h:53
int streamon
Whether the stream has been started (VIDIOC_STREAMON has been sent).
Definition: v4l2_context.h:86
static int v4l2_get_ext_ctrl(V4L2m2mContext *s, unsigned int id, signed int *value, const char *name)
Definition: v4l2_m2m_enc.c:69
static int v4l2_check_b_frame_support(V4L2m2mContext *s)
Definition: v4l2_m2m_enc.c:142
int width
picture width / height.
Definition: avcodec.h:1690
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:109
#define FF_ARRAY_ELEMS(a)
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
int ff_v4l2_context_set_status(V4L2Context *ctx, uint32_t cmd)
Sets the status of a V4L2Context.
Definition: v4l2_context.c:510
V4L2Context capture
Definition: v4l2_m2m.h:48
Libavcodec external API header.
#define FF_PROFILE_H264_HIGH_422_INTRA
Definition: avcodec.h:2891
enum AVCodecID codec_id
Definition: avcodec.h:1528
#define M2MENC(NAME, LONGNAME, CODEC)
Definition: v4l2_m2m_enc.c:325
main external API structure.
Definition: avcodec.h:1518
#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE
Definition: avcodec.h:2918
int qmin
minimum quantizer
Definition: avcodec.h:2355
#define FF_PROFILE_H264_HIGH_10_INTRA
Definition: avcodec.h:2888
#define FF_PROFILE_MPEG4_ADVANCED_CODING
Definition: avcodec.h:2914
mfxU16 profile
Definition: qsvenc.c:44
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
V4L2Context output
Definition: v4l2_m2m.h:49
#define AV_CODEC_FLAG_QPEL
Use qpel MC.
Definition: avcodec.h:845
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:1712
int ff_v4l2_context_enqueue_frame(V4L2Context *ctx, const AVFrame *frame)
Enqueues a buffer to a V4L2Context from an AVFrame.
Definition: v4l2_context.c:524
int den
Denominator.
Definition: rational.h:60
#define MPEG_CID(x)
Definition: v4l2_m2m_enc.c:34
static int v4l2_prepare_encoder(V4L2m2mContext *s)
Definition: v4l2_m2m_enc.c:157
void * priv_data
Definition: avcodec.h:1545
pixel format definitions
#define V4L_M2M_DEFAULT_OPTS
Definition: v4l2_m2m.h:39
static unsigned int v4l2_h264_profile_from_ff(int p)
Definition: v4l2_m2m_enc.c:94
#define FF_PROFILE_H264_HIGH_444_INTRA
Definition: avcodec.h:2895
#define FF_PROFILE_H264_CONSTRAINED_BASELINE
Definition: avcodec.h:2883
#define FF_PROFILE_H264_HIGH_10
Definition: avcodec.h:2887
enum AVCodecID id
This structure stores compressed data.
Definition: avcodec.h:1407
static void v4l2_set_ext_ctrl(V4L2m2mContext *s, unsigned int id, signed int value, const char *name)
Definition: v4l2_m2m_enc.c:49
enum v4l2_buf_type type
Type of this buffer context.
Definition: v4l2_context.h:47
const char * name
Definition: opengl_enc.c:103