diff options
author | Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org> | 2017-10-04 21:04:16 +0200 |
---|---|---|
committer | Mark Thompson <sw@jkqxz.net> | 2017-10-04 23:14:37 +0100 |
commit | 44188993a1865e6a4e204908319f06cec39d5ee9 (patch) | |
tree | 19fbbcc172424004a78a6395f368b3453caec978 | |
parent | 8da5af258423db4e24832b4a880cf6b78d410262 (diff) | |
download | ffmpeg-44188993a1865e6a4e204908319f06cec39d5ee9.tar.gz |
avcodec/v4l2: set sizeimage param for non-raw buffers [fixes #6716]
Some V4L2 drivers fail to allocate buffers when sizeimage is not set
to a max value. This is indeed the case for s5p-mfc [1]
Most drivers should be able to calculate this value from the frame
dimensions and format - or at least have their own default.
However since this work around should not impact those drivers doing
the "right thing" this commit just provides such a default.
The calculations were extracted from the v4l2 driver used to develop
the ffmpeg v4l2_m2m support [2]. See venc.c and vdec.c
[1] linux.git/drivers/media/platform/s5p-mfc
[2] linux.git/drivers/media/platform/qcom/venus/
-rw-r--r-- | libavcodec/v4l2_context.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index 297792f871..9f3b56ddab 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -90,6 +90,20 @@ static inline int v4l2_type_supported(V4L2Context *ctx) ctx->type == V4L2_BUF_TYPE_VIDEO_OUTPUT; } +static inline int v4l2_get_framesize_compressed(V4L2Context* ctx, int width, int height) +{ + V4L2m2mContext *s = ctx_to_m2mctx(ctx); + const int SZ_4K = 0x1000; + int size; + + if (av_codec_is_decoder(s->avctx->codec)) + return ((width * height * 3 / 2) / 2) + 128; + + /* encoder */ + size = FFALIGN(height, 32) * FFALIGN(width, 32) * 3 / 2 / 2; + return FFALIGN(size, SZ_4K); +} + static inline void v4l2_save_to_context(V4L2Context* ctx, struct v4l2_format_update *fmt) { ctx->format.type = ctx->type; @@ -101,13 +115,23 @@ static inline void v4l2_save_to_context(V4L2Context* ctx, struct v4l2_format_upd /* update the sizes to handle the reconfiguration of the capture stream at runtime */ ctx->format.fmt.pix_mp.height = ctx->height; ctx->format.fmt.pix_mp.width = ctx->width; - if (fmt->update_v4l2) + if (fmt->update_v4l2) { ctx->format.fmt.pix_mp.pixelformat = fmt->v4l2_fmt; + + /* s5p-mfc requires the user to specify a buffer size */ + ctx->format.fmt.pix_mp.plane_fmt[0].sizeimage = + v4l2_get_framesize_compressed(ctx, ctx->width, ctx->height); + } } else { ctx->format.fmt.pix.height = ctx->height; ctx->format.fmt.pix.width = ctx->width; - if (fmt->update_v4l2) + if (fmt->update_v4l2) { ctx->format.fmt.pix.pixelformat = fmt->v4l2_fmt; + + /* s5p-mfc requires the user to specify a buffer size */ + ctx->format.fmt.pix.sizeimage = + v4l2_get_framesize_compressed(ctx, ctx->width, ctx->height); + } } } |