[FFmpeg-devel] [PATCH 16/25] avcodec/v4l2_m2m_dec: add support for AV_PIX_FMT_DRM_PRIME
Aman Gupta
ffmpeg at tmm1.net
Tue Sep 3 04:02:21 EEST 2019
From: Aman Gupta <aman at tmm1.net>
Based on patchset submitted to ffmpeg-devel by Lukas Rusak <lorusak at gmail.com>
Signed-off-by: Aman Gupta <aman at 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);
+ switch (avctx->pix_fmt) {
+ case AV_PIX_FMT_DRM_PRIME:
+ avctx->sw_pix_fmt = AV_PIX_FMT_NV12;
+ break;
+
+ case AV_PIX_FMT_NONE:
+ return 0;
+ 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
+ },
+ .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}, \
.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", \
--
2.20.1
More information about the ffmpeg-devel
mailing list