[packages/ffmpeg/ffmpeg-4.4] sync v4l2 request api patch with libreelec

atler atler at pld-linux.org
Mon Jul 18 20:45:04 CEST 2022


commit 6ae8eacc00806dd3dc20177de8dfc2038e5ee13b
Author: Jan Palus <jpalus at fastmail.com>
Date:   Mon Jul 18 20:41:21 2022 +0200

    sync v4l2 request api patch with libreelec
    
    - adds support for mpeg2/vp8/vp9 hardware decoding
    - still drop hevc patches until hevc uapi is stabilized (on its way
      towards upstream, likely for kernel 5.20)

 v4l2-request-hwdec.patch | 1725 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 1657 insertions(+), 68 deletions(-)
---
diff --git a/v4l2-request-hwdec.patch b/v4l2-request-hwdec.patch
index bac2e9b..d56c083 100644
--- a/v4l2-request-hwdec.patch
+++ b/v4l2-request-hwdec.patch
@@ -1,7 +1,7 @@
-From 5e154b0357829007566930846f880b9f5fb404d9 Mon Sep 17 00:00:00 2001
+From 904af26693095364851bbc6c6557fca9b3437b69 Mon Sep 17 00:00:00 2001
 From: Jonas Karlman <jonas at kwiboo.se>
 Date: Mon, 3 Dec 2018 23:48:04 +0100
-Subject: [PATCH] avutil: add av_buffer_pool_flush()
+Subject: [PATCH 01/17] avutil: add av_buffer_pool_flush()
 
 Used by V4L2 request API hwaccel
 
@@ -12,10 +12,10 @@ Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
  2 files changed, 18 insertions(+)
 
 diff --git a/libavutil/buffer.c b/libavutil/buffer.c
-index 38a554208a90..b0fedabc3e7d 100644
+index 858633e8c73..41555d99825 100644
 --- a/libavutil/buffer.c
 +++ b/libavutil/buffer.c
-@@ -273,6 +273,19 @@ static void buffer_pool_free(AVBufferPool *pool)
+@@ -305,6 +305,19 @@ static void buffer_pool_free(AVBufferPool *pool)
      av_freep(&pool);
  }
  
@@ -36,10 +36,10 @@ index 38a554208a90..b0fedabc3e7d 100644
  {
      AVBufferPool *pool;
 diff --git a/libavutil/buffer.h b/libavutil/buffer.h
-index c0f3f6cc9abe..998beec9ac5b 100644
+index 241a80ed670..f41363faf1d 100644
 --- a/libavutil/buffer.h
 +++ b/libavutil/buffer.h
-@@ -267,6 +267,11 @@ AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
+@@ -315,6 +315,11 @@ AVBufferPool *av_buffer_pool_init2(size_t size, void *opaque,
  #endif
                                     void (*pool_free)(void *opaque));
  
@@ -51,10 +51,11 @@ index c0f3f6cc9abe..998beec9ac5b 100644
  /**
   * Mark the pool as being available for freeing. It will actually be freed only
   * once all the allocated buffers associated with the pool are released. Thus it
-From 01319970d90ffd3c073b054a3d2e4784f6ebea0d Mon Sep 17 00:00:00 2001
+
+From ec84dc22e99f544e4de7c43e7f8ef9ab7ee8e19b Mon Sep 17 00:00:00 2001
 From: Jonas Karlman <jonas at kwiboo.se>
 Date: Sat, 15 Dec 2018 22:32:16 +0100
-Subject: [PATCH] Add common V4L2 request API code
+Subject: [PATCH 02/17] Add common V4L2 request API code
 
 Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
 ---
@@ -68,18 +69,18 @@ Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
  create mode 100644 libavcodec/v4l2_request.h
 
 diff --git a/configure b/configure
-index 8569a60bf827..9f9909a23696 100755
+index d7a3f507e83..f2e203d1346 100755
 --- a/configure
 +++ b/configure
-@@ -274,6 +274,7 @@ External library support:
-   --enable-libtls          enable LibreSSL (via libtls), needed for https support
+@@ -279,6 +279,7 @@ External library support:
                             if openssl, gnutls or mbedtls is not used [no]
    --enable-libtwolame      enable MP2 encoding via libtwolame [no]
-+  --enable-libudev         enable libudev [no]
    --enable-libuavs3d       enable AVS3 decoding via libuavs3d [no]
++  --enable-libudev         enable libudev [no]
    --enable-libv4l2         enable libv4l2/v4l-utils [no]
    --enable-libvidstab      enable video stabilization using vid.stab [no]
-@@ -342,6 +343,7 @@ External library support:
+   --enable-libvmaf         enable vmaf filter via libvmaf [no]
+@@ -346,6 +347,7 @@ External library support:
    --enable-omx-rpi         enable OpenMAX IL code for Raspberry Pi [no]
    --enable-rkmpp           enable Rockchip Media Process Platform code [no]
    --disable-v4l2-m2m       disable V4L2 mem2mem code [autodetect]
@@ -87,15 +88,15 @@ index 8569a60bf827..9f9909a23696 100755
    --disable-vaapi          disable Video Acceleration API (mainly Unix/Intel) code [autodetect]
    --disable-vdpau          disable Nvidia Video Decode and Presentation API for Unix code [autodetect]
    --disable-videotoolbox   disable VideoToolbox code [autodetect]
-@@ -1807,6 +1809,7 @@ EXTERNAL_LIBRARY_LIST="
-     libtesseract
+@@ -1814,6 +1816,7 @@ EXTERNAL_LIBRARY_LIST="
      libtheora
      libtwolame
-+    libudev
      libuavs3d
++    libudev
      libv4l2
      libvmaf
-@@ -1861,6 +1864,7 @@ HWACCEL_LIBRARY_LIST="
+     libvorbis
+@@ -1868,6 +1871,7 @@ HWACCEL_LIBRARY_LIST="
      mmal
      omx
      opencl
@@ -103,7 +104,7 @@ index 8569a60bf827..9f9909a23696 100755
      vulkan
  "
  
-@@ -2903,6 +2907,7 @@ d3d11va_deps="dxva_h ID3D11VideoDecoder ID3D11VideoContext"
+@@ -2919,6 +2923,7 @@ d3d11va_deps="dxva_h ID3D11VideoDecoder ID3D11VideoContext"
  dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32"
  ffnvcodec_deps_any="libdl LoadLibrary"
  nvdec_deps="ffnvcodec"
@@ -111,15 +112,15 @@ index 8569a60bf827..9f9909a23696 100755
  vaapi_x11_deps="xlib"
  videotoolbox_hwaccel_deps="videotoolbox pthreads"
  videotoolbox_hwaccel_extralibs="-framework QuartzCore"
-@@ -6376,6 +6381,7 @@ enabled libtls            && require_pkg_config libtls libtls tls.h tls_configur
- enabled libtwolame        && require libtwolame twolame.h twolame_init -ltwolame &&
+@@ -6438,6 +6443,7 @@ enabled libtwolame        && require libtwolame twolame.h twolame_init -ltwolame
                               { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame ||
                                 die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; }
-+enabled libudev           && require_pkg_config libudev libudev libudev.h udev_new
  enabled libuavs3d         && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode
++enabled libudev           && require_pkg_config libudev libudev libudev.h udev_new
  enabled libv4l2           && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl
  enabled libvidstab        && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit
-@@ -6475,6 +6481,10 @@ enabled rkmpp             && { require_pkg_config rkmpp rockchip_mpp  rockchip/r
+ enabled libvmaf           && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf
+@@ -6536,6 +6542,10 @@ enabled rkmpp             && { require_pkg_config rkmpp rockchip_mpp  rockchip/r
                                 { enabled libdrm ||
                                   die "ERROR: rkmpp requires --enable-libdrm"; }
                               }
@@ -130,7 +131,7 @@ index 8569a60bf827..9f9909a23696 100755
  enabled vapoursynth       && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init
  
  
-@@ -6556,6 +6566,8 @@ if enabled v4l2_m2m; then
+@@ -6617,6 +6627,8 @@ if enabled v4l2_m2m; then
      check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;"
  fi
  
@@ -140,10 +141,10 @@ index 8569a60bf827..9f9909a23696 100755
  test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
  
 diff --git a/libavcodec/Makefile b/libavcodec/Makefile
-index 5a6ea59715af..d74220516826 100644
+index 33a280cf695..90dfffcb200 100644
 --- a/libavcodec/Makefile
 +++ b/libavcodec/Makefile
-@@ -153,6 +153,7 @@ OBJS-$(CONFIG_VP3DSP)                  += vp3dsp.o
+@@ -155,6 +155,7 @@ OBJS-$(CONFIG_VP3DSP)                  += vp3dsp.o
  OBJS-$(CONFIG_VP56DSP)                 += vp56dsp.o
  OBJS-$(CONFIG_VP8DSP)                  += vp8dsp.o
  OBJS-$(CONFIG_V4L2_M2M)                += v4l2_m2m.o v4l2_context.o v4l2_buffers.o v4l2_fmt.o
@@ -152,7 +153,7 @@ index 5a6ea59715af..d74220516826 100644
  OBJS-$(CONFIG_WMV2DSP)                 += wmv2dsp.o
  
 diff --git a/libavcodec/hwconfig.h b/libavcodec/hwconfig.h
-index f421dc909f44..ee78d8ab8e89 100644
+index f421dc909f4..ee78d8ab8e8 100644
 --- a/libavcodec/hwconfig.h
 +++ b/libavcodec/hwconfig.h
 @@ -80,6 +80,8 @@ typedef struct AVCodecHWConfigInternal {
@@ -166,7 +167,7 @@ index f421dc909f44..ee78d8ab8e89 100644
      &(const AVCodecHWConfigInternal) { \
 diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
 new file mode 100644
-index 000000000000..5234b5049b0d
+index 00000000000..5234b5049b0
 --- /dev/null
 +++ b/libavcodec/v4l2_request.c
 @@ -0,0 +1,984 @@
@@ -1156,7 +1157,7 @@ index 000000000000..5234b5049b0d
 +}
 diff --git a/libavcodec/v4l2_request.h b/libavcodec/v4l2_request.h
 new file mode 100644
-index 000000000000..58d2aa70af80
+index 00000000000..58d2aa70af8
 --- /dev/null
 +++ b/libavcodec/v4l2_request.h
 @@ -0,0 +1,77 @@
@@ -1237,10 +1238,11 @@ index 000000000000..58d2aa70af80
 +int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx);
 +
 +#endif /* AVCODEC_V4L2_REQUEST_H */
-From a0a5b816593e3911aeedd201baa8057b64a89a39 Mon Sep 17 00:00:00 2001
+
+From e432d3151f4c5507e40fb1fe8b3c3fb7c7a0a08c Mon Sep 17 00:00:00 2001
 From: Ezequiel Garcia <ezequiel at collabora.com>
 Date: Wed, 20 Feb 2019 11:18:00 -0300
-Subject: [PATCH] h264dec: add idr_pic_id to slice context
+Subject: [PATCH 03/17] h264dec: add idr_pic_id to slice context
 
 Used by V4L2 request API h264 hwaccel
 
@@ -1252,10 +1254,10 @@ Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
  2 files changed, 2 insertions(+), 1 deletion(-)
 
 diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
-index db8363e4cc98..a19635a23d44 100644
+index 2d0605c7f4f..c3a7338a704 100644
 --- a/libavcodec/h264_slice.c
 +++ b/libavcodec/h264_slice.c
-@@ -1818,7 +1818,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
+@@ -1830,7 +1830,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
      }
  
      if (nal->type == H264_NAL_IDR_SLICE)
@@ -1265,10 +1267,10 @@ index db8363e4cc98..a19635a23d44 100644
      sl->poc_lsb = 0;
      sl->delta_poc_bottom = 0;
 diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h
-index a419615124b2..316dc6a2c890 100644
+index b7b19ba4f16..0698ab95ba5 100644
 --- a/libavcodec/h264dec.h
 +++ b/libavcodec/h264dec.h
-@@ -335,6 +335,7 @@ typedef struct H264SliceContext {
+@@ -336,6 +336,7 @@ typedef struct H264SliceContext {
      int delta_poc[2];
      int curr_pic_num;
      int max_pic_num;
@@ -1276,11 +1278,12 @@ index a419615124b2..316dc6a2c890 100644
  } H264SliceContext;
  
  /**
-From 6349ae1e10d1b68c47c3b883b27567f9678c6e0c Mon Sep 17 00:00:00 2001
+
+From 84564d13ec0ec40f408622ff6b0d900723bbab5b Mon Sep 17 00:00:00 2001
 From: Boris Brezillon <boris.brezillon at collabora.com>
 Date: Wed, 22 May 2019 14:44:22 +0200
-Subject: [PATCH] h264dec: add ref_pic_marking and pic_order_cnt bit_size to
- slice context
+Subject: [PATCH 04/17] h264dec: add ref_pic_marking and pic_order_cnt bit_size
+ to slice context
 
 Used by V4L2 request API h264 hwaccel
 
@@ -1292,10 +1295,10 @@ Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
  2 files changed, 7 insertions(+), 1 deletion(-)
 
 diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
-index a19635a23d44..5a5ceb09352c 100644
+index c3a7338a704..c28b58cd5d9 100644
 --- a/libavcodec/h264_slice.c
 +++ b/libavcodec/h264_slice.c
-@@ -1736,7 +1736,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
+@@ -1748,7 +1748,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
      unsigned int slice_type, tmp, i;
      int field_pic_flag, bottom_field_flag;
      int first_slice = sl == h->slice_ctx && !h->current_slice;
@@ -1304,7 +1307,7 @@ index a19635a23d44..5a5ceb09352c 100644
  
      if (first_slice)
          av_assert0(!h->setup_finished);
-@@ -1820,6 +1820,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
+@@ -1832,6 +1832,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
      if (nal->type == H264_NAL_IDR_SLICE)
          sl->idr_pic_id = get_ue_golomb_long(&sl->gb);
  
@@ -1312,7 +1315,7 @@ index a19635a23d44..5a5ceb09352c 100644
      sl->poc_lsb = 0;
      sl->delta_poc_bottom = 0;
      if (sps->poc_type == 0) {
-@@ -1833,6 +1834,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
+@@ -1845,6 +1846,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
          if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME)
              sl->delta_poc[1] = get_se_golomb(&sl->gb);
      }
@@ -1320,7 +1323,7 @@ index a19635a23d44..5a5ceb09352c 100644
  
      sl->redundant_pic_count = 0;
      if (pps->redundant_pic_cnt_present)
-@@ -1872,9 +1874,11 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
+@@ -1884,9 +1886,11 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
  
      sl->explicit_ref_marking = 0;
      if (nal->ref_idc) {
@@ -1333,10 +1336,10 @@ index a19635a23d44..5a5ceb09352c 100644
  
      if (sl->slice_type_nos != AV_PICTURE_TYPE_I && pps->cabac) {
 diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h
-index 316dc6a2c890..f2cabac468d0 100644
+index 0698ab95ba5..2b39e82c3b0 100644
 --- a/libavcodec/h264dec.h
 +++ b/libavcodec/h264dec.h
-@@ -328,6 +328,7 @@ typedef struct H264SliceContext {
+@@ -329,6 +329,7 @@ typedef struct H264SliceContext {
      MMCO mmco[MAX_MMCO_COUNT];
      int  nb_mmco;
      int explicit_ref_marking;
@@ -1344,7 +1347,7 @@ index 316dc6a2c890..f2cabac468d0 100644
  
      int frame_num;
      int poc_lsb;
-@@ -336,6 +337,7 @@ typedef struct H264SliceContext {
+@@ -337,6 +338,7 @@ typedef struct H264SliceContext {
      int curr_pic_num;
      int max_pic_num;
      int idr_pic_id;
@@ -1352,10 +1355,11 @@ index 316dc6a2c890..f2cabac468d0 100644
  } H264SliceContext;
  
  /**
-From 650875c24687c35290b2393ef39f77074ca49813 Mon Sep 17 00:00:00 2001
+
+From 5a8628cf6368fe18457d02bf551d5935609efab5 Mon Sep 17 00:00:00 2001
 From: Jernej Skrabec <jernej.skrabec at siol.net>
 Date: Sat, 15 Dec 2018 22:32:16 +0100
-Subject: [PATCH] Add V4L2 request API h264 hwaccel
+Subject: [PATCH 05/17] Add V4L2 request API h264 hwaccel
 
 Signed-off-by: Jernej Skrabec <jernej.skrabec at siol.net>
 Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
@@ -1370,19 +1374,19 @@ Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
  create mode 100644 libavcodec/v4l2_request_h264.c
 
 diff --git a/configure b/configure
-index 9f9909a23696..293d0447f683 100755
+index f2e203d1346..b17e4108c1b 100755
 --- a/configure
 +++ b/configure
-@@ -2925,6 +2925,8 @@ h264_dxva2_hwaccel_deps="dxva2"
+@@ -2951,6 +2951,8 @@ h264_dxva2_hwaccel_deps="dxva2"
  h264_dxva2_hwaccel_select="h264_decoder"
  h264_nvdec_hwaccel_deps="nvdec"
  h264_nvdec_hwaccel_select="h264_decoder"
-+h264_v4l2request_hwaccel_deps="v4l2_request"
++h264_v4l2request_hwaccel_deps="v4l2_request h264_v4l2_request"
 +h264_v4l2request_hwaccel_select="h264_decoder"
  h264_vaapi_hwaccel_deps="vaapi"
  h264_vaapi_hwaccel_select="h264_decoder"
  h264_vdpau_hwaccel_deps="vdpau"
-@@ -6567,6 +6569,7 @@ if enabled v4l2_m2m; then
+@@ -6628,6 +6630,7 @@ if enabled v4l2_m2m; then
  fi
  
  check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
@@ -1391,10 +1395,10 @@ index 9f9909a23696..293d0447f683 100755
  check_headers sys/videoio.h
  test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
 diff --git a/libavcodec/Makefile b/libavcodec/Makefile
-index d74220516826..4f6e7fc2515c 100644
+index 90dfffcb200..426c7528e90 100644
 --- a/libavcodec/Makefile
 +++ b/libavcodec/Makefile
-@@ -903,6 +903,7 @@ OBJS-$(CONFIG_H264_D3D11VA_HWACCEL)       += dxva2_h264.o
+@@ -935,6 +935,7 @@ OBJS-$(CONFIG_H264_D3D11VA_HWACCEL)       += dxva2_h264.o
  OBJS-$(CONFIG_H264_DXVA2_HWACCEL)         += dxva2_h264.o
  OBJS-$(CONFIG_H264_NVDEC_HWACCEL)         += nvdec_h264.o
  OBJS-$(CONFIG_H264_QSV_HWACCEL)           += qsvdec.o
@@ -1403,10 +1407,10 @@ index d74220516826..4f6e7fc2515c 100644
  OBJS-$(CONFIG_H264_VDPAU_HWACCEL)         += vdpau_h264.o
  OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL)  += videotoolbox.o
 diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
-index 5a5ceb09352c..4ed267317184 100644
+index c28b58cd5d9..0a10d00aad9 100644
 --- a/libavcodec/h264_slice.c
 +++ b/libavcodec/h264_slice.c
-@@ -759,6 +759,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
+@@ -768,6 +768,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
  #define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \
                       (CONFIG_H264_D3D11VA_HWACCEL * 2) + \
                       CONFIG_H264_NVDEC_HWACCEL + \
@@ -1414,7 +1418,7 @@ index 5a5ceb09352c..4ed267317184 100644
                       CONFIG_H264_VAAPI_HWACCEL + \
                       CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \
                       CONFIG_H264_VDPAU_HWACCEL)
-@@ -843,6 +844,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
+@@ -852,6 +853,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
  #endif
  #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL
              *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
@@ -1425,10 +1429,10 @@ index 5a5ceb09352c..4ed267317184 100644
              if (h->avctx->codec->pix_fmts)
                  choices = h->avctx->codec->pix_fmts;
 diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
-index 5eedeb3c275d..a504c89565c7 100644
+index 0a999bef43d..d78e3eaee3a 100644
 --- a/libavcodec/h264dec.c
 +++ b/libavcodec/h264dec.c
-@@ -1102,6 +1102,9 @@ AVCodec ff_h264_decoder = {
+@@ -1076,6 +1076,9 @@ AVCodec ff_h264_decoder = {
  #endif
  #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL
                                 HWACCEL_VIDEOTOOLBOX(h264),
@@ -1439,10 +1443,10 @@ index 5eedeb3c275d..a504c89565c7 100644
                                 NULL
                             },
 diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
-index 6109c89bd63c..f758c34ddcf9 100644
+index 8e54cf73f90..969a1da0f4b 100644
 --- a/libavcodec/hwaccels.h
 +++ b/libavcodec/hwaccels.h
-@@ -27,6 +27,7 @@ extern const AVHWAccel ff_h264_d3d11va_hwaccel;
+@@ -32,6 +32,7 @@ extern const AVHWAccel ff_h264_d3d11va_hwaccel;
  extern const AVHWAccel ff_h264_d3d11va2_hwaccel;
  extern const AVHWAccel ff_h264_dxva2_hwaccel;
  extern const AVHWAccel ff_h264_nvdec_hwaccel;
@@ -1452,7 +1456,7 @@ index 6109c89bd63c..f758c34ddcf9 100644
  extern const AVHWAccel ff_h264_videotoolbox_hwaccel;
 diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
 new file mode 100644
-index 000000000000..88da8f0a2db0
+index 00000000000..88da8f0a2db
 --- /dev/null
 +++ b/libavcodec/v4l2_request_h264.c
 @@ -0,0 +1,456 @@
@@ -1912,10 +1916,1262 @@ index 000000000000..88da8f0a2db0
 +    .frame_params   = ff_v4l2_request_frame_params,
 +    .caps_internal  = HWACCEL_CAP_ASYNC_SAFE,
 +};
-From f9f4a89058a6fac25712cc385eab72f70e9ac4c8 Mon Sep 17 00:00:00 2001
+
+From 02b8fb17c2a019463dcab4baa1cb0bec63353183 Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <jonas at kwiboo.se>
+Date: Sat, 15 Dec 2018 22:32:16 +0100
+Subject: [PATCH 06/17] Add V4L2 request API mpeg2 hwaccel
+
+Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
+---
+ configure                       |   3 +
+ libavcodec/Makefile             |   1 +
+ libavcodec/hwaccels.h           |   1 +
+ libavcodec/mpeg12dec.c          |   6 ++
+ libavcodec/v4l2_request_mpeg2.c | 159 ++++++++++++++++++++++++++++++++
+ 5 files changed, 170 insertions(+)
+ create mode 100644 libavcodec/v4l2_request_mpeg2.c
+
+diff --git a/configure b/configure
+index b17e4108c1b..ec141fabbdc 100755
+--- a/configure
++++ b/configure
+@@ -2995,6 +2995,8 @@ mpeg2_dxva2_hwaccel_deps="dxva2"
+ mpeg2_dxva2_hwaccel_select="mpeg2video_decoder"
+ mpeg2_nvdec_hwaccel_deps="nvdec"
+ mpeg2_nvdec_hwaccel_select="mpeg2video_decoder"
++mpeg2_v4l2request_hwaccel_deps="v4l2_request mpeg2_v4l2_request"
++mpeg2_v4l2request_hwaccel_select="mpeg2video_decoder"
+ mpeg2_vaapi_hwaccel_deps="vaapi"
+ mpeg2_vaapi_hwaccel_select="mpeg2video_decoder"
+ mpeg2_vdpau_hwaccel_deps="vdpau"
+@@ -6631,6 +6633,7 @@ fi
+ 
+ check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
+ check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
++check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
+ 
+ check_headers sys/videoio.h
+ test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
+diff --git a/libavcodec/Makefile b/libavcodec/Makefile
+index 426c7528e90..02c023a4477 100644
+--- a/libavcodec/Makefile
++++ b/libavcodec/Makefile
+@@ -955,6 +955,7 @@ OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL)      += dxva2_mpeg2.o
+ OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL)        += dxva2_mpeg2.o
+ OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL)        += nvdec_mpeg12.o
+ OBJS-$(CONFIG_MPEG2_QSV_HWACCEL)          += qsvdec.o
++OBJS-$(CONFIG_MPEG2_V4L2REQUEST_HWACCEL)  += v4l2_request_mpeg2.o
+ OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL)        += vaapi_mpeg2.o
+ OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL)        += vdpau_mpeg12.o
+ OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
+diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
+index 969a1da0f4b..a8ae1483d8e 100644
+--- a/libavcodec/hwaccels.h
++++ b/libavcodec/hwaccels.h
+@@ -53,6 +53,7 @@ extern const AVHWAccel ff_mpeg2_d3d11va_hwaccel;
+ extern const AVHWAccel ff_mpeg2_d3d11va2_hwaccel;
+ extern const AVHWAccel ff_mpeg2_nvdec_hwaccel;
+ extern const AVHWAccel ff_mpeg2_dxva2_hwaccel;
++extern const AVHWAccel ff_mpeg2_v4l2request_hwaccel;
+ extern const AVHWAccel ff_mpeg2_vaapi_hwaccel;
+ extern const AVHWAccel ff_mpeg2_vdpau_hwaccel;
+ extern const AVHWAccel ff_mpeg2_videotoolbox_hwaccel;
+diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
+index 94221da2c15..4b0176f6cb1 100644
+--- a/libavcodec/mpeg12dec.c
++++ b/libavcodec/mpeg12dec.c
+@@ -1147,6 +1147,9 @@ static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = {
+ #endif
+ #if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL
+     AV_PIX_FMT_VIDEOTOOLBOX,
++#endif
++#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL
++    AV_PIX_FMT_DRM_PRIME,
+ #endif
+     AV_PIX_FMT_YUV420P,
+     AV_PIX_FMT_NONE
+@@ -2961,6 +2964,9 @@ AVCodec ff_mpeg2video_decoder = {
+ #endif
+ #if CONFIG_MPEG2_XVMC_HWACCEL
+                         HWACCEL_XVMC(mpeg2),
++#endif
++#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL
++                        HWACCEL_V4L2REQUEST(mpeg2),
+ #endif
+                         NULL
+                     },
+diff --git a/libavcodec/v4l2_request_mpeg2.c b/libavcodec/v4l2_request_mpeg2.c
+new file mode 100644
+index 00000000000..84d53209c79
+--- /dev/null
++++ b/libavcodec/v4l2_request_mpeg2.c
+@@ -0,0 +1,159 @@
++/*
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "hwconfig.h"
++#include "mpegvideo.h"
++#include "v4l2_request.h"
++
++typedef struct V4L2RequestControlsMPEG2 {
++    struct v4l2_ctrl_mpeg2_sequence sequence;
++    struct v4l2_ctrl_mpeg2_picture picture;
++    struct v4l2_ctrl_mpeg2_quantisation quantisation;
++} V4L2RequestControlsMPEG2;
++
++static int v4l2_request_mpeg2_start_frame(AVCodecContext *avctx,
++                                          av_unused const uint8_t *buffer,
++                                          av_unused uint32_t size)
++{
++    const MpegEncContext *s = avctx->priv_data;
++    V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private;
++    V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0];
++
++    controls->sequence = (struct v4l2_ctrl_mpeg2_sequence) {
++        /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */
++        .horizontal_size = s->width,
++        .vertical_size = s->height,
++        .vbv_buffer_size = req->output.size,
++
++        /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */
++        .profile_and_level_indication = 0,
++        .chroma_format = s->chroma_format,
++    };
++
++    if (s->progressive_sequence)
++        controls->sequence.flags |= V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE;
++
++    controls->picture = (struct v4l2_ctrl_mpeg2_picture) {
++        /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */
++        .picture_coding_type = s->pict_type,
++
++        /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */
++        .f_code[0][0] = s->mpeg_f_code[0][0],
++        .f_code[0][1] = s->mpeg_f_code[0][1],
++        .f_code[1][0] = s->mpeg_f_code[1][0],
++        .f_code[1][1] = s->mpeg_f_code[1][1],
++        .picture_structure = s->picture_structure,
++        .intra_dc_precision = s->intra_dc_precision,
++    };
++
++    if (s->top_field_first)
++        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST;
++
++    if (s->frame_pred_frame_dct)
++        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT;
++
++    if (s->concealment_motion_vectors)
++        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV;
++
++    if (s->intra_vlc_format)
++        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_INTRA_VLC;
++
++    if (s->q_scale_type)
++        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE;
++
++    if (s->alternate_scan)
++        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_ALT_SCAN;
++
++    if (s->repeat_first_field)
++        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_REPEAT_FIRST;
++
++    if (s->progressive_frame)
++        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_PROGRESSIVE;
++
++    switch (s->pict_type) {
++    case AV_PICTURE_TYPE_B:
++        controls->picture.backward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->next_picture.f);
++        // fall-through
++    case AV_PICTURE_TYPE_P:
++        controls->picture.forward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->last_picture.f);
++    }
++
++    for (int i = 0; i < 64; i++) {
++        int n = s->idsp.idct_permutation[ff_zigzag_direct[i]];
++        controls->quantisation.intra_quantiser_matrix[i] = s->intra_matrix[n];
++        controls->quantisation.non_intra_quantiser_matrix[i] = s->inter_matrix[n];
++        controls->quantisation.chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n];
++        controls->quantisation.chroma_non_intra_quantiser_matrix[i] = s->chroma_inter_matrix[n];
++    }
++
++    return ff_v4l2_request_reset_frame(avctx, s->current_picture_ptr->f);
++}
++
++static int v4l2_request_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
++{
++    const MpegEncContext *s = avctx->priv_data;
++
++    return ff_v4l2_request_append_output_buffer(avctx, s->current_picture_ptr->f, buffer, size);
++}
++
++static int v4l2_request_mpeg2_end_frame(AVCodecContext *avctx)
++{
++    const MpegEncContext *s = avctx->priv_data;
++    V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private;
++
++    struct v4l2_ext_control control[] = {
++        {
++            .id = V4L2_CID_STATELESS_MPEG2_SEQUENCE,
++            .ptr = &controls->sequence,
++            .size = sizeof(controls->sequence),
++        },
++        {
++            .id = V4L2_CID_STATELESS_MPEG2_PICTURE,
++            .ptr = &controls->picture,
++            .size = sizeof(controls->picture),
++        },
++        {
++            .id = V4L2_CID_STATELESS_MPEG2_QUANTISATION,
++            .ptr = &controls->quantisation,
++            .size = sizeof(controls->quantisation),
++        },
++    };
++
++    return ff_v4l2_request_decode_frame(avctx, s->current_picture_ptr->f, control, FF_ARRAY_ELEMS(control));
++}
++
++static int v4l2_request_mpeg2_init(AVCodecContext *avctx)
++{
++    return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_MPEG2_SLICE, 1024 * 1024, NULL, 0);
++}
++
++const AVHWAccel ff_mpeg2_v4l2request_hwaccel = {
++    .name           = "mpeg2_v4l2request",
++    .type           = AVMEDIA_TYPE_VIDEO,
++    .id             = AV_CODEC_ID_MPEG2VIDEO,
++    .pix_fmt        = AV_PIX_FMT_DRM_PRIME,
++    .start_frame    = v4l2_request_mpeg2_start_frame,
++    .decode_slice   = v4l2_request_mpeg2_decode_slice,
++    .end_frame      = v4l2_request_mpeg2_end_frame,
++    .frame_priv_data_size = sizeof(V4L2RequestControlsMPEG2),
++    .init           = v4l2_request_mpeg2_init,
++    .uninit         = ff_v4l2_request_uninit,
++    .priv_data_size = sizeof(V4L2RequestContext),
++    .frame_params   = ff_v4l2_request_frame_params,
++    .caps_internal  = HWACCEL_CAP_ASYNC_SAFE,
++};
+
+From 1cd61e5730acc12c39c964bcf13c73a54203a390 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon at collabora.com>
+Date: Wed, 22 May 2019 14:46:58 +0200
+Subject: [PATCH 07/17] Add V4L2 request API vp8 hwaccel
+
+Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
+Signed-off-by: Ezequiel Garcia <ezequiel at collabora.com>
+Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
+---
+ configure                     |   3 +
+ libavcodec/Makefile           |   1 +
+ libavcodec/hwaccels.h         |   1 +
+ libavcodec/v4l2_request_vp8.c | 180 ++++++++++++++++++++++++++++++++++
+ libavcodec/vp8.c              |   6 ++
+ 5 files changed, 191 insertions(+)
+ create mode 100644 libavcodec/v4l2_request_vp8.c
+
+diff --git a/configure b/configure
+index ec141fabbdc..f16bed65a3a 100755
+--- a/configure
++++ b/configure
+@@ -3027,6 +3027,8 @@ vc1_vdpau_hwaccel_deps="vdpau"
+ vc1_vdpau_hwaccel_select="vc1_decoder"
+ vp8_nvdec_hwaccel_deps="nvdec"
+ vp8_nvdec_hwaccel_select="vp8_decoder"
++vp8_v4l2request_hwaccel_deps="v4l2_request vp8_v4l2_request"
++vp8_v4l2request_hwaccel_select="vp8_decoder"
+ vp8_vaapi_hwaccel_deps="vaapi"
+ vp8_vaapi_hwaccel_select="vp8_decoder"
+ vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9"
+@@ -6634,6 +6636,7 @@ fi
+ check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
+ check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
+ check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
++check_cc vp8_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP8_FRAME;"
+ 
+ check_headers sys/videoio.h
+ test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
+diff --git a/libavcodec/Makefile b/libavcodec/Makefile
+index 02c023a4477..c79d678eb3e 100644
+--- a/libavcodec/Makefile
++++ b/libavcodec/Makefile
+@@ -971,6 +971,7 @@ OBJS-$(CONFIG_VC1_QSV_HWACCEL)            += qsvdec.o
+ OBJS-$(CONFIG_VC1_VAAPI_HWACCEL)          += vaapi_vc1.o
+ OBJS-$(CONFIG_VC1_VDPAU_HWACCEL)          += vdpau_vc1.o
+ OBJS-$(CONFIG_VP8_NVDEC_HWACCEL)          += nvdec_vp8.o
++OBJS-$(CONFIG_VP8_V4L2REQUEST_HWACCEL)    += v4l2_request_vp8.o
+ OBJS-$(CONFIG_VP8_VAAPI_HWACCEL)          += vaapi_vp8.o
+ OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL)        += dxva2_vp9.o
+ OBJS-$(CONFIG_VP9_DXVA2_HWACCEL)          += dxva2_vp9.o
+diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
+index a8ae1483d8e..9f8d41e367e 100644
+--- a/libavcodec/hwaccels.h
++++ b/libavcodec/hwaccels.h
+@@ -69,6 +69,7 @@ extern const AVHWAccel ff_vc1_nvdec_hwaccel;
+ extern const AVHWAccel ff_vc1_vaapi_hwaccel;
+ extern const AVHWAccel ff_vc1_vdpau_hwaccel;
+ extern const AVHWAccel ff_vp8_nvdec_hwaccel;
++extern const AVHWAccel ff_vp8_v4l2request_hwaccel;
+ extern const AVHWAccel ff_vp8_vaapi_hwaccel;
+ extern const AVHWAccel ff_vp9_d3d11va_hwaccel;
+ extern const AVHWAccel ff_vp9_d3d11va2_hwaccel;
+diff --git a/libavcodec/v4l2_request_vp8.c b/libavcodec/v4l2_request_vp8.c
+new file mode 100644
+index 00000000000..bc0fc400727
+--- /dev/null
++++ b/libavcodec/v4l2_request_vp8.c
+@@ -0,0 +1,180 @@
++/*
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "hwconfig.h"
++#include "v4l2_request.h"
++#include "vp8.h"
++
++typedef struct V4L2RequestControlsVP8 {
++    struct v4l2_ctrl_vp8_frame ctrl;
++} V4L2RequestControlsVP8;
++
++static int v4l2_request_vp8_start_frame(AVCodecContext          *avctx,
++                                        av_unused const uint8_t *buffer,
++                                        av_unused uint32_t       size)
++{
++    const VP8Context *s = avctx->priv_data;
++    V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private;
++
++    memset(&controls->ctrl, 0, sizeof(controls->ctrl));
++    return ff_v4l2_request_reset_frame(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f);
++}
++
++static int v4l2_request_vp8_end_frame(AVCodecContext *avctx)
++{
++    const VP8Context *s = avctx->priv_data;
++    V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private;
++    struct v4l2_ext_control control[] = {
++        {
++            .id = V4L2_CID_STATELESS_VP8_FRAME,
++            .ptr = &controls->ctrl,
++            .size = sizeof(controls->ctrl),
++        },
++    };
++
++    return ff_v4l2_request_decode_frame(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f,
++                                        control, FF_ARRAY_ELEMS(control));
++}
++
++static int v4l2_request_vp8_decode_slice(AVCodecContext *avctx,
++                                         const uint8_t *buffer,
++                                         uint32_t size)
++{
++    const VP8Context *s = avctx->priv_data;
++    V4L2RequestControlsVP8 *controls = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private;
++    struct v4l2_ctrl_vp8_frame *frame = &controls->ctrl;
++    const uint8_t *data = buffer + 3 + 7 * s->keyframe;
++    unsigned int i, j, k;
++
++    frame->version = s->profile & 0x3;
++    frame->width = avctx->width;
++    frame->height = avctx->height;
++    /* FIXME: set ->xx_scale */
++    frame->prob_skip_false = s->prob->mbskip;
++    frame->prob_intra = s->prob->intra;
++    frame->prob_gf = s->prob->golden;
++    frame->prob_last = s->prob->last;
++    frame->first_part_size = s->header_partition_size;
++    frame->first_part_header_bits = (8 * (s->coder_state_at_header_end.input - data) -
++                                    s->coder_state_at_header_end.bit_count - 8);
++    frame->num_dct_parts = s->num_coeff_partitions;
++    for (i = 0; i < 8; i++)
++        frame->dct_part_sizes[i] = s->coeff_partition_size[i];
++
++    frame->coder_state.range = s->coder_state_at_header_end.range;
++    frame->coder_state.value = s->coder_state_at_header_end.value;
++    frame->coder_state.bit_count = s->coder_state_at_header_end.bit_count;
++    if (s->framep[VP56_FRAME_PREVIOUS])
++        frame->last_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_PREVIOUS]->tf.f);
++    if (s->framep[VP56_FRAME_GOLDEN])
++        frame->golden_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_GOLDEN]->tf.f);
++    if (s->framep[VP56_FRAME_GOLDEN2])
++        frame->alt_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP56_FRAME_GOLDEN2]->tf.f);
++    frame->flags |= s->invisible ? 0 : V4L2_VP8_FRAME_FLAG_SHOW_FRAME;
++    frame->flags |= s->mbskip_enabled ? V4L2_VP8_FRAME_FLAG_MB_NO_SKIP_COEFF : 0;
++    frame->flags |= (s->profile & 0x4) ? V4L2_VP8_FRAME_FLAG_EXPERIMENTAL : 0;
++    frame->flags |= s->keyframe ? V4L2_VP8_FRAME_FLAG_KEY_FRAME : 0;
++    frame->flags |= s->sign_bias[VP56_FRAME_GOLDEN] ? V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN : 0;
++    frame->flags |= s->sign_bias[VP56_FRAME_GOLDEN2] ? V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT : 0;
++    frame->segment.flags |= s->segmentation.enabled ? V4L2_VP8_SEGMENT_FLAG_ENABLED : 0;
++    frame->segment.flags |= s->segmentation.update_map ? V4L2_VP8_SEGMENT_FLAG_UPDATE_MAP : 0;
++    frame->segment.flags |= s->segmentation.update_feature_data ? V4L2_VP8_SEGMENT_FLAG_UPDATE_FEATURE_DATA : 0;
++    frame->segment.flags |= s->segmentation.absolute_vals ? 0 : V4L2_VP8_SEGMENT_FLAG_DELTA_VALUE_MODE;
++    for (i = 0; i < 4; i++) {
++        frame->segment.quant_update[i] = s->segmentation.base_quant[i];
++        frame->segment.lf_update[i] = s->segmentation.filter_level[i];
++    }
++
++    for (i = 0; i < 3; i++)
++        frame->segment.segment_probs[i] = s->prob->segmentid[i];
++
++    frame->lf.level = s->filter.level;
++    frame->lf.sharpness_level = s->filter.sharpness;
++    frame->lf.flags |= s->lf_delta.enabled ? V4L2_VP8_LF_ADJ_ENABLE : 0;
++    frame->lf.flags |= s->lf_delta.update ? V4L2_VP8_LF_DELTA_UPDATE : 0;
++    frame->lf.flags |= s->filter.simple ? V4L2_VP8_LF_FILTER_TYPE_SIMPLE : 0;
++    for (i = 0; i < 4; i++) {
++        frame->lf.ref_frm_delta[i] = s->lf_delta.ref[i];
++        frame->lf.mb_mode_delta[i] = s->lf_delta.mode[i + MODE_I4x4];
++    }
++
++    // Probabilites
++    if (s->keyframe) {
++        static const uint8_t keyframe_y_mode_probs[4] = {
++            145, 156, 163, 128
++        };
++        static const uint8_t keyframe_uv_mode_probs[3] = {
++            142, 114, 183
++        };
++
++        memcpy(frame->entropy.y_mode_probs, keyframe_y_mode_probs,  4);
++        memcpy(frame->entropy.uv_mode_probs, keyframe_uv_mode_probs, 3);
++    } else {
++        for (i = 0; i < 4; i++)
++            frame->entropy.y_mode_probs[i] = s->prob->pred16x16[i];
++        for (i = 0; i < 3; i++)
++            frame->entropy.uv_mode_probs[i] = s->prob->pred8x8c[i];
++    }
++    for (i = 0; i < 2; i++)
++        for (j = 0; j < 19; j++)
++            frame->entropy.mv_probs[i][j] = s->prob->mvc[i][j];
++
++    for (i = 0; i < 4; i++) {
++        for (j = 0; j < 8; j++) {
++            static const int coeff_bands_inverse[8] = {
++                0, 1, 2, 3, 5, 6, 4, 15
++            };
++            int coeff_pos = coeff_bands_inverse[j];
++
++            for (k = 0; k < 3; k++) {
++                memcpy(frame->entropy.coeff_probs[i][j][k],
++                       s->prob->token[i][coeff_pos][k], 11);
++            }
++        }
++    }
++
++    frame->quant.y_ac_qi = s->quant.yac_qi;
++    frame->quant.y_dc_delta = s->quant.ydc_delta;
++    frame->quant.y2_dc_delta = s->quant.y2dc_delta;
++    frame->quant.y2_ac_delta = s->quant.y2ac_delta;
++    frame->quant.uv_dc_delta = s->quant.uvdc_delta;
++    frame->quant.uv_ac_delta = s->quant.uvac_delta;
++
++    return ff_v4l2_request_append_output_buffer(avctx, s->framep[VP56_FRAME_CURRENT]->tf.f, buffer, size);
++}
++
++static int v4l2_request_vp8_init(AVCodecContext *avctx)
++{
++    return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP8_FRAME, 2 * 1024 * 1024, NULL, 0);
++}
++
++const AVHWAccel ff_vp8_v4l2request_hwaccel = {
++    .name           = "vp8_v4l2request",
++    .type           = AVMEDIA_TYPE_VIDEO,
++    .id             = AV_CODEC_ID_VP8,
++    .pix_fmt        = AV_PIX_FMT_DRM_PRIME,
++    .start_frame    = v4l2_request_vp8_start_frame,
++    .decode_slice   = v4l2_request_vp8_decode_slice,
++    .end_frame      = v4l2_request_vp8_end_frame,
++    .frame_priv_data_size = sizeof(V4L2RequestControlsVP8),
++    .init           = v4l2_request_vp8_init,
++    .uninit         = ff_v4l2_request_uninit,
++    .priv_data_size = sizeof(V4L2RequestContext),
++    .frame_params   = ff_v4l2_request_frame_params,
++    .caps_internal  = HWACCEL_CAP_ASYNC_SAFE,
++};
+diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
+index d16e7b6aa34..8ee768d875a 100644
+--- a/libavcodec/vp8.c
++++ b/libavcodec/vp8.c
+@@ -176,6 +176,9 @@ static enum AVPixelFormat get_pixel_format(VP8Context *s)
+ #endif
+ #if CONFIG_VP8_NVDEC_HWACCEL
+         AV_PIX_FMT_CUDA,
++#endif
++#if CONFIG_VP8_V4L2REQUEST_HWACCEL
++        AV_PIX_FMT_DRM_PRIME,
+ #endif
+         AV_PIX_FMT_YUV420P,
+         AV_PIX_FMT_NONE,
+@@ -2972,6 +2975,9 @@ AVCodec ff_vp8_decoder = {
+ #endif
+ #if CONFIG_VP8_NVDEC_HWACCEL
+                                HWACCEL_NVDEC(vp8),
++#endif
++#if CONFIG_VP8_V4L2REQUEST_HWACCEL
++                               HWACCEL_V4L2REQUEST(vp8),
+ #endif
+                                NULL
+                            },
+
+From 3c9c4c99eccdda102064ea67a04c8cbf8083ad1a Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon at collabora.com>
+Date: Thu, 12 Dec 2019 16:13:55 +0100
+Subject: [PATCH 09/17] Add V4L2 request API VP9 hwaccel
+
+Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
+Signed-off-by: Jernej Skrabec <jernej.skrabec at gmail.com>
+---
+ configure                     |   3 +
+ libavcodec/Makefile           |   1 +
+ libavcodec/hwaccels.h         |   1 +
+ libavcodec/v4l2_request_vp9.c | 268 ++++++++++++++++++++++++++++++++++
+ libavcodec/vp9.c              | 192 +++++++++++++++++-------
+ libavcodec/vp9dec.h           |   4 +
+ libavcodec/vp9shared.h        |   1 +
+ 7 files changed, 415 insertions(+), 55 deletions(-)
+ create mode 100644 libavcodec/v4l2_request_vp9.c
+
+diff --git a/configure b/configure
+index 02a80cf27fd..0b238c051df 100755
+--- a/configure
++++ b/configure
+@@ -3041,6 +3041,8 @@ vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9"
+ vp9_dxva2_hwaccel_select="vp9_decoder"
+ vp9_nvdec_hwaccel_deps="nvdec"
+ vp9_nvdec_hwaccel_select="vp9_decoder"
++vp9_v4l2request_hwaccel_deps="v4l2_request"
++vp9_v4l2request_hwaccel_select="vp9_decoder"
+ vp9_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferVP9_bit_depth"
+ vp9_vaapi_hwaccel_select="vp9_decoder"
+ vp9_vdpau_hwaccel_deps="vdpau VdpPictureInfoVP9"
+@@ -6640,6 +6642,7 @@ check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
+ check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
+ check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
+ check_cc vp8_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP8_FRAME;"
++check_cc vp9_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP9_FRAME;"
+ 
+ check_headers sys/videoio.h
+ test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
+diff --git a/libavcodec/Makefile b/libavcodec/Makefile
+index 0059074530c..38edf1cfe5e 100644
+--- a/libavcodec/Makefile
++++ b/libavcodec/Makefile
+@@ -977,6 +977,7 @@ OBJS-$(CONFIG_VP8_VAAPI_HWACCEL)          += vaapi_vp8.o
+ OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL)        += dxva2_vp9.o
+ OBJS-$(CONFIG_VP9_DXVA2_HWACCEL)          += dxva2_vp9.o
+ OBJS-$(CONFIG_VP9_NVDEC_HWACCEL)          += nvdec_vp9.o
++OBJS-$(CONFIG_VP9_V4L2REQUEST_HWACCEL)    += v4l2_request_vp9.o
+ OBJS-$(CONFIG_VP9_VAAPI_HWACCEL)          += vaapi_vp9.o
+ OBJS-$(CONFIG_VP9_VDPAU_HWACCEL)          += vdpau_vp9.o
+ OBJS-$(CONFIG_VP8_QSV_HWACCEL)            += qsvdec.o
+diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
+index ffb9fa5087d..fc5d0b0479b 100644
+--- a/libavcodec/hwaccels.h
++++ b/libavcodec/hwaccels.h
+@@ -76,6 +76,7 @@ extern const AVHWAccel ff_vp9_d3d11va_hwaccel;
+ extern const AVHWAccel ff_vp9_d3d11va2_hwaccel;
+ extern const AVHWAccel ff_vp9_dxva2_hwaccel;
+ extern const AVHWAccel ff_vp9_nvdec_hwaccel;
++extern const AVHWAccel ff_vp9_v4l2request_hwaccel;
+ extern const AVHWAccel ff_vp9_vaapi_hwaccel;
+ extern const AVHWAccel ff_vp9_vdpau_hwaccel;
+ extern const AVHWAccel ff_wmv3_d3d11va_hwaccel;
+diff --git a/libavcodec/v4l2_request_vp9.c b/libavcodec/v4l2_request_vp9.c
+new file mode 100644
+index 00000000000..9b95c76cdb8
+--- /dev/null
++++ b/libavcodec/v4l2_request_vp9.c
+@@ -0,0 +1,268 @@
++/*
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "hwconfig.h"
++#include "v4l2_request.h"
++#include "vp9dec.h"
++
++typedef struct V4L2RequestControlsVP9 {
++    struct v4l2_ctrl_vp9_frame decode_params;
++} V4L2RequestControlsVP9;
++
++static int v4l2_request_vp9_set_frame_ctx(AVCodecContext *avctx)
++{
++    VP9Context *s = avctx->priv_data;
++    struct v4l2_ctrl_vp9_compressed_hdr chp;
++    struct v4l2_ext_control control[] = {
++        {
++            .id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR,
++            .ptr = &chp,
++            .size = sizeof(chp),
++        },
++    };
++
++    memset(&chp, 0, sizeof(chp));
++
++    chp.tx_mode = s->s.h.txfmmode;
++    memcpy(chp.tx8, s->prob_raw.p.tx8p, sizeof(s->prob_raw.p.tx8p));
++    memcpy(chp.tx16, s->prob_raw.p.tx16p, sizeof(s->prob_raw.p.tx16p));
++    memcpy(chp.tx32, s->prob_raw.p.tx32p, sizeof(s->prob_raw.p.tx32p));
++    for (unsigned i = 0; i < 4; i++) {
++        for (unsigned j = 0; j < 2; j++) {
++            for (unsigned k = 0; k < 2; k++) {
++                for (unsigned l = 0; l < 6; l++) {
++                    for (unsigned m = 0; m < 6; m++) {
++                        memcpy(chp.coef[i][j][k][l][m], s->prob_raw.coef[i][j][k][l][m], sizeof(chp.coef[0][0][0][0][0]));
++                    }
++                }
++            }
++        }
++    }
++    memcpy(chp.skip, s->prob_raw.p.skip, sizeof(s->prob_raw.p.skip));
++    memcpy(chp.inter_mode, s->prob_raw.p.mv_mode, sizeof(s->prob_raw.p.mv_mode));
++    memcpy(chp.interp_filter, s->prob_raw.p.filter, sizeof(s->prob_raw.p.filter));
++    memcpy(chp.is_inter, s->prob_raw.p.intra, sizeof(s->prob_raw.p.intra));
++    memcpy(chp.comp_mode, s->prob_raw.p.comp, sizeof(s->prob_raw.p.comp));
++    memcpy(chp.single_ref, s->prob_raw.p.single_ref, sizeof(s->prob_raw.p.single_ref));
++    memcpy(chp.comp_ref, s->prob_raw.p.comp_ref, sizeof(s->prob_raw.p.comp_ref));
++    memcpy(chp.y_mode, s->prob_raw.p.y_mode, sizeof(s->prob_raw.p.y_mode));
++    for (unsigned i = 0; i < 10; i++)
++        memcpy(chp.uv_mode[i], s->prob.p.uv_mode[i], sizeof(s->prob.p.uv_mode[0]));
++    for (unsigned i = 0; i < 4; i++)
++        memcpy(chp.partition[i * 4], s->prob_raw.p.partition[i], sizeof(s->prob_raw.p.partition[0]));
++    memcpy(chp.mv.joint, s->prob_raw.p.mv_joint, sizeof(s->prob_raw.p.mv_joint));
++    for (unsigned i = 0; i < 2; i++) {
++         chp.mv.sign[i] = s->prob_raw.p.mv_comp[i].sign;
++         memcpy(chp.mv.classes[i], s->prob_raw.p.mv_comp[i].classes, sizeof(s->prob_raw.p.mv_comp[0].classes));
++         chp.mv.class0_bit[i] = s->prob_raw.p.mv_comp[i].class0;
++         memcpy(chp.mv.bits[i], s->prob_raw.p.mv_comp[i].bits, sizeof(s->prob_raw.p.mv_comp[0].bits));
++         memcpy(chp.mv.class0_fr[i], s->prob_raw.p.mv_comp[i].class0_fp, sizeof(s->prob_raw.p.mv_comp[0].class0_fp));
++         memcpy(chp.mv.fr[i], s->prob_raw.p.mv_comp[i].fp, sizeof(s->prob_raw.p.mv_comp[0].fp));
++         chp.mv.class0_hp[i] = s->prob_raw.p.mv_comp[i].class0_hp;
++         chp.mv.hp[i] = s->prob_raw.p.mv_comp[i].hp;
++    }
++
++    return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control));
++}
++
++static int v4l2_request_vp9_start_frame(AVCodecContext *avctx,
++                                        av_unused const uint8_t *buffer,
++                                        av_unused uint32_t size)
++{
++    const VP9Context *s = avctx->priv_data;
++    const VP9Frame *f = &s->s.frames[CUR_FRAME];
++    V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private;
++    struct v4l2_ctrl_vp9_frame *dec_params = &controls->decode_params;
++    const ThreadFrame *ref;
++    int ret;
++
++    ret = v4l2_request_vp9_set_frame_ctx(avctx);
++    if (ret)
++	return ret;
++
++    memset(dec_params, 0, sizeof(*dec_params));
++
++    if (s->s.h.keyframe)
++        dec_params->flags |= V4L2_VP9_FRAME_FLAG_KEY_FRAME;
++    if (!s->s.h.invisible)
++        dec_params->flags |= V4L2_VP9_FRAME_FLAG_SHOW_FRAME;
++    if (s->s.h.errorres)
++        dec_params->flags |= V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT;
++    if (s->s.h.intraonly)
++        dec_params->flags |= V4L2_VP9_FRAME_FLAG_INTRA_ONLY;
++    if (!s->s.h.keyframe && s->s.h.highprecisionmvs)
++        dec_params->flags |= V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV;
++    if (s->s.h.refreshctx)
++        dec_params->flags |= V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX;
++    if (s->s.h.parallelmode)
++        dec_params->flags |= V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE;
++    if (s->ss_h)
++        dec_params->flags |= V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING;
++    if (s->ss_v)
++        dec_params->flags |= V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING;
++    if (avctx->color_range == AVCOL_RANGE_JPEG)
++        dec_params->flags |= V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING;
++
++    dec_params->compressed_header_size = s->s.h.compressed_header_size;
++    dec_params->uncompressed_header_size = s->s.h.uncompressed_header_size;
++    dec_params->profile = s->s.h.profile;
++    dec_params->reset_frame_context = s->s.h.resetctx > 0 ? s->s.h.resetctx - 1 : 0;
++    dec_params->frame_context_idx = s->s.h.framectxid;
++    dec_params->bit_depth = s->s.h.bpp;
++
++    dec_params->interpolation_filter = s->s.h.filtermode ^ (s->s.h.filtermode <= 1);
++    dec_params->tile_cols_log2 = s->s.h.tiling.log2_tile_cols;
++    dec_params->tile_rows_log2 = s->s.h.tiling.log2_tile_rows;
++    dec_params->reference_mode = s->s.h.comppredmode;
++    dec_params->frame_width_minus_1 = s->w - 1;
++    dec_params->frame_height_minus_1 = s->h - 1;
++    //dec_params->render_width_minus_1 = avctx->width - 1;
++    //dec_params->render_height_minus_1 = avctx->height - 1;
++
++    ref = &s->s.refs[s->s.h.refidx[0]];
++    if (ref->f && ref->f->buf[0])
++        dec_params->last_frame_ts = ff_v4l2_request_get_capture_timestamp(ref->f);
++    ref = &s->s.refs[s->s.h.refidx[1]];
++    if (ref->f && ref->f->buf[0])
++        dec_params->golden_frame_ts = ff_v4l2_request_get_capture_timestamp(ref->f);
++    ref = &s->s.refs[s->s.h.refidx[2]];
++    if (ref->f && ref->f->buf[0])
++        dec_params->alt_frame_ts = ff_v4l2_request_get_capture_timestamp(ref->f);
++
++    if (s->s.h.signbias[0])
++        dec_params->ref_frame_sign_bias |= V4L2_VP9_SIGN_BIAS_LAST;
++    if (s->s.h.signbias[1])
++        dec_params->ref_frame_sign_bias |= V4L2_VP9_SIGN_BIAS_GOLDEN;
++    if (s->s.h.signbias[2])
++        dec_params->ref_frame_sign_bias |= V4L2_VP9_SIGN_BIAS_ALT;
++
++    if (s->s.h.lf_delta.enabled)
++        dec_params->lf.flags |= V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED;
++    if (s->s.h.lf_delta.updated)
++        dec_params->lf.flags |= V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE;
++
++    dec_params->lf.level = s->s.h.filter.level;
++    dec_params->lf.sharpness = s->s.h.filter.sharpness;
++    for (unsigned i = 0; i < 4; i++)
++        dec_params->lf.ref_deltas[i] = s->s.h.lf_delta.ref[i];
++    for (unsigned i = 0; i < 2; i++)
++        dec_params->lf.mode_deltas[i] = s->s.h.lf_delta.mode[i];
++
++    dec_params->quant.base_q_idx = s->s.h.yac_qi;
++    dec_params->quant.delta_q_y_dc = s->s.h.ydc_qdelta;
++    dec_params->quant.delta_q_uv_dc = s->s.h.uvdc_qdelta;
++    dec_params->quant.delta_q_uv_ac = s->s.h.uvac_qdelta;
++
++    if (s->s.h.segmentation.enabled)
++        dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_ENABLED;
++    if (s->s.h.segmentation.update_map)
++        dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP;
++    if (s->s.h.segmentation.temporal)
++        dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE;
++    if (s->s.h.segmentation.update_data)
++        dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA;
++    if (s->s.h.segmentation.absolute_vals)
++        dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE;
++
++    for (unsigned i = 0; i < 7; i++)
++        dec_params->seg.tree_probs[i] = s->s.h.segmentation.prob[i];
++
++    if (s->s.h.segmentation.temporal) {
++        for (unsigned i = 0; i < 3; i++)
++            dec_params->seg.pred_probs[i] = s->s.h.segmentation.pred_prob[i];
++    } else {
++        memset(dec_params->seg.pred_probs, 255, sizeof(dec_params->seg.pred_probs));
++    }
++
++    for (unsigned i = 0; i < 8; i++) {
++        if (s->s.h.segmentation.feat[i].q_enabled) {
++            dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEG_LVL_ALT_Q;
++            dec_params->seg.feature_data[i][V4L2_VP9_SEG_LVL_ALT_Q] = s->s.h.segmentation.feat[i].q_val;
++        }
++
++        if (s->s.h.segmentation.feat[i].lf_enabled) {
++            dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEG_LVL_ALT_L;
++            dec_params->seg.feature_data[i][V4L2_VP9_SEG_LVL_ALT_L] = s->s.h.segmentation.feat[i].lf_val;
++        }
++
++        if (s->s.h.segmentation.feat[i].ref_enabled) {
++            dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEG_LVL_REF_FRAME;
++            dec_params->seg.feature_data[i][V4L2_VP9_SEG_LVL_REF_FRAME] = s->s.h.segmentation.feat[i].ref_val;
++        }
++
++        if (s->s.h.segmentation.feat[i].skip_enabled)
++            dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEG_LVL_SKIP;
++    }
++
++    return ff_v4l2_request_reset_frame(avctx, f->tf.f);
++}
++
++static int v4l2_request_vp9_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
++{
++    const VP9Context *s = avctx->priv_data;
++    const VP9Frame *f = &s->s.frames[CUR_FRAME];
++
++    return ff_v4l2_request_append_output_buffer(avctx, f->tf.f, buffer, size);
++}
++
++static int v4l2_request_vp9_end_frame(AVCodecContext *avctx)
++{
++    const VP9Context *s = avctx->priv_data;
++    const VP9Frame *f = &s->s.frames[CUR_FRAME];
++    V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private;
++    int ret;
++
++    struct v4l2_ext_control control[] = {
++        {
++            .id = V4L2_CID_STATELESS_VP9_FRAME,
++            .ptr = &controls->decode_params,
++            .size = sizeof(controls->decode_params),
++        },
++    };
++
++    ret = ff_v4l2_request_decode_frame(avctx, f->tf.f, control, FF_ARRAY_ELEMS(control));
++    if (ret)
++        return ret;
++
++    if (!s->s.h.refreshctx)
++        return 0;
++
++    return 0;
++}
++
++static int v4l2_request_vp9_init(AVCodecContext *avctx)
++{
++    // TODO: check V4L2_CID_MPEG_VIDEO_VP9_PROFILE
++    return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP9_FRAME, 3 * 1024 * 1024, NULL, 0);
++}
++
++const AVHWAccel ff_vp9_v4l2request_hwaccel = {
++    .name           = "vp9_v4l2request",
++    .type           = AVMEDIA_TYPE_VIDEO,
++    .id             = AV_CODEC_ID_VP9,
++    .pix_fmt        = AV_PIX_FMT_DRM_PRIME,
++    .start_frame    = v4l2_request_vp9_start_frame,
++    .decode_slice   = v4l2_request_vp9_decode_slice,
++    .end_frame      = v4l2_request_vp9_end_frame,
++    .frame_priv_data_size = sizeof(V4L2RequestControlsVP9),
++    .init           = v4l2_request_vp9_init,
++    .uninit         = ff_v4l2_request_uninit,
++    .priv_data_size = sizeof(V4L2RequestContext),
++    .frame_params   = ff_v4l2_request_frame_params,
++    .caps_internal  = HWACCEL_CAP_ASYNC_SAFE,
++};
+diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c
+index 4659f94ee8b..1b2f1eeaf69 100644
+--- a/libavcodec/vp9.c
++++ b/libavcodec/vp9.c
+@@ -191,6 +191,7 @@ static int update_size(AVCodecContext *avctx, int w, int h)
+ #define HWACCEL_MAX (CONFIG_VP9_DXVA2_HWACCEL + \
+                      CONFIG_VP9_D3D11VA_HWACCEL * 2 + \
+                      CONFIG_VP9_NVDEC_HWACCEL + \
++                     CONFIG_VP9_V4L2REQUEST_HWACCEL + \
+                      CONFIG_VP9_VAAPI_HWACCEL + \
+                      CONFIG_VP9_VDPAU_HWACCEL)
+     enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts;
+@@ -223,6 +224,9 @@ static int update_size(AVCodecContext *avctx, int w, int h)
+ #endif
+ #if CONFIG_VP9_VDPAU_HWACCEL
+             *fmtp++ = AV_PIX_FMT_VDPAU;
++#endif
++#if CONFIG_VP9_V4L2REQUEST_HWACCEL
++            *fmtp++ = AV_PIX_FMT_DRM_PRIME;
+ #endif
+             break;
+         case AV_PIX_FMT_YUV420P12:
+@@ -234,6 +238,9 @@ static int update_size(AVCodecContext *avctx, int w, int h)
+ #endif
+ #if CONFIG_VP9_VDPAU_HWACCEL
+             *fmtp++ = AV_PIX_FMT_VDPAU;
++#endif
++#if CONFIG_VP9_V4L2REQUEST_HWACCEL
++            *fmtp++ = AV_PIX_FMT_DRM_PRIME;
+ #endif
+             break;
+         }
+@@ -382,7 +389,7 @@ static av_always_inline int inv_recenter_nonneg(int v, int m)
+ }
+ 
+ // differential forward probability updates
+-static int update_prob(VP56RangeCoder *c, int p)
++static int read_prob_delta(VP56RangeCoder *c)
+ {
+     static const uint8_t inv_map_table[255] = {
+           7,  20,  33,  46,  59,  72,  85,  98, 111, 124, 137, 150, 163, 176,
+@@ -436,8 +443,13 @@ static int update_prob(VP56RangeCoder *c, int p)
+         av_assert2(d < FF_ARRAY_ELEMS(inv_map_table));
+     }
+ 
+-    return p <= 128 ? 1 + inv_recenter_nonneg(inv_map_table[d], p - 1) :
+-                    255 - inv_recenter_nonneg(inv_map_table[d], 255 - p);
++    return inv_map_table[d];
++}
++
++static int update_prob(int p, int d)
++{
++    return p <= 128 ? 1 + inv_recenter_nonneg(d, p - 1) :
++                    255 - inv_recenter_nonneg(d, 255 - p);
+ }
+ 
+ static int read_colorspace_details(AVCodecContext *avctx)
+@@ -703,7 +715,8 @@ static int decode_frame_header(AVCodecContext *avctx,
+                                          get_bits(&s->gb, 8) : 255;
+         }
+ 
+-        if (get_bits1(&s->gb)) {
++        s->s.h.segmentation.update_data = get_bits1(&s->gb);
++        if (s->s.h.segmentation.update_data) {
+             s->s.h.segmentation.absolute_vals = get_bits1(&s->gb);
+             for (i = 0; i < 8; i++) {
+                 if ((s->s.h.segmentation.feat[i].q_enabled = get_bits1(&s->gb)))
+@@ -904,6 +917,8 @@ static int decode_frame_header(AVCodecContext *avctx,
+      * as explicit copies if the fw update is missing (and skip the copy upon
+      * fw update)? */
+     s->prob.p = s->prob_ctx[c].p;
++    memset(&s->prob_raw.p, 0, sizeof(s->prob_raw.p));
++    memset(&s->prob_raw.coef, 0, sizeof(s->prob_raw.coef));
+ 
+     // txfm updates
+     if (s->s.h.lossless) {
+@@ -915,18 +930,25 @@ static int decode_frame_header(AVCodecContext *avctx,
+ 
+         if (s->s.h.txfmmode == TX_SWITCHABLE) {
+             for (i = 0; i < 2; i++)
+-                if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                    s->prob.p.tx8p[i] = update_prob(&s->c, s->prob.p.tx8p[i]);
++                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                    s->prob_raw.p.tx8p[i] = read_prob_delta(&s->c);
++                    s->prob.p.tx8p[i] = update_prob(s->prob.p.tx8p[i],
++                                                    s->prob_raw.p.tx8p[i]);
++                }
+             for (i = 0; i < 2; i++)
+                 for (j = 0; j < 2; j++)
+-                    if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                        s->prob.p.tx16p[i][j] =
+-                            update_prob(&s->c, s->prob.p.tx16p[i][j]);
++                    if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                        s->prob_raw.p.tx16p[i][j] = read_prob_delta(&s->c);
++                        s->prob.p.tx16p[i][j] = update_prob(s->prob.p.tx16p[i][j],
++                                                            s->prob_raw.p.tx16p[i][j]);
++                    }
+             for (i = 0; i < 2; i++)
+                 for (j = 0; j < 3; j++)
+-                    if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                        s->prob.p.tx32p[i][j] =
+-                            update_prob(&s->c, s->prob.p.tx32p[i][j]);
++                    if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                        s->prob_raw.p.tx32p[i][j] = read_prob_delta(&s->c);
++                        s->prob.p.tx32p[i][j] = update_prob(s->prob.p.tx32p[i][j],
++                                                            s->prob_raw.p.tx32p[i][j]);
++                    }
+         }
+     }
+ 
+@@ -938,15 +960,18 @@ static int decode_frame_header(AVCodecContext *avctx,
+                 for (k = 0; k < 2; k++)
+                     for (l = 0; l < 6; l++)
+                         for (m = 0; m < 6; m++) {
++                            uint8_t *pd = s->prob_raw.coef[i][j][k][l][m];
+                             uint8_t *p = s->prob.coef[i][j][k][l][m];
+                             uint8_t *r = ref[j][k][l][m];
+                             if (m >= 3 && l == 0) // dc only has 3 pt
+                                 break;
+                             for (n = 0; n < 3; n++) {
+-                                if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                                    p[n] = update_prob(&s->c, r[n]);
+-                                else
++                                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                                    pd[n] = read_prob_delta(&s->c);
++                                    p[n] = update_prob(r[n], pd[n]);
++                                } else {
+                                     p[n] = r[n];
++                                }
+                             }
+                             memcpy(&p[3], ff_vp9_model_pareto8[p[2]], 8);
+                         }
+@@ -961,7 +986,7 @@ static int decode_frame_header(AVCodecContext *avctx,
+                                 break;
+                             memcpy(p, r, 3);
+                             memcpy(&p[3], ff_vp9_model_pareto8[p[2]], 8);
+-                        }
++                         }
+         }
+         if (s->s.h.txfmmode == i)
+             break;
+@@ -969,25 +994,37 @@ static int decode_frame_header(AVCodecContext *avctx,
+ 
+     // mode updates
+     for (i = 0; i < 3; i++)
+-        if (vp56_rac_get_prob_branchy(&s->c, 252))
+-            s->prob.p.skip[i] = update_prob(&s->c, s->prob.p.skip[i]);
++        if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++            s->prob_raw.p.skip[i] = read_prob_delta(&s->c);
++            s->prob.p.skip[i] = update_prob(s->prob.p.skip[i],
++                                            s->prob_raw.p.skip[i]);
++        }
+     if (!s->s.h.keyframe && !s->s.h.intraonly) {
+         for (i = 0; i < 7; i++)
+             for (j = 0; j < 3; j++)
+-                if (vp56_rac_get_prob_branchy(&s->c, 252))
++                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                    s->prob_raw.p.mv_mode[i][j] = read_prob_delta(&s->c);
+                     s->prob.p.mv_mode[i][j] =
+-                        update_prob(&s->c, s->prob.p.mv_mode[i][j]);
++                        update_prob(s->prob.p.mv_mode[i][j],
++                                    s->prob_raw.p.mv_mode[i][j]);
++                }
+ 
+         if (s->s.h.filtermode == FILTER_SWITCHABLE)
+             for (i = 0; i < 4; i++)
+                 for (j = 0; j < 2; j++)
+-                    if (vp56_rac_get_prob_branchy(&s->c, 252))
++                    if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                        s->prob_raw.p.filter[i][j] = read_prob_delta(&s->c);
+                         s->prob.p.filter[i][j] =
+-                            update_prob(&s->c, s->prob.p.filter[i][j]);
++                            update_prob(s->prob.p.filter[i][j],
++                                        s->prob_raw.p.filter[i][j]);
++                    }
+ 
+         for (i = 0; i < 4; i++)
+-            if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                s->prob.p.intra[i] = update_prob(&s->c, s->prob.p.intra[i]);
++            if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                s->prob_raw.p.intra[i] = read_prob_delta(&s->c);
++                s->prob.p.intra[i] = update_prob(s->prob.p.intra[i],
++                                                 s->prob_raw.p.intra[i]);
++            }
+ 
+         if (s->s.h.allowcompinter) {
+             s->s.h.comppredmode = vp8_rac_get(&s->c);
+@@ -995,92 +1032,134 @@ static int decode_frame_header(AVCodecContext *avctx,
+                 s->s.h.comppredmode += vp8_rac_get(&s->c);
+             if (s->s.h.comppredmode == PRED_SWITCHABLE)
+                 for (i = 0; i < 5; i++)
+-                    if (vp56_rac_get_prob_branchy(&s->c, 252))
++                    if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                        s->prob_raw.p.comp[i] = read_prob_delta(&s->c);
+                         s->prob.p.comp[i] =
+-                            update_prob(&s->c, s->prob.p.comp[i]);
++                            update_prob(s->prob.p.comp[i], s->prob_raw.p.comp[i]);
++                    }
+         } else {
+             s->s.h.comppredmode = PRED_SINGLEREF;
+         }
+ 
+         if (s->s.h.comppredmode != PRED_COMPREF) {
+             for (i = 0; i < 5; i++) {
+-                if (vp56_rac_get_prob_branchy(&s->c, 252))
++                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                    s->prob_raw.p.single_ref[i][0] = read_prob_delta(&s->c);
+                     s->prob.p.single_ref[i][0] =
+-                        update_prob(&s->c, s->prob.p.single_ref[i][0]);
+-                if (vp56_rac_get_prob_branchy(&s->c, 252))
++                        update_prob(s->prob.p.single_ref[i][0],
++                                    s->prob_raw.p.single_ref[i][0]);
++                }
++                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                    s->prob_raw.p.single_ref[i][1] = read_prob_delta(&s->c);
+                     s->prob.p.single_ref[i][1] =
+-                        update_prob(&s->c, s->prob.p.single_ref[i][1]);
++                        update_prob(s->prob.p.single_ref[i][1],
++                                    s->prob_raw.p.single_ref[i][1]);
++                }
+             }
+         }
+ 
+         if (s->s.h.comppredmode != PRED_SINGLEREF) {
+             for (i = 0; i < 5; i++)
+-                if (vp56_rac_get_prob_branchy(&s->c, 252))
++                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                    s->prob_raw.p.comp_ref[i] = read_prob_delta(&s->c);
+                     s->prob.p.comp_ref[i] =
+-                        update_prob(&s->c, s->prob.p.comp_ref[i]);
++                        update_prob(s->prob.p.comp_ref[i],
++                                    s->prob_raw.p.comp_ref[i]);
++                }
+         }
+ 
+         for (i = 0; i < 4; i++)
+             for (j = 0; j < 9; j++)
+-                if (vp56_rac_get_prob_branchy(&s->c, 252))
++                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                    s->prob_raw.p.y_mode[i][j] = read_prob_delta(&s->c);
+                     s->prob.p.y_mode[i][j] =
+-                        update_prob(&s->c, s->prob.p.y_mode[i][j]);
++                        update_prob(s->prob.p.y_mode[i][j],
++                                    s->prob_raw.p.y_mode[i][j]);
++                }
+ 
+         for (i = 0; i < 4; i++)
+             for (j = 0; j < 4; j++)
+                 for (k = 0; k < 3; k++)
+-                    if (vp56_rac_get_prob_branchy(&s->c, 252))
++                    if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                        s->prob_raw.p.partition[i][j][k] = read_prob_delta(&s->c);
+                         s->prob.p.partition[3 - i][j][k] =
+-                            update_prob(&s->c,
+-                                        s->prob.p.partition[3 - i][j][k]);
++                            update_prob(s->prob.p.partition[3 - i][j][k],
++                                        s->prob_raw.p.partition[i][j][k]);
++                    }
+ 
+         // mv fields don't use the update_prob subexp model for some reason
+         for (i = 0; i < 3; i++)
+-            if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                s->prob.p.mv_joint[i] = (vp8_rac_get_uint(&s->c, 7) << 1) | 1;
++            if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                s->prob_raw.p.mv_joint[i] = (vp8_rac_get_uint(&s->c, 7) << 1) | 1;
++                s->prob.p.mv_joint[i] = s->prob_raw.p.mv_joint[i];
++            }
+ 
+         for (i = 0; i < 2; i++) {
+-            if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                s->prob.p.mv_comp[i].sign =
++            if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                s->prob_raw.p.mv_comp[i].sign =
+                     (vp8_rac_get_uint(&s->c, 7) << 1) | 1;
++                s->prob.p.mv_comp[i].sign =
++                    s->prob_raw.p.mv_comp[i].sign;
++            }
+ 
+             for (j = 0; j < 10; j++)
+-                if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                    s->prob.p.mv_comp[i].classes[j] =
++                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                    s->prob_raw.p.mv_comp[i].classes[j] =
+                         (vp8_rac_get_uint(&s->c, 7) << 1) | 1;
++                    s->prob.p.mv_comp[i].classes[j] =
++                        s->prob_raw.p.mv_comp[i].classes[j];
++                }
+ 
+-            if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                s->prob.p.mv_comp[i].class0 =
++            if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                s->prob_raw.p.mv_comp[i].class0 =
+                     (vp8_rac_get_uint(&s->c, 7) << 1) | 1;
++                s->prob.p.mv_comp[i].class0 =
++                    s->prob_raw.p.mv_comp[i].class0;
++            }
+ 
+             for (j = 0; j < 10; j++)
+-                if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                    s->prob.p.mv_comp[i].bits[j] =
++                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                    s->prob_raw.p.mv_comp[i].bits[j] =
+                         (vp8_rac_get_uint(&s->c, 7) << 1) | 1;
++                    s->prob.p.mv_comp[i].bits[j] =
++                        s->prob_raw.p.mv_comp[i].bits[j];
++                }
+         }
+ 
+         for (i = 0; i < 2; i++) {
+             for (j = 0; j < 2; j++)
+                 for (k = 0; k < 3; k++)
+-                    if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                        s->prob.p.mv_comp[i].class0_fp[j][k] =
++                    if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                        s->prob_raw.p.mv_comp[i].class0_fp[j][k] =
+                             (vp8_rac_get_uint(&s->c, 7) << 1) | 1;
++                        s->prob.p.mv_comp[i].class0_fp[j][k] =
++                            s->prob_raw.p.mv_comp[i].class0_fp[j][k];
++                    }
+ 
+             for (j = 0; j < 3; j++)
+-                if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                    s->prob.p.mv_comp[i].fp[j] =
++                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                    s->prob_raw.p.mv_comp[i].fp[j] =
+                         (vp8_rac_get_uint(&s->c, 7) << 1) | 1;
++                    s->prob.p.mv_comp[i].fp[j] =
++                        s->prob_raw.p.mv_comp[i].fp[j];
++                }
+         }
+ 
+         if (s->s.h.highprecisionmvs) {
+             for (i = 0; i < 2; i++) {
+-                if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                    s->prob.p.mv_comp[i].class0_hp =
++                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                    s->prob_raw.p.mv_comp[i].class0_hp =
+                         (vp8_rac_get_uint(&s->c, 7) << 1) | 1;
++                    s->prob.p.mv_comp[i].class0_hp =
++                        s->prob_raw.p.mv_comp[i].class0_hp;
++                }
+ 
+-                if (vp56_rac_get_prob_branchy(&s->c, 252))
+-                    s->prob.p.mv_comp[i].hp =
++                if (vp56_rac_get_prob_branchy(&s->c, 252)) {
++                    s->prob_raw.p.mv_comp[i].hp =
+                         (vp8_rac_get_uint(&s->c, 7) << 1) | 1;
++                    s->prob.p.mv_comp[i].hp =
++                        s->prob_raw.p.mv_comp[i].hp;
++                }
+             }
+         }
+     }
+@@ -1912,6 +1991,9 @@ AVCodec ff_vp9_decoder = {
+ #endif
+ #if CONFIG_VP9_VDPAU_HWACCEL
+                                HWACCEL_VDPAU(vp9),
++#endif
++#if CONFIG_VP9_V4L2REQUEST_HWACCEL
++                               HWACCEL_V4L2REQUEST(vp9),
+ #endif
+                                NULL
+                            },
+diff --git a/libavcodec/vp9dec.h b/libavcodec/vp9dec.h
+index d82b258a3d8..8d2c341e0b9 100644
+--- a/libavcodec/vp9dec.h
++++ b/libavcodec/vp9dec.h
+@@ -131,6 +131,10 @@ typedef struct VP9Context {
+         ProbContext p;
+         uint8_t coef[4][2][2][6][6][11];
+     } prob;
++    struct {
++        ProbContext p;
++        uint8_t coef[4][2][2][6][6][11];
++    } prob_raw;
+ 
+     // contextual (above) cache
+     uint8_t *above_partition_ctx;
+diff --git a/libavcodec/vp9shared.h b/libavcodec/vp9shared.h
+index 54726df742f..fee3568736f 100644
+--- a/libavcodec/vp9shared.h
++++ b/libavcodec/vp9shared.h
+@@ -131,6 +131,7 @@ typedef struct VP9BitstreamHeader {
+         uint8_t temporal;
+         uint8_t absolute_vals;
+         uint8_t update_map;
++        uint8_t update_data;
+         uint8_t prob[7];
+         uint8_t pred_prob[3];
+         struct {
+
+From bb3cf90c0533a0096dff74b416f55832814293e0 Mon Sep 17 00:00:00 2001
 From: Jonas Karlman <jonas at kwiboo.se>
 Date: Mon, 29 Apr 2019 22:08:59 +0000
-Subject: [PATCH] HACK: hwcontext_drm: do not require drm device
+Subject: [PATCH 11/17] HACK: hwcontext_drm: do not require drm device
 
 Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
 ---
@@ -1923,10 +3179,10 @@ Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
  1 file changed, 5 insertions(+)
 
 diff --git a/libavutil/hwcontext_drm.c b/libavutil/hwcontext_drm.c
-index 32cbde82ebfa..aa4794c5e665 100644
+index 7a9fdbd263d..6297d1f9b61 100644
 --- a/libavutil/hwcontext_drm.c
 +++ b/libavutil/hwcontext_drm.c
-@@ -43,6 +43,11 @@ static int drm_device_create(AVHWDeviceContext *hwdev, const char *device,
+@@ -53,6 +53,11 @@ static int drm_device_create(AVHWDeviceContext *hwdev, const char *device,
      AVDRMDeviceContext *hwctx = hwdev->hwctx;
      drmVersionPtr version;
  
@@ -1938,17 +3194,105 @@ index 32cbde82ebfa..aa4794c5e665 100644
      hwctx->fd = open(device, O_RDWR);
      if (hwctx->fd < 0)
          return AVERROR(errno);
-From fa7165e391287bf970569e36b0b19bff947b084f Mon Sep 17 00:00:00 2001
+
+From 154405d2d8987c741e722f59430fda9326c8cdef Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <jonas at kwiboo.se>
+Date: Fri, 15 May 2020 16:54:05 +0000
+Subject: [PATCH 13/17] WIP: add NV15 and NV20 support
+
+Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
+---
+ libavcodec/h264_slice.c   | 14 ++++++++++++--
+ libavcodec/v4l2_request.c | 23 +++++++++++++++++++++++
+ 2 files changed, 35 insertions(+), 2 deletions(-)
+
+diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
+index 0a10d00aad9..45057fd049b 100644
+--- a/libavcodec/h264_slice.c
++++ b/libavcodec/h264_slice.c
+@@ -794,10 +794,17 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
+                 *fmt++ = AV_PIX_FMT_GBRP10;
+             } else
+                 *fmt++ = AV_PIX_FMT_YUV444P10;
+-        } else if (CHROMA422(h))
++        } else if (CHROMA422(h)) {
++#if CONFIG_H264_V4L2REQUEST_HWACCEL
++            *fmt++ = AV_PIX_FMT_DRM_PRIME;
++#endif
+             *fmt++ = AV_PIX_FMT_YUV422P10;
+-        else
++        } else {
++#if CONFIG_H264_V4L2REQUEST_HWACCEL
++            *fmt++ = AV_PIX_FMT_DRM_PRIME;
++#endif
+             *fmt++ = AV_PIX_FMT_YUV420P10;
++        }
+         break;
+     case 12:
+         if (CHROMA444(h)) {
+@@ -836,6 +843,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
+             else
+                 *fmt++ = AV_PIX_FMT_YUV444P;
+         } else if (CHROMA422(h)) {
++#if CONFIG_H264_V4L2REQUEST_HWACCEL
++                *fmt++ = AV_PIX_FMT_DRM_PRIME;
++#endif
+             if (h->avctx->color_range == AVCOL_RANGE_JPEG)
+                 *fmt++ = AV_PIX_FMT_YUVJ422P;
+             else
+diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
+index 5234b5049b0..0b294feff2e 100644
+--- a/libavcodec/v4l2_request.c
++++ b/libavcodec/v4l2_request.c
+@@ -188,6 +188,13 @@ const uint32_t v4l2_request_capture_pixelformats[] = {
+ #ifdef DRM_FORMAT_MOD_ALLWINNER_TILED
+     V4L2_PIX_FMT_SUNXI_TILED_NV12,
+ #endif
++#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15)
++    V4L2_PIX_FMT_NV15,
++#endif
++    V4L2_PIX_FMT_NV16,
++#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20)
++    V4L2_PIX_FMT_NV20,
++#endif
+ };
+ 
+ static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4l2_format *format)
+@@ -206,6 +213,22 @@ static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4
+         layer->format = DRM_FORMAT_NV12;
+         desc->objects[0].format_modifier = DRM_FORMAT_MOD_ALLWINNER_TILED;
+         break;
++#endif
++#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15)
++    case V4L2_PIX_FMT_NV15:
++        layer->format = DRM_FORMAT_NV15;
++        desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR;
++        break;
++#endif
++    case V4L2_PIX_FMT_NV16:
++        layer->format = DRM_FORMAT_NV16;
++        desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR;
++        break;
++#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20)
++    case V4L2_PIX_FMT_NV20:
++        layer->format = DRM_FORMAT_NV20;
++        desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR;
++        break;
+ #endif
+     default:
+         return -1;
+
+From d7933e19a712a59af418f6b029c0984d5b29afe9 Mon Sep 17 00:00:00 2001
 From: Jonas Karlman <jonas at kwiboo.se>
 Date: Mon, 27 Jul 2020 23:15:45 +0000
-Subject: [PATCH] HACK: define drm NV15 and NV20 format
+Subject: [PATCH 14/17] HACK: define drm NV15 and NV20 format
 
 ---
  libavcodec/v4l2_request.c | 8 ++++++++
  1 file changed, 8 insertions(+)
 
 diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
-index 0b294feff2eb..a8f0ee79eeef 100644
+index 0b294feff2e..a8f0ee79eee 100644
 --- a/libavcodec/v4l2_request.c
 +++ b/libavcodec/v4l2_request.c
 @@ -30,6 +30,14 @@
@@ -1966,3 +3310,248 @@ index 0b294feff2eb..a8f0ee79eeef 100644
  uint64_t ff_v4l2_request_get_capture_timestamp(AVFrame *frame)
  {
      V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0];
+
+From c9ae9a29ef84096bb2e4d37fbdea6c3b3d20fff7 Mon Sep 17 00:00:00 2001
+From: Alex Bee <knaerzche at gmail.com>
+Date: Sun, 19 Sep 2021 13:10:55 +0200
+Subject: [PATCH 16/17] v4l2_request: validate supported framesizes
+
+Signed-off-by: Alex Bee <knaerzche at gmail.com>
+---
+ libavcodec/v4l2_request.c | 38 +++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 37 insertions(+), 1 deletion(-)
+
+diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
+index a8f0ee79eee..2fbe1663416 100644
+--- a/libavcodec/v4l2_request.c
++++ b/libavcodec/v4l2_request.c
+@@ -376,6 +376,42 @@ int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v
+     return v4l2_request_queue_decode(avctx, frame, control, count, 1, 1);
+ }
+ 
++static int v4l2_request_try_framesize(AVCodecContext *avctx, uint32_t pixelformat)
++{
++    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
++    struct v4l2_frmsizeenum frmsize = {
++        .index = 0,
++        .pixel_format = pixelformat,
++    };
++
++    if (ioctl(ctx->video_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) < 0)
++        return 0;
++
++    /*
++     * We only validate min/max framesize for V4L2_FRMSIZE_TYPE_STEPWISE here, since the alignment
++     * which is eventually needed will be done driver-side later in VIDIOC_S_FMT and there is no need
++     * validate step_width/step_height here
++     */
++
++    do {
++
++        if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE && frmsize.discrete.width == avctx->coded_width &&
++            frmsize.discrete.height == avctx->coded_height)
++            return 0;
++        else if ((frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE || frmsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) &&
++                 avctx->coded_width >= frmsize.stepwise.min_width && avctx->coded_height >= frmsize.stepwise.min_height &&
++                 avctx->coded_width <= frmsize.stepwise.max_width && avctx->coded_height <= frmsize.stepwise.max_height)
++            return 0;
++
++        frmsize.index++;
++
++    } while (ioctl(ctx->video_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0);
++
++    av_log(avctx, AV_LOG_INFO, "%s: pixelformat %u not supported for width %u height %u\n", __func__, pixelformat, avctx->coded_width, avctx->coded_height);
++
++    return -1;
++}
++
+ static int v4l2_request_try_format(AVCodecContext *avctx, enum v4l2_buf_type type, uint32_t pixelformat)
+ {
+     V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
+@@ -404,7 +440,7 @@ static int v4l2_request_try_format(AVCodecContext *avctx, enum v4l2_buf_type typ
+ 
+     while (ioctl(ctx->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) >= 0) {
+         if (fmtdesc.pixelformat == pixelformat)
+-            return 0;
++            return v4l2_request_try_framesize(avctx, pixelformat);
+ 
+         fmtdesc.index++;
+     }
+
+From c415926540fe04141bb1e8cabd24049b61752d4f Mon Sep 17 00:00:00 2001
+From: Jernej Skrabec <jernej.skrabec at gmail.com>
+Date: Sun, 27 Feb 2022 18:54:21 +0100
+Subject: [PATCH 17/17] Improve VP9 decoding
+
+---
+ libavcodec/v4l2_request_vp9.c | 110 +++++++++++++++++++---------------
+ 1 file changed, 62 insertions(+), 48 deletions(-)
+
+diff --git a/libavcodec/v4l2_request_vp9.c b/libavcodec/v4l2_request_vp9.c
+index 9b95c76cdb8..ec0300f66db 100644
+--- a/libavcodec/v4l2_request_vp9.c
++++ b/libavcodec/v4l2_request_vp9.c
+@@ -22,78 +22,62 @@
+ 
+ typedef struct V4L2RequestControlsVP9 {
+     struct v4l2_ctrl_vp9_frame decode_params;
++    struct v4l2_ctrl_vp9_compressed_hdr chp;
+ } V4L2RequestControlsVP9;
+ 
+-static int v4l2_request_vp9_set_frame_ctx(AVCodecContext *avctx)
++static void v4l2_request_vp9_set_frame_ctx(AVCodecContext *avctx)
+ {
+     VP9Context *s = avctx->priv_data;
+-    struct v4l2_ctrl_vp9_compressed_hdr chp;
+-    struct v4l2_ext_control control[] = {
+-        {
+-            .id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR,
+-            .ptr = &chp,
+-            .size = sizeof(chp),
+-        },
+-    };
++    const VP9Frame *f = &s->s.frames[CUR_FRAME];
++    V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private;
++    struct v4l2_ctrl_vp9_compressed_hdr *chp = &controls->chp;
+ 
+-    memset(&chp, 0, sizeof(chp));
++    memset(chp, 0, sizeof(&chp));
+ 
+-    chp.tx_mode = s->s.h.txfmmode;
+-    memcpy(chp.tx8, s->prob_raw.p.tx8p, sizeof(s->prob_raw.p.tx8p));
+-    memcpy(chp.tx16, s->prob_raw.p.tx16p, sizeof(s->prob_raw.p.tx16p));
+-    memcpy(chp.tx32, s->prob_raw.p.tx32p, sizeof(s->prob_raw.p.tx32p));
++    chp->tx_mode = s->s.h.txfmmode;
++    memcpy(chp->tx8, s->prob_raw.p.tx8p, sizeof(s->prob_raw.p.tx8p));
++    memcpy(chp->tx16, s->prob_raw.p.tx16p, sizeof(s->prob_raw.p.tx16p));
++    memcpy(chp->tx32, s->prob_raw.p.tx32p, sizeof(s->prob_raw.p.tx32p));
+     for (unsigned i = 0; i < 4; i++) {
+         for (unsigned j = 0; j < 2; j++) {
+             for (unsigned k = 0; k < 2; k++) {
+                 for (unsigned l = 0; l < 6; l++) {
+                     for (unsigned m = 0; m < 6; m++) {
+-                        memcpy(chp.coef[i][j][k][l][m], s->prob_raw.coef[i][j][k][l][m], sizeof(chp.coef[0][0][0][0][0]));
++                        memcpy(chp->coef[i][j][k][l][m], s->prob_raw.coef[i][j][k][l][m], sizeof(chp->coef[0][0][0][0][0]));
+                     }
+                 }
+             }
+         }
+     }
+-    memcpy(chp.skip, s->prob_raw.p.skip, sizeof(s->prob_raw.p.skip));
+-    memcpy(chp.inter_mode, s->prob_raw.p.mv_mode, sizeof(s->prob_raw.p.mv_mode));
+-    memcpy(chp.interp_filter, s->prob_raw.p.filter, sizeof(s->prob_raw.p.filter));
+-    memcpy(chp.is_inter, s->prob_raw.p.intra, sizeof(s->prob_raw.p.intra));
+-    memcpy(chp.comp_mode, s->prob_raw.p.comp, sizeof(s->prob_raw.p.comp));
+-    memcpy(chp.single_ref, s->prob_raw.p.single_ref, sizeof(s->prob_raw.p.single_ref));
+-    memcpy(chp.comp_ref, s->prob_raw.p.comp_ref, sizeof(s->prob_raw.p.comp_ref));
+-    memcpy(chp.y_mode, s->prob_raw.p.y_mode, sizeof(s->prob_raw.p.y_mode));
++    memcpy(chp->skip, s->prob_raw.p.skip, sizeof(s->prob_raw.p.skip));
++    memcpy(chp->inter_mode, s->prob_raw.p.mv_mode, sizeof(s->prob_raw.p.mv_mode));
++    memcpy(chp->interp_filter, s->prob_raw.p.filter, sizeof(s->prob_raw.p.filter));
++    memcpy(chp->is_inter, s->prob_raw.p.intra, sizeof(s->prob_raw.p.intra));
++    memcpy(chp->comp_mode, s->prob_raw.p.comp, sizeof(s->prob_raw.p.comp));
++    memcpy(chp->single_ref, s->prob_raw.p.single_ref, sizeof(s->prob_raw.p.single_ref));
++    memcpy(chp->comp_ref, s->prob_raw.p.comp_ref, sizeof(s->prob_raw.p.comp_ref));
++    memcpy(chp->y_mode, s->prob_raw.p.y_mode, sizeof(s->prob_raw.p.y_mode));
+     for (unsigned i = 0; i < 10; i++)
+-        memcpy(chp.uv_mode[i], s->prob.p.uv_mode[i], sizeof(s->prob.p.uv_mode[0]));
++        memcpy(chp->uv_mode[i], s->prob.p.uv_mode[i], sizeof(s->prob.p.uv_mode[0]));
+     for (unsigned i = 0; i < 4; i++)
+-        memcpy(chp.partition[i * 4], s->prob_raw.p.partition[i], sizeof(s->prob_raw.p.partition[0]));
+-    memcpy(chp.mv.joint, s->prob_raw.p.mv_joint, sizeof(s->prob_raw.p.mv_joint));
++        memcpy(chp->partition[i * 4], s->prob_raw.p.partition[i], sizeof(s->prob_raw.p.partition[0]));
++    memcpy(chp->mv.joint, s->prob_raw.p.mv_joint, sizeof(s->prob_raw.p.mv_joint));
+     for (unsigned i = 0; i < 2; i++) {
+-         chp.mv.sign[i] = s->prob_raw.p.mv_comp[i].sign;
+-         memcpy(chp.mv.classes[i], s->prob_raw.p.mv_comp[i].classes, sizeof(s->prob_raw.p.mv_comp[0].classes));
+-         chp.mv.class0_bit[i] = s->prob_raw.p.mv_comp[i].class0;
+-         memcpy(chp.mv.bits[i], s->prob_raw.p.mv_comp[i].bits, sizeof(s->prob_raw.p.mv_comp[0].bits));
+-         memcpy(chp.mv.class0_fr[i], s->prob_raw.p.mv_comp[i].class0_fp, sizeof(s->prob_raw.p.mv_comp[0].class0_fp));
+-         memcpy(chp.mv.fr[i], s->prob_raw.p.mv_comp[i].fp, sizeof(s->prob_raw.p.mv_comp[0].fp));
+-         chp.mv.class0_hp[i] = s->prob_raw.p.mv_comp[i].class0_hp;
+-         chp.mv.hp[i] = s->prob_raw.p.mv_comp[i].hp;
++         chp->mv.sign[i] = s->prob_raw.p.mv_comp[i].sign;
++         memcpy(chp->mv.classes[i], s->prob_raw.p.mv_comp[i].classes, sizeof(s->prob_raw.p.mv_comp[0].classes));
++         chp->mv.class0_bit[i] = s->prob_raw.p.mv_comp[i].class0;
++         memcpy(chp->mv.bits[i], s->prob_raw.p.mv_comp[i].bits, sizeof(s->prob_raw.p.mv_comp[0].bits));
++         memcpy(chp->mv.class0_fr[i], s->prob_raw.p.mv_comp[i].class0_fp, sizeof(s->prob_raw.p.mv_comp[0].class0_fp));
++         memcpy(chp->mv.fr[i], s->prob_raw.p.mv_comp[i].fp, sizeof(s->prob_raw.p.mv_comp[0].fp));
++         chp->mv.class0_hp[i] = s->prob_raw.p.mv_comp[i].class0_hp;
++         chp->mv.hp[i] = s->prob_raw.p.mv_comp[i].hp;
+     }
+-
+-    return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control));
+ }
+ 
+-static int v4l2_request_vp9_start_frame(AVCodecContext *avctx,
+-                                        av_unused const uint8_t *buffer,
+-                                        av_unused uint32_t size)
++static void fill_frame(struct v4l2_ctrl_vp9_frame *dec_params, AVCodecContext *avctx)
+ {
+     const VP9Context *s = avctx->priv_data;
+-    const VP9Frame *f = &s->s.frames[CUR_FRAME];
+-    V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private;
+-    struct v4l2_ctrl_vp9_frame *dec_params = &controls->decode_params;
+     const ThreadFrame *ref;
+-    int ret;
+-
+-    ret = v4l2_request_vp9_set_frame_ctx(avctx);
+-    if (ret)
+-	return ret;
+ 
+     memset(dec_params, 0, sizeof(*dec_params));
+ 
+@@ -208,6 +192,19 @@ static int v4l2_request_vp9_start_frame(AVCodecContext *avctx,
+         if (s->s.h.segmentation.feat[i].skip_enabled)
+             dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEG_LVL_SKIP;
+     }
++}
++
++static int v4l2_request_vp9_start_frame(AVCodecContext *avctx,
++                                        av_unused const uint8_t *buffer,
++                                        av_unused uint32_t size)
++{
++    const VP9Context *s = avctx->priv_data;
++    const VP9Frame *f = &s->s.frames[CUR_FRAME];
++    V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private;
++
++    v4l2_request_vp9_set_frame_ctx(avctx);
++
++    fill_frame(&controls->decode_params, avctx);
+ 
+     return ff_v4l2_request_reset_frame(avctx, f->tf.f);
+ }
+@@ -233,6 +230,11 @@ static int v4l2_request_vp9_end_frame(AVCodecContext *avctx)
+             .ptr = &controls->decode_params,
+             .size = sizeof(controls->decode_params),
+         },
++        {
++            .id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR,
++            .ptr = &controls->chp,
++            .size = sizeof(controls->chp),
++        },
+     };
+ 
+     ret = ff_v4l2_request_decode_frame(avctx, f->tf.f, control, FF_ARRAY_ELEMS(control));
+@@ -247,8 +249,20 @@ static int v4l2_request_vp9_end_frame(AVCodecContext *avctx)
+ 
+ static int v4l2_request_vp9_init(AVCodecContext *avctx)
+ {
++    struct v4l2_ctrl_vp9_frame frame;
++
++    struct v4l2_ext_control control[] = {
++        {
++            .id = V4L2_CID_STATELESS_VP9_FRAME,
++            .ptr = &frame,
++            .size = sizeof(frame),
++        },
++    };
++
++    fill_frame(&frame, avctx);
++
+     // TODO: check V4L2_CID_MPEG_VIDEO_VP9_PROFILE
+-    return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP9_FRAME, 3 * 1024 * 1024, NULL, 0);
++    return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP9_FRAME, 3 * 1024 * 1024, control, FF_ARRAY_ELEMS(control));
+ }
+ 
+ const AVHWAccel ff_vp9_v4l2request_hwaccel = {
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/ffmpeg.git/commitdiff/98d75c054e78c405360de46a3ccc01fca9974fe1




More information about the pld-cvs-commit mailing list