On 03/09/2019 02:02, Aman Gupta wrote:
> From: Aman Gupta <a...@tmm1.net>
> 
> Based on patchset submitted to ffmpeg-devel by Lukas Rusak <loru...@gmail.com>
> 
> Signed-off-by: Aman Gupta <a...@tmm1.net>
> ---
>  libavcodec/v4l2_m2m_dec.c | 85 ++++++++++++++++++++++++++++++++++++---
>  1 file changed, 80 insertions(+), 5 deletions(-)
> 
> diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
> index a3744208f3..6b73d2ffd9 100644
> --- a/libavcodec/v4l2_m2m_dec.c
> +++ b/libavcodec/v4l2_m2m_dec.c
> @@ -23,11 +23,16 @@
>  
>  #include <linux/videodev2.h>
>  #include <sys/ioctl.h>
> +
> +#include "libavutil/hwcontext.h"
> +#include "libavutil/hwcontext_drm.h"
>  #include "libavutil/pixfmt.h"
>  #include "libavutil/pixdesc.h"
>  #include "libavutil/opt.h"
>  #include "libavcodec/avcodec.h"
>  #include "libavcodec/decode.h"
> +#include "libavcodec/hwaccel.h"
> +#include "libavcodec/internal.h"
>  
>  #include "v4l2_context.h"
>  #include "v4l2_m2m.h"
> @@ -39,7 +44,7 @@ static int v4l2_try_start(AVCodecContext *avctx)
>      V4L2Context *const capture = &s->capture;
>      V4L2Context *const output = &s->output;
>      struct v4l2_selection selection;
> -    int ret;
> +    int ret, pix_fmt;
>  
>      /* 1. start the output process */
>      if (!output->streamon) {
> @@ -62,8 +67,13 @@ static int v4l2_try_start(AVCodecContext *avctx)
>      }
>  
>      /* 2.1 update the AVCodecContext */
> -    avctx->pix_fmt = 
> ff_v4l2_format_v4l2_to_avfmt(capture->format.fmt.pix_mp.pixelformat, 
> AV_CODEC_ID_RAWVIDEO);
> +    pix_fmt = 
> ff_v4l2_format_v4l2_to_avfmt(capture->format.fmt.pix_mp.pixelformat, 
> AV_CODEC_ID_RAWVIDEO);
> +    if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME)
> +        avctx->pix_fmt = pix_fmt;
> +    else
> +        avctx->sw_pix_fmt = pix_fmt;
>      capture->av_pix_fmt = avctx->pix_fmt;
> +    capture->sw_pix_fmt = avctx->sw_pix_fmt;
>  
>      /* 3. set the crop parameters */
>      selection.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> @@ -189,15 +199,42 @@ static av_cold int v4l2_decode_init(AVCodecContext 
> *avctx)
>      output->av_codec_id = avctx->codec_id;
>      output->av_pix_fmt  = AV_PIX_FMT_NONE;
>  
> +    /* negotiate drm vs software pixel formats */
> +    avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);

The codec array allows choice between NV12 and YUV420P, but probably only one 
of those is actually supported?  You need to make this array with the 
actually-supported format.

Do all V4L2 M2M devices necessarily support VIDIOC_EXPBUF?

> +    switch (avctx->pix_fmt) {
> +    case AV_PIX_FMT_DRM_PRIME:
> +        avctx->sw_pix_fmt = AV_PIX_FMT_NV12;

The previous patch strongly suggests that this is not always true.

> +        break;
> +
> +    case AV_PIX_FMT_NONE:
> +        return 0;

I think this should be an error code - zero indicates success.

> +        break;
> +
> +    default:
> +        break;
> +    }
> +
>      capture->av_codec_id = AV_CODEC_ID_RAWVIDEO;
>      capture->av_pix_fmt = avctx->pix_fmt;
> +    capture->sw_pix_fmt = avctx->sw_pix_fmt;
> +
> +    if (avctx->hw_device_ctx) {
> +        s->device_ref = av_buffer_ref(avctx->hw_device_ctx);
> +    } else {
> +        s->device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
> +        if (!s->device_ref)
> +            return AVERROR(ENOMEM);
> +
> +        ret = av_hwdevice_ctx_init(s->device_ref);
> +        if (ret < 0) {
> +            av_buffer_unref(&s->device_ref);
> +            return ret;
> +        }
> +    }
>  
>      ret = ff_v4l2_m2m_codec_init(priv);
>      if (ret) {
>          av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n");
> -        s->self_ref = NULL;
> -        av_buffer_unref(&priv->context_ref);
> -
>          return ret;
>      }
>      s->avctx = avctx;
> @@ -210,6 +247,25 @@ static av_cold int v4l2_decode_close(AVCodecContext 
> *avctx)
>      return ff_v4l2_m2m_codec_end(avctx->priv_data);
>  }
>  
> +static void v4l2_flush(AVCodecContext *avctx)
> +{
> +    V4L2m2mPriv *priv = avctx->priv_data;
> +    V4L2m2mContext* s = priv->context;
> +    int ret;
> +
> +    /* wait for pending buffer references */
> +    if (atomic_load(&s->refcount))
> +        while(sem_wait(&s->refsync) == -1 && errno == EINTR);
> +
> +    ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF);
> +    if (ret)
> +        av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name);
> +
> +    ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF);
> +    if (ret)
> +        av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", 
> s->capture.name);
> +}
> +
>  #define OFFSET(x) offsetof(V4L2m2mPriv, x)
>  #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
>  
> @@ -220,6 +276,19 @@ static const AVOption options[] = {
>      { NULL},
>  };
>  
> +static const AVCodecHWConfigInternal *v4l2_m2m_hw_configs[] = {
> +    &(const AVCodecHWConfigInternal) {
> +        .public = {
> +            .pix_fmt     = AV_PIX_FMT_DRM_PRIME,
> +            .methods     = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX |
> +                           AV_CODEC_HW_CONFIG_METHOD_INTERNAL,
> +            .device_type = AV_HWDEVICE_TYPE_DRM

The external device doesn't do anything here - this should just be 
METHOD_INTERNAL and not offer a device type.

(The device is always guessed inside the code, I suppose with the assumption 
that no system will ever have two decoders.  Possibly some sort of V4L2 device 
would make sense for proper selection, though I'm not sure how that would work.)

> +        },
> +        .hwaccel = NULL,
> +    },
> +    NULL
> +};
> +
>  #define M2MDEC_CLASS(NAME) \
>      static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \
>          .class_name = #NAME "_v4l2m2m_decoder", \
> @@ -240,7 +309,13 @@ static const AVOption options[] = {
>          .init           = v4l2_decode_init, \
>          .receive_frame  = v4l2_receive_frame, \
>          .close          = v4l2_decode_close, \
> +        .flush          = v4l2_flush, \
> +        .pix_fmts       = (const enum AVPixelFormat[]) { 
> AV_PIX_FMT_DRM_PRIME, \
> +                                                         AV_PIX_FMT_NV12, \
> +                                                         AV_PIX_FMT_YUV420P, 
> \
> +                                                         AV_PIX_FMT_NONE}, \

As above, this is likely to be wrong.  It's probably better to leave this empty 
like other decoders which don't have a fixed format.

>          .bsfs           = bsf_name, \
> +        .hw_configs     = v4l2_m2m_hw_configs, \
>          .capabilities   = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | 
> AV_CODEC_CAP_AVOID_PROBING, \
>          .caps_internal  = FF_CODEC_CAP_SETS_PKT_DTS, \
>          .wrapper_name   = "v4l2m2m", \
> 

- Mark
_______________________________________________
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".

Reply via email to