[FFmpeg-devel] [PATCH] libavcodec/libdav1d: add libdav1d_get_format method to call ff_get_format
This will allow applications to properly init the decoder in cases where a hardware decoder is tried first and and software decoder is tried after by calling the get_format callback. Even though there is no hardware pixel formats available we still need to return the software pixel format. Tested with Kodi by checking if multithreaded software decoding is properly activated. --- libavcodec/libdav1d.c | 12 +++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 30c6eccfef..fa71834543 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -48,6 +48,16 @@ static const enum AVPixelFormat pix_fmt[][3] = { [DAV1D_PIXEL_LAYOUT_I444] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12 }, }; +static enum AVPixelFormat libdav1d_get_format(AVCodecContext *avctx, const Dav1dPicture *p) +{ + enum AVPixelFormat pix_fmts[2], *fmt = pix_fmts; + + *fmt++ = pix_fmt[p->p.layout][p->seq_hdr->hbd]; + *fmt = AV_PIX_FMT_NONE; + + return ff_get_format(avctx, pix_fmts); +} + static void libdav1d_log_callback(void *opaque, const char *fmt, va_list vl) { AVCodecContext *c = opaque; @@ -214,7 +224,7 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) frame->linesize[2] = p->stride[1]; c->profile = p->seq_hdr->profile; -frame->format = c->pix_fmt = pix_fmt[p->p.layout][p->seq_hdr->hbd]; +frame->format = c->pix_fmt = libdav1d_get_format(c, p); frame->width = p->p.w; frame->height = p->p.h; if (c->width != p->p.w || c->height != p->p.h) { -- 2.20.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH] libavcodec/libdav1d: add libdav1d_get_format method to call ff_get_format
On Thu, 2019-04-11 at 21:03 +0200, Hendrik Leppkes wrote: > On Thu, Apr 11, 2019 at 7:47 PM Peter F > wrote: > > Hi, > > > > Am Do., 11. Apr. 2019 um 00:50 Uhr schrieb Hendrik Leppkes > > : > > > On Thu, Apr 11, 2019 at 12:39 AM Lukas Rusak > > > wrote: > > > > This will allow applications to properly init the decoder in > > > > cases where a hardware decoder is tried first and and software > > > > decoder is tried after by calling the get_format callback. > > > > > > > > Even though there is no hardware pixel formats available > > > > we still need to return the software pixel format. > > > > > > > > Tested with Kodi by checking if multithreaded software > > > > decoding is properly activated. > > > > --- > > > > libavcodec/libdav1d.c | 12 +++- > > > > 1 file changed, 11 insertions(+), 1 deletion(-) > > > > > > > > > > This doesn't make sense to m e. get_format isn't called on a wide > > > variety of decoders, and is only useful when there is a hardware > > > format of any kind. > > > Please elaborate what exactly this is trying to achieve. > > > > Can you elaborate on how to use ffmpeg's API properly as a client > > to > > decide if a decoder is a SW decoder and therefore howto properly > > setup > > (multi-)threading, especially it cannot be changed once > > initialized? > > > > I think you are approaching this from the wrong side. Even if the > decoder would support hardware, generally hardware support is > limited. > So if someone plays a 10-bit H264 file, which no consumer hardware > supports, or even worse, a very high resolution file which is beyond > hardware limits, do you want to run single-threaded and slow? I hope > not. > > The way I solve that is to just close the decoder and re-open it if > needed, so I can change such settings. You also fare much better if > you accept that you might need to hard-code which codecs support > hardware at all. Considering thats one new one every 4 years or so, > it'll probably be fine. > > - Hendrik So why don't the software only formats follow the api and also call ff_get_format like is done here? That would stop from applications having to hardcode the hardware decoding formats. What we do currently is open the codec single threaded to try hardware formats. The get_format callback will return a hardware format for the decoder and if not we reopen the codec with multithreading enabled. Is there a better method to do this initialization? Regards, Lukas Rusak ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavcodec: v4l2m2m: allow lower minimum buffer values
There is no reason to enforce a high minimum. In the context of streaming only a few output buffers and capture buffers are even needed for continuous playback. This also helps alleviate memory pressure when decoding 4K media. --- libavcodec/v4l2_m2m.h | 2 +- libavcodec/v4l2_m2m_dec.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h index 61cb919771..feeb162812 100644 --- a/libavcodec/v4l2_m2m.h +++ b/libavcodec/v4l2_m2m.h @@ -38,7 +38,7 @@ #define V4L_M2M_DEFAULT_OPTS \ { "num_output_buffers", "Number of buffers in the output context",\ -OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 6, INT_MAX, FLAGS } +OFFSET(num_output_buffers), AV_OPT_TYPE_INT, { .i64 = 16 }, 2, INT_MAX, FLAGS } typedef struct V4L2m2mContext { char devname[PATH_MAX]; diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index c6b865fde8..b9725be377 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -262,7 +262,7 @@ static av_cold int v4l2_decode_close(AVCodecContext *avctx) static const AVOption options[] = { V4L_M2M_DEFAULT_OPTS, { "num_capture_buffers", "Number of buffers in the capture context", -OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 20, INT_MAX, FLAGS }, +OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 2, INT_MAX, FLAGS }, { NULL}, }; -- 2.24.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 2/3] libavcodec: v4l2m2m: output AVDRMFrameDescriptor
This is V2 of my previous patch. I have worked together with Jorge to get this working properly. We have made it so that AV_PIX_FMT_DRM_PRIME output can be selected by setting avctx->pix_fmt. This allows v4l2 to export the buffer so we can use it for zero-copy. If AV_PIX_FMT_DRM_PRIME is not selected then the standard pixel formats will be used and the buffers will not be exported. --- libavcodec/v4l2_buffers.c | 228 +++--- libavcodec/v4l2_buffers.h | 5 +- libavcodec/v4l2_context.c | 40 ++- libavcodec/v4l2_m2m.c | 4 +- libavcodec/v4l2_m2m.h | 3 + libavcodec/v4l2_m2m_dec.c | 23 6 files changed, 257 insertions(+), 46 deletions(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index aef911f3bb..d715bc6a7c 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -21,6 +21,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include @@ -29,6 +30,7 @@ #include #include "libavcodec/avcodec.h" #include "libavcodec/internal.h" +#include "libavutil/hwcontext.h" #include "v4l2_context.h" #include "v4l2_buffers.h" #include "v4l2_m2m.h" @@ -203,7 +205,65 @@ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf) return AVCOL_TRC_UNSPECIFIED; } -static void v4l2_free_buffer(void *opaque, uint8_t *unused) +static uint8_t * v4l2_get_drm_frame(V4L2Buffer *avbuf) +{ +AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame; +AVDRMLayerDescriptor *layer; + +/* fill the DRM frame descriptor */ +drm_desc->nb_objects = 1; +drm_desc->nb_layers = 1; + +layer = &drm_desc->layers[0]; +layer->planes[0].object_index = 0; +layer->planes[0].offset = 0; +layer->planes[0].pitch = avbuf->plane_info[0].bytesperline; + +switch (avbuf->context->av_pix_fmt) { +case AV_PIX_FMT_NV12: +case AV_PIX_FMT_NV21: + +if (avbuf->num_planes > 1) +break; + +layer->format = avbuf->context->av_pix_fmt == AV_PIX_FMT_NV12 ? +DRM_FORMAT_NV12 : DRM_FORMAT_NV21; +layer->nb_planes = 2; + +layer->planes[1].object_index = 0; +layer->planes[1].offset = avbuf->plane_info[0].bytesperline * +avbuf->context->format.fmt.pix_mp.height; +layer->planes[1].pitch = avbuf->plane_info[0].bytesperline; +break; + +case AV_PIX_FMT_YUV420P: + +if (avbuf->num_planes > 1) +break; + +layer->format = DRM_FORMAT_YUV420; +layer->nb_planes = 3; + +layer->planes[1].object_index = 0; +layer->planes[1].offset = avbuf->plane_info[0].bytesperline * +avbuf->context->format.fmt.pix_mp.height; +layer->planes[1].pitch = avbuf->plane_info[0].bytesperline >> 1; + +layer->planes[2].object_index = 0; +layer->planes[2].offset = layer->planes[1].offset + +((avbuf->plane_info[0].bytesperline * + avbuf->context->format.fmt.pix_mp.height) >> 2); +layer->planes[2].pitch = avbuf->plane_info[0].bytesperline >> 1; +break; + +default: +break; +} + +return (uint8_t *) drm_desc; +} + +static void v4l2_free_buffer(void *opaque, uint8_t *data) { V4L2Buffer* avbuf = opaque; V4L2m2mContext *s = buf_to_m2mctx(avbuf); @@ -227,27 +287,49 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused) } } -static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) +static int v4l2_buffer_export_drm(V4L2Buffer* avbuf) { -V4L2m2mContext *s = buf_to_m2mctx(in); +struct v4l2_exportbuffer expbuf; +int i, ret; -if (plane >= in->num_planes) -return AVERROR(EINVAL); +for (i = 0; i < avbuf->num_planes; i++) { +memset(&expbuf, 0, sizeof(expbuf)); -/* even though most encoders return 0 in data_offset encoding vp8 does require this value */ -*buf = av_buffer_create((char *)in->plane_info[plane].mm_addr + in->planes[plane].data_offset, -in->plane_info[plane].length, v4l2_free_buffer, in, 0); -if (!*buf) -return AVERROR(ENOMEM); +expbuf.index = avbuf->buf.index; +expbuf.type = avbuf->buf.type; +expbuf.plane = i; + +ret = ioctl(buf_to_m2mctx(avbuf)->fd, VIDIOC_EXPBUF, &expbuf); +if (ret < 0) +return AVERROR(errno); + +if (V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type)) { +avbuf->buf.m.planes[i].m.fd = expbuf.fd; +/* drm frame */ +avbuf->drm_frame.objects[i].size = avbuf->buf.m.planes[i].length; +avbuf->drm_frame.objects[i].fd = expbuf.fd; +} else { +avbuf->buf.m.fd = expbuf.fd; +/* drm frame */ +avbuf->drm_frame.objects[0].size = avbuf->buf.length; +avbuf->drm_frame.objects[0].fd = expbuf.fd; +} +} + +return 0; +} + +static int v4l2_buf_inc
[FFmpeg-devel] [PATCH 3/3] libavcodec: v4l2m2m: fix error handling during buffer init
From: Jorge Ramirez-Ortiz Signed-off-by: Jorge Ramirez-Ortiz --- libavcodec/v4l2_context.c | 19 --- libavcodec/v4l2_m2m_dec.c | 11 --- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index 9457fadb1e..fd3161ce2f 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -263,6 +263,12 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) /* if we are draining and there are no more capture buffers queued in the driver we are done */ if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) { for (i = 0; i < ctx->num_buffers; i++) { +/* catpture buffer initialization happens during decode hence + * detection happens at runtime + */ +if (!ctx->buffers) +break; + if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER) goto start; } @@ -724,9 +730,8 @@ int ff_v4l2_context_init(V4L2Context* ctx) ctx->buffers[i].context = ctx; ret = ff_v4l2_buffer_initialize(&ctx->buffers[i], i); if (ret < 0) { -av_log(logger(ctx), AV_LOG_ERROR, "%s buffer initialization (%s)\n", ctx->name, av_err2str(ret)); -av_free(ctx->buffers); -return ret; +av_log(logger(ctx), AV_LOG_ERROR, "%s buffer[%d] initialization (%s)\n", ctx->name, i, av_err2str(ret)); +goto error; } } @@ -739,4 +744,12 @@ int ff_v4l2_context_init(V4L2Context* ctx) V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].bytesperline : ctx->format.fmt.pix.bytesperline); return 0; + +error: +v4l2_release_buffers(ctx); + +av_free(ctx->buffers); +ctx->buffers = NULL; + +return ret; } diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 2b33badb08..1bfd11e216 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -92,8 +92,8 @@ static int v4l2_try_start(AVCodecContext *avctx) if (!capture->buffers) { ret = ff_v4l2_context_init(capture); if (ret) { -av_log(avctx, AV_LOG_DEBUG, "can't request output buffers\n"); -return ret; +av_log(avctx, AV_LOG_ERROR, "can't request capture buffers\n"); +return AVERROR(ENOMEM); } } @@ -155,8 +155,13 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) if (avpkt.size) { ret = v4l2_try_start(avctx); -if (ret) +if (ret) { +/* cant recover */ +if (ret == AVERROR(ENOMEM)) +return ret; + return 0; +} } dequeue: -- 2.17.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/3] libavcodec: v4l2m2m: fix indentation and add M2MDEC_CLASS
This is just some formatting that is taken from the rkmpp decoder. I find that this make is more readable. --- libavcodec/v4l2_m2m_dec.c | 44 --- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index bca45be148..ed5193ecc1 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -202,28 +202,30 @@ static const AVOption options[] = { { NULL}, }; +#define M2MDEC_CLASS(NAME) \ +static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \ +.class_name = #NAME "_v4l2_m2m_decoder", \ +.item_name = av_default_item_name, \ +.option = options, \ +.version= LIBAVUTIL_VERSION_INT, \ +}; + #define M2MDEC(NAME, LONGNAME, CODEC, bsf_name) \ -static const AVClass v4l2_m2m_ ## NAME ## _dec_class = {\ -.class_name = #NAME "_v4l2_m2m_decoder",\ -.item_name = av_default_item_name,\ -.option = options,\ -.version= LIBAVUTIL_VERSION_INT,\ -};\ -\ -AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \ -.name = #NAME "_v4l2m2m" ,\ -.long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"),\ -.type = AVMEDIA_TYPE_VIDEO,\ -.id = CODEC ,\ -.priv_data_size = sizeof(V4L2m2mPriv),\ -.priv_class = &v4l2_m2m_ ## NAME ## _dec_class,\ -.init = v4l2_decode_init,\ -.receive_frame = v4l2_receive_frame,\ -.close = ff_v4l2_m2m_codec_end,\ -.bsfs = bsf_name, \ -.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \ -.wrapper_name = "v4l2m2m", \ -}; +M2MDEC_CLASS(NAME) \ +AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \ +.name = #NAME "_v4l2m2m" , \ +.long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"), \ +.type = AVMEDIA_TYPE_VIDEO, \ +.id = CODEC , \ +.priv_data_size = sizeof(V4L2m2mPriv), \ +.priv_class = &v4l2_m2m_ ## NAME ## _dec_class, \ +.init = v4l2_decode_init, \ +.receive_frame = v4l2_receive_frame, \ +.close = ff_v4l2_m2m_codec_end, \ +.bsfs = bsf_name, \ +.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \ +.wrapper_name = "v4l2m2m", \ +}; M2MDEC(h264, "H.264", AV_CODEC_ID_H264, "h264_mp4toannexb"); M2MDEC(hevc, "HEVC", AV_CODEC_ID_HEVC, "hevc_mp4toannexb"); -- 2.17.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/3] libavcodec/v4l2_buffers: return int64_t in v4l2_get_pts
v4l2_pts is type int64_t we should return that instead of uint64_t --- libavcodec/v4l2_buffers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index ba70c5d14b..fdafe7edca 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -62,7 +62,7 @@ static inline void v4l2_set_pts(V4L2Buffer *out, int64_t pts) out->buf.timestamp.tv_sec = v4l2_pts / USEC_PER_SEC; } -static inline uint64_t v4l2_get_pts(V4L2Buffer *avbuf) +static inline int64_t v4l2_get_pts(V4L2Buffer *avbuf) { V4L2m2mContext *s = buf_to_m2mctx(avbuf); AVRational v4l2_timebase = { 1, USEC_PER_SEC }; -- 2.14.3 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 2/3] libavcodec/v4l2_buffers: check for valid pts value
we check for a valid pts in v4l2_set_pts so we should do the same here --- libavcodec/v4l2_buffers.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index fdafe7edca..5337f6f287 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -71,7 +71,10 @@ static inline int64_t v4l2_get_pts(V4L2Buffer *avbuf) /* convert pts back to encoder timebase */ v4l2_pts = avbuf->buf.timestamp.tv_sec * USEC_PER_SEC + avbuf->buf.timestamp.tv_usec; -return av_rescale_q(v4l2_pts, v4l2_timebase, s->avctx->time_base); +if (v4l2_pts == 0) +return AV_NOPTS_VALUE; +else +return av_rescale_q(v4l2_pts, v4l2_timebase, s->avctx->time_base); } static enum AVColorPrimaries v4l2_get_color_primaries(V4L2Buffer *buf) -- 2.14.3 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 3/3] libavcodec/v4l2_m2m_dec: set default time base
This default time base should be set in order for ffmpeg to rescale the timebase in v4l2_get_pts and v4l2_set_pts --- libavcodec/v4l2_m2m_dec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 8308613978..4de091a011 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -177,6 +177,8 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) capture->av_codec_id = AV_CODEC_ID_RAWVIDEO; capture->av_pix_fmt = avctx->pix_fmt; +avctx->time_base = AV_TIME_BASE_Q; + ret = ff_v4l2_m2m_codec_init(avctx); if (ret) { av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n"); -- 2.14.3 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 0/3] v4l2: some small fixes
Some small fixes that I have done while working with v4l2 Lukas Rusak (3): libavcodec/v4l2_buffers: return int64_t in v4l2_get_pts libavcodec/v4l2_buffers: check for valid pts value libavcodec/v4l2_m2m_dec: set default time base libavcodec/v4l2_buffers.c | 7 +-- libavcodec/v4l2_m2m_dec.c | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) -- 2.14.3 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH][RFC] libavcodec/v4l2_m2m_dec: output AVDRMFrameDescriptor
This is a patch I have been testing for a while in combination with kodi's drmprime renderer I have been testing this with i.MX6 and Dragonboard 410c. So it covers single and multiplanar formats. I'm looking to get some comments on how to integrate this properly so that if we request AV_PIX_FMT_DRM_PRIME we can use that otherwise just use the default buffers. I basically followed how it was done in the rockchip decoder. --- libavcodec/v4l2_buffers.c | 97 +++ libavcodec/v4l2_buffers.h | 1 + libavcodec/v4l2_m2m_dec.c | 45 -- 3 files changed, 97 insertions(+), 46 deletions(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index ba70c5d14b..065074c944 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -21,6 +21,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include @@ -29,6 +30,8 @@ #include #include "libavcodec/avcodec.h" #include "libavcodec/internal.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_drm.h" #include "v4l2_context.h" #include "v4l2_buffers.h" #include "v4l2_m2m.h" @@ -202,11 +205,14 @@ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf) return AVCOL_TRC_UNSPECIFIED; } -static void v4l2_free_buffer(void *opaque, uint8_t *unused) +static void v4l2_free_buffer(void *opaque, uint8_t *data) { +AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)data; V4L2Buffer* avbuf = opaque; V4L2m2mContext *s = buf_to_m2mctx(avbuf); +av_free(desc); + atomic_fetch_sub_explicit(&s->refcount, 1, memory_order_acq_rel); if (s->reinit) { if (!atomic_load(&s->refcount)) @@ -289,35 +295,15 @@ int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer* out) int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) { V4L2m2mContext *s = buf_to_m2mctx(avbuf); -int i, ret; +AVDRMFrameDescriptor *desc = NULL; +AVDRMLayerDescriptor *layer = NULL; +int ret; av_frame_unref(frame); -/* 1. get references to the actual data */ -for (i = 0; i < avbuf->num_planes; i++) { -ret = v4l2_buf_to_bufref(avbuf, i, &frame->buf[i]); -if (ret) -return ret; - -frame->linesize[i] = avbuf->plane_info[i].bytesperline; -frame->data[i] = frame->buf[i]->data; -} - -/* 1.1 fixup special cases */ -switch (avbuf->context->av_pix_fmt) { -case AV_PIX_FMT_NV12: -if (avbuf->num_planes > 1) -break; -frame->linesize[1] = avbuf->plane_info[0].bytesperline; -frame->data[1] = frame->buf[0]->data + avbuf->plane_info[0].bytesperline * avbuf->context->format.fmt.pix_mp.height; -break; -default: -break; -} - /* 2. get frame information */ frame->key_frame = !!(avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME); -frame->format = avbuf->context->av_pix_fmt; +frame->format = AV_PIX_FMT_DRM_PRIME; frame->color_primaries = v4l2_get_color_primaries(avbuf); frame->colorspace = v4l2_get_color_space(avbuf); frame->color_range = v4l2_get_color_range(avbuf); @@ -328,6 +314,42 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) frame->height = s->output.height; frame->width = s->output.width; +ret = ff_v4l2_buffer_export(avbuf); +if (ret < 0) { +return AVERROR(errno); +} + +desc = av_mallocz(sizeof(AVDRMFrameDescriptor)); +if (!desc) { +return AVERROR(ENOMEM); +} + +desc->nb_objects = 1; + +if (V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type)) { +desc->objects[0].fd = avbuf->buf.m.planes[0].m.fd; +desc->objects[0].size = avbuf->buf.m.planes[0].length; +} else { +desc->objects[0].fd = avbuf->buf.m.fd; +desc->objects[0].size = avbuf->buf.length; +} + +desc->nb_layers = 1; +layer = &desc->layers[0]; +layer->format = DRM_FORMAT_NV12; +layer->nb_planes = 2; + +layer->planes[0].object_index = 0; +layer->planes[0].offset = 0; +layer->planes[0].pitch = avbuf->plane_info[0].bytesperline; + +layer->planes[1].object_index = 0; +layer->planes[1].offset = layer->planes[0].pitch * avbuf->context->format.fmt.pix_mp.height; +layer->planes[1].pitch = avbuf->plane_info[0].bytesperline; + +frame->data[0] = (uint8_t *)desc; +frame->buf[0] = av_buffer_create((uint8_t *)desc, sizeof(*desc), v4l2_free_buffer, avbuf, AV_BUFFER_FLAG_READONLY); + /* 3. report errors upstream */ if (avbuf->buf.flags & V4L2_BUF_FLAG_ERROR) { av_log(logger(avbuf), AV_LOG_ERROR, "%s: driver decode error\n", avbuf->context->name); @@ -461,3 +483,28 @@ int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf) return 0; } + +int ff_v4l2_buffer_export(V4L2Buffer* avbuf) +{ +int i, ret; + +for (i = 0; i < avbuf->num_planes; i++) { + +str
Re: [FFmpeg-devel] [PATCH 2/3] libavcodec/v4l2_buffers: check for valid pts value
Hmm ok, disregard then. On Mon, Jan 8, 2018 at 3:53 PM wm4 wrote: > On Mon, 8 Jan 2018 15:27:38 -0800 > Lukas Rusak wrote: > > > we check for a valid pts in v4l2_set_pts so we should do the same here > > > > --- > > libavcodec/v4l2_buffers.c | 5 - > > 1 file changed, 4 insertions(+), 1 deletion(-) > > > > diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c > > index fdafe7edca..5337f6f287 100644 > > --- a/libavcodec/v4l2_buffers.c > > +++ b/libavcodec/v4l2_buffers.c > > @@ -71,7 +71,10 @@ static inline int64_t v4l2_get_pts(V4L2Buffer *avbuf) > > /* convert pts back to encoder timebase */ > > v4l2_pts = avbuf->buf.timestamp.tv_sec * USEC_PER_SEC + > avbuf->buf.timestamp.tv_usec; > > > > -return av_rescale_q(v4l2_pts, v4l2_timebase, s->avctx->time_base); > > +if (v4l2_pts == 0) > > +return AV_NOPTS_VALUE; > > +else > > +return av_rescale_q(v4l2_pts, v4l2_timebase, > s->avctx->time_base); > > } > > > > static enum AVColorPrimaries v4l2_get_color_primaries(V4L2Buffer *buf) > > So, what about pts=0, which is valid? You shouldn't just turn 0 into > AV_NOPTS_VALUE. > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel > ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH 3/3] libavcodec/v4l2_m2m_dec: set default time base
I'm not really sure what to do then. Should I just replace time_base with pkt_timebase instead? Or Should I just remove the time base rescaling completely in v4l2_set_pts and v4l2_get_pts as it seems to be 1:1 anyways. On Mon, Jan 8, 2018 at 3:45 PM wm4 wrote: > On Mon, 8 Jan 2018 15:27:39 -0800 > Lukas Rusak wrote: > > > This default time base should be set in order for ffmpeg to rescale the > timebase in v4l2_get_pts and v4l2_set_pts > > > > --- > > libavcodec/v4l2_m2m_dec.c | 2 ++ > > 1 file changed, 2 insertions(+) > > > > diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c > > index 8308613978..4de091a011 100644 > > --- a/libavcodec/v4l2_m2m_dec.c > > +++ b/libavcodec/v4l2_m2m_dec.c > > @@ -177,6 +177,8 @@ static av_cold int v4l2_decode_init(AVCodecContext > *avctx) > > capture->av_codec_id = AV_CODEC_ID_RAWVIDEO; > > capture->av_pix_fmt = avctx->pix_fmt; > > > > +avctx->time_base = AV_TIME_BASE_Q; > > + > > ret = ff_v4l2_m2m_codec_init(avctx); > > if (ret) { > > av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n"); > > Decoders in FFmpeg don't really have a concept of a timebase. If they > do, they should not use avctx->time_base, but avctx->pkt_timebase. > > (I don't think avctx->pkt_timebase even needs to be set - API users > normally expect that the decoder simply passes through timestamps, > regardless of timebase. But if pkt_timebase is set, it should be the > same timebase that AVPacket uses, and the output AVFrames must use the > same timebase. > > avctx->time_base doesn't really mean anything for decoding. There is an > obscure "other" use of it that has been deprecated, and the replacement > has the same obscure use (see doxygen). > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel > ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] libavcodec: v4l2m2m: make sure to unref avpkt
This was found using valgrind. Using this patch there is no more memleak present. --- libavcodec/v4l2_m2m_dec.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 598dc10781..710e40efd8 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -149,11 +149,14 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) if (avpkt.size) { ret = v4l2_try_start(avctx); -if (ret) +if (ret) { +av_packet_unref(&avpkt); return 0; +} } dequeue: +av_packet_unref(&avpkt); return ff_v4l2_context_dequeue_frame(capture, frame); } -- 2.17.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 2/4] libavcodec: v4l2m2m: output AVDRMFrameDescriptor
This allows for a zero-copy output by exporting the v4l2 buffer then wrapping that buffer in the AVDRMFrameDescriptor like it is done in rkmpp. This has been in use for quite some time with great success on many platforms including: - Amlogic S905 - Raspberry Pi - i.MX6 - Dragonboard 410c This was developed in conjunction with Kodi to allow handling the zero-copy buffer rendering. A simply utility for testing is also available here: https://github.com/BayLibre/ffmpeg-drm todo: - allow selecting pixel format output from decoder - allow configuring amount of output and capture buffers V2: - allow selecting AV_PIX_FMT_DRM_PRIME V3: - use get_format to select AV_PIX_FMT_DRM_PRIME - use hw_configs - add handling of AV_PIX_FMT_YUV420P format (for raspberry pi) - add handling of AV_PIX_FMT_YUYV422 format (for i.MX6 coda decoder) --- libavcodec/v4l2_buffers.c | 216 -- libavcodec/v4l2_buffers.h | 4 + libavcodec/v4l2_context.c | 40 ++- libavcodec/v4l2_m2m.c | 4 +- libavcodec/v4l2_m2m.h | 3 + libavcodec/v4l2_m2m_dec.c | 23 6 files changed, 253 insertions(+), 37 deletions(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index aef911f3bb..e5c46ac81e 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -21,6 +21,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include @@ -29,6 +30,7 @@ #include #include "libavcodec/avcodec.h" #include "libavcodec/internal.h" +#include "libavutil/hwcontext.h" #include "v4l2_context.h" #include "v4l2_buffers.h" #include "v4l2_m2m.h" @@ -203,7 +205,79 @@ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf) return AVCOL_TRC_UNSPECIFIED; } -static void v4l2_free_buffer(void *opaque, uint8_t *unused) +static uint8_t * v4l2_get_drm_frame(V4L2Buffer *avbuf) +{ +AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame; +AVDRMLayerDescriptor *layer; + +/* fill the DRM frame descriptor */ +drm_desc->nb_objects = avbuf->num_planes; +drm_desc->nb_layers = 1; + +layer = &drm_desc->layers[0]; +layer->nb_planes = avbuf->num_planes; + +for (int i = 0; i < avbuf->num_planes; i++) { +layer->planes[i].object_index = i; +layer->planes[i].offset = 0; +layer->planes[i].pitch = avbuf->plane_info[i].bytesperline; +} + +switch (avbuf->context->av_pix_fmt) { +case AV_PIX_FMT_YUYV422: + +layer->format = DRM_FORMAT_YUYV; +layer->nb_planes = 1; + +break; + +case AV_PIX_FMT_NV12: +case AV_PIX_FMT_NV21: + +layer->format = avbuf->context->av_pix_fmt == AV_PIX_FMT_NV12 ? +DRM_FORMAT_NV12 : DRM_FORMAT_NV21; + +if (avbuf->num_planes > 1) +break; + +layer->nb_planes = 2; + +layer->planes[1].object_index = 0; +layer->planes[1].offset = avbuf->plane_info[0].bytesperline * +avbuf->context->format.fmt.pix.height; +layer->planes[1].pitch = avbuf->plane_info[0].bytesperline; +break; + +case AV_PIX_FMT_YUV420P: + +layer->format = DRM_FORMAT_YUV420; + +if (avbuf->num_planes > 1) +break; + +layer->nb_planes = 3; + +layer->planes[1].object_index = 0; +layer->planes[1].offset = avbuf->plane_info[0].bytesperline * +avbuf->context->format.fmt.pix.height; +layer->planes[1].pitch = avbuf->plane_info[0].bytesperline >> 1; + +layer->planes[2].object_index = 0; +layer->planes[2].offset = layer->planes[1].offset + +((avbuf->plane_info[0].bytesperline * + avbuf->context->format.fmt.pix.height) >> 2); +layer->planes[2].pitch = avbuf->plane_info[0].bytesperline >> 1; +break; + +default: +drm_desc->nb_layers = 0; +break; +} + +return (uint8_t *) drm_desc; +} + +static void v4l2_free_buffer(void *opaque, uint8_t *data) { V4L2Buffer* avbuf = opaque; V4L2m2mContext *s = buf_to_m2mctx(avbuf); @@ -227,27 +301,47 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused) } } -static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) +static int v4l2_buffer_export_drm(V4L2Buffer* avbuf) { -V4L2m2mContext *s = buf_to_m2mctx(in); +struct v4l2_exportbuffer expbuf; +int i, ret; -if (plane >= in->num_planes) -return AVERROR(EINVAL); +for (i = 0; i < avbuf->num_planes; i++) { +memset(&expbuf, 0, sizeof(expbuf)); -/* even though most encoders return 0 in data_offset encoding vp8 does require this value */ -*buf = av_buffer_create((char *)in->plane_info[plane].mm_addr + in->planes[plane].data_offset, -in->plane_info[plane].length, v4l2_free_buffer, in, 0); -if (!*buf) -return AVERROR(ENOMEM); +expbuf.index = avbuf->buf.index; +
[FFmpeg-devel] [PATCH 4/4] libavcodec: v4l2m2m: fix error handling during buffer init
From: Jorge Ramirez-Ortiz Signed-off-by: Jorge Ramirez-Ortiz --- libavcodec/v4l2_context.c | 19 --- libavcodec/v4l2_m2m_dec.c | 9 +++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index 9457fadb1e..fd3161ce2f 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -263,6 +263,12 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) /* if we are draining and there are no more capture buffers queued in the driver we are done */ if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) { for (i = 0; i < ctx->num_buffers; i++) { +/* catpture buffer initialization happens during decode hence + * detection happens at runtime + */ +if (!ctx->buffers) +break; + if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER) goto start; } @@ -724,9 +730,8 @@ int ff_v4l2_context_init(V4L2Context* ctx) ctx->buffers[i].context = ctx; ret = ff_v4l2_buffer_initialize(&ctx->buffers[i], i); if (ret < 0) { -av_log(logger(ctx), AV_LOG_ERROR, "%s buffer initialization (%s)\n", ctx->name, av_err2str(ret)); -av_free(ctx->buffers); -return ret; +av_log(logger(ctx), AV_LOG_ERROR, "%s buffer[%d] initialization (%s)\n", ctx->name, i, av_err2str(ret)); +goto error; } } @@ -739,4 +744,12 @@ int ff_v4l2_context_init(V4L2Context* ctx) V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].bytesperline : ctx->format.fmt.pix.bytesperline); return 0; + +error: +v4l2_release_buffers(ctx); + +av_free(ctx->buffers); +ctx->buffers = NULL; + +return ret; } diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 29d894492f..c4f4f7837f 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -92,8 +92,8 @@ static int v4l2_try_start(AVCodecContext *avctx) if (!capture->buffers) { ret = ff_v4l2_context_init(capture); if (ret) { -av_log(avctx, AV_LOG_DEBUG, "can't request output buffers\n"); -return ret; +av_log(avctx, AV_LOG_ERROR, "can't request capture buffers\n"); +return AVERROR(ENOMEM); } } @@ -157,6 +157,11 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) ret = v4l2_try_start(avctx); if (ret) { av_packet_unref(&avpkt); + +/* cant recover */ +if (ret == AVERROR(ENOMEM)) +return ret; + return 0; } } -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/4] libavcodec: v4l2m2m: fix indentation and add M2MDEC_CLASS
This just makes the M2MDEC_CLASS similar to how it is done in rkmpp. It looks clean and has proper indentation --- libavcodec/v4l2_m2m_dec.c | 46 --- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 710e40efd8..7926e25efa 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -205,29 +205,31 @@ static const AVOption options[] = { { NULL}, }; +#define M2MDEC_CLASS(NAME) \ +static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \ +.class_name = #NAME "_v4l2_m2m_decoder", \ +.item_name = av_default_item_name, \ +.option = options, \ +.version= LIBAVUTIL_VERSION_INT, \ +}; + #define M2MDEC(NAME, LONGNAME, CODEC, bsf_name) \ -static const AVClass v4l2_m2m_ ## NAME ## _dec_class = {\ -.class_name = #NAME "_v4l2_m2m_decoder",\ -.item_name = av_default_item_name,\ -.option = options,\ -.version= LIBAVUTIL_VERSION_INT,\ -};\ -\ -AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \ -.name = #NAME "_v4l2m2m" ,\ -.long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"),\ -.type = AVMEDIA_TYPE_VIDEO,\ -.id = CODEC ,\ -.priv_data_size = sizeof(V4L2m2mPriv),\ -.priv_class = &v4l2_m2m_ ## NAME ## _dec_class,\ -.init = v4l2_decode_init,\ -.receive_frame = v4l2_receive_frame,\ -.close = ff_v4l2_m2m_codec_end,\ -.bsfs = bsf_name, \ -.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | \ - AV_CODEC_CAP_AVOID_PROBING, \ -.wrapper_name = "v4l2m2m", \ -}; +M2MDEC_CLASS(NAME) \ +AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \ +.name = #NAME "_v4l2m2m" , \ +.long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"), \ +.type = AVMEDIA_TYPE_VIDEO, \ +.id = CODEC , \ +.priv_data_size = sizeof(V4L2m2mPriv), \ +.priv_class = &v4l2_m2m_ ## NAME ## _dec_class, \ +.init = v4l2_decode_init, \ +.receive_frame = v4l2_receive_frame, \ +.close = ff_v4l2_m2m_codec_end, \ +.bsfs = bsf_name, \ +.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \ + AV_CODEC_CAP_AVOID_PROBING, \ +.wrapper_name = "v4l2m2m", \ +}; M2MDEC(h264, "H.264", AV_CODEC_ID_H264, "h264_mp4toannexb"); M2MDEC(hevc, "HEVC", AV_CODEC_ID_HEVC, "hevc_mp4toannexb"); -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 3/4] libavcodec: v4l2m2m: adjust formatting
just some simple formatting fixes that unify the code quality --- libavcodec/v4l2_buffers.c | 23 +++ libavcodec/v4l2_buffers.h | 1 - 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index e5c46ac81e..897c3c4636 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -401,7 +401,8 @@ static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, i bytesused = FFMIN(size, out->plane_info[plane].length); length = out->plane_info[plane].length; -memcpy(out->plane_info[plane].mm_addr, data, FFMIN(size, out->plane_info[plane].length)); +memcpy(out->plane_info[plane].mm_addr, data, + FFMIN(size, out->plane_info[plane].length)); if (V4L2_TYPE_IS_MULTIPLANAR(out->buf.type)) { out->planes[plane].bytesused = bytesused; @@ -425,7 +426,10 @@ int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer* out) int i, ret; for(i = 0; i < out->num_planes; i++) { -ret = v4l2_bufref_to_buf(out, i, frame->buf[i]->data, frame->buf[i]->size, frame->buf[i]); +ret = v4l2_bufref_to_buf(out, i, +frame->buf[i]->data, +frame->buf[i]->size, +frame->buf[i]); if (ret) return ret; } @@ -480,8 +484,8 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) /* 2. get frame information */ frame->key_frame = !!(avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME); frame->color_primaries = v4l2_get_color_primaries(avbuf); -frame->colorspace = v4l2_get_color_space(avbuf); frame->color_range = v4l2_get_color_range(avbuf); +frame->colorspace = v4l2_get_color_space(avbuf); frame->color_trc = v4l2_get_color_trc(avbuf); frame->pts = v4l2_get_pts(avbuf); @@ -507,7 +511,8 @@ int ff_v4l2_buffer_buf_to_avpkt(AVPacket *pkt, V4L2Buffer *avbuf) if (ret) return ret; -pkt->size = V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type) ? avbuf->buf.m.planes[0].bytesused : avbuf->buf.bytesused; +pkt->size = V4L2_TYPE_IS_MULTIPLANAR(avbuf->buf.type) ? +avbuf->buf.m.planes[0].bytesused : avbuf->buf.bytesused; pkt->data = pkt->buf->data; if (avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME) @@ -563,6 +568,7 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) /* in MP, the V4L2 API states that buf.length means num_planes */ if (avbuf->num_planes >= avbuf->buf.length) break; + if (avbuf->buf.m.planes[avbuf->num_planes].length) avbuf->num_planes++; } @@ -579,12 +585,14 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) avbuf->plane_info[i].length = avbuf->buf.m.planes[i].length; avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.m.planes[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, - buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.planes[i].m.mem_offset); + buf_to_m2mctx(avbuf)->fd, + avbuf->buf.m.planes[i].m.mem_offset); } else { avbuf->plane_info[i].length = avbuf->buf.length; avbuf->plane_info[i].mm_addr = mmap(NULL, avbuf->buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, - buf_to_m2mctx(avbuf)->fd, avbuf->buf.m.offset); + buf_to_m2mctx(avbuf)->fd, + avbuf->buf.m.offset); } if (avbuf->plane_info[i].mm_addr == MAP_FAILED) @@ -594,9 +602,8 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) avbuf->status = V4L2BUF_AVAILABLE; if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { -avbuf->buf.m.planes = avbuf->planes; avbuf->buf.length = avbuf->num_planes; - +avbuf->buf.m.planes = avbuf->planes; } else { avbuf->buf.bytesused = avbuf->planes[0].bytesused; avbuf->buf.length= avbuf->planes[0].length; diff --git a/libavcodec/v4l2_buffers.h b/libavcodec/v4l2_buffers.h index a8a50ecc65..c609a6c676 100644 --- a/libavcodec/v4l2_buffers.h +++ b/libavcodec/v4l2_buffers.h @@ -131,5 +131,4 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index); */ int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf); - #endif // AVCODEC_V4L2_BUFFERS_H -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH 2/4] libavcodec: v4l2m2m: output AVDRMFrameDescriptor
On Sat, 2018-08-04 at 22:43 +0100, Mark Thompson wrote: > On 04/08/18 01:40, Lukas Rusak wrote: > > This allows for a zero-copy output by exporting the v4l2 buffer > > then wrapping that buffer > > in the AVDRMFrameDescriptor like it is done in rkmpp. > > > > This has been in use for quite some time with great success on many > > platforms including: > > - Amlogic S905 > > - Raspberry Pi > > - i.MX6 > > - Dragonboard 410c > > > > This was developed in conjunction with Kodi to allow handling the > > zero-copy buffer rendering. > > A simply utility for testing is also available here: > > https://github.com/BayLibre/ffmpeg-drm > > > > todo: > > - allow selecting pixel format output from decoder > > - allow configuring amount of output and capture buffers > > > > V2: > > - allow selecting AV_PIX_FMT_DRM_PRIME > > > > V3: > > - use get_format to select AV_PIX_FMT_DRM_PRIME > > - use hw_configs > > - add handling of AV_PIX_FMT_YUV420P format (for raspberry pi) > > - add handling of AV_PIX_FMT_YUYV422 format (for i.MX6 coda > > decoder) > > --- > > libavcodec/v4l2_buffers.c | 216 > > -- > > libavcodec/v4l2_buffers.h | 4 + > > libavcodec/v4l2_context.c | 40 ++- > > libavcodec/v4l2_m2m.c | 4 +- > > libavcodec/v4l2_m2m.h | 3 + > > libavcodec/v4l2_m2m_dec.c | 23 > > 6 files changed, 253 insertions(+), 37 deletions(-) > > The v4l2_m2m decoders need to depend on libdrm in configure for > this. (And if you don't want that as a hard dependency then you'll > need #ifdefs everywhere.) Yes, I'll update the patch to include libdrm > > > diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c > > index aef911f3bb..e5c46ac81e 100644 > > --- a/libavcodec/v4l2_buffers.c > > +++ b/libavcodec/v4l2_buffers.c > > @@ -21,6 +21,7 @@ > > * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > > 02110-1301 USA > > */ > > > > +#include > > Don't include the outer path, pkg-config deals with it. (The path > you've picked is wrong for a default install of current libdrm.) > I'll fix that. Thanks! > > #include > > #include > > #include > > @@ -29,6 +30,7 @@ > > #include > > #include "libavcodec/avcodec.h" > > #include "libavcodec/internal.h" > > +#include "libavutil/hwcontext.h" > > #include "v4l2_context.h" > > #include "v4l2_buffers.h" > > #include "v4l2_m2m.h" > > @@ -203,7 +205,79 @@ static enum AVColorTransferCharacteristic > > v4l2_get_color_trc(V4L2Buffer *buf) > > return AVCOL_TRC_UNSPECIFIED; > > } > > > > -static void v4l2_free_buffer(void *opaque, uint8_t *unused) > > +static uint8_t * v4l2_get_drm_frame(V4L2Buffer *avbuf) > > +{ > > +AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame; > > +AVDRMLayerDescriptor *layer; > > + > > +/* fill the DRM frame descriptor */ > > +drm_desc->nb_objects = avbuf->num_planes; > > +drm_desc->nb_layers = 1; > > + > > +layer = &drm_desc->layers[0]; > > +layer->nb_planes = avbuf->num_planes; > > + > > +for (int i = 0; i < avbuf->num_planes; i++) { > > +layer->planes[i].object_index = i; > > +layer->planes[i].offset = 0; > > +layer->planes[i].pitch = avbuf- > > >plane_info[i].bytesperline; > > +} > > + > > +switch (avbuf->context->av_pix_fmt) { > > +case AV_PIX_FMT_YUYV422: > > + > > +layer->format = DRM_FORMAT_YUYV; > > +layer->nb_planes = 1; > > + > > +break; > > + > > +case AV_PIX_FMT_NV12: > > +case AV_PIX_FMT_NV21: > > + > > +layer->format = avbuf->context->av_pix_fmt == > > AV_PIX_FMT_NV12 ? > > +DRM_FORMAT_NV12 : DRM_FORMAT_NV21; > > + > > +if (avbuf->num_planes > 1) > > +break; > > + > > +layer->nb_planes = 2; > > + > > +layer->planes[1].object_index = 0; > > +layer->planes[1].offset = avbuf- > > >plane_info[0].bytesperline * > > +avbuf->context->format.fmt.pix.height; > > +layer->planes[1].pitch = avbuf- > > >plane_info[0].bytesperline; > > To confirm, it's necessarily true tha
Re: [FFmpeg-devel] [PATCH 2/4] libavcodec: v4l2m2m: output AVDRMFrameDescriptor
Just an FYI i will be developing here if anyone wants to comment and/or PR other changes for V4. https://github.com/lrusak/FFmpeg/commits/v4l2-drmprime-v4 > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel