]> git.pld-linux.org Git - packages/ffmpeg.git/blob - v4l2-request-hwdec.patch
- added patch for vulkan sdk 1.3.280, note on ffmpeg 7
[packages/ffmpeg.git] / v4l2-request-hwdec.patch
1 From 8b34700cbd43b18950dc81cceb958d0b39126806 Mon Sep 17 00:00:00 2001
2 From: Jonas Karlman <jonas@kwiboo.se>
3 Date: Mon, 3 Dec 2018 23:48:04 +0100
4 Subject: [PATCH 01/18] avutil: add av_buffer_pool_flush()
5
6 Used by V4L2 request API hwaccel
7
8 Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
9 ---
10  libavutil/buffer.c | 13 +++++++++++++
11  libavutil/buffer.h |  5 +++++
12  2 files changed, 18 insertions(+)
13
14 diff --git a/libavutil/buffer.c b/libavutil/buffer.c
15 index e4562a7..09da632 100644
16 --- a/libavutil/buffer.c
17 +++ b/libavutil/buffer.c
18 @@ -319,6 +319,19 @@ static void buffer_pool_free(AVBufferPool *pool)
19      av_freep(&pool);
20  }
21  
22 +void av_buffer_pool_flush(AVBufferPool *pool)
23 +{
24 +    ff_mutex_lock(&pool->mutex);
25 +    while (pool->pool) {
26 +        BufferPoolEntry *buf = pool->pool;
27 +        pool->pool = buf->next;
28 +
29 +        buf->free(buf->opaque, buf->data);
30 +        av_freep(&buf);
31 +    }
32 +    ff_mutex_unlock(&pool->mutex);
33 +}
34 +
35  void av_buffer_pool_uninit(AVBufferPool **ppool)
36  {
37      AVBufferPool *pool;
38 diff --git a/libavutil/buffer.h b/libavutil/buffer.h
39 index e1ef5b7..fde9bae 100644
40 --- a/libavutil/buffer.h
41 +++ b/libavutil/buffer.h
42 @@ -284,6 +284,11 @@ AVBufferPool *av_buffer_pool_init2(size_t size, void *opaque,
43                                     AVBufferRef* (*alloc)(void *opaque, size_t size),
44                                     void (*pool_free)(void *opaque));
45  
46 +/**
47 + * Free all available buffers in a buffer pool.
48 + */
49 + void av_buffer_pool_flush(AVBufferPool *pool);
50 +
51  /**
52   * Mark the pool as being available for freeing. It will actually be freed only
53   * once all the allocated buffers associated with the pool are released. Thus it
54 -- 
55 2.44.0
56
57
58 From da33bb8f94c073c8fb6dc7a3f3efe72d78b64a14 Mon Sep 17 00:00:00 2001
59 From: Jonas Karlman <jonas@kwiboo.se>
60 Date: Sat, 15 Dec 2018 22:32:16 +0100
61 Subject: [PATCH 02/18] Add common V4L2 request API code
62
63 Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
64 Signed-off-by: Alex Bee <knaerzche@gmail.com>
65 ---
66  configure                 |   12 +
67  libavcodec/Makefile       |    1 +
68  libavcodec/hwconfig.h     |    2 +
69  libavcodec/v4l2_request.c | 1048 +++++++++++++++++++++++++++++++++++++
70  libavcodec/v4l2_request.h |   78 +++
71  5 files changed, 1141 insertions(+)
72  create mode 100644 libavcodec/v4l2_request.c
73  create mode 100644 libavcodec/v4l2_request.h
74
75 diff --git a/configure b/configure
76 index a89cfa6..503eb06 100755
77 --- a/configure
78 +++ b/configure
79 @@ -279,6 +279,7 @@ External library support:
80                             if openssl, gnutls or mbedtls is not used [no]
81    --enable-libtwolame      enable MP2 encoding via libtwolame [no]
82    --enable-libuavs3d       enable AVS3 decoding via libuavs3d [no]
83 +  --enable-libudev         enable libudev [no]
84    --enable-libv4l2         enable libv4l2/v4l-utils [no]
85    --enable-libvidstab      enable video stabilization using vid.stab [no]
86    --enable-libvmaf         enable vmaf filter via libvmaf [no]
87 @@ -347,6 +348,7 @@ External library support:
88    --enable-omx-rpi         enable OpenMAX IL code for Raspberry Pi [no]
89    --enable-rkmpp           enable Rockchip Media Process Platform code [no]
90    --disable-v4l2-m2m       disable V4L2 mem2mem code [autodetect]
91 +  --enable-v4l2-request    enable V4L2 request API code [no]
92    --disable-vaapi          disable Video Acceleration API (mainly Unix/Intel) code [autodetect]
93    --disable-vdpau          disable Nvidia Video Decode and Presentation API for Unix code [autodetect]
94    --disable-videotoolbox   disable VideoToolbox code [autodetect]
95 @@ -1896,6 +1898,7 @@ EXTERNAL_LIBRARY_LIST="
96      libtheora
97      libtwolame
98      libuavs3d
99 +    libudev
100      libv4l2
101      libvmaf
102      libvorbis
103 @@ -1952,6 +1955,7 @@ HWACCEL_LIBRARY_LIST="
104      mmal
105      omx
106      opencl
107 +    v4l2_request
108  "
109  
110  DOCUMENT_LIST="
111 @@ -3045,6 +3049,7 @@ dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32"
112  ffnvcodec_deps_any="libdl LoadLibrary"
113  mediacodec_deps="android"
114  nvdec_deps="ffnvcodec"
115 +v4l2_request_deps="linux_videodev2_h linux_media_h v4l2_timeval_to_ns libdrm libudev"
116  vaapi_x11_deps="xlib_x11"
117  videotoolbox_hwaccel_deps="videotoolbox pthreads"
118  videotoolbox_hwaccel_extralibs="-framework QuartzCore"
119 @@ -6807,6 +6812,7 @@ enabled libtwolame        && require libtwolame twolame.h twolame_init -ltwolame
120                               { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame ||
121                                 die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; }
122  enabled libuavs3d         && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode
123 +enabled libudev           && require_pkg_config libudev libudev libudev.h udev_new
124  enabled libv4l2           && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl
125  enabled libvidstab        && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit
126  enabled libvmaf           && require_pkg_config libvmaf "libvmaf >= 2.0.0" libvmaf.h vmaf_init
127 @@ -6910,6 +6916,10 @@ enabled rkmpp             && { require_pkg_config rkmpp rockchip_mpp  rockchip/r
128                                 { enabled libdrm ||
129                                   die "ERROR: rkmpp requires --enable-libdrm"; }
130                               }
131 +enabled v4l2_request      && { enabled libdrm ||
132 +                               die "ERROR: v4l2-request requires --enable-libdrm"; } &&
133 +                             { enabled libudev ||
134 +                               die "ERROR: v4l2-request requires --enable-libudev"; }
135  enabled vapoursynth       && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init
136  
137  
138 @@ -6992,6 +7002,8 @@ if enabled v4l2_m2m; then
139      check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;"
140  fi
141  
142 +check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
143 +
144  check_headers sys/videoio.h
145  test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
146  
147 diff --git a/libavcodec/Makefile b/libavcodec/Makefile
148 index ec57e53..5e626c9 100644
149 --- a/libavcodec/Makefile
150 +++ b/libavcodec/Makefile
151 @@ -169,6 +169,7 @@ OBJS-$(CONFIG_VP3DSP)                  += vp3dsp.o
152  OBJS-$(CONFIG_VP56DSP)                 += vp56dsp.o
153  OBJS-$(CONFIG_VP8DSP)                  += vp8dsp.o
154  OBJS-$(CONFIG_V4L2_M2M)                += v4l2_m2m.o v4l2_context.o v4l2_buffers.o v4l2_fmt.o
155 +OBJS-$(CONFIG_V4L2_REQUEST)            += v4l2_request.o
156  OBJS-$(CONFIG_WMA_FREQS)               += wma_freqs.o
157  OBJS-$(CONFIG_WMV2DSP)                 += wmv2dsp.o
158  
159 diff --git a/libavcodec/hwconfig.h b/libavcodec/hwconfig.h
160 index e164722..ebafb6f 100644
161 --- a/libavcodec/hwconfig.h
162 +++ b/libavcodec/hwconfig.h
163 @@ -77,6 +77,8 @@ void ff_hwaccel_uninit(AVCodecContext *avctx);
164      HW_CONFIG_HWACCEL(1, 1, 1, VULKAN,       VULKAN,       ff_ ## codec ## _vulkan_hwaccel)
165  #define HWACCEL_D3D11VA(codec) \
166      HW_CONFIG_HWACCEL(0, 0, 1, D3D11VA_VLD,  NONE,         ff_ ## codec ## _d3d11va_hwaccel)
167 +#define HWACCEL_V4L2REQUEST(codec) \
168 +    HW_CONFIG_HWACCEL(1, 0, 0, DRM_PRIME,    DRM,          ff_ ## codec ## _v4l2request_hwaccel)
169  
170  #define HW_CONFIG_ENCODER(device, frames, ad_hoc, format, device_type_) \
171      &(const AVCodecHWConfigInternal) { \
172 diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
173 new file mode 100644
174 index 0000000..595a53e
175 --- /dev/null
176 +++ b/libavcodec/v4l2_request.c
177 @@ -0,0 +1,1048 @@
178 +/*
179 + * This file is part of FFmpeg.
180 + *
181 + * FFmpeg is free software; you can redistribute it and/or
182 + * modify it under the terms of the GNU Lesser General Public
183 + * License as published by the Free Software Foundation; either
184 + * version 2.1 of the License, or (at your option) any later version.
185 + *
186 + * FFmpeg is distributed in the hope that it will be useful,
187 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
188 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
189 + * Lesser General Public License for more details.
190 + *
191 + * You should have received a copy of the GNU Lesser General Public
192 + * License along with FFmpeg; if not, write to the Free Software
193 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
194 + */
195 +
196 +#include <drm_fourcc.h>
197 +#include <fcntl.h>
198 +#include <libudev.h>
199 +#include <linux/media.h>
200 +#include <sys/ioctl.h>
201 +#include <sys/mman.h>
202 +#include <sys/stat.h>
203 +#include <sys/sysmacros.h>
204 +#include <sys/types.h>
205 +#include <unistd.h>
206 +
207 +#include "decode.h"
208 +#include "internal.h"
209 +#include "v4l2_request.h"
210 +
211 +static const AVClass v4l2_request_context_class = {
212 +    .class_name = "V4L2RequestContext",
213 +    .item_name  = av_default_item_name,
214 +    .version    = LIBAVUTIL_VERSION_INT,
215 +};
216 +
217 +uint64_t ff_v4l2_request_get_capture_timestamp(AVFrame *frame)
218 +{
219 +    V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0];
220 +    return req ? v4l2_timeval_to_ns(&req->capture.buffer.timestamp) : 0;
221 +}
222 +
223 +int ff_v4l2_request_reset_frame(AVCodecContext *avctx, AVFrame *frame)
224 +{
225 +    V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0];
226 +    memset(&req->drm, 0, sizeof(AVDRMFrameDescriptor));
227 +    req->output.used = 0;
228 +    return 0;
229 +}
230 +
231 +int ff_v4l2_request_append_output_buffer(AVCodecContext *avctx, AVFrame *frame, const uint8_t *data, uint32_t size)
232 +{
233 +    V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0];
234 +    if (req->output.used + size + (AV_INPUT_BUFFER_PADDING_SIZE * 4) <= req->output.size) {
235 +        memcpy(req->output.addr + req->output.used, data, size);
236 +        req->output.used += size;
237 +    } else {
238 +        av_log(avctx, AV_LOG_ERROR, "%s: output.used=%u output.size=%u size=%u\n", __func__, req->output.used, req->output.size, size);
239 +    }
240 +    return 0;
241 +}
242 +
243 +static int v4l2_request_controls(V4L2RequestContext *ctx, int request_fd, unsigned long type, struct v4l2_ext_control *control, int count)
244 +{
245 +    struct v4l2_ext_controls controls = {
246 +        .controls = control,
247 +        .count = count,
248 +        .request_fd = request_fd,
249 +        .which = (request_fd >= 0) ? V4L2_CTRL_WHICH_REQUEST_VAL : 0,
250 +    };
251 +
252 +    if (!control || !count)
253 +        return 0;
254 +
255 +    return ioctl(ctx->video_fd, type, &controls);
256 +}
257 +
258 +static int v4l2_request_set_controls(V4L2RequestContext *ctx, int request_fd, struct v4l2_ext_control *control, int count)
259 +{
260 +    return v4l2_request_controls(ctx, request_fd, VIDIOC_S_EXT_CTRLS, control, count);
261 +}
262 +
263 +int ff_v4l2_request_set_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count)
264 +{
265 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
266 +    int ret;
267 +
268 +    ret = v4l2_request_controls(ctx, -1, VIDIOC_S_EXT_CTRLS, control, count);
269 +    if (ret < 0) {
270 +        av_log(avctx, AV_LOG_ERROR, "%s: set controls failed, %s (%d)\n", __func__, strerror(errno), errno);
271 +        return AVERROR(EINVAL);
272 +    }
273 +
274 +    return ret;
275 +}
276 +
277 +int ff_v4l2_request_get_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count)
278 +{
279 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
280 +    int ret;
281 +
282 +    ret = v4l2_request_controls(ctx, -1, VIDIOC_G_EXT_CTRLS, control, count);
283 +    if (ret < 0) {
284 +        av_log(avctx, AV_LOG_ERROR, "%s: get controls failed, %s (%d)\n", __func__, strerror(errno), errno);
285 +        return AVERROR(EINVAL);
286 +    }
287 +
288 +    return ret;
289 +}
290 +
291 +int ff_v4l2_request_query_control(AVCodecContext *avctx, struct v4l2_query_ext_ctrl *control)
292 +{
293 +    int ret;
294 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
295 +
296 +    ret = ioctl(ctx->video_fd, VIDIOC_QUERY_EXT_CTRL, control);
297 +    if (ret < 0) {
298 +        av_log(avctx, AV_LOG_ERROR, "%s: query control failed, %s (%d)\n", __func__, strerror(errno), errno);
299 +        return AVERROR(EINVAL);
300 +    }
301 +
302 +    return 0;
303 +}
304 +
305 +int ff_v4l2_request_query_control_default_value(AVCodecContext *avctx, uint32_t id)
306 +{
307 +    int ret;
308 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
309 +    struct v4l2_queryctrl control = {
310 +        .id = id,
311 +    };
312 +
313 +    ret = ioctl(ctx->video_fd, VIDIOC_QUERYCTRL, &control);
314 +    if (ret < 0) {
315 +        av_log(avctx, AV_LOG_ERROR, "%s: query control failed, %s (%d)\n", __func__, strerror(errno), errno);
316 +        return AVERROR(EINVAL);
317 +    }
318 +
319 +    return control.default_value;
320 +}
321 +
322 +static int v4l2_request_queue_buffer(V4L2RequestContext *ctx, int request_fd, V4L2RequestBuffer *buf, uint32_t flags)
323 +{
324 +    struct v4l2_plane planes[1] = {};
325 +    struct v4l2_buffer buffer = {
326 +        .type = buf->buffer.type,
327 +        .memory = buf->buffer.memory,
328 +        .index = buf->index,
329 +        .timestamp.tv_usec = buf->index + 1,
330 +        .bytesused = buf->used,
331 +        .request_fd = request_fd,
332 +        .flags = ((request_fd >= 0) ? V4L2_BUF_FLAG_REQUEST_FD : 0) | flags,
333 +    };
334 +
335 +    if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) {
336 +        planes[0].bytesused = buf->used;
337 +        buffer.bytesused = 0;
338 +        buffer.length = 1;
339 +        buffer.m.planes = planes;
340 +    }
341 +
342 +    return ioctl(ctx->video_fd, VIDIOC_QBUF, &buffer);
343 +}
344 +
345 +static int v4l2_request_dequeue_buffer(V4L2RequestContext *ctx, V4L2RequestBuffer *buf)
346 +{
347 +    int ret;
348 +    struct v4l2_plane planes[1] = {};
349 +    struct v4l2_buffer buffer = {
350 +        .type = buf->buffer.type,
351 +        .memory = buf->buffer.memory,
352 +        .index = buf->index,
353 +    };
354 +
355 +    if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) {
356 +        buffer.length = 1;
357 +        buffer.m.planes = planes;
358 +    }
359 +
360 +    ret = ioctl(ctx->video_fd, VIDIOC_DQBUF, &buffer);
361 +    if (ret < 0)
362 +        return ret;
363 +
364 +    buf->buffer.timestamp = buffer.timestamp;
365 +    return 0;
366 +}
367 +
368 +static const struct {
369 +    uint32_t pixelformat;
370 +    enum AVPixelFormat sw_format;
371 +    uint32_t drm_format;
372 +    uint64_t format_modifier;
373 +} v4l2_request_capture_pixelformats[] = {
374 +    { V4L2_PIX_FMT_NV12, AV_PIX_FMT_NV12, DRM_FORMAT_NV12, DRM_FORMAT_MOD_LINEAR },
375 +    { V4L2_PIX_FMT_SUNXI_TILED_NV12, AV_PIX_FMT_NV12, DRM_FORMAT_NV12, DRM_FORMAT_MOD_ALLWINNER_TILED },
376 +};
377 +
378 +static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4l2_format *format)
379 +{
380 +    AVDRMFrameDescriptor *desc = &req->drm;
381 +    AVDRMLayerDescriptor *layer = &desc->layers[0];
382 +    uint32_t pixelformat = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.pixelformat : format->fmt.pix.pixelformat;
383 +
384 +    layer->format = 0;
385 +    for (int i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) {
386 +        if (pixelformat == v4l2_request_capture_pixelformats[i].pixelformat) {
387 +            layer->format = v4l2_request_capture_pixelformats[i].drm_format;
388 +            desc->objects[0].format_modifier = v4l2_request_capture_pixelformats[i].format_modifier;
389 +            break;
390 +        }
391 +    }
392 +
393 +    if (!layer->format)
394 +        return -1;
395 +
396 +    desc->nb_objects = 1;
397 +    desc->objects[0].fd = req->capture.fd;
398 +    desc->objects[0].size = req->capture.size;
399 +
400 +    desc->nb_layers = 1;
401 +    layer->nb_planes = 2;
402 +
403 +    layer->planes[0].object_index = 0;
404 +    layer->planes[0].offset = 0;
405 +    layer->planes[0].pitch = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.plane_fmt[0].bytesperline : format->fmt.pix.bytesperline;
406 +
407 +    layer->planes[1].object_index = 0;
408 +    layer->planes[1].offset = layer->planes[0].pitch * (V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.height : format->fmt.pix.height);
409 +    layer->planes[1].pitch = layer->planes[0].pitch;
410 +
411 +    return 0;
412 +}
413 +
414 +static int v4l2_request_queue_decode(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice)
415 +{
416 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
417 +    V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0];
418 +    struct timeval tv = { 2, 0 };
419 +    fd_set except_fds;
420 +    int ret;
421 +
422 +    av_log(avctx, AV_LOG_DEBUG, "%s: ctx=%p used=%u controls=%d index=%d fd=%d request_fd=%d first_slice=%d last_slice=%d\n", __func__,
423 +           ctx, req->output.used, count, req->capture.index, req->capture.fd, req->request_fd, first_slice, last_slice);
424 +
425 +    ret = v4l2_request_set_controls(ctx, req->request_fd, control, count);
426 +    if (ret < 0) {
427 +        av_log(avctx, AV_LOG_ERROR, "%s: set controls failed for request %d, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno);
428 +        return -1;
429 +    }
430 +
431 +    memset(req->output.addr + req->output.used, 0, AV_INPUT_BUFFER_PADDING_SIZE * 4);
432 +
433 +    ret = v4l2_request_queue_buffer(ctx, req->request_fd, &req->output, last_slice ? 0 : V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF);
434 +    if (ret < 0) {
435 +        av_log(avctx, AV_LOG_ERROR, "%s: queue output buffer %d failed for request %d, %s (%d)\n", __func__, req->output.index, req->request_fd, strerror(errno), errno);
436 +        return -1;
437 +    }
438 +
439 +    if (first_slice) {
440 +        ret = v4l2_request_queue_buffer(ctx, -1, &req->capture, 0);
441 +        if (ret < 0) {
442 +            av_log(avctx, AV_LOG_ERROR, "%s: queue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno);
443 +            return -1;
444 +        }
445 +    }
446 +
447 +    // NOTE: do we need to dequeue when request fails/timeout?
448 +
449 +    // 4. queue request and wait
450 +    ret = ioctl(req->request_fd, MEDIA_REQUEST_IOC_QUEUE, NULL);
451 +    if (ret < 0) {
452 +        av_log(avctx, AV_LOG_ERROR, "%s: queue request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno);
453 +        goto fail;
454 +    }
455 +
456 +    FD_ZERO(&except_fds);
457 +    FD_SET(req->request_fd, &except_fds);
458 +
459 +    ret = select(req->request_fd + 1, NULL, NULL, &except_fds, &tv);
460 +    if (ret == 0) {
461 +        av_log(avctx, AV_LOG_ERROR, "%s: request %d timeout\n", __func__, req->request_fd);
462 +        goto fail;
463 +    } else if (ret < 0) {
464 +        av_log(avctx, AV_LOG_ERROR, "%s: select request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno);
465 +        goto fail;
466 +    }
467 +
468 +    ret = v4l2_request_dequeue_buffer(ctx, &req->output);
469 +    if (ret < 0) {
470 +        av_log(avctx, AV_LOG_ERROR, "%s: dequeue output buffer %d failed for request %d, %s (%d)\n", __func__, req->output.index, req->request_fd, strerror(errno), errno);
471 +        return -1;
472 +    }
473 +
474 +    if (last_slice) {
475 +        ret = v4l2_request_dequeue_buffer(ctx, &req->capture);
476 +        if (ret < 0) {
477 +            av_log(avctx, AV_LOG_ERROR, "%s: dequeue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno);
478 +            return -1;
479 +        }
480 +    }
481 +
482 +    // TODO: check errors
483 +    // buffer.flags & V4L2_BUF_FLAG_ERROR
484 +
485 +    ret = ioctl(req->request_fd, MEDIA_REQUEST_IOC_REINIT, NULL);
486 +    if (ret < 0) {
487 +        av_log(avctx, AV_LOG_ERROR, "%s: reinit request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno);
488 +        return -1;
489 +    }
490 +
491 +    if (last_slice)
492 +        return v4l2_request_set_drm_descriptor(req, &ctx->format);
493 +
494 +    return 0;
495 +
496 +fail:
497 +    ret = v4l2_request_dequeue_buffer(ctx, &req->output);
498 +    if (ret < 0)
499 +        av_log(avctx, AV_LOG_ERROR, "%s: dequeue output buffer %d failed for request %d, %s (%d)\n", __func__, req->output.index, req->request_fd, strerror(errno), errno);
500 +
501 +    ret = v4l2_request_dequeue_buffer(ctx, &req->capture);
502 +    if (ret < 0)
503 +        av_log(avctx, AV_LOG_ERROR, "%s: dequeue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno);
504 +
505 +    ret = ioctl(req->request_fd, MEDIA_REQUEST_IOC_REINIT, NULL);
506 +    if (ret < 0)
507 +        av_log(avctx, AV_LOG_ERROR, "%s: reinit request %d failed, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno);
508 +
509 +    return -1;
510 +}
511 +
512 +int ff_v4l2_request_decode_slice(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice)
513 +{
514 +    V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0];
515 +
516 +    // fall back to queue each slice as a full frame
517 +    if ((req->output.capabilities & V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF) != V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF)
518 +        return v4l2_request_queue_decode(avctx, frame, control, count, 1, 1);
519 +
520 +    return v4l2_request_queue_decode(avctx, frame, control, count, first_slice, last_slice);
521 +}
522 +
523 +int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count)
524 +{
525 +    return v4l2_request_queue_decode(avctx, frame, control, count, 1, 1);
526 +}
527 +
528 +static int v4l2_request_try_framesize(AVCodecContext *avctx, uint32_t pixelformat)
529 +{
530 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
531 +    struct v4l2_frmsizeenum frmsize = {
532 +        .index = 0,
533 +        .pixel_format = pixelformat,
534 +    };
535 +
536 +    if (ioctl(ctx->video_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) < 0)
537 +        return 0;
538 +
539 +    /*
540 +     * We only validate min/max framesize for V4L2_FRMSIZE_TYPE_STEPWISE here, since the alignment
541 +     * which is eventually needed will be done driver-side later in VIDIOC_S_FMT and there is no need
542 +     * validate step_width/step_height here
543 +     */
544 +    do {
545 +        if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE && frmsize.discrete.width == avctx->coded_width &&
546 +            frmsize.discrete.height == avctx->coded_height)
547 +            return 0;
548 +        else if ((frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE || frmsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) &&
549 +                 avctx->coded_width >= frmsize.stepwise.min_width && avctx->coded_height >= frmsize.stepwise.min_height &&
550 +                 avctx->coded_width <= frmsize.stepwise.max_width && avctx->coded_height <= frmsize.stepwise.max_height)
551 +            return 0;
552 +
553 +        frmsize.index++;
554 +    } while (ioctl(ctx->video_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0);
555 +
556 +    av_log(avctx, AV_LOG_INFO, "%s: pixelformat %s not supported for width %u height %u\n", __func__, av_fourcc2str(pixelformat), avctx->coded_width, avctx->coded_height);
557 +    return -1;
558 +}
559 +
560 +static int v4l2_request_try_format(AVCodecContext *avctx, enum v4l2_buf_type type, uint32_t pixelformat)
561 +{
562 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
563 +    struct v4l2_fmtdesc fmtdesc = {
564 +        .index = 0,
565 +        .type = type,
566 +    };
567 +
568 +    if (V4L2_TYPE_IS_OUTPUT(type)) {
569 +        struct v4l2_create_buffers buffers = {
570 +            .count = 0,
571 +            .memory = V4L2_MEMORY_MMAP,
572 +            .format.type = type,
573 +        };
574 +
575 +        if (ioctl(ctx->video_fd, VIDIOC_CREATE_BUFS, &buffers) < 0) {
576 +            av_log(avctx, AV_LOG_ERROR, "%s: create buffers failed for type %u, %s (%d)\n", __func__, type, strerror(errno), errno);
577 +            return -1;
578 +        }
579 +
580 +        if ((buffers.capabilities & V4L2_BUF_CAP_SUPPORTS_REQUESTS) != V4L2_BUF_CAP_SUPPORTS_REQUESTS) {
581 +            av_log(avctx, AV_LOG_INFO, "%s: output buffer type do not support requests, capabilities %u\n", __func__, buffers.capabilities);
582 +            return -1;
583 +        }
584 +    }
585 +
586 +    while (ioctl(ctx->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) >= 0) {
587 +        if (fmtdesc.pixelformat == pixelformat)
588 +            return 0;
589 +
590 +        fmtdesc.index++;
591 +    }
592 +
593 +    av_log(avctx, AV_LOG_DEBUG, "%s: pixelformat %s not supported for type %u\n", __func__, av_fourcc2str(pixelformat), type);
594 +    return -1;
595 +}
596 +
597 +static int v4l2_request_set_format(AVCodecContext *avctx, enum v4l2_buf_type type, uint32_t pixelformat, uint32_t buffersize)
598 +{
599 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
600 +    struct v4l2_format format = {
601 +        .type = type,
602 +    };
603 +
604 +    if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
605 +        format.fmt.pix_mp.width = avctx->coded_width;
606 +        format.fmt.pix_mp.height = avctx->coded_height;
607 +        format.fmt.pix_mp.pixelformat = pixelformat;
608 +        format.fmt.pix_mp.plane_fmt[0].sizeimage = buffersize;
609 +        format.fmt.pix_mp.num_planes = 1;
610 +    } else {
611 +        format.fmt.pix.width = avctx->coded_width;
612 +        format.fmt.pix.height = avctx->coded_height;
613 +        format.fmt.pix.pixelformat = pixelformat;
614 +        format.fmt.pix.sizeimage = buffersize;
615 +    }
616 +
617 +    return ioctl(ctx->video_fd, VIDIOC_S_FMT, &format);
618 +}
619 +
620 +static int v4l2_request_select_capture_format(AVCodecContext *avctx)
621 +{
622 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
623 +    enum v4l2_buf_type type = ctx->format.type;
624 +
625 +#if 1
626 +    struct v4l2_format format = {
627 +        .type = type,
628 +    };
629 +    struct v4l2_fmtdesc fmtdesc = {
630 +        .index = 0,
631 +        .type = type,
632 +    };
633 +    uint32_t pixelformat;
634 +
635 +    if (ioctl(ctx->video_fd, VIDIOC_G_FMT, &format) < 0) {
636 +        av_log(avctx, AV_LOG_ERROR, "%s: get capture format failed, %s (%d)\n", __func__, strerror(errno), errno);
637 +        return -1;
638 +    }
639 +
640 +    pixelformat = V4L2_TYPE_IS_MULTIPLANAR(type) ? format.fmt.pix_mp.pixelformat : format.fmt.pix.pixelformat;
641 +
642 +    for (int i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) {
643 +        if (pixelformat == v4l2_request_capture_pixelformats[i].pixelformat)
644 +            return v4l2_request_set_format(avctx, type, pixelformat, 0);
645 +    }
646 +
647 +    while (ioctl(ctx->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) >= 0) {
648 +        for (int i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) {
649 +            if (fmtdesc.pixelformat == v4l2_request_capture_pixelformats[i].pixelformat)
650 +                return v4l2_request_set_format(avctx, type, fmtdesc.pixelformat, 0);
651 +        }
652 +
653 +        fmtdesc.index++;
654 +    }
655 +#else
656 +    for (int i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) {
657 +        uint32_t pixelformat = v4l2_request_capture_pixelformats[i].pixelformat;
658 +        if (!v4l2_request_try_format(avctx, type, pixelformat))
659 +            return v4l2_request_set_format(avctx, type, pixelformat, 0);
660 +    }
661 +#endif
662 +
663 +    return -1;
664 +}
665 +
666 +static int v4l2_request_probe_video_device(struct udev_device *device, AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count)
667 +{
668 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
669 +    int ret = AVERROR(EINVAL);
670 +    struct v4l2_capability capability = {0};
671 +    unsigned int capabilities = 0;
672 +
673 +    const char *path = udev_device_get_devnode(device);
674 +    if (!path) {
675 +        av_log(avctx, AV_LOG_ERROR, "%s: get video device devnode failed\n", __func__);
676 +        ret = AVERROR(EINVAL);
677 +        goto fail;
678 +    }
679 +
680 +    ctx->video_fd = open(path, O_RDWR | O_NONBLOCK, 0);
681 +    if (ctx->video_fd < 0) {
682 +        av_log(avctx, AV_LOG_ERROR, "%s: opening %s failed, %s (%d)\n", __func__, path, strerror(errno), errno);
683 +        ret = AVERROR(EINVAL);
684 +        goto fail;
685 +    }
686 +
687 +    ret = ioctl(ctx->video_fd, VIDIOC_QUERYCAP, &capability);
688 +    if (ret < 0) {
689 +        av_log(avctx, AV_LOG_ERROR, "%s: get video capability failed, %s (%d)\n", __func__, strerror(errno), errno);
690 +        ret = AVERROR(EINVAL);
691 +        goto fail;
692 +    }
693 +
694 +    if (capability.capabilities & V4L2_CAP_DEVICE_CAPS)
695 +        capabilities = capability.device_caps;
696 +    else
697 +        capabilities = capability.capabilities;
698 +
699 +    av_log(avctx, AV_LOG_DEBUG, "%s: ctx=%p path=%s capabilities=%u\n", __func__, ctx, path, capabilities);
700 +
701 +    if ((capabilities & V4L2_CAP_STREAMING) != V4L2_CAP_STREAMING) {
702 +        av_log(avctx, AV_LOG_ERROR, "%s: missing required streaming capability\n", __func__);
703 +        ret = AVERROR(EINVAL);
704 +        goto fail;
705 +    }
706 +
707 +    if ((capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) == V4L2_CAP_VIDEO_M2M_MPLANE) {
708 +        ctx->output_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
709 +        ctx->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
710 +    } else if ((capabilities & V4L2_CAP_VIDEO_M2M) == V4L2_CAP_VIDEO_M2M) {
711 +        ctx->output_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
712 +        ctx->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
713 +    } else {
714 +        av_log(avctx, AV_LOG_ERROR, "%s: missing required mem2mem capability\n", __func__);
715 +        ret = AVERROR(EINVAL);
716 +        goto fail;
717 +    }
718 +
719 +    ret = v4l2_request_try_format(avctx, ctx->output_type, pixelformat);
720 +    if (ret < 0) {
721 +        av_log(avctx, AV_LOG_DEBUG, "%s: try output format failed\n", __func__);
722 +        ret = AVERROR(EINVAL);
723 +        goto fail;
724 +    }
725 +
726 +    ret = v4l2_request_try_framesize(avctx, pixelformat);
727 +    if (ret < 0) {
728 +        av_log(avctx, AV_LOG_DEBUG, "%s: try framesize failed\n", __func__);
729 +        ret = AVERROR(EINVAL);
730 +        goto fail;
731 +    }
732 +
733 +    ret = v4l2_request_set_format(avctx, ctx->output_type, pixelformat, buffersize);
734 +    if (ret < 0) {
735 +        av_log(avctx, AV_LOG_ERROR, "%s: set output format failed, %s (%d)\n", __func__, strerror(errno), errno);
736 +        ret = AVERROR(EINVAL);
737 +        goto fail;
738 +    }
739 +
740 +    ret = v4l2_request_set_controls(ctx, -1, control, count);
741 +    if (ret < 0) {
742 +        av_log(avctx, AV_LOG_DEBUG, "%s: set controls failed, %s (%d)\n", __func__, strerror(errno), errno);
743 +        ret = AVERROR(EINVAL);
744 +        goto fail;
745 +    }
746 +
747 +    ret = v4l2_request_select_capture_format(avctx);
748 +    if (ret < 0) {
749 +        av_log(avctx, AV_LOG_DEBUG, "%s: select capture format failed\n", __func__);
750 +        ret = AVERROR(EINVAL);
751 +        goto fail;
752 +    }
753 +
754 +    return 0;
755 +
756 +fail:
757 +    if (ctx->video_fd >= 0) {
758 +        close(ctx->video_fd);
759 +        ctx->video_fd = -1;
760 +    }
761 +    return ret;
762 +}
763 +
764 +static int v4l2_request_init_context(AVCodecContext *avctx)
765 +{
766 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
767 +    int ret;
768 +
769 +    ret = ioctl(ctx->video_fd, VIDIOC_G_FMT, &ctx->format);
770 +    if (ret < 0) {
771 +        av_log(avctx, AV_LOG_ERROR, "%s: get capture format failed, %s (%d)\n", __func__, strerror(errno), errno);
772 +        ret = AVERROR(EINVAL);
773 +        goto fail;
774 +    }
775 +
776 +    if (V4L2_TYPE_IS_MULTIPLANAR(ctx->format.type)) {
777 +        struct v4l2_pix_format_mplane *fmt = &ctx->format.fmt.pix_mp;
778 +        av_log(ctx, AV_LOG_DEBUG, "%s: pixelformat=%s width=%u height=%u bytesperline=%u sizeimage=%u num_planes=%u\n", __func__,
779 +               av_fourcc2str(fmt->pixelformat), fmt->width, fmt->height, fmt->plane_fmt[0].bytesperline, fmt->plane_fmt[0].sizeimage, fmt->num_planes);
780 +    } else {
781 +        struct v4l2_pix_format *fmt = &ctx->format.fmt.pix;
782 +        av_log(ctx, AV_LOG_DEBUG, "%s: pixelformat=%s width=%u height=%u bytesperline=%u sizeimage=%u\n", __func__,
783 +               av_fourcc2str(fmt->pixelformat), fmt->width, fmt->height, fmt->bytesperline, fmt->sizeimage);
784 +    }
785 +
786 +    ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_DRM);
787 +    if (ret < 0)
788 +        goto fail;
789 +
790 +    ret = ioctl(ctx->video_fd, VIDIOC_STREAMON, &ctx->output_type);
791 +    if (ret < 0) {
792 +        av_log(avctx, AV_LOG_ERROR, "%s: output stream on failed, %s (%d)\n", __func__, strerror(errno), errno);
793 +        ret = AVERROR(EINVAL);
794 +        goto fail;
795 +    }
796 +
797 +    ret = ioctl(ctx->video_fd, VIDIOC_STREAMON, &ctx->format.type);
798 +    if (ret < 0) {
799 +        av_log(avctx, AV_LOG_ERROR, "%s: capture stream on failed, %s (%d)\n", __func__, strerror(errno), errno);
800 +        ret = AVERROR(EINVAL);
801 +        goto fail;
802 +    }
803 +
804 +    return 0;
805 +
806 +fail:
807 +    ff_v4l2_request_uninit(avctx);
808 +    return ret;
809 +}
810 +
811 +static int v4l2_request_probe_media_device(struct udev_device *device, AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count)
812 +{
813 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
814 +    int ret;
815 +    struct media_device_info device_info = {0};
816 +    struct media_v2_topology topology = {0};
817 +    struct media_v2_interface *interfaces = NULL;
818 +    struct udev *udev = udev_device_get_udev(device);
819 +    struct udev_device *video_device;
820 +    dev_t devnum;
821 +
822 +    const char *path = udev_device_get_devnode(device);
823 +    if (!path) {
824 +        av_log(avctx, AV_LOG_ERROR, "%s: get media device devnode failed\n", __func__);
825 +        ret = AVERROR(EINVAL);
826 +        goto fail;
827 +    }
828 +
829 +    ctx->media_fd = open(path, O_RDWR, 0);
830 +    if (ctx->media_fd < 0) {
831 +        av_log(avctx, AV_LOG_ERROR, "%s: opening %s failed, %s (%d)\n", __func__, path, strerror(errno), errno);
832 +        ret = AVERROR(EINVAL);
833 +        goto fail;
834 +    }
835 +
836 +    ret = ioctl(ctx->media_fd, MEDIA_IOC_DEVICE_INFO, &device_info);
837 +    if (ret < 0) {
838 +        av_log(avctx, AV_LOG_ERROR, "%s: get media device info failed, %s (%d)\n", __func__, strerror(errno), errno);
839 +        ret = AVERROR(EINVAL);
840 +        goto fail;
841 +    }
842 +
843 +    av_log(avctx, AV_LOG_DEBUG, "%s: ctx=%p path=%s driver=%s\n", __func__, ctx, path, device_info.driver);
844 +
845 +    ret = ioctl(ctx->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology);
846 +    if (ret < 0) {
847 +        av_log(avctx, AV_LOG_ERROR, "%s: get media topology failed, %s (%d)\n", __func__, strerror(errno), errno);
848 +        ret = AVERROR(EINVAL);
849 +        goto fail;
850 +    }
851 +
852 +    if (topology.num_interfaces <= 0) {
853 +        av_log(avctx, AV_LOG_ERROR, "%s: media device has no interfaces\n", __func__);
854 +        ret = AVERROR(EINVAL);
855 +        goto fail;
856 +    }
857 +
858 +    interfaces = av_mallocz(topology.num_interfaces * sizeof(struct media_v2_interface));
859 +    if (!interfaces) {
860 +        av_log(avctx, AV_LOG_ERROR, "%s: allocating media interface struct failed\n", __func__);
861 +        ret = AVERROR(ENOMEM);
862 +        goto fail;
863 +    }
864 +
865 +    topology.ptr_interfaces = (__u64)(uintptr_t)interfaces;
866 +    ret = ioctl(ctx->media_fd, MEDIA_IOC_G_TOPOLOGY, &topology);
867 +    if (ret < 0) {
868 +        av_log(avctx, AV_LOG_ERROR, "%s: get media topology failed, %s (%d)\n", __func__, strerror(errno), errno);
869 +        ret = AVERROR(EINVAL);
870 +        goto fail;
871 +    }
872 +
873 +    ret = AVERROR(EINVAL);
874 +    for (int i = 0; i < topology.num_interfaces; i++) {
875 +        if (interfaces[i].intf_type != MEDIA_INTF_T_V4L_VIDEO)
876 +            continue;
877 +
878 +        devnum = makedev(interfaces[i].devnode.major, interfaces[i].devnode.minor);
879 +        video_device = udev_device_new_from_devnum(udev, 'c', devnum);
880 +        if (!video_device) {
881 +            av_log(avctx, AV_LOG_ERROR, "%s: video_device=%p\n", __func__, video_device);
882 +            continue;
883 +        }
884 +
885 +        ret = v4l2_request_probe_video_device(video_device, avctx, pixelformat, buffersize, control, count);
886 +        udev_device_unref(video_device);
887 +
888 +        if (!ret) {
889 +            av_freep(&interfaces);
890 +            av_log(avctx, AV_LOG_INFO, "Using V4L2 media device %s (%s) for %s\n", path, device_info.driver, av_fourcc2str(pixelformat));
891 +            return 0;
892 +        }
893 +    }
894 +
895 +fail:
896 +    av_freep(&interfaces);
897 +    if (ctx->media_fd >= 0) {
898 +        close(ctx->media_fd);
899 +        ctx->media_fd = -1;
900 +    }
901 +    return ret;
902 +}
903 +
904 +int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count)
905 +{
906 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
907 +    int ret = AVERROR(EINVAL);
908 +    struct udev *udev;
909 +    struct udev_enumerate *enumerate;
910 +    struct udev_list_entry *devices;
911 +    struct udev_list_entry *entry;
912 +    struct udev_device *device;
913 +
914 +    av_log(avctx, AV_LOG_DEBUG, "%s: ctx=%p hw_device_ctx=%p hw_frames_ctx=%p\n", __func__, ctx, avctx->hw_device_ctx, avctx->hw_frames_ctx);
915 +
916 +    ctx->av_class = &v4l2_request_context_class;
917 +    ctx->media_fd = -1;
918 +    ctx->video_fd = -1;
919 +
920 +    udev = udev_new();
921 +    if (!udev) {
922 +        av_log(avctx, AV_LOG_ERROR, "%s: allocating udev context failed\n", __func__);
923 +        ret = AVERROR(ENOMEM);
924 +        goto fail;
925 +    }
926 +
927 +    enumerate = udev_enumerate_new(udev);
928 +    if (!enumerate) {
929 +        av_log(avctx, AV_LOG_ERROR, "%s: allocating udev enumerator failed\n", __func__);
930 +        ret = AVERROR(ENOMEM);
931 +        goto fail;
932 +    }
933 +
934 +    udev_enumerate_add_match_subsystem(enumerate, "media");
935 +    udev_enumerate_scan_devices(enumerate);
936 +
937 +    devices = udev_enumerate_get_list_entry(enumerate);
938 +    udev_list_entry_foreach(entry, devices) {
939 +        const char *path = udev_list_entry_get_name(entry);
940 +        if (!path)
941 +            continue;
942 +
943 +        device = udev_device_new_from_syspath(udev, path);
944 +        if (!device)
945 +            continue;
946 +
947 +        ret = v4l2_request_probe_media_device(device, avctx, pixelformat, buffersize, control, count);
948 +        udev_device_unref(device);
949 +
950 +        if (!ret)
951 +            break;
952 +    }
953 +
954 +    udev_enumerate_unref(enumerate);
955 +
956 +    if (!ret)
957 +        ret = v4l2_request_init_context(avctx);
958 +    else
959 +        av_log(avctx, AV_LOG_INFO, "No V4L2 media device found for %s\n", av_fourcc2str(pixelformat));
960 +
961 +fail:
962 +    udev_unref(udev);
963 +    return ret;
964 +}
965 +
966 +int ff_v4l2_request_uninit(AVCodecContext *avctx)
967 +{
968 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
969 +    int ret;
970 +
971 +    av_log(ctx, AV_LOG_DEBUG, "%s: avctx=%p\n", __func__, avctx);
972 +
973 +    if (ctx->video_fd >= 0) {
974 +        ret = ioctl(ctx->video_fd, VIDIOC_STREAMOFF, &ctx->output_type);
975 +        if (ret < 0)
976 +            av_log(avctx, AV_LOG_ERROR, "%s: output stream off failed, %s (%d)\n", __func__, strerror(errno), errno);
977 +
978 +        ret = ioctl(ctx->video_fd, VIDIOC_STREAMOFF, &ctx->format.type);
979 +        if (ret < 0)
980 +            av_log(avctx, AV_LOG_ERROR, "%s: capture stream off failed, %s (%d)\n", __func__, strerror(errno), errno);
981 +    }
982 +
983 +    if (avctx->hw_frames_ctx) {
984 +        AVHWFramesContext *hwfc = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
985 +        av_buffer_pool_flush(hwfc->pool);
986 +    }
987 +
988 +    if (ctx->video_fd >= 0)
989 +        close(ctx->video_fd);
990 +
991 +    if (ctx->media_fd >= 0)
992 +        close(ctx->media_fd);
993 +
994 +    return 0;
995 +}
996 +
997 +static int v4l2_request_buffer_alloc(V4L2RequestContext *ctx, V4L2RequestBuffer *buf, enum v4l2_buf_type type)
998 +{
999 +    int ret;
1000 +    struct v4l2_plane planes[1] = {};
1001 +    struct v4l2_create_buffers buffers = {
1002 +        .count = 1,
1003 +        .memory = V4L2_MEMORY_MMAP,
1004 +        .format.type = type,
1005 +    };
1006 +
1007 +    av_log(ctx, AV_LOG_DEBUG, "%s: buf=%p type=%u\n", __func__, buf, type);
1008 +
1009 +    ret = ioctl(ctx->video_fd, VIDIOC_G_FMT, &buffers.format);
1010 +    if (ret < 0) {
1011 +        av_log(ctx, AV_LOG_ERROR, "%s: get format failed for type %u, %s (%d)\n", __func__, type, strerror(errno), errno);
1012 +        return ret;
1013 +    }
1014 +
1015 +    if (V4L2_TYPE_IS_MULTIPLANAR(buffers.format.type)) {
1016 +        struct v4l2_pix_format_mplane *fmt = &buffers.format.fmt.pix_mp;
1017 +        av_log(ctx, AV_LOG_DEBUG, "%s: pixelformat=%s width=%u height=%u bytesperline=%u sizeimage=%u num_planes=%u\n", __func__,
1018 +               av_fourcc2str(fmt->pixelformat), fmt->width, fmt->height, fmt->plane_fmt[0].bytesperline, fmt->plane_fmt[0].sizeimage, fmt->num_planes);
1019 +    } else {
1020 +        struct v4l2_pix_format *fmt = &buffers.format.fmt.pix;
1021 +        av_log(ctx, AV_LOG_DEBUG, "%s: pixelformat=%s width=%u height=%u bytesperline=%u sizeimage=%u\n", __func__,
1022 +               av_fourcc2str(fmt->pixelformat), fmt->width, fmt->height, fmt->bytesperline, fmt->sizeimage);
1023 +    }
1024 +
1025 +    ret = ioctl(ctx->video_fd, VIDIOC_CREATE_BUFS, &buffers);
1026 +    if (ret < 0) {
1027 +        av_log(ctx, AV_LOG_ERROR, "%s: create buffers failed for type %u, %s (%d)\n", __func__, type, strerror(errno), errno);
1028 +        return ret;
1029 +    }
1030 +
1031 +    if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
1032 +        buf->width = buffers.format.fmt.pix_mp.width;
1033 +        buf->height = buffers.format.fmt.pix_mp.height;
1034 +        buf->size = buffers.format.fmt.pix_mp.plane_fmt[0].sizeimage;
1035 +        buf->buffer.length = 1;
1036 +        buf->buffer.m.planes = planes;
1037 +    } else {
1038 +        buf->width = buffers.format.fmt.pix.width;
1039 +        buf->height = buffers.format.fmt.pix.height;
1040 +        buf->size = buffers.format.fmt.pix.sizeimage;
1041 +    }
1042 +
1043 +    buf->index = buffers.index;
1044 +    buf->capabilities = buffers.capabilities;
1045 +    buf->used = 0;
1046 +
1047 +    buf->buffer.type = type;
1048 +    buf->buffer.memory = V4L2_MEMORY_MMAP;
1049 +    buf->buffer.index = buf->index;
1050 +
1051 +    ret = ioctl(ctx->video_fd, VIDIOC_QUERYBUF, &buf->buffer);
1052 +    if (ret < 0) {
1053 +        av_log(ctx, AV_LOG_ERROR, "%s: query buffer %d failed, %s (%d)\n", __func__, buf->index, strerror(errno), errno);
1054 +        return ret;
1055 +    }
1056 +
1057 +    buf->buffer.timestamp.tv_usec = buf->index + 1;
1058 +
1059 +    if (V4L2_TYPE_IS_OUTPUT(type)) {
1060 +        uint32_t offset = V4L2_TYPE_IS_MULTIPLANAR(type) ? buf->buffer.m.planes[0].m.mem_offset : buf->buffer.m.offset;
1061 +        void *addr = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, ctx->video_fd, offset);
1062 +        if (addr == MAP_FAILED) {
1063 +            av_log(ctx, AV_LOG_ERROR, "%s: mmap failed, %s (%d)\n", __func__, strerror(errno), errno);
1064 +            return -1;
1065 +        }
1066 +
1067 +        buf->addr = (uint8_t*)addr;
1068 +    } else {
1069 +        struct v4l2_exportbuffer exportbuffer = {
1070 +            .type = type,
1071 +            .index = buf->index,
1072 +            .flags = O_RDONLY,
1073 +        };
1074 +
1075 +        ret = ioctl(ctx->video_fd, VIDIOC_EXPBUF, &exportbuffer);
1076 +        if (ret < 0) {
1077 +            av_log(ctx, AV_LOG_ERROR, "%s: export buffer %d failed, %s (%d)\n", __func__, buf->index, strerror(errno), errno);
1078 +            return ret;
1079 +        }
1080 +
1081 +        buf->fd = exportbuffer.fd;
1082 +    }
1083 +
1084 +    av_log(ctx, AV_LOG_DEBUG, "%s: buf=%p index=%d fd=%d addr=%p width=%u height=%u size=%u\n", __func__,
1085 +           buf, buf->index, buf->fd, buf->addr, buf->width, buf->height, buf->size);
1086 +    return 0;
1087 +}
1088 +
1089 +static void v4l2_request_buffer_free(V4L2RequestBuffer *buf)
1090 +{
1091 +    av_log(NULL, AV_LOG_DEBUG, "%s: buf=%p index=%d fd=%d addr=%p width=%u height=%u size=%u\n", __func__,
1092 +           buf, buf->index, buf->fd, buf->addr, buf->width, buf->height, buf->size);
1093 +
1094 +    if (buf->addr)
1095 +        munmap(buf->addr, buf->size);
1096 +
1097 +    if (buf->fd >= 0)
1098 +        close(buf->fd);
1099 +}
1100 +
1101 +static void v4l2_request_frame_free(void *opaque, uint8_t *data)
1102 +{
1103 +    V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)data;
1104 +
1105 +    av_log(NULL, AV_LOG_DEBUG, "%s: opaque=%p data=%p request_fd=%d\n", __func__, opaque, data, req->request_fd);
1106 +
1107 +    if (req->request_fd >= 0)
1108 +        close(req->request_fd);
1109 +
1110 +    v4l2_request_buffer_free(&req->capture);
1111 +    v4l2_request_buffer_free(&req->output);
1112 +
1113 +    av_free(data);
1114 +}
1115 +
1116 +static AVBufferRef *v4l2_request_frame_alloc(void *opaque, size_t size)
1117 +{
1118 +    V4L2RequestContext *ctx = opaque;
1119 +    V4L2RequestDescriptor *req;
1120 +    AVBufferRef *ref;
1121 +    uint8_t *data;
1122 +    int ret;
1123 +
1124 +    data = av_mallocz(size);
1125 +    if (!data)
1126 +        return NULL;
1127 +
1128 +    av_log(ctx, AV_LOG_DEBUG, "%s: size=%zu data=%p\n", __func__, size, data);
1129 +
1130 +    ref = av_buffer_create(data, size, v4l2_request_frame_free, ctx, 0);
1131 +    if (!ref) {
1132 +        av_freep(&data);
1133 +        return NULL;
1134 +    }
1135 +
1136 +    req = (V4L2RequestDescriptor*)data;
1137 +    req->request_fd = -1;
1138 +    req->output.fd = -1;
1139 +    req->capture.fd = -1;
1140 +
1141 +    ret = v4l2_request_buffer_alloc(ctx, &req->output, ctx->output_type);
1142 +    if (ret < 0) {
1143 +        av_buffer_unref(&ref);
1144 +        return NULL;
1145 +    }
1146 +
1147 +    ret = v4l2_request_buffer_alloc(ctx, &req->capture, ctx->format.type);
1148 +    if (ret < 0) {
1149 +        av_buffer_unref(&ref);
1150 +        return NULL;
1151 +    }
1152 +
1153 +    ret = ioctl(ctx->media_fd, MEDIA_IOC_REQUEST_ALLOC, &req->request_fd);
1154 +    if (ret < 0) {
1155 +        av_log(ctx, AV_LOG_ERROR, "%s: request alloc failed, %s (%d)\n", __func__, strerror(errno), errno);
1156 +        av_buffer_unref(&ref);
1157 +        return NULL;
1158 +    }
1159 +
1160 +    av_log(ctx, AV_LOG_DEBUG, "%s: size=%zu data=%p request_fd=%d\n", __func__, size, data, req->request_fd);
1161 +    return ref;
1162 +}
1163 +
1164 +static void v4l2_request_pool_free(void *opaque)
1165 +{
1166 +    av_log(NULL, AV_LOG_DEBUG, "%s: opaque=%p\n", __func__, opaque);
1167 +}
1168 +
1169 +static void v4l2_request_hwframe_ctx_free(AVHWFramesContext *hwfc)
1170 +{
1171 +    av_log(NULL, AV_LOG_DEBUG, "%s: hwfc=%p pool=%p\n", __func__, hwfc, hwfc->pool);
1172 +
1173 +    av_buffer_pool_flush(hwfc->pool);
1174 +    av_buffer_pool_uninit(&hwfc->pool);
1175 +}
1176 +
1177 +int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
1178 +{
1179 +    V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
1180 +    AVHWFramesContext *hwfc = (AVHWFramesContext*)hw_frames_ctx->data;
1181 +    uint32_t pixelformat;
1182 +
1183 +    hwfc->format = AV_PIX_FMT_DRM_PRIME;
1184 +    hwfc->sw_format = AV_PIX_FMT_NONE;
1185 +
1186 +    if (V4L2_TYPE_IS_MULTIPLANAR(ctx->format.type)) {
1187 +        hwfc->width = ctx->format.fmt.pix_mp.width;
1188 +        hwfc->height = ctx->format.fmt.pix_mp.height;
1189 +        pixelformat = ctx->format.fmt.pix_mp.pixelformat;
1190 +    } else {
1191 +        hwfc->width = ctx->format.fmt.pix.width;
1192 +        hwfc->height = ctx->format.fmt.pix.height;
1193 +        pixelformat = ctx->format.fmt.pix.pixelformat;
1194 +    }
1195 +
1196 +    for (int i = 0; i < FF_ARRAY_ELEMS(v4l2_request_capture_pixelformats); i++) {
1197 +        if (pixelformat == v4l2_request_capture_pixelformats[i].pixelformat) {
1198 +            hwfc->sw_format = v4l2_request_capture_pixelformats[i].sw_format;
1199 +            break;
1200 +        }
1201 +    }
1202 +
1203 +    hwfc->pool = av_buffer_pool_init2(sizeof(V4L2RequestDescriptor), ctx, v4l2_request_frame_alloc, v4l2_request_pool_free);
1204 +    if (!hwfc->pool)
1205 +        return AVERROR(ENOMEM);
1206 +
1207 +    hwfc->free = v4l2_request_hwframe_ctx_free;
1208 +
1209 +    hwfc->initial_pool_size = 1;
1210 +
1211 +    switch (avctx->codec_id) {
1212 +    case AV_CODEC_ID_VP9:
1213 +        hwfc->initial_pool_size += 8;
1214 +        break;
1215 +    case AV_CODEC_ID_VP8:
1216 +        hwfc->initial_pool_size += 3;
1217 +        break;
1218 +    default:
1219 +        hwfc->initial_pool_size += 2;
1220 +    }
1221 +
1222 +    av_log(ctx, AV_LOG_DEBUG, "%s: avctx=%p hw_frames_ctx=%p hwfc=%p pool=%p width=%d height=%d initial_pool_size=%d\n", __func__,
1223 +           avctx, hw_frames_ctx, hwfc, hwfc->pool, hwfc->width, hwfc->height, hwfc->initial_pool_size);
1224 +    return 0;
1225 +}
1226 diff --git a/libavcodec/v4l2_request.h b/libavcodec/v4l2_request.h
1227 new file mode 100644
1228 index 0000000..5f105d8
1229 --- /dev/null
1230 +++ b/libavcodec/v4l2_request.h
1231 @@ -0,0 +1,78 @@
1232 +/*
1233 + * This file is part of FFmpeg.
1234 + *
1235 + * FFmpeg is free software; you can redistribute it and/or
1236 + * modify it under the terms of the GNU Lesser General Public
1237 + * License as published by the Free Software Foundation; either
1238 + * version 2.1 of the License, or (at your option) any later version.
1239 + *
1240 + * FFmpeg is distributed in the hope that it will be useful,
1241 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1242 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1243 + * Lesser General Public License for more details.
1244 + *
1245 + * You should have received a copy of the GNU Lesser General Public
1246 + * License along with FFmpeg; if not, write to the Free Software
1247 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1248 + */
1249 +
1250 +#ifndef AVCODEC_V4L2_REQUEST_H
1251 +#define AVCODEC_V4L2_REQUEST_H
1252 +
1253 +#include <linux/videodev2.h>
1254 +
1255 +#include "libavutil/hwcontext_drm.h"
1256 +
1257 +typedef struct V4L2RequestContext {
1258 +    const AVClass *av_class;
1259 +    int video_fd;
1260 +    int media_fd;
1261 +    enum v4l2_buf_type output_type;
1262 +    struct v4l2_format format;
1263 +    int timestamp;
1264 +} V4L2RequestContext;
1265 +
1266 +typedef struct V4L2RequestBuffer {
1267 +    int index;
1268 +    int fd;
1269 +    uint8_t *addr;
1270 +    uint32_t width;
1271 +    uint32_t height;
1272 +    uint32_t size;
1273 +    uint32_t used;
1274 +    uint32_t capabilities;
1275 +    struct v4l2_buffer buffer;
1276 +} V4L2RequestBuffer;
1277 +
1278 +typedef struct V4L2RequestDescriptor {
1279 +    AVDRMFrameDescriptor drm;
1280 +    int request_fd;
1281 +    V4L2RequestBuffer output;
1282 +    V4L2RequestBuffer capture;
1283 +} V4L2RequestDescriptor;
1284 +
1285 +uint64_t ff_v4l2_request_get_capture_timestamp(AVFrame *frame);
1286 +
1287 +int ff_v4l2_request_reset_frame(AVCodecContext *avctx, AVFrame *frame);
1288 +
1289 +int ff_v4l2_request_append_output_buffer(AVCodecContext *avctx, AVFrame *frame, const uint8_t *data, uint32_t size);
1290 +
1291 +int ff_v4l2_request_set_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count);
1292 +
1293 +int ff_v4l2_request_get_controls(AVCodecContext *avctx, struct v4l2_ext_control *control, int count);
1294 +
1295 +int ff_v4l2_request_query_control(AVCodecContext *avctx, struct v4l2_query_ext_ctrl *control);
1296 +
1297 +int ff_v4l2_request_query_control_default_value(AVCodecContext *avctx, uint32_t id);
1298 +
1299 +int ff_v4l2_request_decode_slice(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice);
1300 +
1301 +int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count);
1302 +
1303 +int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count);
1304 +
1305 +int ff_v4l2_request_uninit(AVCodecContext *avctx);
1306 +
1307 +int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx);
1308 +
1309 +#endif /* AVCODEC_V4L2_REQUEST_H */
1310 -- 
1311 2.44.0
1312
1313
1314 From 9c440906da4c4f0f63faa71a0b988d2447ca57bf Mon Sep 17 00:00:00 2001
1315 From: Boris Brezillon <boris.brezillon@collabora.com>
1316 Date: Wed, 22 May 2019 14:44:22 +0200
1317 Subject: [PATCH 03/18] h264dec: add ref_pic_marking and pic_order_cnt bit_size
1318  to slice context
1319
1320 Used by V4L2 request API h264 hwaccel
1321
1322 Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
1323 Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
1324 ---
1325  libavcodec/h264_slice.c | 6 +++++-
1326  libavcodec/h264dec.h    | 2 ++
1327  2 files changed, 7 insertions(+), 1 deletion(-)
1328
1329 diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
1330 index 5c17edf..ea7e882 100644
1331 --- a/libavcodec/h264_slice.c
1332 +++ b/libavcodec/h264_slice.c
1333 @@ -1685,7 +1685,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
1334      unsigned int slice_type, tmp, i;
1335      int field_pic_flag, bottom_field_flag;
1336      int first_slice = sl == h->slice_ctx && !h->current_slice;
1337 -    int picture_structure;
1338 +    int picture_structure, pos;
1339  
1340      if (first_slice)
1341          av_assert0(!h->setup_finished);
1342 @@ -1776,6 +1776,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
1343  
1344      sl->poc_lsb = 0;
1345      sl->delta_poc_bottom = 0;
1346 +    pos = sl->gb.index;
1347      if (sps->poc_type == 0) {
1348          sl->poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb);
1349  
1350 @@ -1790,6 +1791,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
1351          if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME)
1352              sl->delta_poc[1] = get_se_golomb(&sl->gb);
1353      }
1354 +    sl->pic_order_cnt_bit_size = sl->gb.index - pos;
1355  
1356      sl->redundant_pic_count = 0;
1357      if (pps->redundant_pic_cnt_present)
1358 @@ -1829,9 +1831,11 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
1359  
1360      sl->explicit_ref_marking = 0;
1361      if (nal->ref_idc) {
1362 +        pos = sl->gb.index;
1363          ret = ff_h264_decode_ref_pic_marking(sl, &sl->gb, nal, h->avctx);
1364          if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
1365              return AVERROR_INVALIDDATA;
1366 +        sl->ref_pic_marking_bit_size = sl->gb.index - pos;
1367      }
1368  
1369      if (sl->slice_type_nos != AV_PICTURE_TYPE_I && pps->cabac) {
1370 diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h
1371 index 675be9b..a9d515d 100644
1372 --- a/libavcodec/h264dec.h
1373 +++ b/libavcodec/h264dec.h
1374 @@ -315,6 +315,7 @@ typedef struct H264SliceContext {
1375      MMCO mmco[H264_MAX_MMCO_COUNT];
1376      int  nb_mmco;
1377      int explicit_ref_marking;
1378 +    int ref_pic_marking_bit_size;
1379  
1380      int frame_num;
1381      int idr_pic_id;
1382 @@ -323,6 +324,7 @@ typedef struct H264SliceContext {
1383      int delta_poc[2];
1384      int curr_pic_num;
1385      int max_pic_num;
1386 +    int pic_order_cnt_bit_size;
1387  } H264SliceContext;
1388  
1389  /**
1390 -- 
1391 2.44.0
1392
1393
1394 From d507e050b4dbab847abcc3d97c902f8e01d39945 Mon Sep 17 00:00:00 2001
1395 From: Jernej Skrabec <jernej.skrabec@siol.net>
1396 Date: Sat, 15 Dec 2018 22:32:16 +0100
1397 Subject: [PATCH 04/18] Add V4L2 request API h264 hwaccel
1398
1399 Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
1400 Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
1401 ---
1402  configure                      |   3 +
1403  libavcodec/Makefile            |   1 +
1404  libavcodec/h264_slice.c        |   4 +
1405  libavcodec/h264dec.c           |   3 +
1406  libavcodec/hwaccels.h          |   1 +
1407  libavcodec/v4l2_request_h264.c | 462 +++++++++++++++++++++++++++++++++
1408  6 files changed, 474 insertions(+)
1409  create mode 100644 libavcodec/v4l2_request_h264.c
1410
1411 diff --git a/configure b/configure
1412 index 503eb06..252d188 100755
1413 --- a/configure
1414 +++ b/configure
1415 @@ -3081,6 +3081,8 @@ h264_dxva2_hwaccel_deps="dxva2"
1416  h264_dxva2_hwaccel_select="h264_decoder"
1417  h264_nvdec_hwaccel_deps="nvdec"
1418  h264_nvdec_hwaccel_select="h264_decoder"
1419 +h264_v4l2request_hwaccel_deps="v4l2_request h264_v4l2_request"
1420 +h264_v4l2request_hwaccel_select="h264_decoder"
1421  h264_vaapi_hwaccel_deps="vaapi"
1422  h264_vaapi_hwaccel_select="h264_decoder"
1423  h264_vdpau_hwaccel_deps="vdpau"
1424 @@ -7003,6 +7005,7 @@ if enabled v4l2_m2m; then
1425  fi
1426  
1427  check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
1428 +check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
1429  
1430  check_headers sys/videoio.h
1431  test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
1432 diff --git a/libavcodec/Makefile b/libavcodec/Makefile
1433 index 5e626c9..4bfd477 100644
1434 --- a/libavcodec/Makefile
1435 +++ b/libavcodec/Makefile
1436 @@ -1001,6 +1001,7 @@ OBJS-$(CONFIG_H264_D3D11VA_HWACCEL)       += dxva2_h264.o
1437  OBJS-$(CONFIG_H264_DXVA2_HWACCEL)         += dxva2_h264.o
1438  OBJS-$(CONFIG_H264_NVDEC_HWACCEL)         += nvdec_h264.o
1439  OBJS-$(CONFIG_H264_QSV_HWACCEL)           += qsvdec.o
1440 +OBJS-$(CONFIG_H264_V4L2REQUEST_HWACCEL)   += v4l2_request_h264.o
1441  OBJS-$(CONFIG_H264_VAAPI_HWACCEL)         += vaapi_h264.o
1442  OBJS-$(CONFIG_H264_VDPAU_HWACCEL)         += vdpau_h264.o
1443  OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL)  += videotoolbox.o
1444 diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
1445 index ea7e882..236bdc6 100644
1446 --- a/libavcodec/h264_slice.c
1447 +++ b/libavcodec/h264_slice.c
1448 @@ -786,6 +786,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
1449  #define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \
1450                       (CONFIG_H264_D3D11VA_HWACCEL * 2) + \
1451                       CONFIG_H264_NVDEC_HWACCEL + \
1452 +                     CONFIG_H264_V4L2REQUEST_HWACCEL + \
1453                       CONFIG_H264_VAAPI_HWACCEL + \
1454                       CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \
1455                       CONFIG_H264_VDPAU_HWACCEL + \
1456 @@ -890,6 +891,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
1457  #endif
1458  #if CONFIG_H264_VAAPI_HWACCEL
1459              *fmt++ = AV_PIX_FMT_VAAPI;
1460 +#endif
1461 +#if CONFIG_H264_V4L2REQUEST_HWACCEL
1462 +            *fmt++ = AV_PIX_FMT_DRM_PRIME;
1463  #endif
1464              if (h->avctx->color_range == AVCOL_RANGE_JPEG)
1465                  *fmt++ = AV_PIX_FMT_YUVJ420P;
1466 diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
1467 index f346c65..8d6334d 100644
1468 --- a/libavcodec/h264dec.c
1469 +++ b/libavcodec/h264dec.c
1470 @@ -1135,6 +1135,9 @@ const FFCodec ff_h264_decoder = {
1471  #endif
1472  #if CONFIG_H264_VULKAN_HWACCEL
1473                                 HWACCEL_VULKAN(h264),
1474 +#endif
1475 +#if CONFIG_H264_V4L2REQUEST_HWACCEL
1476 +                               HWACCEL_V4L2REQUEST(h264),
1477  #endif
1478                                 NULL
1479                             },
1480 diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
1481 index c463071..5211553 100644
1482 --- a/libavcodec/hwaccels.h
1483 +++ b/libavcodec/hwaccels.h
1484 @@ -32,6 +32,7 @@ extern const struct FFHWAccel ff_h264_d3d11va_hwaccel;
1485  extern const struct FFHWAccel ff_h264_d3d11va2_hwaccel;
1486  extern const struct FFHWAccel ff_h264_dxva2_hwaccel;
1487  extern const struct FFHWAccel ff_h264_nvdec_hwaccel;
1488 +extern const struct FFHWAccel ff_h264_v4l2request_hwaccel;
1489  extern const struct FFHWAccel ff_h264_vaapi_hwaccel;
1490  extern const struct FFHWAccel ff_h264_vdpau_hwaccel;
1491  extern const struct FFHWAccel ff_h264_videotoolbox_hwaccel;
1492 diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
1493 new file mode 100644
1494 index 0000000..980cd93
1495 --- /dev/null
1496 +++ b/libavcodec/v4l2_request_h264.c
1497 @@ -0,0 +1,462 @@
1498 +/*
1499 + * This file is part of FFmpeg.
1500 + *
1501 + * FFmpeg is free software; you can redistribute it and/or
1502 + * modify it under the terms of the GNU Lesser General Public
1503 + * License as published by the Free Software Foundation; either
1504 + * version 2.1 of the License, or (at your option) any later version.
1505 + *
1506 + * FFmpeg is distributed in the hope that it will be useful,
1507 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1508 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1509 + * Lesser General Public License for more details.
1510 + *
1511 + * You should have received a copy of the GNU Lesser General Public
1512 + * License along with FFmpeg; if not, write to the Free Software
1513 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1514 + */
1515 +
1516 +#include "h264dec.h"
1517 +#include "hwaccel_internal.h"
1518 +#include "hwconfig.h"
1519 +#include "internal.h"
1520 +#include "v4l2_request.h"
1521 +
1522 +typedef struct V4L2RequestControlsH264 {
1523 +    struct v4l2_ctrl_h264_sps sps;
1524 +    struct v4l2_ctrl_h264_pps pps;
1525 +    struct v4l2_ctrl_h264_scaling_matrix scaling_matrix;
1526 +    struct v4l2_ctrl_h264_decode_params decode_params;
1527 +    struct v4l2_ctrl_h264_slice_params slice_params;
1528 +    struct v4l2_ctrl_h264_pred_weights pred_weights;
1529 +    int pred_weights_required;
1530 +    int first_slice;
1531 +    int num_slices;
1532 +} V4L2RequestControlsH264;
1533 +
1534 +typedef struct V4L2RequestContextH264 {
1535 +    V4L2RequestContext base;
1536 +    int decode_mode;
1537 +    int start_code;
1538 +} V4L2RequestContextH264;
1539 +
1540 +static uint8_t nalu_slice_start_code[] = { 0x00, 0x00, 0x01 };
1541 +
1542 +static void fill_weight_factors(struct v4l2_h264_weight_factors *factors, int list, const H264SliceContext *sl)
1543 +{
1544 +    for (int i = 0; i < sl->ref_count[list]; i++) {
1545 +        if (sl->pwt.luma_weight_flag[list]) {
1546 +            factors->luma_weight[i] = sl->pwt.luma_weight[i][list][0];
1547 +            factors->luma_offset[i] = sl->pwt.luma_weight[i][list][1];
1548 +        } else {
1549 +            factors->luma_weight[i] = 1 << sl->pwt.luma_log2_weight_denom;
1550 +            factors->luma_offset[i] = 0;
1551 +        }
1552 +        for (int j = 0; j < 2; j++) {
1553 +            if (sl->pwt.chroma_weight_flag[list]) {
1554 +                factors->chroma_weight[i][j] = sl->pwt.chroma_weight[i][list][j][0];
1555 +                factors->chroma_offset[i][j] = sl->pwt.chroma_weight[i][list][j][1];
1556 +            } else {
1557 +                factors->chroma_weight[i][j] = 1 << sl->pwt.chroma_log2_weight_denom;
1558 +                factors->chroma_offset[i][j] = 0;
1559 +            }
1560 +        }
1561 +    }
1562 +}
1563 +
1564 +static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture *pic, int long_idx)
1565 +{
1566 +    entry->reference_ts = ff_v4l2_request_get_capture_timestamp(pic->f);
1567 +    entry->pic_num = pic->pic_id;
1568 +    entry->frame_num = pic->long_ref ? long_idx : pic->frame_num;
1569 +    entry->fields = pic->reference & V4L2_H264_FRAME_REF;
1570 +    entry->flags = V4L2_H264_DPB_ENTRY_FLAG_VALID;
1571 +    if (entry->fields)
1572 +        entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_ACTIVE;
1573 +    if (pic->long_ref)
1574 +        entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM;
1575 +    if (pic->field_picture)
1576 +        entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_FIELD;
1577 +    if (pic->field_poc[0] != INT_MAX)
1578 +        entry->top_field_order_cnt = pic->field_poc[0];
1579 +    if (pic->field_poc[1] != INT_MAX)
1580 +        entry->bottom_field_order_cnt = pic->field_poc[1];
1581 +}
1582 +
1583 +static void fill_dpb(struct v4l2_ctrl_h264_decode_params *decode, const H264Context *h)
1584 +{
1585 +    int entries = 0;
1586 +
1587 +    for (int i = 0; i < h->short_ref_count; i++) {
1588 +        const H264Picture *pic = h->short_ref[i];
1589 +        if (pic && (pic->field_poc[0] != INT_MAX || pic->field_poc[1] != INT_MAX))
1590 +            fill_dpb_entry(&decode->dpb[entries++], pic, pic->pic_id);
1591 +    }
1592 +
1593 +    if (!h->long_ref_count)
1594 +        return;
1595 +
1596 +    for (int i = 0; i < FF_ARRAY_ELEMS(h->long_ref); i++) {
1597 +        const H264Picture *pic = h->long_ref[i];
1598 +        if (pic && (pic->field_poc[0] != INT_MAX || pic->field_poc[1] != INT_MAX))
1599 +            fill_dpb_entry(&decode->dpb[entries++], pic, i);
1600 +    }
1601 +}
1602 +
1603 +static void fill_ref_list(struct v4l2_h264_reference *reference, struct v4l2_ctrl_h264_decode_params *decode, const H264Ref *ref)
1604 +{
1605 +    uint64_t timestamp;
1606 +
1607 +    if (!ref->parent)
1608 +        return;
1609 +
1610 +    timestamp = ff_v4l2_request_get_capture_timestamp(ref->parent->f);
1611 +
1612 +    for (uint8_t i = 0; i < FF_ARRAY_ELEMS(decode->dpb); i++) {
1613 +        struct v4l2_h264_dpb_entry *entry = &decode->dpb[i];
1614 +        if ((entry->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID) &&
1615 +            entry->reference_ts == timestamp) {
1616 +            reference->fields = ref->reference & V4L2_H264_FRAME_REF;
1617 +            reference->index = i;
1618 +            return;
1619 +        }
1620 +    }
1621 +}
1622 +
1623 +static void fill_sps(struct v4l2_ctrl_h264_sps *ctrl, const H264Context *h)
1624 +{
1625 +    const SPS *sps = h->ps.sps;
1626 +
1627 +    *ctrl = (struct v4l2_ctrl_h264_sps) {
1628 +        .profile_idc = sps->profile_idc,
1629 +        .constraint_set_flags = sps->constraint_set_flags,
1630 +        .level_idc = sps->level_idc,
1631 +        .seq_parameter_set_id = sps->sps_id,
1632 +        .chroma_format_idc = sps->chroma_format_idc,
1633 +        .bit_depth_luma_minus8 = sps->bit_depth_luma - 8,
1634 +        .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
1635 +        .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4,
1636 +        .pic_order_cnt_type = sps->poc_type,
1637 +        .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4,
1638 +        .max_num_ref_frames = sps->ref_frame_count,
1639 +        .num_ref_frames_in_pic_order_cnt_cycle = sps->poc_cycle_length,
1640 +        .offset_for_non_ref_pic = sps->offset_for_non_ref_pic,
1641 +        .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field,
1642 +        .pic_width_in_mbs_minus1 = h->mb_width - 1,
1643 +        .pic_height_in_map_units_minus1 = sps->frame_mbs_only_flag ? h->mb_height - 1 : h->mb_height / 2 - 1,
1644 +    };
1645 +
1646 +    if (sps->poc_cycle_length > 0 && sps->poc_cycle_length <= 255)
1647 +        memcpy(ctrl->offset_for_ref_frame, sps->offset_for_ref_frame, sps->poc_cycle_length * sizeof(ctrl->offset_for_ref_frame[0]));
1648 +
1649 +    if (sps->residual_color_transform_flag)
1650 +        ctrl->flags |= V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE;
1651 +    if (sps->transform_bypass)
1652 +        ctrl->flags |= V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS;
1653 +    if (sps->delta_pic_order_always_zero_flag)
1654 +        ctrl->flags |= V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO;
1655 +    if (sps->gaps_in_frame_num_allowed_flag)
1656 +        ctrl->flags |= V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED;
1657 +    if (sps->frame_mbs_only_flag)
1658 +        ctrl->flags |= V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY;
1659 +    if (sps->mb_aff)
1660 +        ctrl->flags |= V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD;
1661 +    if (sps->direct_8x8_inference_flag)
1662 +        ctrl->flags |= V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE;
1663 +}
1664 +
1665 +static void fill_pps(struct v4l2_ctrl_h264_pps *ctrl, const H264Context *h)
1666 +{
1667 +    const SPS *sps = h->ps.sps;
1668 +    const PPS *pps = h->ps.pps;
1669 +    const H264SliceContext *sl = &h->slice_ctx[0];
1670 +    int qp_bd_offset = 6 * (sps->bit_depth_luma - 8);
1671 +
1672 +    *ctrl = (struct v4l2_ctrl_h264_pps) {
1673 +        .pic_parameter_set_id = sl->pps_id,
1674 +        .seq_parameter_set_id = pps->sps_id,
1675 +        .num_slice_groups_minus1 = pps->slice_group_count - 1,
1676 +        .num_ref_idx_l0_default_active_minus1 = pps->ref_count[0] - 1,
1677 +        .num_ref_idx_l1_default_active_minus1 = pps->ref_count[1] - 1,
1678 +        .weighted_bipred_idc = pps->weighted_bipred_idc,
1679 +        .pic_init_qp_minus26 = pps->init_qp - 26 - qp_bd_offset,
1680 +        .pic_init_qs_minus26 = pps->init_qs - 26 - qp_bd_offset,
1681 +        .chroma_qp_index_offset = pps->chroma_qp_index_offset[0],
1682 +        .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1],
1683 +    };
1684 +
1685 +    if (pps->cabac)
1686 +        ctrl->flags |= V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE;
1687 +    if (pps->pic_order_present)
1688 +        ctrl->flags |= V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT;
1689 +    if (pps->weighted_pred)
1690 +        ctrl->flags |= V4L2_H264_PPS_FLAG_WEIGHTED_PRED;
1691 +    if (pps->deblocking_filter_parameters_present)
1692 +        ctrl->flags |= V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT;
1693 +    if (pps->constrained_intra_pred)
1694 +        ctrl->flags |= V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED;
1695 +    if (pps->redundant_pic_cnt_present)
1696 +        ctrl->flags |= V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT;
1697 +    if (pps->transform_8x8_mode)
1698 +        ctrl->flags |= V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE;
1699 +
1700 +    /* FFmpeg always provide a scaling matrix */
1701 +    ctrl->flags |= V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT;
1702 +}
1703 +
1704 +static int v4l2_request_h264_start_frame(AVCodecContext *avctx,
1705 +                                         av_unused const uint8_t *buffer,
1706 +                                         av_unused uint32_t size)
1707 +{
1708 +    const H264Context *h = avctx->priv_data;
1709 +    const PPS *pps = h->ps.pps;
1710 +    const SPS *sps = h->ps.sps;
1711 +    const H264SliceContext *sl = &h->slice_ctx[0];
1712 +    V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private;
1713 +
1714 +    fill_sps(&controls->sps, h);
1715 +    fill_pps(&controls->pps, h);
1716 +
1717 +    memcpy(controls->scaling_matrix.scaling_list_4x4, pps->scaling_matrix4, sizeof(controls->scaling_matrix.scaling_list_4x4));
1718 +    memcpy(controls->scaling_matrix.scaling_list_8x8[0], pps->scaling_matrix8[0], sizeof(controls->scaling_matrix.scaling_list_8x8[0]));
1719 +    memcpy(controls->scaling_matrix.scaling_list_8x8[1], pps->scaling_matrix8[3], sizeof(controls->scaling_matrix.scaling_list_8x8[1]));
1720 +
1721 +    if (sps->chroma_format_idc == 3) {
1722 +        memcpy(controls->scaling_matrix.scaling_list_8x8[2], pps->scaling_matrix8[1], sizeof(controls->scaling_matrix.scaling_list_8x8[2]));
1723 +        memcpy(controls->scaling_matrix.scaling_list_8x8[3], pps->scaling_matrix8[4], sizeof(controls->scaling_matrix.scaling_list_8x8[3]));
1724 +        memcpy(controls->scaling_matrix.scaling_list_8x8[4], pps->scaling_matrix8[2], sizeof(controls->scaling_matrix.scaling_list_8x8[4]));
1725 +        memcpy(controls->scaling_matrix.scaling_list_8x8[5], pps->scaling_matrix8[5], sizeof(controls->scaling_matrix.scaling_list_8x8[5]));
1726 +    }
1727 +
1728 +    controls->decode_params = (struct v4l2_ctrl_h264_decode_params) {
1729 +        .nal_ref_idc = h->nal_ref_idc,
1730 +        .frame_num = h->poc.frame_num,
1731 +        .top_field_order_cnt = h->cur_pic_ptr->field_poc[0] != INT_MAX ? h->cur_pic_ptr->field_poc[0] : 0,
1732 +        .bottom_field_order_cnt = h->cur_pic_ptr->field_poc[1] != INT_MAX ? h->cur_pic_ptr->field_poc[1] : 0,
1733 +        .idr_pic_id = sl->idr_pic_id,
1734 +        .pic_order_cnt_lsb = sl->poc_lsb,
1735 +        .delta_pic_order_cnt_bottom = sl->delta_poc_bottom,
1736 +        .delta_pic_order_cnt0 = sl->delta_poc[0],
1737 +        .delta_pic_order_cnt1 = sl->delta_poc[1],
1738 +        /* Size in bits of dec_ref_pic_marking() syntax element. */
1739 +        .dec_ref_pic_marking_bit_size = sl->ref_pic_marking_bit_size,
1740 +        /* Size in bits of pic order count syntax. */
1741 +        .pic_order_cnt_bit_size = sl->pic_order_cnt_bit_size,
1742 +        .slice_group_change_cycle = 0, /* slice group not supported by FFmpeg */
1743 +    };
1744 +
1745 +    if (h->picture_idr)
1746 +        controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC;
1747 +    if (FIELD_PICTURE(h))
1748 +        controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC;
1749 +    if (h->picture_structure == PICT_BOTTOM_FIELD)
1750 +        controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD;
1751 +    if (sl->slice_type_nos == AV_PICTURE_TYPE_P)
1752 +        controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_PFRAME;
1753 +    if (sl->slice_type_nos == AV_PICTURE_TYPE_B)
1754 +        controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_BFRAME;
1755 +
1756 +    fill_dpb(&controls->decode_params, h);
1757 +
1758 +    controls->first_slice = 1;
1759 +    controls->num_slices = 0;
1760 +
1761 +    return ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f);
1762 +}
1763 +
1764 +static int v4l2_request_h264_queue_decode(AVCodecContext *avctx, int last_slice)
1765 +{
1766 +    const H264Context *h = avctx->priv_data;
1767 +    V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private;
1768 +    V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data;
1769 +
1770 +    struct v4l2_ext_control control[] = {
1771 +        {
1772 +            .id = V4L2_CID_STATELESS_H264_SPS,
1773 +            .ptr = &controls->sps,
1774 +            .size = sizeof(controls->sps),
1775 +        },
1776 +        {
1777 +            .id = V4L2_CID_STATELESS_H264_PPS,
1778 +            .ptr = &controls->pps,
1779 +            .size = sizeof(controls->pps),
1780 +        },
1781 +        {
1782 +            .id = V4L2_CID_STATELESS_H264_SCALING_MATRIX,
1783 +            .ptr = &controls->scaling_matrix,
1784 +            .size = sizeof(controls->scaling_matrix),
1785 +        },
1786 +        {
1787 +            .id = V4L2_CID_STATELESS_H264_DECODE_PARAMS,
1788 +            .ptr = &controls->decode_params,
1789 +            .size = sizeof(controls->decode_params),
1790 +        },
1791 +        {
1792 +            .id = V4L2_CID_STATELESS_H264_SLICE_PARAMS,
1793 +            .ptr = &controls->slice_params,
1794 +            .size = sizeof(controls->slice_params),
1795 +        },
1796 +        {
1797 +            .id = V4L2_CID_STATELESS_H264_PRED_WEIGHTS,
1798 +            .ptr = &controls->pred_weights,
1799 +            .size = sizeof(controls->pred_weights),
1800 +        },
1801 +    };
1802 +
1803 +    if (ctx->decode_mode == V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED) {
1804 +        int count = FF_ARRAY_ELEMS(control) - (controls->pred_weights_required ? 0 : 1);
1805 +        return ff_v4l2_request_decode_slice(avctx, h->cur_pic_ptr->f, control, count, controls->first_slice, last_slice);
1806 +    }
1807 +
1808 +    return ff_v4l2_request_decode_frame(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control) - 2);
1809 +}
1810 +
1811 +static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
1812 +{
1813 +    const H264Context *h = avctx->priv_data;
1814 +    const PPS *pps = h->ps.pps;
1815 +    const H264SliceContext *sl = &h->slice_ctx[0];
1816 +    V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private;
1817 +    V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data;
1818 +    int i, ret, count;
1819 +
1820 +    if (ctx->decode_mode == V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED && controls->num_slices) {
1821 +        ret = v4l2_request_h264_queue_decode(avctx, 0);
1822 +        if (ret)
1823 +            return ret;
1824 +
1825 +        ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f);
1826 +        controls->first_slice = 0;
1827 +    }
1828 +
1829 +    if (ctx->start_code == V4L2_STATELESS_H264_START_CODE_ANNEX_B) {
1830 +        ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, nalu_slice_start_code, 3);
1831 +        if (ret)
1832 +            return ret;
1833 +    }
1834 +
1835 +    ret = ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, buffer, size);
1836 +    if (ret)
1837 +        return ret;
1838 +
1839 +    if (ctx->decode_mode != V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED)
1840 +        return 0;
1841 +
1842 +    controls->slice_params = (struct v4l2_ctrl_h264_slice_params) {
1843 +        /* Offset in bits to slice_data() from the beginning of this slice. */
1844 +        .header_bit_size = get_bits_count(&sl->gb),
1845 +
1846 +        .first_mb_in_slice = sl->first_mb_addr,
1847 +
1848 +        .slice_type = ff_h264_get_slice_type(sl),
1849 +        .colour_plane_id = 0, /* separate colour plane not supported by FFmpeg */
1850 +        .redundant_pic_cnt = sl->redundant_pic_count,
1851 +        .cabac_init_idc = sl->cabac_init_idc,
1852 +        .slice_qp_delta = sl->qscale - pps->init_qp,
1853 +        .slice_qs_delta = 0, /* not implemented by FFmpeg */
1854 +        .disable_deblocking_filter_idc = sl->deblocking_filter < 2 ? !sl->deblocking_filter : sl->deblocking_filter,
1855 +        .slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2,
1856 +        .slice_beta_offset_div2 = sl->slice_beta_offset / 2,
1857 +        .num_ref_idx_l0_active_minus1 = sl->list_count > 0 ? sl->ref_count[0] - 1 : 0,
1858 +        .num_ref_idx_l1_active_minus1 = sl->list_count > 1 ? sl->ref_count[1] - 1 : 0,
1859 +    };
1860 +
1861 +    if (sl->slice_type == AV_PICTURE_TYPE_B && sl->direct_spatial_mv_pred)
1862 +        controls->slice_params.flags |= V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED;
1863 +
1864 +    /* V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH: not implemented by FFmpeg */
1865 +
1866 +    controls->pred_weights_required = V4L2_H264_CTRL_PRED_WEIGHTS_REQUIRED(&controls->pps, &controls->slice_params);
1867 +    if (controls->pred_weights_required) {
1868 +        controls->pred_weights.chroma_log2_weight_denom = sl->pwt.chroma_log2_weight_denom;
1869 +        controls->pred_weights.luma_log2_weight_denom = sl->pwt.luma_log2_weight_denom;
1870 +    }
1871 +
1872 +    count = sl->list_count > 0 ? sl->ref_count[0] : 0;
1873 +    for (i = 0; i < count; i++)
1874 +        fill_ref_list(&controls->slice_params.ref_pic_list0[i], &controls->decode_params, &sl->ref_list[0][i]);
1875 +    if (count && controls->pred_weights_required)
1876 +        fill_weight_factors(&controls->pred_weights.weight_factors[0], 0, sl);
1877 +
1878 +    count = sl->list_count > 1 ? sl->ref_count[1] : 0;
1879 +    for (i = 0; i < count; i++)
1880 +        fill_ref_list(&controls->slice_params.ref_pic_list1[i], &controls->decode_params, &sl->ref_list[1][i]);
1881 +    if (count && controls->pred_weights_required)
1882 +        fill_weight_factors(&controls->pred_weights.weight_factors[1], 1, sl);
1883 +
1884 +    controls->num_slices++;
1885 +    return 0;
1886 +}
1887 +
1888 +static int v4l2_request_h264_end_frame(AVCodecContext *avctx)
1889 +{
1890 +    return v4l2_request_h264_queue_decode(avctx, 1);
1891 +}
1892 +
1893 +static int v4l2_request_h264_set_controls(AVCodecContext *avctx)
1894 +{
1895 +    V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data;
1896 +
1897 +    struct v4l2_ext_control control[] = {
1898 +        { .id = V4L2_CID_STATELESS_H264_DECODE_MODE, },
1899 +        { .id = V4L2_CID_STATELESS_H264_START_CODE, },
1900 +    };
1901 +
1902 +    ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_STATELESS_H264_DECODE_MODE);
1903 +    if (ctx->decode_mode != V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED &&
1904 +        ctx->decode_mode != V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED) {
1905 +        av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode, %d\n", __func__, ctx->decode_mode);
1906 +        return AVERROR(EINVAL);
1907 +    }
1908 +
1909 +    ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_STATELESS_H264_START_CODE);
1910 +    if (ctx->start_code != V4L2_STATELESS_H264_START_CODE_NONE &&
1911 +        ctx->start_code != V4L2_STATELESS_H264_START_CODE_ANNEX_B) {
1912 +        av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code, %d\n", __func__, ctx->start_code);
1913 +        return AVERROR(EINVAL);
1914 +    }
1915 +
1916 +    control[0].value = ctx->decode_mode;
1917 +    control[1].value = ctx->start_code;
1918 +
1919 +    return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control));
1920 +}
1921 +
1922 +static int v4l2_request_h264_init(AVCodecContext *avctx)
1923 +{
1924 +    const H264Context *h = avctx->priv_data;
1925 +    struct v4l2_ctrl_h264_sps sps;
1926 +    int ret;
1927 +
1928 +    struct v4l2_ext_control control[] = {
1929 +        {
1930 +            .id = V4L2_CID_STATELESS_H264_SPS,
1931 +            .ptr = &sps,
1932 +            .size = sizeof(sps),
1933 +        },
1934 +    };
1935 +
1936 +    fill_sps(&sps, h);
1937 +
1938 +    ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_H264_SLICE, 4 * 1024 * 1024, control, FF_ARRAY_ELEMS(control));
1939 +    if (ret)
1940 +        return ret;
1941 +
1942 +    return v4l2_request_h264_set_controls(avctx);
1943 +}
1944 +
1945 +const FFHWAccel ff_h264_v4l2request_hwaccel = {
1946 +    .p.name         = "h264_v4l2request",
1947 +    .p.type         = AVMEDIA_TYPE_VIDEO,
1948 +    .p.id           = AV_CODEC_ID_H264,
1949 +    .p.pix_fmt      = AV_PIX_FMT_DRM_PRIME,
1950 +    .start_frame    = v4l2_request_h264_start_frame,
1951 +    .decode_slice   = v4l2_request_h264_decode_slice,
1952 +    .end_frame      = v4l2_request_h264_end_frame,
1953 +    .frame_priv_data_size = sizeof(V4L2RequestControlsH264),
1954 +    .init           = v4l2_request_h264_init,
1955 +    .uninit         = ff_v4l2_request_uninit,
1956 +    .priv_data_size = sizeof(V4L2RequestContextH264),
1957 +    .frame_params   = ff_v4l2_request_frame_params,
1958 +    .caps_internal  = HWACCEL_CAP_ASYNC_SAFE,
1959 +};
1960 -- 
1961 2.44.0
1962
1963
1964 From f125ce861fcf1f4dfba26304f72a46dc15553d5a Mon Sep 17 00:00:00 2001
1965 From: Jonas Karlman <jonas@kwiboo.se>
1966 Date: Sat, 15 Dec 2018 22:32:16 +0100
1967 Subject: [PATCH 05/18] Add V4L2 request API mpeg2 hwaccel
1968
1969 Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
1970 ---
1971  configure                       |   3 +
1972  libavcodec/Makefile             |   1 +
1973  libavcodec/hwaccels.h           |   1 +
1974  libavcodec/mpeg12dec.c          |   6 ++
1975  libavcodec/v4l2_request_mpeg2.c | 160 ++++++++++++++++++++++++++++++++
1976  5 files changed, 171 insertions(+)
1977  create mode 100644 libavcodec/v4l2_request_mpeg2.c
1978
1979 diff --git a/configure b/configure
1980 index 252d188..3127877 100755
1981 --- a/configure
1982 +++ b/configure
1983 @@ -3125,6 +3125,8 @@ mpeg2_dxva2_hwaccel_deps="dxva2"
1984  mpeg2_dxva2_hwaccel_select="mpeg2video_decoder"
1985  mpeg2_nvdec_hwaccel_deps="nvdec"
1986  mpeg2_nvdec_hwaccel_select="mpeg2video_decoder"
1987 +mpeg2_v4l2request_hwaccel_deps="v4l2_request mpeg2_v4l2_request"
1988 +mpeg2_v4l2request_hwaccel_select="mpeg2video_decoder"
1989  mpeg2_vaapi_hwaccel_deps="vaapi"
1990  mpeg2_vaapi_hwaccel_select="mpeg2video_decoder"
1991  mpeg2_vdpau_hwaccel_deps="vdpau"
1992 @@ -7006,6 +7008,7 @@ fi
1993  
1994  check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
1995  check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
1996 +check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
1997  
1998  check_headers sys/videoio.h
1999  test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
2000 diff --git a/libavcodec/Makefile b/libavcodec/Makefile
2001 index 4bfd477..668f06a 100644
2002 --- a/libavcodec/Makefile
2003 +++ b/libavcodec/Makefile
2004 @@ -1022,6 +1022,7 @@ OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL)      += dxva2_mpeg2.o
2005  OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL)        += dxva2_mpeg2.o
2006  OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL)        += nvdec_mpeg12.o
2007  OBJS-$(CONFIG_MPEG2_QSV_HWACCEL)          += qsvdec.o
2008 +OBJS-$(CONFIG_MPEG2_V4L2REQUEST_HWACCEL)  += v4l2_request_mpeg2.o
2009  OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL)        += vaapi_mpeg2.o
2010  OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL)        += vdpau_mpeg12.o
2011  OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
2012 diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
2013 index 5211553..f5baf8a 100644
2014 --- a/libavcodec/hwaccels.h
2015 +++ b/libavcodec/hwaccels.h
2016 @@ -54,6 +54,7 @@ extern const struct FFHWAccel ff_mpeg2_d3d11va_hwaccel;
2017  extern const struct FFHWAccel ff_mpeg2_d3d11va2_hwaccel;
2018  extern const struct FFHWAccel ff_mpeg2_dxva2_hwaccel;
2019  extern const struct FFHWAccel ff_mpeg2_nvdec_hwaccel;
2020 +extern const struct FFHWAccel ff_mpeg2_v4l2request_hwaccel;
2021  extern const struct FFHWAccel ff_mpeg2_vaapi_hwaccel;
2022  extern const struct FFHWAccel ff_mpeg2_vdpau_hwaccel;
2023  extern const struct FFHWAccel ff_mpeg2_videotoolbox_hwaccel;
2024 diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
2025 index 5dac83e..4aa341c 100644
2026 --- a/libavcodec/mpeg12dec.c
2027 +++ b/libavcodec/mpeg12dec.c
2028 @@ -1120,6 +1120,9 @@ static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = {
2029  #endif
2030  #if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL
2031      AV_PIX_FMT_VIDEOTOOLBOX,
2032 +#endif
2033 +#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL
2034 +    AV_PIX_FMT_DRM_PRIME,
2035  #endif
2036      AV_PIX_FMT_YUV420P,
2037      AV_PIX_FMT_NONE
2038 @@ -2896,6 +2899,9 @@ const FFCodec ff_mpeg2video_decoder = {
2039  #endif
2040  #if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL
2041                          HWACCEL_VIDEOTOOLBOX(mpeg2),
2042 +#endif
2043 +#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL
2044 +                        HWACCEL_V4L2REQUEST(mpeg2),
2045  #endif
2046                          NULL
2047                      },
2048 diff --git a/libavcodec/v4l2_request_mpeg2.c b/libavcodec/v4l2_request_mpeg2.c
2049 new file mode 100644
2050 index 0000000..ae3f043
2051 --- /dev/null
2052 +++ b/libavcodec/v4l2_request_mpeg2.c
2053 @@ -0,0 +1,160 @@
2054 +/*
2055 + * This file is part of FFmpeg.
2056 + *
2057 + * FFmpeg is free software; you can redistribute it and/or
2058 + * modify it under the terms of the GNU Lesser General Public
2059 + * License as published by the Free Software Foundation; either
2060 + * version 2.1 of the License, or (at your option) any later version.
2061 + *
2062 + * FFmpeg is distributed in the hope that it will be useful,
2063 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2064 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2065 + * Lesser General Public License for more details.
2066 + *
2067 + * You should have received a copy of the GNU Lesser General Public
2068 + * License along with FFmpeg; if not, write to the Free Software
2069 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2070 + */
2071 +
2072 +#include "hwaccel_internal.h"
2073 +#include "hwconfig.h"
2074 +#include "mpegvideo.h"
2075 +#include "v4l2_request.h"
2076 +
2077 +typedef struct V4L2RequestControlsMPEG2 {
2078 +    struct v4l2_ctrl_mpeg2_sequence sequence;
2079 +    struct v4l2_ctrl_mpeg2_picture picture;
2080 +    struct v4l2_ctrl_mpeg2_quantisation quantisation;
2081 +} V4L2RequestControlsMPEG2;
2082 +
2083 +static int v4l2_request_mpeg2_start_frame(AVCodecContext *avctx,
2084 +                                          av_unused const uint8_t *buffer,
2085 +                                          av_unused uint32_t size)
2086 +{
2087 +    const MpegEncContext *s = avctx->priv_data;
2088 +    V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private;
2089 +    V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0];
2090 +
2091 +    controls->sequence = (struct v4l2_ctrl_mpeg2_sequence) {
2092 +        /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */
2093 +        .horizontal_size = s->width,
2094 +        .vertical_size = s->height,
2095 +        .vbv_buffer_size = req->output.size,
2096 +
2097 +        /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */
2098 +        .profile_and_level_indication = 0,
2099 +        .chroma_format = s->chroma_format,
2100 +    };
2101 +
2102 +    if (s->progressive_sequence)
2103 +        controls->sequence.flags |= V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE;
2104 +
2105 +    controls->picture = (struct v4l2_ctrl_mpeg2_picture) {
2106 +        /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */
2107 +        .picture_coding_type = s->pict_type,
2108 +
2109 +        /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */
2110 +        .f_code[0][0] = s->mpeg_f_code[0][0],
2111 +        .f_code[0][1] = s->mpeg_f_code[0][1],
2112 +        .f_code[1][0] = s->mpeg_f_code[1][0],
2113 +        .f_code[1][1] = s->mpeg_f_code[1][1],
2114 +        .picture_structure = s->picture_structure,
2115 +        .intra_dc_precision = s->intra_dc_precision,
2116 +    };
2117 +
2118 +    if (s->top_field_first)
2119 +        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST;
2120 +
2121 +    if (s->frame_pred_frame_dct)
2122 +        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT;
2123 +
2124 +    if (s->concealment_motion_vectors)
2125 +        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV;
2126 +
2127 +    if (s->intra_vlc_format)
2128 +        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_INTRA_VLC;
2129 +
2130 +    if (s->q_scale_type)
2131 +        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE;
2132 +
2133 +    if (s->alternate_scan)
2134 +        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_ALT_SCAN;
2135 +
2136 +    if (s->repeat_first_field)
2137 +        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_REPEAT_FIRST;
2138 +
2139 +    if (s->progressive_frame)
2140 +        controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_PROGRESSIVE;
2141 +
2142 +    switch (s->pict_type) {
2143 +    case AV_PICTURE_TYPE_B:
2144 +        controls->picture.backward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->next_picture.f);
2145 +        // fall-through
2146 +    case AV_PICTURE_TYPE_P:
2147 +        controls->picture.forward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->last_picture.f);
2148 +    }
2149 +
2150 +    for (int i = 0; i < 64; i++) {
2151 +        int n = s->idsp.idct_permutation[ff_zigzag_direct[i]];
2152 +        controls->quantisation.intra_quantiser_matrix[i] = s->intra_matrix[n];
2153 +        controls->quantisation.non_intra_quantiser_matrix[i] = s->inter_matrix[n];
2154 +        controls->quantisation.chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n];
2155 +        controls->quantisation.chroma_non_intra_quantiser_matrix[i] = s->chroma_inter_matrix[n];
2156 +    }
2157 +
2158 +    return ff_v4l2_request_reset_frame(avctx, s->current_picture_ptr->f);
2159 +}
2160 +
2161 +static int v4l2_request_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
2162 +{
2163 +    const MpegEncContext *s = avctx->priv_data;
2164 +
2165 +    return ff_v4l2_request_append_output_buffer(avctx, s->current_picture_ptr->f, buffer, size);
2166 +}
2167 +
2168 +static int v4l2_request_mpeg2_end_frame(AVCodecContext *avctx)
2169 +{
2170 +    const MpegEncContext *s = avctx->priv_data;
2171 +    V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private;
2172 +
2173 +    struct v4l2_ext_control control[] = {
2174 +        {
2175 +            .id = V4L2_CID_STATELESS_MPEG2_SEQUENCE,
2176 +            .ptr = &controls->sequence,
2177 +            .size = sizeof(controls->sequence),
2178 +        },
2179 +        {
2180 +            .id = V4L2_CID_STATELESS_MPEG2_PICTURE,
2181 +            .ptr = &controls->picture,
2182 +            .size = sizeof(controls->picture),
2183 +        },
2184 +        {
2185 +            .id = V4L2_CID_STATELESS_MPEG2_QUANTISATION,
2186 +            .ptr = &controls->quantisation,
2187 +            .size = sizeof(controls->quantisation),
2188 +        },
2189 +    };
2190 +
2191 +    return ff_v4l2_request_decode_frame(avctx, s->current_picture_ptr->f, control, FF_ARRAY_ELEMS(control));
2192 +}
2193 +
2194 +static int v4l2_request_mpeg2_init(AVCodecContext *avctx)
2195 +{
2196 +    return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_MPEG2_SLICE, 1024 * 1024, NULL, 0);
2197 +}
2198 +
2199 +const FFHWAccel ff_mpeg2_v4l2request_hwaccel = {
2200 +    .p.name         = "mpeg2_v4l2request",
2201 +    .p.type         = AVMEDIA_TYPE_VIDEO,
2202 +    .p.id           = AV_CODEC_ID_MPEG2VIDEO,
2203 +    .p.pix_fmt      = AV_PIX_FMT_DRM_PRIME,
2204 +    .start_frame    = v4l2_request_mpeg2_start_frame,
2205 +    .decode_slice   = v4l2_request_mpeg2_decode_slice,
2206 +    .end_frame      = v4l2_request_mpeg2_end_frame,
2207 +    .frame_priv_data_size = sizeof(V4L2RequestControlsMPEG2),
2208 +    .init           = v4l2_request_mpeg2_init,
2209 +    .uninit         = ff_v4l2_request_uninit,
2210 +    .priv_data_size = sizeof(V4L2RequestContext),
2211 +    .frame_params   = ff_v4l2_request_frame_params,
2212 +    .caps_internal  = HWACCEL_CAP_ASYNC_SAFE,
2213 +};
2214 -- 
2215 2.44.0
2216
2217
2218 From 54cf5e04d320bac0839879728d912c30787b983b Mon Sep 17 00:00:00 2001
2219 From: Boris Brezillon <boris.brezillon@collabora.com>
2220 Date: Wed, 22 May 2019 14:46:58 +0200
2221 Subject: [PATCH 06/18] Add V4L2 request API vp8 hwaccel
2222
2223 Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
2224 Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
2225 Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
2226 ---
2227  configure                     |   3 +
2228  libavcodec/Makefile           |   1 +
2229  libavcodec/hwaccels.h         |   1 +
2230  libavcodec/v4l2_request_vp8.c | 181 ++++++++++++++++++++++++++++++++++
2231  libavcodec/vp8.c              |   6 ++
2232  5 files changed, 192 insertions(+)
2233  create mode 100644 libavcodec/v4l2_request_vp8.c
2234
2235 diff --git a/configure b/configure
2236 index 3127877..3ea4a3f 100755
2237 --- a/configure
2238 +++ b/configure
2239 @@ -3157,6 +3157,8 @@ vc1_vdpau_hwaccel_deps="vdpau"
2240  vc1_vdpau_hwaccel_select="vc1_decoder"
2241  vp8_nvdec_hwaccel_deps="nvdec"
2242  vp8_nvdec_hwaccel_select="vp8_decoder"
2243 +vp8_v4l2request_hwaccel_deps="v4l2_request vp8_v4l2_request"
2244 +vp8_v4l2request_hwaccel_select="vp8_decoder"
2245  vp8_vaapi_hwaccel_deps="vaapi"
2246  vp8_vaapi_hwaccel_select="vp8_decoder"
2247  vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9"
2248 @@ -7009,6 +7011,7 @@ fi
2249  check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
2250  check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
2251  check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
2252 +check_cc vp8_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP8_FRAME;"
2253  
2254  check_headers sys/videoio.h
2255  test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
2256 diff --git a/libavcodec/Makefile b/libavcodec/Makefile
2257 index 668f06a..3de7182 100644
2258 --- a/libavcodec/Makefile
2259 +++ b/libavcodec/Makefile
2260 @@ -1037,6 +1037,7 @@ OBJS-$(CONFIG_VC1_QSV_HWACCEL)            += qsvdec.o
2261  OBJS-$(CONFIG_VC1_VAAPI_HWACCEL)          += vaapi_vc1.o
2262  OBJS-$(CONFIG_VC1_VDPAU_HWACCEL)          += vdpau_vc1.o
2263  OBJS-$(CONFIG_VP8_NVDEC_HWACCEL)          += nvdec_vp8.o
2264 +OBJS-$(CONFIG_VP8_V4L2REQUEST_HWACCEL)    += v4l2_request_vp8.o
2265  OBJS-$(CONFIG_VP8_VAAPI_HWACCEL)          += vaapi_vp8.o
2266  OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL)        += dxva2_vp9.o
2267  OBJS-$(CONFIG_VP9_DXVA2_HWACCEL)          += dxva2_vp9.o
2268 diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
2269 index f5baf8a..a531226 100644
2270 --- a/libavcodec/hwaccels.h
2271 +++ b/libavcodec/hwaccels.h
2272 @@ -70,6 +70,7 @@ extern const struct FFHWAccel ff_vc1_nvdec_hwaccel;
2273  extern const struct FFHWAccel ff_vc1_vaapi_hwaccel;
2274  extern const struct FFHWAccel ff_vc1_vdpau_hwaccel;
2275  extern const struct FFHWAccel ff_vp8_nvdec_hwaccel;
2276 +extern const struct FFHWAccel ff_vp8_v4l2request_hwaccel;
2277  extern const struct FFHWAccel ff_vp8_vaapi_hwaccel;
2278  extern const struct FFHWAccel ff_vp9_d3d11va_hwaccel;
2279  extern const struct FFHWAccel ff_vp9_d3d11va2_hwaccel;
2280 diff --git a/libavcodec/v4l2_request_vp8.c b/libavcodec/v4l2_request_vp8.c
2281 new file mode 100644
2282 index 0000000..415a4c4
2283 --- /dev/null
2284 +++ b/libavcodec/v4l2_request_vp8.c
2285 @@ -0,0 +1,181 @@
2286 +/*
2287 + * This file is part of FFmpeg.
2288 + *
2289 + * FFmpeg is free software; you can redistribute it and/or
2290 + * modify it under the terms of the GNU Lesser General Public
2291 + * License as published by the Free Software Foundation; either
2292 + * version 2.1 of the License, or (at your option) any later version.
2293 + *
2294 + * FFmpeg is distributed in the hope that it will be useful,
2295 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2296 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2297 + * Lesser General Public License for more details.
2298 + *
2299 + * You should have received a copy of the GNU Lesser General Public
2300 + * License along with FFmpeg; if not, write to the Free Software
2301 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2302 + */
2303 +
2304 +#include "hwaccel_internal.h"
2305 +#include "hwconfig.h"
2306 +#include "v4l2_request.h"
2307 +#include "vp8.h"
2308 +
2309 +typedef struct V4L2RequestControlsVP8 {
2310 +    struct v4l2_ctrl_vp8_frame ctrl;
2311 +} V4L2RequestControlsVP8;
2312 +
2313 +static int v4l2_request_vp8_start_frame(AVCodecContext          *avctx,
2314 +                                        av_unused const uint8_t *buffer,
2315 +                                        av_unused uint32_t       size)
2316 +{
2317 +    const VP8Context *s = avctx->priv_data;
2318 +    V4L2RequestControlsVP8 *controls = s->framep[VP8_FRAME_CURRENT]->hwaccel_picture_private;
2319 +
2320 +    memset(&controls->ctrl, 0, sizeof(controls->ctrl));
2321 +    return ff_v4l2_request_reset_frame(avctx, s->framep[VP8_FRAME_CURRENT]->tf.f);
2322 +}
2323 +
2324 +static int v4l2_request_vp8_end_frame(AVCodecContext *avctx)
2325 +{
2326 +    const VP8Context *s = avctx->priv_data;
2327 +    V4L2RequestControlsVP8 *controls = s->framep[VP8_FRAME_CURRENT]->hwaccel_picture_private;
2328 +    struct v4l2_ext_control control[] = {
2329 +        {
2330 +            .id = V4L2_CID_STATELESS_VP8_FRAME,
2331 +            .ptr = &controls->ctrl,
2332 +            .size = sizeof(controls->ctrl),
2333 +        },
2334 +    };
2335 +
2336 +    return ff_v4l2_request_decode_frame(avctx, s->framep[VP8_FRAME_CURRENT]->tf.f,
2337 +                                        control, FF_ARRAY_ELEMS(control));
2338 +}
2339 +
2340 +static int v4l2_request_vp8_decode_slice(AVCodecContext *avctx,
2341 +                                         const uint8_t *buffer,
2342 +                                         uint32_t size)
2343 +{
2344 +    const VP8Context *s = avctx->priv_data;
2345 +    V4L2RequestControlsVP8 *controls = s->framep[VP8_FRAME_CURRENT]->hwaccel_picture_private;
2346 +    struct v4l2_ctrl_vp8_frame *frame = &controls->ctrl;
2347 +    const uint8_t *data = buffer + 3 + 7 * s->keyframe;
2348 +    unsigned int i, j, k;
2349 +
2350 +    frame->version = s->profile & 0x3;
2351 +    frame->width = avctx->width;
2352 +    frame->height = avctx->height;
2353 +    /* FIXME: set ->xx_scale */
2354 +    frame->prob_skip_false = s->prob->mbskip;
2355 +    frame->prob_intra = s->prob->intra;
2356 +    frame->prob_gf = s->prob->golden;
2357 +    frame->prob_last = s->prob->last;
2358 +    frame->first_part_size = s->header_partition_size;
2359 +    frame->first_part_header_bits = (8 * (s->coder_state_at_header_end.input - data) -
2360 +                                    s->coder_state_at_header_end.bit_count - 8);
2361 +    frame->num_dct_parts = s->num_coeff_partitions;
2362 +    for (i = 0; i < 8; i++)
2363 +        frame->dct_part_sizes[i] = s->coeff_partition_size[i];
2364 +
2365 +    frame->coder_state.range = s->coder_state_at_header_end.range;
2366 +    frame->coder_state.value = s->coder_state_at_header_end.value;
2367 +    frame->coder_state.bit_count = s->coder_state_at_header_end.bit_count;
2368 +    if (s->framep[VP8_FRAME_PREVIOUS])
2369 +        frame->last_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP8_FRAME_PREVIOUS]->tf.f);
2370 +    if (s->framep[VP8_FRAME_GOLDEN])
2371 +        frame->golden_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP8_FRAME_GOLDEN]->tf.f);
2372 +    if (s->framep[VP8_FRAME_ALTREF])
2373 +        frame->alt_frame_ts = ff_v4l2_request_get_capture_timestamp(s->framep[VP8_FRAME_ALTREF]->tf.f);
2374 +    frame->flags |= s->invisible ? 0 : V4L2_VP8_FRAME_FLAG_SHOW_FRAME;
2375 +    frame->flags |= s->mbskip_enabled ? V4L2_VP8_FRAME_FLAG_MB_NO_SKIP_COEFF : 0;
2376 +    frame->flags |= (s->profile & 0x4) ? V4L2_VP8_FRAME_FLAG_EXPERIMENTAL : 0;
2377 +    frame->flags |= s->keyframe ? V4L2_VP8_FRAME_FLAG_KEY_FRAME : 0;
2378 +    frame->flags |= s->sign_bias[VP8_FRAME_GOLDEN] ? V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN : 0;
2379 +    frame->flags |= s->sign_bias[VP8_FRAME_ALTREF] ? V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT : 0;
2380 +    frame->segment.flags |= s->segmentation.enabled ? V4L2_VP8_SEGMENT_FLAG_ENABLED : 0;
2381 +    frame->segment.flags |= s->segmentation.update_map ? V4L2_VP8_SEGMENT_FLAG_UPDATE_MAP : 0;
2382 +    frame->segment.flags |= s->segmentation.update_feature_data ? V4L2_VP8_SEGMENT_FLAG_UPDATE_FEATURE_DATA : 0;
2383 +    frame->segment.flags |= s->segmentation.absolute_vals ? 0 : V4L2_VP8_SEGMENT_FLAG_DELTA_VALUE_MODE;
2384 +    for (i = 0; i < 4; i++) {
2385 +        frame->segment.quant_update[i] = s->segmentation.base_quant[i];
2386 +        frame->segment.lf_update[i] = s->segmentation.filter_level[i];
2387 +    }
2388 +
2389 +    for (i = 0; i < 3; i++)
2390 +        frame->segment.segment_probs[i] = s->prob->segmentid[i];
2391 +
2392 +    frame->lf.level = s->filter.level;
2393 +    frame->lf.sharpness_level = s->filter.sharpness;
2394 +    frame->lf.flags |= s->lf_delta.enabled ? V4L2_VP8_LF_ADJ_ENABLE : 0;
2395 +    frame->lf.flags |= s->lf_delta.update ? V4L2_VP8_LF_DELTA_UPDATE : 0;
2396 +    frame->lf.flags |= s->filter.simple ? V4L2_VP8_LF_FILTER_TYPE_SIMPLE : 0;
2397 +    for (i = 0; i < 4; i++) {
2398 +        frame->lf.ref_frm_delta[i] = s->lf_delta.ref[i];
2399 +        frame->lf.mb_mode_delta[i] = s->lf_delta.mode[i + MODE_I4x4];
2400 +    }
2401 +
2402 +    // Probabilites
2403 +    if (s->keyframe) {
2404 +        static const uint8_t keyframe_y_mode_probs[4] = {
2405 +            145, 156, 163, 128
2406 +        };
2407 +        static const uint8_t keyframe_uv_mode_probs[3] = {
2408 +            142, 114, 183
2409 +        };
2410 +
2411 +        memcpy(frame->entropy.y_mode_probs, keyframe_y_mode_probs,  4);
2412 +        memcpy(frame->entropy.uv_mode_probs, keyframe_uv_mode_probs, 3);
2413 +    } else {
2414 +        for (i = 0; i < 4; i++)
2415 +            frame->entropy.y_mode_probs[i] = s->prob->pred16x16[i];
2416 +        for (i = 0; i < 3; i++)
2417 +            frame->entropy.uv_mode_probs[i] = s->prob->pred8x8c[i];
2418 +    }
2419 +    for (i = 0; i < 2; i++)
2420 +        for (j = 0; j < 19; j++)
2421 +            frame->entropy.mv_probs[i][j] = s->prob->mvc[i][j];
2422 +
2423 +    for (i = 0; i < 4; i++) {
2424 +        for (j = 0; j < 8; j++) {
2425 +            static const int coeff_bands_inverse[8] = {
2426 +                0, 1, 2, 3, 5, 6, 4, 15
2427 +            };
2428 +            int coeff_pos = coeff_bands_inverse[j];
2429 +
2430 +            for (k = 0; k < 3; k++) {
2431 +                memcpy(frame->entropy.coeff_probs[i][j][k],
2432 +                       s->prob->token[i][coeff_pos][k], 11);
2433 +            }
2434 +        }
2435 +    }
2436 +
2437 +    frame->quant.y_ac_qi = s->quant.yac_qi;
2438 +    frame->quant.y_dc_delta = s->quant.ydc_delta;
2439 +    frame->quant.y2_dc_delta = s->quant.y2dc_delta;
2440 +    frame->quant.y2_ac_delta = s->quant.y2ac_delta;
2441 +    frame->quant.uv_dc_delta = s->quant.uvdc_delta;
2442 +    frame->quant.uv_ac_delta = s->quant.uvac_delta;
2443 +
2444 +    return ff_v4l2_request_append_output_buffer(avctx, s->framep[VP8_FRAME_CURRENT]->tf.f, buffer, size);
2445 +}
2446 +
2447 +static int v4l2_request_vp8_init(AVCodecContext *avctx)
2448 +{
2449 +    return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP8_FRAME, 2 * 1024 * 1024, NULL, 0);
2450 +}
2451 +
2452 +const FFHWAccel ff_vp8_v4l2request_hwaccel = {
2453 +    .p.name         = "vp8_v4l2request",
2454 +    .p.type         = AVMEDIA_TYPE_VIDEO,
2455 +    .p.id           = AV_CODEC_ID_VP8,
2456 +    .p.pix_fmt      = AV_PIX_FMT_DRM_PRIME,
2457 +    .start_frame    = v4l2_request_vp8_start_frame,
2458 +    .decode_slice   = v4l2_request_vp8_decode_slice,
2459 +    .end_frame      = v4l2_request_vp8_end_frame,
2460 +    .frame_priv_data_size = sizeof(V4L2RequestControlsVP8),
2461 +    .init           = v4l2_request_vp8_init,
2462 +    .uninit         = ff_v4l2_request_uninit,
2463 +    .priv_data_size = sizeof(V4L2RequestContext),
2464 +    .frame_params   = ff_v4l2_request_frame_params,
2465 +    .caps_internal  = HWACCEL_CAP_ASYNC_SAFE,
2466 +};
2467 diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
2468 index ffc430d..eb619c9 100644
2469 --- a/libavcodec/vp8.c
2470 +++ b/libavcodec/vp8.c
2471 @@ -197,6 +197,9 @@ static enum AVPixelFormat get_pixel_format(VP8Context *s)
2472  #endif
2473  #if CONFIG_VP8_NVDEC_HWACCEL
2474          AV_PIX_FMT_CUDA,
2475 +#endif
2476 +#if CONFIG_VP8_V4L2REQUEST_HWACCEL
2477 +        AV_PIX_FMT_DRM_PRIME,
2478  #endif
2479          AV_PIX_FMT_YUV420P,
2480          AV_PIX_FMT_NONE,
2481 @@ -3002,6 +3005,9 @@ const FFCodec ff_vp8_decoder = {
2482  #endif
2483  #if CONFIG_VP8_NVDEC_HWACCEL
2484                                 HWACCEL_NVDEC(vp8),
2485 +#endif
2486 +#if CONFIG_VP8_V4L2REQUEST_HWACCEL
2487 +                               HWACCEL_V4L2REQUEST(vp8),
2488  #endif
2489                                 NULL
2490                             },
2491 -- 
2492 2.44.0
2493
2494
2495 From 8f67d3099fcb63251f3fe718bc464417a053eb8e Mon Sep 17 00:00:00 2001
2496 From: Jernej Skrabec <jernej.skrabec@siol.net>
2497 Date: Sat, 15 Dec 2018 22:32:16 +0100
2498 Subject: [PATCH 07/18] Add V4L2 request API hevc hwaccel
2499
2500 Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
2501 Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
2502 Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
2503 Signed-off-by: Alex Bee <knaerzche@gmail.com>
2504 ---
2505  configure                      |   3 +
2506  libavcodec/Makefile            |   1 +
2507  libavcodec/hevcdec.c           |  10 +
2508  libavcodec/hwaccels.h          |   1 +
2509  libavcodec/v4l2_request_hevc.c | 682 +++++++++++++++++++++++++++++++++
2510  5 files changed, 697 insertions(+)
2511  create mode 100644 libavcodec/v4l2_request_hevc.c
2512
2513 diff --git a/configure b/configure
2514 index 3ea4a3f..ad9af0b 100755
2515 --- a/configure
2516 +++ b/configure
2517 @@ -3099,6 +3099,8 @@ hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC"
2518  hevc_dxva2_hwaccel_select="hevc_decoder"
2519  hevc_nvdec_hwaccel_deps="nvdec"
2520  hevc_nvdec_hwaccel_select="hevc_decoder"
2521 +hevc_v4l2request_hwaccel_deps="v4l2_request hevc_v4l2_request"
2522 +hevc_v4l2request_hwaccel_select="hevc_decoder"
2523  hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC"
2524  hevc_vaapi_hwaccel_select="hevc_decoder"
2525  hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC"
2526 @@ -7010,6 +7012,7 @@ fi
2527  
2528  check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
2529  check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
2530 +check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC_SLICE;"
2531  check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
2532  check_cc vp8_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP8_FRAME;"
2533  
2534 diff --git a/libavcodec/Makefile b/libavcodec/Makefile
2535 index 3de7182..e32bd18 100644
2536 --- a/libavcodec/Makefile
2537 +++ b/libavcodec/Makefile
2538 @@ -1010,6 +1010,7 @@ OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL)       += dxva2_hevc.o
2539  OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL)         += dxva2_hevc.o
2540  OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL)         += nvdec_hevc.o
2541  OBJS-$(CONFIG_HEVC_QSV_HWACCEL)           += qsvdec.o
2542 +OBJS-$(CONFIG_HEVC_V4L2REQUEST_HWACCEL)   += v4l2_request_hevc.o
2543  OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL)         += vaapi_hevc.o h265_profile_level.o
2544  OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL)         += vdpau_hevc.o h265_profile_level.o
2545  OBJS-$(CONFIG_HEVC_VULKAN_HWACCEL)        += vulkan_decode.o vulkan_hevc.o
2546 diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
2547 index b267f6e..2086ef3 100644
2548 --- a/libavcodec/hevcdec.c
2549 +++ b/libavcodec/hevcdec.c
2550 @@ -401,6 +401,7 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
2551  #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + \
2552                       CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \
2553                       CONFIG_HEVC_NVDEC_HWACCEL + \
2554 +                     CONFIG_HEVC_V4L2REQUEST_HWACCEL + \
2555                       CONFIG_HEVC_VAAPI_HWACCEL + \
2556                       CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + \
2557                       CONFIG_HEVC_VDPAU_HWACCEL + \
2558 @@ -431,6 +432,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
2559  #endif
2560  #if CONFIG_HEVC_VULKAN_HWACCEL
2561          *fmt++ = AV_PIX_FMT_VULKAN;
2562 +#endif
2563 +#if CONFIG_HEVC_V4L2REQUEST_HWACCEL
2564 +        *fmt++ = AV_PIX_FMT_DRM_PRIME;
2565  #endif
2566          break;
2567      case AV_PIX_FMT_YUV420P10:
2568 @@ -455,6 +459,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
2569  #endif
2570  #if CONFIG_HEVC_NVDEC_HWACCEL
2571          *fmt++ = AV_PIX_FMT_CUDA;
2572 +#endif
2573 +#if CONFIG_HEVC_V4L2REQUEST_HWACCEL
2574 +        *fmt++ = AV_PIX_FMT_DRM_PRIME;
2575  #endif
2576          break;
2577      case AV_PIX_FMT_YUV444P:
2578 @@ -3728,6 +3735,9 @@ const FFCodec ff_hevc_decoder = {
2579  #endif
2580  #if CONFIG_HEVC_VULKAN_HWACCEL
2581                                 HWACCEL_VULKAN(hevc),
2582 +#endif
2583 +#if CONFIG_HEVC_V4L2REQUEST_HWACCEL
2584 +                               HWACCEL_V4L2REQUEST(hevc),
2585  #endif
2586                                 NULL
2587                             },
2588 diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
2589 index a531226..4a0de92 100644
2590 --- a/libavcodec/hwaccels.h
2591 +++ b/libavcodec/hwaccels.h
2592 @@ -41,6 +41,7 @@ extern const struct FFHWAccel ff_hevc_d3d11va_hwaccel;
2593  extern const struct FFHWAccel ff_hevc_d3d11va2_hwaccel;
2594  extern const struct FFHWAccel ff_hevc_dxva2_hwaccel;
2595  extern const struct FFHWAccel ff_hevc_nvdec_hwaccel;
2596 +extern const struct FFHWAccel ff_hevc_v4l2request_hwaccel;
2597  extern const struct FFHWAccel ff_hevc_vaapi_hwaccel;
2598  extern const struct FFHWAccel ff_hevc_vdpau_hwaccel;
2599  extern const struct FFHWAccel ff_hevc_videotoolbox_hwaccel;
2600 diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c
2601 new file mode 100644
2602 index 0000000..2c3537d
2603 --- /dev/null
2604 +++ b/libavcodec/v4l2_request_hevc.c
2605 @@ -0,0 +1,682 @@
2606 +/*
2607 + * This file is part of FFmpeg.
2608 + *
2609 + * FFmpeg is free software; you can redistribute it and/or
2610 + * modify it under the terms of the GNU Lesser General Public
2611 + * License as published by the Free Software Foundation; either
2612 + * version 2.1 of the License, or (at your option) any later version.
2613 + *
2614 + * FFmpeg is distributed in the hope that it will be useful,
2615 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2616 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2617 + * Lesser General Public License for more details.
2618 + *
2619 + * You should have received a copy of the GNU Lesser General Public
2620 + * License along with FFmpeg; if not, write to the Free Software
2621 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2622 + */
2623 +
2624 +#include "hevcdec.h"
2625 +#include "hwaccel_internal.h"
2626 +#include "hwconfig.h"
2627 +#include "internal.h"
2628 +#include "v4l2_request.h"
2629 +
2630 +#define MAX_SLICES 600 // as per HEVC spec ?
2631 +#define V4L2_HEVC_CONTROLS_MAX 6
2632 +
2633 +typedef struct V4L2RequestControlsHEVC {
2634 +    struct v4l2_ctrl_hevc_sps sps;
2635 +    struct v4l2_ctrl_hevc_pps pps;
2636 +    struct v4l2_ctrl_hevc_decode_params dec_params;
2637 +    struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix;
2638 +    struct v4l2_ctrl_hevc_slice_params slice_params[MAX_SLICES];
2639 +    __u32 *entry_point_offsets;
2640 +    unsigned int num_entry_point_offsets;
2641 +    int first_slice;
2642 +    int num_slices;
2643 +} V4L2RequestControlsHEVC;
2644 +
2645 +typedef struct V4L2RequestContextHEVC {
2646 +    V4L2RequestContext base;
2647 +    unsigned int decode_mode;
2648 +    unsigned int start_code;
2649 +    __u32 max_slices;
2650 +    unsigned int supports_entry_point_offsets;
2651 +    unsigned int supports_slices;
2652 +    unsigned int supports_scaling_matrix;
2653 +} V4L2RequestContextHEVC;
2654 +
2655 +static uint8_t nalu_slice_start_code[] = { 0x00, 0x00, 0x01 };
2656 +
2657 +static void v4l2_request_hevc_fill_pred_table(const HEVCContext *h, struct v4l2_hevc_pred_weight_table *table)
2658 +{
2659 +    int32_t luma_weight_denom, chroma_weight_denom;
2660 +    const SliceHeader *sh = &h->sh;
2661 +
2662 +    if (sh->slice_type == HEVC_SLICE_I ||
2663 +        (sh->slice_type == HEVC_SLICE_P && !h->ps.pps->weighted_pred_flag) ||
2664 +        (sh->slice_type == HEVC_SLICE_B && !h->ps.pps->weighted_bipred_flag))
2665 +        return;
2666 +
2667 +    table->luma_log2_weight_denom = sh->luma_log2_weight_denom;
2668 +
2669 +    if (h->ps.sps->chroma_format_idc)
2670 +        table->delta_chroma_log2_weight_denom = sh->chroma_log2_weight_denom - sh->luma_log2_weight_denom;
2671 +
2672 +    luma_weight_denom = (1 << sh->luma_log2_weight_denom);
2673 +    chroma_weight_denom = (1 << sh->chroma_log2_weight_denom);
2674 +
2675 +    for (int i = 0; i < 15 && i < sh->nb_refs[L0]; i++) {
2676 +        table->delta_luma_weight_l0[i] = sh->luma_weight_l0[i] - luma_weight_denom;
2677 +        table->luma_offset_l0[i] = sh->luma_offset_l0[i];
2678 +        table->delta_chroma_weight_l0[i][0] = sh->chroma_weight_l0[i][0] - chroma_weight_denom;
2679 +        table->delta_chroma_weight_l0[i][1] = sh->chroma_weight_l0[i][1] - chroma_weight_denom;
2680 +        table->chroma_offset_l0[i][0] = sh->chroma_offset_l0[i][0];
2681 +        table->chroma_offset_l0[i][1] = sh->chroma_offset_l0[i][1];
2682 +    }
2683 +
2684 +    if (sh->slice_type != HEVC_SLICE_B)
2685 +        return;
2686 +
2687 +    for (int i = 0; i < 15 && i < sh->nb_refs[L1]; i++) {
2688 +        table->delta_luma_weight_l1[i] = sh->luma_weight_l1[i] - luma_weight_denom;
2689 +        table->luma_offset_l1[i] = sh->luma_offset_l1[i];
2690 +        table->delta_chroma_weight_l1[i][0] = sh->chroma_weight_l1[i][0] - chroma_weight_denom;
2691 +        table->delta_chroma_weight_l1[i][1] = sh->chroma_weight_l1[i][1] - chroma_weight_denom;
2692 +        table->chroma_offset_l1[i][0] = sh->chroma_offset_l1[i][0];
2693 +        table->chroma_offset_l1[i][1] = sh->chroma_offset_l1[i][1];
2694 +    }
2695 +}
2696 +
2697 +static uint8_t get_ref_pic_index(const HEVCContext *h, const HEVCFrame *frame,
2698 +                                 struct v4l2_ctrl_hevc_decode_params *dec_params)
2699 +{
2700 +    uint64_t timestamp;
2701 +
2702 +    if (!frame)
2703 +        return 0;
2704 +
2705 +    timestamp = ff_v4l2_request_get_capture_timestamp(frame->frame);
2706 +
2707 +    for (uint8_t i = 0; i < dec_params->num_active_dpb_entries; i++) {
2708 +        struct v4l2_hevc_dpb_entry *entry = &dec_params->dpb[i];
2709 +        if (entry->timestamp == timestamp)
2710 +            return i;
2711 +    }
2712 +
2713 +    return 0;
2714 +}
2715 +
2716 +static void fill_dec_params(struct v4l2_ctrl_hevc_decode_params *dec_params, const HEVCContext *h)
2717 +{
2718 +    const HEVCFrame *pic = h->ref;
2719 +    const SliceHeader *sh = &h->sh;
2720 +    int i, entries = 0;
2721 +
2722 +    *dec_params = (struct v4l2_ctrl_hevc_decode_params) {
2723 +        .pic_order_cnt_val = pic->poc, /* FIXME: is this same as slice_params->slice_pic_order_cnt ? */
2724 +        .short_term_ref_pic_set_size = sh->short_term_ref_pic_set_size,
2725 +        .long_term_ref_pic_set_size = sh->long_term_ref_pic_set_size,
2726 +        .num_poc_st_curr_before = h->rps[ST_CURR_BEF].nb_refs,
2727 +        .num_poc_st_curr_after = h->rps[ST_CURR_AFT].nb_refs,
2728 +        .num_poc_lt_curr = h->rps[LT_CURR].nb_refs,
2729 +    };
2730 +
2731 +    for (i = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {
2732 +        const HEVCFrame *frame = &h->DPB[i];
2733 +        if (frame != pic && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) {
2734 +            struct v4l2_hevc_dpb_entry *entry = &dec_params->dpb[entries++];
2735 +
2736 +            entry->timestamp = ff_v4l2_request_get_capture_timestamp(frame->frame);
2737 +            entry->field_pic = !!(frame->frame->flags & AV_FRAME_FLAG_INTERLACED);
2738 +            entry->flags = 0;
2739 +            if (frame->flags & HEVC_FRAME_FLAG_LONG_REF)
2740 +                entry->flags |= V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE;
2741 +
2742 +            entry->pic_order_cnt_val = frame->poc;
2743 +        }
2744 +    }
2745 +
2746 +    dec_params->num_active_dpb_entries = entries;
2747 +
2748 +    if (IS_IRAP(h))
2749 +        dec_params->flags |= V4L2_HEVC_DECODE_PARAM_FLAG_IRAP_PIC;
2750 +
2751 +    if (IS_IDR(h))
2752 +        dec_params->flags |= V4L2_HEVC_DECODE_PARAM_FLAG_IDR_PIC;
2753 +
2754 +    if (sh->no_output_of_prior_pics_flag)
2755 +        dec_params->flags |= V4L2_HEVC_DECODE_PARAM_FLAG_NO_OUTPUT_OF_PRIOR;
2756 +
2757 +    for (i = 0; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) {
2758 +        dec_params->poc_st_curr_before[i] = get_ref_pic_index(h, h->rps[ST_CURR_BEF].ref[i], dec_params);
2759 +        dec_params->poc_st_curr_after[i] = get_ref_pic_index(h, h->rps[ST_CURR_AFT].ref[i], dec_params);
2760 +        dec_params->poc_lt_curr[i] = get_ref_pic_index(h, h->rps[LT_CURR].ref[i], dec_params);
2761 +    }
2762 +}
2763 +
2764 +static int v4l2_request_hevc_fill_slice_params(const HEVCContext *h,
2765 +                                               V4L2RequestControlsHEVC *controls,
2766 +                                               int slice)
2767 +{
2768 +    struct v4l2_ctrl_hevc_slice_params *slice_params = &controls->slice_params[slice];
2769 +    struct v4l2_ctrl_hevc_decode_params *dec_params = &controls->dec_params;
2770 +    const HEVCFrame *pic = h->ref;
2771 +    const SliceHeader *sh = &h->sh;
2772 +    RefPicList *rpl;
2773 +    int i;
2774 +
2775 +    *slice_params = (struct v4l2_ctrl_hevc_slice_params) {
2776 +        .bit_size = 0,
2777 +        .data_byte_offset = (get_bits_count(&h->HEVClc->gb) + 1 + 7) / 8,
2778 +        .num_entry_point_offsets = sh->num_entry_point_offsets,
2779 +
2780 +        /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
2781 +        .nal_unit_type = h->nal_unit_type,
2782 +        .nuh_temporal_id_plus1 = h->temporal_id + 1,
2783 +
2784 +        /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
2785 +        .slice_type = sh->slice_type,
2786 +        .colour_plane_id = sh->colour_plane_id,
2787 +        .slice_pic_order_cnt = pic->poc,
2788 +        .num_ref_idx_l0_active_minus1 = sh->nb_refs[L0] ? sh->nb_refs[L0] - 1 : 0,
2789 +        .num_ref_idx_l1_active_minus1 = sh->nb_refs[L1] ? sh->nb_refs[L1] - 1 : 0,
2790 +        .collocated_ref_idx = sh->slice_temporal_mvp_enabled_flag ? sh->collocated_ref_idx : 0,
2791 +        .five_minus_max_num_merge_cand = sh->slice_type == HEVC_SLICE_I ? 0 : 5 - sh->max_num_merge_cand,
2792 +        .slice_qp_delta = sh->slice_qp_delta,
2793 +        .slice_cb_qp_offset = sh->slice_cb_qp_offset,
2794 +        .slice_cr_qp_offset = sh->slice_cr_qp_offset,
2795 +        .slice_act_y_qp_offset = 0,
2796 +        .slice_act_cb_qp_offset = 0,
2797 +        .slice_act_cr_qp_offset = 0,
2798 +        .slice_beta_offset_div2 = sh->beta_offset / 2,
2799 +        .slice_tc_offset_div2 = sh->tc_offset / 2,
2800 +
2801 +        /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */
2802 +        .pic_struct = h->sei.picture_timing.picture_struct,
2803 +
2804 +        /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
2805 +        .slice_segment_addr = sh->slice_segment_addr,
2806 +        .short_term_ref_pic_set_size = sh->short_term_ref_pic_set_size,
2807 +        .long_term_ref_pic_set_size = sh->long_term_ref_pic_set_size,
2808 +    };
2809 +
2810 +    if (sh->slice_sample_adaptive_offset_flag[0])
2811 +        slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA;
2812 +
2813 +    if (sh->slice_sample_adaptive_offset_flag[1])
2814 +        slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA;
2815 +
2816 +    if (sh->slice_temporal_mvp_enabled_flag)
2817 +        slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED;
2818 +
2819 +    if (sh->mvd_l1_zero_flag)
2820 +        slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO;
2821 +
2822 +    if (sh->cabac_init_flag)
2823 +        slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT;
2824 +
2825 +    if (sh->collocated_list == L0)
2826 +        slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0;
2827 +
2828 +    /* TODO: V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV */
2829 +
2830 +    if (sh->disable_deblocking_filter_flag)
2831 +        slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED;
2832 +
2833 +    if (sh->slice_loop_filter_across_slices_enabled_flag)
2834 +        slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED;
2835 +
2836 +    if (sh->dependent_slice_segment_flag)
2837 +        slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT;
2838 +
2839 +    if (sh->slice_type != HEVC_SLICE_I) {
2840 +        rpl = &h->ref->refPicList[0];
2841 +        for (i = 0; i < rpl->nb_refs; i++)
2842 +            slice_params->ref_idx_l0[i] = get_ref_pic_index(h, rpl->ref[i], dec_params);
2843 +    }
2844 +
2845 +    if (sh->slice_type == HEVC_SLICE_B) {
2846 +        rpl = &h->ref->refPicList[1];
2847 +        for (i = 0; i < rpl->nb_refs; i++)
2848 +            slice_params->ref_idx_l1[i] = get_ref_pic_index(h, rpl->ref[i], dec_params);
2849 +    }
2850 +
2851 +    v4l2_request_hevc_fill_pred_table(h, &slice_params->pred_weight_table);
2852 +
2853 +    if (controls->num_entry_point_offsets < sh->num_entry_point_offsets) {
2854 +        av_freep(&controls->entry_point_offsets);
2855 +        controls->entry_point_offsets = av_mallocz(sizeof(*controls->entry_point_offsets) * sh->num_entry_point_offsets);
2856 +        if (!controls->entry_point_offsets)
2857 +            return AVERROR(ENOMEM);
2858 +        controls->num_entry_point_offsets = sh->num_entry_point_offsets;
2859 +    }
2860 +
2861 +    for (i = 0; i < sh->num_entry_point_offsets; i++)
2862 +        controls->entry_point_offsets[i] = sh->entry_point_offset[i];
2863 +
2864 +    return 0;
2865 +}
2866 +
2867 +static void fill_sps(struct v4l2_ctrl_hevc_sps *ctrl, const HEVCContext *h)
2868 +{
2869 +    const HEVCSPS *sps = h->ps.sps;
2870 +    const HEVCPPS *pps = h->ps.pps;
2871 +
2872 +    /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */
2873 +    *ctrl = (struct v4l2_ctrl_hevc_sps) {
2874 +        .video_parameter_set_id = sps->vps_id,
2875 +        .seq_parameter_set_id = pps->sps_id,
2876 +        .pic_width_in_luma_samples = sps->width,
2877 +        .pic_height_in_luma_samples = sps->height,
2878 +        .bit_depth_luma_minus8 = sps->bit_depth - 8,
2879 +        .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
2880 +        .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4,
2881 +        .sps_max_dec_pic_buffering_minus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering - 1,
2882 +        .sps_max_num_reorder_pics = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics,
2883 +        .sps_max_latency_increase_plus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_latency_increase + 1,
2884 +        .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3,
2885 +        .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size,
2886 +        .log2_min_luma_transform_block_size_minus2 = sps->log2_min_tb_size - 2,
2887 +        .log2_diff_max_min_luma_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size,
2888 +        .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
2889 +        .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
2890 +        .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1,
2891 +        .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1,
2892 +        .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3,
2893 +        .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size,
2894 +        .num_short_term_ref_pic_sets = sps->nb_st_rps,
2895 +        .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps,
2896 +        .chroma_format_idc = sps->chroma_format_idc,
2897 +        .sps_max_sub_layers_minus1 = sps->max_sub_layers - 1,
2898 +    };
2899 +
2900 +    if (sps->separate_colour_plane_flag)
2901 +        ctrl->flags |= V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE;
2902 +
2903 +    if (sps->scaling_list_enable_flag)
2904 +        ctrl->flags |= V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED;
2905 +
2906 +    if (sps->amp_enabled_flag)
2907 +        ctrl->flags |= V4L2_HEVC_SPS_FLAG_AMP_ENABLED;
2908 +
2909 +    if (sps->sao_enabled)
2910 +        ctrl->flags |= V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET;
2911 +
2912 +    if (sps->pcm_enabled_flag)
2913 +        ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_ENABLED;
2914 +
2915 +    if (sps->pcm.loop_filter_disable_flag)
2916 +        ctrl->flags |= V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED;
2917 +
2918 +    if (sps->long_term_ref_pics_present_flag)
2919 +        ctrl->flags |= V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT;
2920 +
2921 +    if (sps->sps_temporal_mvp_enabled_flag)
2922 +        ctrl->flags |= V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED;
2923 +
2924 +    if (sps->sps_strong_intra_smoothing_enable_flag)
2925 +        ctrl->flags |= V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED;
2926 +}
2927 +
2928 +static int v4l2_request_hevc_start_frame(AVCodecContext *avctx,
2929 +                                         av_unused const uint8_t *buffer,
2930 +                                         av_unused uint32_t size)
2931 +{
2932 +    const HEVCContext *h = avctx->priv_data;
2933 +    const HEVCPPS *pps = h->ps.pps;
2934 +    const HEVCSPS *sps = h->ps.sps;
2935 +    const ScalingList *sl = pps->scaling_list_data_present_flag ?
2936 +                            &pps->scaling_list :
2937 +                            sps->scaling_list_enable_flag ?
2938 +                            &sps->scaling_list : NULL;
2939 +    V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
2940 +    const SliceHeader *sh = &h->sh;
2941 +
2942 +    fill_sps(&controls->sps, h);
2943 +    fill_dec_params(&controls->dec_params, h);
2944 +
2945 +    if (sl) {
2946 +        for (int i = 0; i < 6; i++) {
2947 +            for (int j = 0; j < 16; j++)
2948 +                controls->scaling_matrix.scaling_list_4x4[i][j] = sl->sl[0][i][j];
2949 +            for (int j = 0; j < 64; j++) {
2950 +                controls->scaling_matrix.scaling_list_8x8[i][j]   = sl->sl[1][i][j];
2951 +                controls->scaling_matrix.scaling_list_16x16[i][j] = sl->sl[2][i][j];
2952 +                if (i < 2)
2953 +                    controls->scaling_matrix.scaling_list_32x32[i][j] = sl->sl[3][i * 3][j];
2954 +            }
2955 +            controls->scaling_matrix.scaling_list_dc_coef_16x16[i] = sl->sl_dc[0][i];
2956 +            if (i < 2)
2957 +                controls->scaling_matrix.scaling_list_dc_coef_32x32[i] = sl->sl_dc[1][i * 3];
2958 +        }
2959 +    }
2960 +
2961 +    /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */
2962 +    controls->pps = (struct v4l2_ctrl_hevc_pps) {
2963 +        .pic_parameter_set_id = sh->pps_id,
2964 +        .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
2965 +        .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1,
2966 +        .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1,
2967 +        .init_qp_minus26 = pps->pic_init_qp_minus26,
2968 +        .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
2969 +        .pps_cb_qp_offset = pps->cb_qp_offset,
2970 +        .pps_cr_qp_offset = pps->cr_qp_offset,
2971 +        .pps_beta_offset_div2 = pps->beta_offset / 2,
2972 +        .pps_tc_offset_div2 = pps->tc_offset / 2,
2973 +        .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2,
2974 +    };
2975 +
2976 +    if (pps->dependent_slice_segments_enabled_flag)
2977 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED;
2978 +
2979 +    if (pps->output_flag_present_flag)
2980 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT;
2981 +
2982 +    if (pps->sign_data_hiding_flag)
2983 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED;
2984 +
2985 +    if (pps->cabac_init_present_flag)
2986 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT;
2987 +
2988 +    if (pps->constrained_intra_pred_flag)
2989 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED;
2990 +
2991 +    if (pps->transform_skip_enabled_flag)
2992 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED;
2993 +
2994 +    if (pps->cu_qp_delta_enabled_flag)
2995 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED;
2996 +
2997 +    if (pps->pic_slice_level_chroma_qp_offsets_present_flag)
2998 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT;
2999 +
3000 +    if (pps->weighted_pred_flag)
3001 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED;
3002 +
3003 +    if (pps->weighted_bipred_flag)
3004 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED;
3005 +
3006 +    if (pps->transquant_bypass_enable_flag)
3007 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED;
3008 +
3009 +    if (pps->tiles_enabled_flag)
3010 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TILES_ENABLED;
3011 +
3012 +    if (pps->entropy_coding_sync_enabled_flag)
3013 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED;
3014 +
3015 +    if (pps->loop_filter_across_tiles_enabled_flag)
3016 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED;
3017 +
3018 +    if (pps->seq_loop_filter_across_slices_enabled_flag)
3019 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED;
3020 +
3021 +    if (pps->deblocking_filter_override_enabled_flag)
3022 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED;
3023 +
3024 +    if (pps->disable_dbf)
3025 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER;
3026 +
3027 +    if (pps->lists_modification_present_flag)
3028 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT;
3029 +
3030 +    if (pps->slice_header_extension_present_flag)
3031 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT;
3032 +
3033 +    if (pps->deblocking_filter_control_present_flag)
3034 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT;
3035 +
3036 +    if (pps->uniform_spacing_flag)
3037 +        controls->pps.flags |= V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING;
3038 +
3039 +    if (pps->tiles_enabled_flag) {
3040 +        controls->pps.num_tile_columns_minus1 = pps->num_tile_columns - 1;
3041 +        controls->pps.num_tile_rows_minus1 = pps->num_tile_rows - 1;
3042 +
3043 +        for (int i = 0; i < pps->num_tile_columns; i++)
3044 +            controls->pps.column_width_minus1[i] = pps->column_width[i] - 1;
3045 +
3046 +        for (int i = 0; i < pps->num_tile_rows; i++)
3047 +            controls->pps.row_height_minus1[i] = pps->row_height[i] - 1;
3048 +    }
3049 +
3050 +    controls->first_slice = 1;
3051 +    controls->num_slices = 0;
3052 +    controls->num_entry_point_offsets = 0;
3053 +
3054 +    return ff_v4l2_request_reset_frame(avctx, h->ref->frame);
3055 +}
3056 +
3057 +static int v4l2_request_hevc_queue_decode(AVCodecContext *avctx, int last_slice)
3058 +{
3059 +    const HEVCContext *h = avctx->priv_data;
3060 +    V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
3061 +    struct v4l2_ctrl_hevc_slice_params *first_slice_params = &controls->slice_params[0];
3062 +    V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data;
3063 +    int num_controls = 0;
3064 +
3065 +    struct v4l2_ext_control control[V4L2_HEVC_CONTROLS_MAX] = {};
3066 +
3067 +    control[num_controls++] = (struct v4l2_ext_control) {
3068 +        .id = V4L2_CID_STATELESS_HEVC_SPS,
3069 +        .ptr = &controls->sps,
3070 +        .size = sizeof(controls->sps),
3071 +    };
3072 +
3073 +    control[num_controls++] = (struct v4l2_ext_control) {
3074 +        .id = V4L2_CID_STATELESS_HEVC_PPS,
3075 +        .ptr = &controls->pps,
3076 +        .size = sizeof(controls->pps),
3077 +    };
3078 +
3079 +    control[num_controls++] = (struct v4l2_ext_control) {
3080 +        .id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS,
3081 +        .ptr = &controls->dec_params,
3082 +        .size = sizeof(controls->dec_params),
3083 +    };
3084 +
3085 +    if (ctx->supports_scaling_matrix) {
3086 +        control[num_controls++] = (struct v4l2_ext_control) {
3087 +            .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX,
3088 +            .ptr = &controls->scaling_matrix,
3089 +            .size = sizeof(controls->scaling_matrix),
3090 +        };
3091 +    }
3092 +
3093 +    if (ctx->supports_slices) {
3094 +        control[num_controls++] = (struct v4l2_ext_control) {
3095 +            .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS,
3096 +            .ptr = &controls->slice_params,
3097 +            .size = sizeof(*first_slice_params) * controls->num_slices,
3098 +        };
3099 +    }
3100 +
3101 +    //this assumes that decoders supporting entry_point_offsets submit a single slice per request
3102 +    if (ctx->supports_entry_point_offsets && first_slice_params->num_entry_point_offsets > 0) {
3103 +        control[num_controls++] = (struct v4l2_ext_control) {
3104 +            .id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS,
3105 +            .ptr = controls->entry_point_offsets,
3106 +            .size = sizeof(*controls->entry_point_offsets) * first_slice_params->num_entry_point_offsets,
3107 +        };
3108 +    }
3109 +
3110 +    if (ctx->decode_mode == V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED)
3111 +        return ff_v4l2_request_decode_slice(avctx, h->ref->frame, control, num_controls, controls->first_slice, last_slice);
3112 +
3113 +    return ff_v4l2_request_decode_frame(avctx, h->ref->frame, control, num_controls);
3114 +}
3115 +
3116 +static int v4l2_request_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
3117 +{
3118 +    const HEVCContext *h = avctx->priv_data;
3119 +    V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
3120 +    V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data;
3121 +    V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->ref->frame->data[0];
3122 +    int ret, slice = FFMIN(controls->num_slices, MAX_SLICES - 1);
3123 +
3124 +    if (ctx->decode_mode == V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED && slice) {
3125 +        ret = v4l2_request_hevc_queue_decode(avctx, 0);
3126 +        if (ret)
3127 +            return ret;
3128 +
3129 +        ff_v4l2_request_reset_frame(avctx, h->ref->frame);
3130 +        slice = controls->num_slices = 0;
3131 +        controls->first_slice = 0;
3132 +    }
3133 +
3134 +    ret = v4l2_request_hevc_fill_slice_params(h, controls, slice);
3135 +    if (ret)
3136 +        return ret;
3137 +
3138 +    if (ctx->start_code == V4L2_STATELESS_HEVC_START_CODE_ANNEX_B) {
3139 +        ret = ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, nalu_slice_start_code, 3);
3140 +        if (ret)
3141 +            return ret;
3142 +    }
3143 +
3144 +    ret = ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, buffer, size);
3145 +    if (ret)
3146 +        return ret;
3147 +
3148 +    controls->slice_params[slice].bit_size = req->output.used * 8; //FIXME
3149 +    controls->num_slices++;
3150 +    return 0;
3151 +}
3152 +
3153 +static int v4l2_request_hevc_end_frame(AVCodecContext *avctx)
3154 +{
3155 +    const HEVCContext *h = avctx->priv_data;
3156 +    V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
3157 +    int ret;
3158 +
3159 +    ret = v4l2_request_hevc_queue_decode(avctx, 1);
3160 +
3161 +    av_freep(&controls->entry_point_offsets);
3162 +
3163 +    return ret;
3164 +}
3165 +
3166 +static int v4l2_request_hevc_set_controls(AVCodecContext *avctx)
3167 +{
3168 +    V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data;
3169 +    int ret;
3170 +
3171 +    struct v4l2_ext_control control[] = {
3172 +        { .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, },
3173 +        { .id = V4L2_CID_STATELESS_HEVC_START_CODE, },
3174 +    };
3175 +    struct v4l2_query_ext_ctrl entry_point_offsets = {
3176 +        .id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS,
3177 +    };
3178 +    struct v4l2_query_ext_ctrl slice_params = {
3179 +        .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS,
3180 +    };
3181 +    struct v4l2_query_ext_ctrl scaling_matrix = {
3182 +        .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX,
3183 +    };
3184 +
3185 +    ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_STATELESS_HEVC_DECODE_MODE);
3186 +    if (ctx->decode_mode != V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED &&
3187 +        ctx->decode_mode != V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED) {
3188 +        av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode, %d\n", __func__, ctx->decode_mode);
3189 +        return AVERROR(EINVAL);
3190 +    }
3191 +
3192 +    ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_STATELESS_HEVC_START_CODE);
3193 +    if (ctx->start_code != V4L2_STATELESS_HEVC_START_CODE_NONE &&
3194 +        ctx->start_code != V4L2_STATELESS_HEVC_START_CODE_ANNEX_B) {
3195 +        av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code, %d\n", __func__, ctx->start_code);
3196 +        return AVERROR(EINVAL);
3197 +    }
3198 +
3199 +    ret = ff_v4l2_request_query_control(avctx, &entry_point_offsets);
3200 +    if (ret)
3201 +        ctx->supports_entry_point_offsets = 0;
3202 +    else
3203 +        ctx->supports_entry_point_offsets = 1;
3204 +
3205 +    ret = ff_v4l2_request_query_control(avctx, &slice_params);
3206 +    if (ret) {
3207 +        ctx->supports_slices = 0;
3208 +        ctx->max_slices = 0;
3209 +        if (ctx->decode_mode == V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED) {
3210 +            av_log(avctx, AV_LOG_ERROR, "%s: decoder is slice-based, \
3211 +                but doesn't support V4L2_CID_STATELESS_HEVC_SLICE_PARAMS control \n", __func__);
3212 +            return AVERROR(EINVAL);
3213 +        }
3214 +
3215 +        if (ctx->supports_entry_point_offsets) {
3216 +            av_log(avctx, AV_LOG_ERROR, "%s: decoder supports entry_point_offsets, \
3217 +                but doesn't support V4L2_CID_STATELESS_HEVC_SLICE_PARAMS control \n", __func__);
3218 +            return AVERROR(EINVAL);
3219 +        }
3220 +    } else {
3221 +        ctx->supports_slices = 1;
3222 +        ctx->max_slices = slice_params.dims[0];
3223 +        if (ctx->max_slices > MAX_SLICES) {
3224 +            av_log(avctx, AV_LOG_ERROR, "%s: unsupported max slices, %u\n", __func__, ctx->max_slices);
3225 +            return AVERROR(EINVAL);
3226 +        }
3227 +    }
3228 +
3229 +    ret = ff_v4l2_request_query_control(avctx, &scaling_matrix);
3230 +    if (ret)
3231 +        ctx->supports_scaling_matrix = 0;
3232 +    else
3233 +        ctx->supports_scaling_matrix = 1;
3234 +
3235 +    av_log(avctx, AV_LOG_DEBUG, "%s: decoder is %s and supports slices %d, supports entry_point_offsets: %d supports scaling_matrix: %d max slices: %u\n",
3236 +           __func__,
3237 +          ctx->decode_mode == V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED ? "slice based" : "frame based",
3238 +          ctx->supports_slices,
3239 +          ctx->supports_entry_point_offsets,
3240 +          ctx->supports_scaling_matrix,
3241 +          ctx->max_slices
3242 +    );
3243 +
3244 +    control[0].value = ctx->decode_mode;
3245 +    control[1].value = ctx->start_code;
3246 +
3247 +    return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control));
3248 +}
3249 +
3250 +static int v4l2_request_hevc_init(AVCodecContext *avctx)
3251 +{
3252 +    const HEVCContext *h = avctx->priv_data;
3253 +    struct v4l2_ctrl_hevc_sps sps;
3254 +    int ret;
3255 +
3256 +    struct v4l2_ext_control control[] = {
3257 +        {
3258 +            .id = V4L2_CID_STATELESS_HEVC_SPS,
3259 +            .ptr = &sps,
3260 +            .size = sizeof(sps),
3261 +        },
3262 +    };
3263 +
3264 +    fill_sps(&sps, h);
3265 +
3266 +    ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, 4 * 1024 * 1024, control, FF_ARRAY_ELEMS(control));
3267 +    if (ret)
3268 +        return ret;
3269 +
3270 +    return v4l2_request_hevc_set_controls(avctx);
3271 +}
3272 +
3273 +const FFHWAccel ff_hevc_v4l2request_hwaccel = {
3274 +    .p.name         = "hevc_v4l2request",
3275 +    .p.type         = AVMEDIA_TYPE_VIDEO,
3276 +    .p.id           = AV_CODEC_ID_HEVC,
3277 +    .p.pix_fmt      = AV_PIX_FMT_DRM_PRIME,
3278 +    .start_frame    = v4l2_request_hevc_start_frame,
3279 +    .decode_slice   = v4l2_request_hevc_decode_slice,
3280 +    .end_frame      = v4l2_request_hevc_end_frame,
3281 +    .frame_priv_data_size = sizeof(V4L2RequestControlsHEVC),
3282 +    .init           = v4l2_request_hevc_init,
3283 +    .uninit         = ff_v4l2_request_uninit,
3284 +    .priv_data_size = sizeof(V4L2RequestContextHEVC),
3285 +    .frame_params   = ff_v4l2_request_frame_params,
3286 +    .caps_internal  = HWACCEL_CAP_ASYNC_SAFE,
3287 +};
3288 -- 
3289 2.44.0
3290
3291
3292 From 381025bd969276c176fd4fda0b6f2271cedfac8e Mon Sep 17 00:00:00 2001
3293 From: Boris Brezillon <boris.brezillon@collabora.com>
3294 Date: Thu, 12 Dec 2019 16:13:55 +0100
3295 Subject: [PATCH 08/18] Add V4L2 request API vp9 hwaccel
3296
3297 Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
3298 Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
3299 ---
3300  configure                     |   3 +
3301  libavcodec/Makefile           |   1 +
3302  libavcodec/hwaccels.h         |   1 +
3303  libavcodec/v4l2_request_vp9.c | 283 ++++++++++++++++++++++++++++++++++
3304  libavcodec/vp9.c              | 190 ++++++++++++++++-------
3305  libavcodec/vp9dec.h           |   4 +
3306  libavcodec/vp9shared.h        |   1 +
3307  7 files changed, 429 insertions(+), 54 deletions(-)
3308  create mode 100644 libavcodec/v4l2_request_vp9.c
3309
3310 diff --git a/configure b/configure
3311 index ad9af0b..810e57c 100755
3312 --- a/configure
3313 +++ b/configure
3314 @@ -3171,6 +3171,8 @@ vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9"
3315  vp9_dxva2_hwaccel_select="vp9_decoder"
3316  vp9_nvdec_hwaccel_deps="nvdec"
3317  vp9_nvdec_hwaccel_select="vp9_decoder"
3318 +vp9_v4l2request_hwaccel_deps="v4l2_request"
3319 +vp9_v4l2request_hwaccel_select="vp9_decoder"
3320  vp9_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferVP9_bit_depth"
3321  vp9_vaapi_hwaccel_select="vp9_decoder"
3322  vp9_vdpau_hwaccel_deps="vdpau VdpPictureInfoVP9"
3323 @@ -7015,6 +7017,7 @@ check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE;"
3324  check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC_SLICE;"
3325  check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
3326  check_cc vp8_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP8_FRAME;"
3327 +check_cc vp9_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_VP9_FRAME;"
3328  
3329  check_headers sys/videoio.h
3330  test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
3331 diff --git a/libavcodec/Makefile b/libavcodec/Makefile
3332 index e32bd18..a2dffd5 100644
3333 --- a/libavcodec/Makefile
3334 +++ b/libavcodec/Makefile
3335 @@ -1043,6 +1043,7 @@ OBJS-$(CONFIG_VP8_VAAPI_HWACCEL)          += vaapi_vp8.o
3336  OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL)        += dxva2_vp9.o
3337  OBJS-$(CONFIG_VP9_DXVA2_HWACCEL)          += dxva2_vp9.o
3338  OBJS-$(CONFIG_VP9_NVDEC_HWACCEL)          += nvdec_vp9.o
3339 +OBJS-$(CONFIG_VP9_V4L2REQUEST_HWACCEL)    += v4l2_request_vp9.o
3340  OBJS-$(CONFIG_VP9_VAAPI_HWACCEL)          += vaapi_vp9.o
3341  OBJS-$(CONFIG_VP9_VDPAU_HWACCEL)          += vdpau_vp9.o
3342  OBJS-$(CONFIG_VP9_VIDEOTOOLBOX_HWACCEL)   += videotoolbox_vp9.o
3343 diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
3344 index 4a0de92..8d0d348 100644
3345 --- a/libavcodec/hwaccels.h
3346 +++ b/libavcodec/hwaccels.h
3347 @@ -77,6 +77,7 @@ extern const struct FFHWAccel ff_vp9_d3d11va_hwaccel;
3348  extern const struct FFHWAccel ff_vp9_d3d11va2_hwaccel;
3349  extern const struct FFHWAccel ff_vp9_dxva2_hwaccel;
3350  extern const struct FFHWAccel ff_vp9_nvdec_hwaccel;
3351 +extern const struct FFHWAccel ff_vp9_v4l2request_hwaccel;
3352  extern const struct FFHWAccel ff_vp9_vaapi_hwaccel;
3353  extern const struct FFHWAccel ff_vp9_vdpau_hwaccel;
3354  extern const struct FFHWAccel ff_vp9_videotoolbox_hwaccel;
3355 diff --git a/libavcodec/v4l2_request_vp9.c b/libavcodec/v4l2_request_vp9.c
3356 new file mode 100644
3357 index 0000000..2c6a9e4
3358 --- /dev/null
3359 +++ b/libavcodec/v4l2_request_vp9.c
3360 @@ -0,0 +1,283 @@
3361 +/*
3362 + * This file is part of FFmpeg.
3363 + *
3364 + * FFmpeg is free software; you can redistribute it and/or
3365 + * modify it under the terms of the GNU Lesser General Public
3366 + * License as published by the Free Software Foundation; either
3367 + * version 2.1 of the License, or (at your option) any later version.
3368 + *
3369 + * FFmpeg is distributed in the hope that it will be useful,
3370 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3371 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3372 + * Lesser General Public License for more details.
3373 + *
3374 + * You should have received a copy of the GNU Lesser General Public
3375 + * License along with FFmpeg; if not, write to the Free Software
3376 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3377 + */
3378 +
3379 +#include "hwaccel_internal.h"
3380 +#include "hwconfig.h"
3381 +#include "v4l2_request.h"
3382 +#include "vp9dec.h"
3383 +
3384 +typedef struct V4L2RequestControlsVP9 {
3385 +    struct v4l2_ctrl_vp9_frame decode_params;
3386 +    struct v4l2_ctrl_vp9_compressed_hdr chp;
3387 +} V4L2RequestControlsVP9;
3388 +
3389 +static void v4l2_request_vp9_set_frame_ctx(AVCodecContext *avctx)
3390 +{
3391 +    VP9Context *s = avctx->priv_data;
3392 +    const VP9Frame *f = &s->s.frames[CUR_FRAME];
3393 +    V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private;
3394 +    struct v4l2_ctrl_vp9_compressed_hdr *chp = &controls->chp;
3395 +
3396 +    memset(chp, 0, sizeof(&chp));
3397 +
3398 +    chp->tx_mode = s->s.h.txfmmode;
3399 +    memcpy(chp->tx8, s->prob_raw.p.tx8p, sizeof(s->prob_raw.p.tx8p));
3400 +    memcpy(chp->tx16, s->prob_raw.p.tx16p, sizeof(s->prob_raw.p.tx16p));
3401 +    memcpy(chp->tx32, s->prob_raw.p.tx32p, sizeof(s->prob_raw.p.tx32p));
3402 +    for (unsigned i = 0; i < 4; i++) {
3403 +        for (unsigned j = 0; j < 2; j++) {
3404 +            for (unsigned k = 0; k < 2; k++) {
3405 +                for (unsigned l = 0; l < 6; l++) {
3406 +                    for (unsigned m = 0; m < 6; m++) {
3407 +                        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]));
3408 +                    }
3409 +                }
3410 +            }
3411 +        }
3412 +    }
3413 +    memcpy(chp->skip, s->prob_raw.p.skip, sizeof(s->prob_raw.p.skip));
3414 +    memcpy(chp->inter_mode, s->prob_raw.p.mv_mode, sizeof(s->prob_raw.p.mv_mode));
3415 +    memcpy(chp->interp_filter, s->prob_raw.p.filter, sizeof(s->prob_raw.p.filter));
3416 +    memcpy(chp->is_inter, s->prob_raw.p.intra, sizeof(s->prob_raw.p.intra));
3417 +    memcpy(chp->comp_mode, s->prob_raw.p.comp, sizeof(s->prob_raw.p.comp));
3418 +    memcpy(chp->single_ref, s->prob_raw.p.single_ref, sizeof(s->prob_raw.p.single_ref));
3419 +    memcpy(chp->comp_ref, s->prob_raw.p.comp_ref, sizeof(s->prob_raw.p.comp_ref));
3420 +    memcpy(chp->y_mode, s->prob_raw.p.y_mode, sizeof(s->prob_raw.p.y_mode));
3421 +    for (unsigned i = 0; i < 10; i++)
3422 +        memcpy(chp->uv_mode[i], s->prob.p.uv_mode[i], sizeof(s->prob.p.uv_mode[0]));
3423 +    for (unsigned i = 0; i < 4; i++)
3424 +        memcpy(chp->partition[i * 4], s->prob_raw.p.partition[i], sizeof(s->prob_raw.p.partition[0]));
3425 +    memcpy(chp->mv.joint, s->prob_raw.p.mv_joint, sizeof(s->prob_raw.p.mv_joint));
3426 +    for (unsigned i = 0; i < 2; i++) {
3427 +         chp->mv.sign[i] = s->prob_raw.p.mv_comp[i].sign;
3428 +         memcpy(chp->mv.classes[i], s->prob_raw.p.mv_comp[i].classes, sizeof(s->prob_raw.p.mv_comp[0].classes));
3429 +         chp->mv.class0_bit[i] = s->prob_raw.p.mv_comp[i].class0;
3430 +         memcpy(chp->mv.bits[i], s->prob_raw.p.mv_comp[i].bits, sizeof(s->prob_raw.p.mv_comp[0].bits));
3431 +         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));
3432 +         memcpy(chp->mv.fr[i], s->prob_raw.p.mv_comp[i].fp, sizeof(s->prob_raw.p.mv_comp[0].fp));
3433 +         chp->mv.class0_hp[i] = s->prob_raw.p.mv_comp[i].class0_hp;
3434 +         chp->mv.hp[i] = s->prob_raw.p.mv_comp[i].hp;
3435 +    }
3436 +}
3437 +
3438 +static void fill_frame(struct v4l2_ctrl_vp9_frame *dec_params, AVCodecContext *avctx)
3439 +{
3440 +    const VP9Context *s = avctx->priv_data;
3441 +    const ThreadFrame *ref;
3442 +
3443 +    memset(dec_params, 0, sizeof(*dec_params));
3444 +
3445 +    if (s->s.h.keyframe)
3446 +        dec_params->flags |= V4L2_VP9_FRAME_FLAG_KEY_FRAME;
3447 +    if (!s->s.h.invisible)
3448 +        dec_params->flags |= V4L2_VP9_FRAME_FLAG_SHOW_FRAME;
3449 +    if (s->s.h.errorres)
3450 +        dec_params->flags |= V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT;
3451 +    if (s->s.h.intraonly)
3452 +        dec_params->flags |= V4L2_VP9_FRAME_FLAG_INTRA_ONLY;
3453 +    if (!s->s.h.keyframe && s->s.h.highprecisionmvs)
3454 +        dec_params->flags |= V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV;
3455 +    if (s->s.h.refreshctx)
3456 +        dec_params->flags |= V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX;
3457 +    if (s->s.h.parallelmode)
3458 +        dec_params->flags |= V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE;
3459 +    if (s->ss_h)
3460 +        dec_params->flags |= V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING;
3461 +    if (s->ss_v)
3462 +        dec_params->flags |= V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING;
3463 +    if (avctx->color_range == AVCOL_RANGE_JPEG)
3464 +        dec_params->flags |= V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING;
3465 +
3466 +    dec_params->compressed_header_size = s->s.h.compressed_header_size;
3467 +    dec_params->uncompressed_header_size = s->s.h.uncompressed_header_size;
3468 +    dec_params->profile = s->s.h.profile;
3469 +    dec_params->reset_frame_context = s->s.h.resetctx > 0 ? s->s.h.resetctx - 1 : 0;
3470 +    dec_params->frame_context_idx = s->s.h.framectxid;
3471 +    dec_params->bit_depth = s->s.h.bpp;
3472 +
3473 +    dec_params->interpolation_filter = s->s.h.filtermode ^ (s->s.h.filtermode <= 1);
3474 +    dec_params->tile_cols_log2 = s->s.h.tiling.log2_tile_cols;
3475 +    dec_params->tile_rows_log2 = s->s.h.tiling.log2_tile_rows;
3476 +    dec_params->reference_mode = s->s.h.comppredmode;
3477 +    dec_params->frame_width_minus_1 = s->w - 1;
3478 +    dec_params->frame_height_minus_1 = s->h - 1;
3479 +    //dec_params->render_width_minus_1 = avctx->width - 1;
3480 +    //dec_params->render_height_minus_1 = avctx->height - 1;
3481 +
3482 +    ref = &s->s.refs[s->s.h.refidx[0]];
3483 +    if (ref->f && ref->f->buf[0])
3484 +        dec_params->last_frame_ts = ff_v4l2_request_get_capture_timestamp(ref->f);
3485 +    ref = &s->s.refs[s->s.h.refidx[1]];
3486 +    if (ref->f && ref->f->buf[0])
3487 +        dec_params->golden_frame_ts = ff_v4l2_request_get_capture_timestamp(ref->f);
3488 +    ref = &s->s.refs[s->s.h.refidx[2]];
3489 +    if (ref->f && ref->f->buf[0])
3490 +        dec_params->alt_frame_ts = ff_v4l2_request_get_capture_timestamp(ref->f);
3491 +
3492 +    if (s->s.h.signbias[0])
3493 +        dec_params->ref_frame_sign_bias |= V4L2_VP9_SIGN_BIAS_LAST;
3494 +    if (s->s.h.signbias[1])
3495 +        dec_params->ref_frame_sign_bias |= V4L2_VP9_SIGN_BIAS_GOLDEN;
3496 +    if (s->s.h.signbias[2])
3497 +        dec_params->ref_frame_sign_bias |= V4L2_VP9_SIGN_BIAS_ALT;
3498 +
3499 +    if (s->s.h.lf_delta.enabled)
3500 +        dec_params->lf.flags |= V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED;
3501 +    if (s->s.h.lf_delta.updated)
3502 +        dec_params->lf.flags |= V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE;
3503 +
3504 +    dec_params->lf.level = s->s.h.filter.level;
3505 +    dec_params->lf.sharpness = s->s.h.filter.sharpness;
3506 +    for (unsigned i = 0; i < 4; i++)
3507 +        dec_params->lf.ref_deltas[i] = s->s.h.lf_delta.ref[i];
3508 +    for (unsigned i = 0; i < 2; i++)
3509 +        dec_params->lf.mode_deltas[i] = s->s.h.lf_delta.mode[i];
3510 +
3511 +    dec_params->quant.base_q_idx = s->s.h.yac_qi;
3512 +    dec_params->quant.delta_q_y_dc = s->s.h.ydc_qdelta;
3513 +    dec_params->quant.delta_q_uv_dc = s->s.h.uvdc_qdelta;
3514 +    dec_params->quant.delta_q_uv_ac = s->s.h.uvac_qdelta;
3515 +
3516 +    if (s->s.h.segmentation.enabled)
3517 +        dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_ENABLED;
3518 +    if (s->s.h.segmentation.update_map)
3519 +        dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP;
3520 +    if (s->s.h.segmentation.temporal)
3521 +        dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE;
3522 +    if (s->s.h.segmentation.update_data)
3523 +        dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA;
3524 +    if (s->s.h.segmentation.absolute_vals)
3525 +        dec_params->seg.flags |= V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE;
3526 +
3527 +    for (unsigned i = 0; i < 7; i++)
3528 +        dec_params->seg.tree_probs[i] = s->s.h.segmentation.prob[i];
3529 +
3530 +    if (s->s.h.segmentation.temporal) {
3531 +        for (unsigned i = 0; i < 3; i++)
3532 +            dec_params->seg.pred_probs[i] = s->s.h.segmentation.pred_prob[i];
3533 +    } else {
3534 +        memset(dec_params->seg.pred_probs, 255, sizeof(dec_params->seg.pred_probs));
3535 +    }
3536 +
3537 +    for (unsigned i = 0; i < 8; i++) {
3538 +        if (s->s.h.segmentation.feat[i].q_enabled) {
3539 +            dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEG_LVL_ALT_Q;
3540 +            dec_params->seg.feature_data[i][V4L2_VP9_SEG_LVL_ALT_Q] = s->s.h.segmentation.feat[i].q_val;
3541 +        }
3542 +
3543 +        if (s->s.h.segmentation.feat[i].lf_enabled) {
3544 +            dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEG_LVL_ALT_L;
3545 +            dec_params->seg.feature_data[i][V4L2_VP9_SEG_LVL_ALT_L] = s->s.h.segmentation.feat[i].lf_val;
3546 +        }
3547 +
3548 +        if (s->s.h.segmentation.feat[i].ref_enabled) {
3549 +            dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEG_LVL_REF_FRAME;
3550 +            dec_params->seg.feature_data[i][V4L2_VP9_SEG_LVL_REF_FRAME] = s->s.h.segmentation.feat[i].ref_val;
3551 +        }
3552 +
3553 +        if (s->s.h.segmentation.feat[i].skip_enabled)
3554 +            dec_params->seg.feature_enabled[i] |= 1 << V4L2_VP9_SEG_LVL_SKIP;
3555 +    }
3556 +}
3557 +
3558 +static int v4l2_request_vp9_start_frame(AVCodecContext *avctx,
3559 +                                        av_unused const uint8_t *buffer,
3560 +                                        av_unused uint32_t size)
3561 +{
3562 +    const VP9Context *s = avctx->priv_data;
3563 +    const VP9Frame *f = &s->s.frames[CUR_FRAME];
3564 +    V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private;
3565 +
3566 +    v4l2_request_vp9_set_frame_ctx(avctx);
3567 +
3568 +    fill_frame(&controls->decode_params, avctx);
3569 +
3570 +    return ff_v4l2_request_reset_frame(avctx, f->tf.f);
3571 +}
3572 +
3573 +static int v4l2_request_vp9_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
3574 +{
3575 +    const VP9Context *s = avctx->priv_data;
3576 +    const VP9Frame *f = &s->s.frames[CUR_FRAME];
3577 +
3578 +    return ff_v4l2_request_append_output_buffer(avctx, f->tf.f, buffer, size);
3579 +}
3580 +
3581 +static int v4l2_request_vp9_end_frame(AVCodecContext *avctx)
3582 +{
3583 +    const VP9Context *s = avctx->priv_data;
3584 +    const VP9Frame *f = &s->s.frames[CUR_FRAME];
3585 +    V4L2RequestControlsVP9 *controls = f->hwaccel_picture_private;
3586 +    int ret;
3587 +
3588 +    struct v4l2_ext_control control[] = {
3589 +        {
3590 +            .id = V4L2_CID_STATELESS_VP9_FRAME,
3591 +            .ptr = &controls->decode_params,
3592 +            .size = sizeof(controls->decode_params),
3593 +        },
3594 +        {
3595 +            .id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR,
3596 +            .ptr = &controls->chp,
3597 +            .size = sizeof(controls->chp),
3598 +        },
3599 +    };
3600 +
3601 +    ret = ff_v4l2_request_decode_frame(avctx, f->tf.f, control, FF_ARRAY_ELEMS(control));
3602 +    if (ret)
3603 +        return ret;
3604 +
3605 +    if (!s->s.h.refreshctx)
3606 +        return 0;
3607 +
3608 +    return 0;
3609 +}
3610 +
3611 +static int v4l2_request_vp9_init(AVCodecContext *avctx)
3612 +{
3613 +    struct v4l2_ctrl_vp9_frame frame;
3614 +
3615 +    struct v4l2_ext_control control[] = {
3616 +        {
3617 +            .id = V4L2_CID_STATELESS_VP9_FRAME,
3618 +            .ptr = &frame,
3619 +            .size = sizeof(frame),
3620 +        },
3621 +    };
3622 +
3623 +    fill_frame(&frame, avctx);
3624 +
3625 +    // TODO: check V4L2_CID_MPEG_VIDEO_VP9_PROFILE
3626 +    return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_VP9_FRAME, 3 * 1024 * 1024, control, FF_ARRAY_ELEMS(control));
3627 +}
3628 +
3629 +const FFHWAccel ff_vp9_v4l2request_hwaccel = {
3630 +    .p.name         = "vp9_v4l2request",
3631 +    .p.type         = AVMEDIA_TYPE_VIDEO,
3632 +    .p.id           = AV_CODEC_ID_VP9,
3633 +    .p.pix_fmt      = AV_PIX_FMT_DRM_PRIME,
3634 +    .start_frame    = v4l2_request_vp9_start_frame,
3635 +    .decode_slice   = v4l2_request_vp9_decode_slice,
3636 +    .end_frame      = v4l2_request_vp9_end_frame,
3637 +    .frame_priv_data_size = sizeof(V4L2RequestControlsVP9),
3638 +    .init           = v4l2_request_vp9_init,
3639 +    .uninit         = ff_v4l2_request_uninit,
3640 +    .priv_data_size = sizeof(V4L2RequestContext),
3641 +    .frame_params   = ff_v4l2_request_frame_params,
3642 +    .caps_internal  = HWACCEL_CAP_ASYNC_SAFE,
3643 +};
3644 diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c
3645 index 885500f..6ab88e5 100644
3646 --- a/libavcodec/vp9.c
3647 +++ b/libavcodec/vp9.c
3648 @@ -177,6 +177,7 @@ static int update_size(AVCodecContext *avctx, int w, int h)
3649  #define HWACCEL_MAX (CONFIG_VP9_DXVA2_HWACCEL + \
3650                       CONFIG_VP9_D3D11VA_HWACCEL * 2 + \
3651                       CONFIG_VP9_NVDEC_HWACCEL + \
3652 +                     CONFIG_VP9_V4L2REQUEST_HWACCEL + \
3653                       CONFIG_VP9_VAAPI_HWACCEL + \
3654                       CONFIG_VP9_VDPAU_HWACCEL + \
3655                       CONFIG_VP9_VIDEOTOOLBOX_HWACCEL)
3656 @@ -205,6 +206,9 @@ static int update_size(AVCodecContext *avctx, int w, int h)
3657  #if CONFIG_VP9_NVDEC_HWACCEL
3658              *fmtp++ = AV_PIX_FMT_CUDA;
3659  #endif
3660 +#if CONFIG_VP9_V4L2REQUEST_HWACCEL
3661 +            *fmtp++ = AV_PIX_FMT_DRM_PRIME;
3662 +#endif
3663  #if CONFIG_VP9_VAAPI_HWACCEL
3664              *fmtp++ = AV_PIX_FMT_VAAPI;
3665  #endif
3666 @@ -219,6 +223,9 @@ static int update_size(AVCodecContext *avctx, int w, int h)
3667  #if CONFIG_VP9_NVDEC_HWACCEL
3668              *fmtp++ = AV_PIX_FMT_CUDA;
3669  #endif
3670 +#if CONFIG_VP9_V4L2REQUEST_HWACCEL
3671 +            *fmtp++ = AV_PIX_FMT_DRM_PRIME;
3672 +#endif
3673  #if CONFIG_VP9_VAAPI_HWACCEL
3674              *fmtp++ = AV_PIX_FMT_VAAPI;
3675  #endif
3676 @@ -386,7 +393,7 @@ static av_always_inline int inv_recenter_nonneg(int v, int m)
3677  }
3678  
3679  // differential forward probability updates
3680 -static int update_prob(VPXRangeCoder *c, int p)
3681 +static int read_prob_delta(VPXRangeCoder *c)
3682  {
3683      static const uint8_t inv_map_table[255] = {
3684            7,  20,  33,  46,  59,  72,  85,  98, 111, 124, 137, 150, 163, 176,
3685 @@ -440,8 +447,13 @@ static int update_prob(VPXRangeCoder *c, int p)
3686          av_assert2(d < FF_ARRAY_ELEMS(inv_map_table));
3687      }
3688  
3689 -    return p <= 128 ? 1 + inv_recenter_nonneg(inv_map_table[d], p - 1) :
3690 -                    255 - inv_recenter_nonneg(inv_map_table[d], 255 - p);
3691 +    return inv_map_table[d];
3692 +}
3693 +
3694 +static int update_prob(int p, int d)
3695 +{
3696 +    return p <= 128 ? 1 + inv_recenter_nonneg(d, p - 1) :
3697 +                    255 - inv_recenter_nonneg(d, 255 - p);
3698  }
3699  
3700  static int read_colorspace_details(AVCodecContext *avctx)
3701 @@ -707,7 +719,8 @@ static int decode_frame_header(AVCodecContext *avctx,
3702                                           get_bits(&s->gb, 8) : 255;
3703          }
3704  
3705 -        if (get_bits1(&s->gb)) {
3706 +        s->s.h.segmentation.update_data = get_bits1(&s->gb);
3707 +        if (s->s.h.segmentation.update_data) {
3708              s->s.h.segmentation.absolute_vals = get_bits1(&s->gb);
3709              for (i = 0; i < 8; i++) {
3710                  if ((s->s.h.segmentation.feat[i].q_enabled = get_bits1(&s->gb)))
3711 @@ -907,6 +920,8 @@ static int decode_frame_header(AVCodecContext *avctx,
3712       * as explicit copies if the fw update is missing (and skip the copy upon
3713       * fw update)? */
3714      s->prob.p = s->prob_ctx[c].p;
3715 +    memset(&s->prob_raw.p, 0, sizeof(s->prob_raw.p));
3716 +    memset(&s->prob_raw.coef, 0, sizeof(s->prob_raw.coef));
3717  
3718      // txfm updates
3719      if (s->s.h.lossless) {
3720 @@ -918,18 +933,25 @@ static int decode_frame_header(AVCodecContext *avctx,
3721  
3722          if (s->s.h.txfmmode == TX_SWITCHABLE) {
3723              for (i = 0; i < 2; i++)
3724 -                if (vpx_rac_get_prob_branchy(&s->c, 252))
3725 -                    s->prob.p.tx8p[i] = update_prob(&s->c, s->prob.p.tx8p[i]);
3726 +                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3727 +                    s->prob_raw.p.tx8p[i] = read_prob_delta(&s->c);
3728 +                    s->prob.p.tx8p[i] = update_prob(s->prob.p.tx8p[i],
3729 +                                                    s->prob_raw.p.tx8p[i]);
3730 +                }
3731              for (i = 0; i < 2; i++)
3732                  for (j = 0; j < 2; j++)
3733 -                    if (vpx_rac_get_prob_branchy(&s->c, 252))
3734 -                        s->prob.p.tx16p[i][j] =
3735 -                            update_prob(&s->c, s->prob.p.tx16p[i][j]);
3736 +                    if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3737 +                        s->prob_raw.p.tx16p[i][j] = read_prob_delta(&s->c);
3738 +                        s->prob.p.tx16p[i][j] = update_prob(s->prob.p.tx16p[i][j],
3739 +                                                            s->prob_raw.p.tx16p[i][j]);
3740 +                    }
3741              for (i = 0; i < 2; i++)
3742                  for (j = 0; j < 3; j++)
3743 -                    if (vpx_rac_get_prob_branchy(&s->c, 252))
3744 -                        s->prob.p.tx32p[i][j] =
3745 -                            update_prob(&s->c, s->prob.p.tx32p[i][j]);
3746 +                    if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3747 +                        s->prob_raw.p.tx32p[i][j] = read_prob_delta(&s->c);
3748 +                        s->prob.p.tx32p[i][j] = update_prob(s->prob.p.tx32p[i][j],
3749 +                                                            s->prob_raw.p.tx32p[i][j]);
3750 +                    }
3751          }
3752      }
3753  
3754 @@ -941,15 +963,18 @@ static int decode_frame_header(AVCodecContext *avctx,
3755                  for (k = 0; k < 2; k++)
3756                      for (l = 0; l < 6; l++)
3757                          for (m = 0; m < 6; m++) {
3758 +                            uint8_t *pd = s->prob_raw.coef[i][j][k][l][m];
3759                              uint8_t *p = s->prob.coef[i][j][k][l][m];
3760                              uint8_t *r = ref[j][k][l][m];
3761                              if (m >= 3 && l == 0) // dc only has 3 pt
3762                                  break;
3763                              for (n = 0; n < 3; n++) {
3764 -                                if (vpx_rac_get_prob_branchy(&s->c, 252))
3765 -                                    p[n] = update_prob(&s->c, r[n]);
3766 -                                else
3767 +                                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3768 +                                    pd[n] = read_prob_delta(&s->c);
3769 +                                    p[n] = update_prob(r[n], pd[n]);
3770 +                                } else {
3771                                      p[n] = r[n];
3772 +                                }
3773                              }
3774                              memcpy(&p[3], ff_vp9_model_pareto8[p[2]], 8);
3775                          }
3776 @@ -972,25 +997,37 @@ static int decode_frame_header(AVCodecContext *avctx,
3777  
3778      // mode updates
3779      for (i = 0; i < 3; i++)
3780 -        if (vpx_rac_get_prob_branchy(&s->c, 252))
3781 -            s->prob.p.skip[i] = update_prob(&s->c, s->prob.p.skip[i]);
3782 +        if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3783 +            s->prob_raw.p.skip[i] = read_prob_delta(&s->c);
3784 +            s->prob.p.skip[i] = update_prob(s->prob.p.skip[i],
3785 +                                            s->prob_raw.p.skip[i]);
3786 +        }
3787      if (!s->s.h.keyframe && !s->s.h.intraonly) {
3788          for (i = 0; i < 7; i++)
3789              for (j = 0; j < 3; j++)
3790 -                if (vpx_rac_get_prob_branchy(&s->c, 252))
3791 +                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3792 +                    s->prob_raw.p.mv_mode[i][j] = read_prob_delta(&s->c);
3793                      s->prob.p.mv_mode[i][j] =
3794 -                        update_prob(&s->c, s->prob.p.mv_mode[i][j]);
3795 +                        update_prob(s->prob.p.mv_mode[i][j],
3796 +                                    s->prob_raw.p.mv_mode[i][j]);
3797 +                }
3798  
3799          if (s->s.h.filtermode == FILTER_SWITCHABLE)
3800              for (i = 0; i < 4; i++)
3801                  for (j = 0; j < 2; j++)
3802 -                    if (vpx_rac_get_prob_branchy(&s->c, 252))
3803 +                    if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3804 +                        s->prob_raw.p.filter[i][j] = read_prob_delta(&s->c);
3805                          s->prob.p.filter[i][j] =
3806 -                            update_prob(&s->c, s->prob.p.filter[i][j]);
3807 +                            update_prob(s->prob.p.filter[i][j],
3808 +                                        s->prob_raw.p.filter[i][j]);
3809 +                    }
3810  
3811          for (i = 0; i < 4; i++)
3812 -            if (vpx_rac_get_prob_branchy(&s->c, 252))
3813 -                s->prob.p.intra[i] = update_prob(&s->c, s->prob.p.intra[i]);
3814 +            if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3815 +                s->prob_raw.p.intra[i] = read_prob_delta(&s->c);
3816 +                s->prob.p.intra[i] = update_prob(s->prob.p.intra[i],
3817 +                                                 s->prob_raw.p.intra[i]);
3818 +            }
3819  
3820          if (s->s.h.allowcompinter) {
3821              s->s.h.comppredmode = vp89_rac_get(&s->c);
3822 @@ -998,92 +1035,134 @@ static int decode_frame_header(AVCodecContext *avctx,
3823                  s->s.h.comppredmode += vp89_rac_get(&s->c);
3824              if (s->s.h.comppredmode == PRED_SWITCHABLE)
3825                  for (i = 0; i < 5; i++)
3826 -                    if (vpx_rac_get_prob_branchy(&s->c, 252))
3827 +                    if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3828 +                        s->prob_raw.p.comp[i] = read_prob_delta(&s->c);
3829                          s->prob.p.comp[i] =
3830 -                            update_prob(&s->c, s->prob.p.comp[i]);
3831 +                            update_prob(s->prob.p.comp[i], s->prob_raw.p.comp[i]);
3832 +                    }
3833          } else {
3834              s->s.h.comppredmode = PRED_SINGLEREF;
3835          }
3836  
3837          if (s->s.h.comppredmode != PRED_COMPREF) {
3838              for (i = 0; i < 5; i++) {
3839 -                if (vpx_rac_get_prob_branchy(&s->c, 252))
3840 +                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3841 +                    s->prob_raw.p.single_ref[i][0] = read_prob_delta(&s->c);
3842                      s->prob.p.single_ref[i][0] =
3843 -                        update_prob(&s->c, s->prob.p.single_ref[i][0]);
3844 -                if (vpx_rac_get_prob_branchy(&s->c, 252))
3845 +                        update_prob(s->prob.p.single_ref[i][0],
3846 +                                    s->prob_raw.p.single_ref[i][0]);
3847 +                }
3848 +                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3849 +                    s->prob_raw.p.single_ref[i][1] = read_prob_delta(&s->c);
3850                      s->prob.p.single_ref[i][1] =
3851 -                        update_prob(&s->c, s->prob.p.single_ref[i][1]);
3852 +                        update_prob(s->prob.p.single_ref[i][1],
3853 +                                    s->prob_raw.p.single_ref[i][1]);
3854 +                }
3855              }
3856          }
3857  
3858          if (s->s.h.comppredmode != PRED_SINGLEREF) {
3859              for (i = 0; i < 5; i++)
3860 -                if (vpx_rac_get_prob_branchy(&s->c, 252))
3861 +                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3862 +                    s->prob_raw.p.comp_ref[i] = read_prob_delta(&s->c);
3863                      s->prob.p.comp_ref[i] =
3864 -                        update_prob(&s->c, s->prob.p.comp_ref[i]);
3865 +                        update_prob(s->prob.p.comp_ref[i],
3866 +                                    s->prob_raw.p.comp_ref[i]);
3867 +                }
3868          }
3869  
3870          for (i = 0; i < 4; i++)
3871              for (j = 0; j < 9; j++)
3872 -                if (vpx_rac_get_prob_branchy(&s->c, 252))
3873 +                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3874 +                    s->prob_raw.p.y_mode[i][j] = read_prob_delta(&s->c);
3875                      s->prob.p.y_mode[i][j] =
3876 -                        update_prob(&s->c, s->prob.p.y_mode[i][j]);
3877 +                        update_prob(s->prob.p.y_mode[i][j],
3878 +                                    s->prob_raw.p.y_mode[i][j]);
3879 +                }
3880  
3881          for (i = 0; i < 4; i++)
3882              for (j = 0; j < 4; j++)
3883                  for (k = 0; k < 3; k++)
3884 -                    if (vpx_rac_get_prob_branchy(&s->c, 252))
3885 +                    if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3886 +                        s->prob_raw.p.partition[i][j][k] = read_prob_delta(&s->c);
3887                          s->prob.p.partition[3 - i][j][k] =
3888 -                            update_prob(&s->c,
3889 -                                        s->prob.p.partition[3 - i][j][k]);
3890 +                            update_prob(s->prob.p.partition[3 - i][j][k],
3891 +                                        s->prob_raw.p.partition[i][j][k]);
3892 +                    }
3893  
3894          // mv fields don't use the update_prob subexp model for some reason
3895          for (i = 0; i < 3; i++)
3896 -            if (vpx_rac_get_prob_branchy(&s->c, 252))
3897 -                s->prob.p.mv_joint[i] = (vp89_rac_get_uint(&s->c, 7) << 1) | 1;
3898 +            if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3899 +                s->prob_raw.p.mv_joint[i] = (vp89_rac_get_uint(&s->c, 7) << 1) | 1;
3900 +                s->prob.p.mv_joint[i] = s->prob_raw.p.mv_joint[i];
3901 +            }
3902  
3903          for (i = 0; i < 2; i++) {
3904 -            if (vpx_rac_get_prob_branchy(&s->c, 252))
3905 -                s->prob.p.mv_comp[i].sign =
3906 +            if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3907 +                s->prob_raw.p.mv_comp[i].sign =
3908                      (vp89_rac_get_uint(&s->c, 7) << 1) | 1;
3909 +                s->prob.p.mv_comp[i].sign =
3910 +                    s->prob_raw.p.mv_comp[i].sign;
3911 +            }
3912  
3913              for (j = 0; j < 10; j++)
3914 -                if (vpx_rac_get_prob_branchy(&s->c, 252))
3915 -                    s->prob.p.mv_comp[i].classes[j] =
3916 +                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3917 +                    s->prob_raw.p.mv_comp[i].classes[j] =
3918                          (vp89_rac_get_uint(&s->c, 7) << 1) | 1;
3919 +                    s->prob.p.mv_comp[i].classes[j] =
3920 +                        s->prob_raw.p.mv_comp[i].classes[j];
3921 +                }
3922  
3923 -            if (vpx_rac_get_prob_branchy(&s->c, 252))
3924 -                s->prob.p.mv_comp[i].class0 =
3925 +            if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3926 +                s->prob_raw.p.mv_comp[i].class0 =
3927                      (vp89_rac_get_uint(&s->c, 7) << 1) | 1;
3928 +                s->prob.p.mv_comp[i].class0 =
3929 +                    s->prob_raw.p.mv_comp[i].class0;
3930 +            }
3931  
3932              for (j = 0; j < 10; j++)
3933 -                if (vpx_rac_get_prob_branchy(&s->c, 252))
3934 -                    s->prob.p.mv_comp[i].bits[j] =
3935 +                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3936 +                    s->prob_raw.p.mv_comp[i].bits[j] =
3937                          (vp89_rac_get_uint(&s->c, 7) << 1) | 1;
3938 +                    s->prob.p.mv_comp[i].bits[j] =
3939 +                        s->prob_raw.p.mv_comp[i].bits[j];
3940 +                }
3941          }
3942  
3943          for (i = 0; i < 2; i++) {
3944              for (j = 0; j < 2; j++)
3945                  for (k = 0; k < 3; k++)
3946 -                    if (vpx_rac_get_prob_branchy(&s->c, 252))
3947 -                        s->prob.p.mv_comp[i].class0_fp[j][k] =
3948 +                    if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3949 +                        s->prob_raw.p.mv_comp[i].class0_fp[j][k] =
3950                              (vp89_rac_get_uint(&s->c, 7) << 1) | 1;
3951 +                        s->prob.p.mv_comp[i].class0_fp[j][k] =
3952 +                            s->prob_raw.p.mv_comp[i].class0_fp[j][k];
3953 +                    }
3954  
3955              for (j = 0; j < 3; j++)
3956 -                if (vpx_rac_get_prob_branchy(&s->c, 252))
3957 -                    s->prob.p.mv_comp[i].fp[j] =
3958 +                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3959 +                    s->prob_raw.p.mv_comp[i].fp[j] =
3960                          (vp89_rac_get_uint(&s->c, 7) << 1) | 1;
3961 +                    s->prob.p.mv_comp[i].fp[j] =
3962 +                        s->prob_raw.p.mv_comp[i].fp[j];
3963 +                }
3964          }
3965  
3966          if (s->s.h.highprecisionmvs) {
3967              for (i = 0; i < 2; i++) {
3968 -                if (vpx_rac_get_prob_branchy(&s->c, 252))
3969 -                    s->prob.p.mv_comp[i].class0_hp =
3970 +                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3971 +                    s->prob_raw.p.mv_comp[i].class0_hp =
3972                          (vp89_rac_get_uint(&s->c, 7) << 1) | 1;
3973 +                    s->prob.p.mv_comp[i].class0_hp =
3974 +                        s->prob_raw.p.mv_comp[i].class0_hp;
3975 +                }
3976  
3977 -                if (vpx_rac_get_prob_branchy(&s->c, 252))
3978 -                    s->prob.p.mv_comp[i].hp =
3979 +                if (vpx_rac_get_prob_branchy(&s->c, 252)) {
3980 +                    s->prob_raw.p.mv_comp[i].hp =
3981                          (vp89_rac_get_uint(&s->c, 7) << 1) | 1;
3982 +                    s->prob.p.mv_comp[i].hp =
3983 +                        s->prob_raw.p.mv_comp[i].hp;
3984 +                }
3985              }
3986          }
3987      }
3988 @@ -1912,6 +1991,9 @@ const FFCodec ff_vp9_decoder = {
3989  #if CONFIG_VP9_VDPAU_HWACCEL
3990                                 HWACCEL_VDPAU(vp9),
3991  #endif
3992 +#if CONFIG_VP9_V4L2REQUEST_HWACCEL
3993 +                               HWACCEL_V4L2REQUEST(vp9),
3994 +#endif
3995  #if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL
3996                                 HWACCEL_VIDEOTOOLBOX(vp9),
3997  #endif
3998 diff --git a/libavcodec/vp9dec.h b/libavcodec/vp9dec.h
3999 index de7aba0..5935ba6 100644
4000 --- a/libavcodec/vp9dec.h
4001 +++ b/libavcodec/vp9dec.h
4002 @@ -135,6 +135,10 @@ typedef struct VP9Context {
4003          ProbContext p;
4004          uint8_t coef[4][2][2][6][6][11];
4005      } prob;
4006 +    struct {
4007 +        ProbContext p;
4008 +        uint8_t coef[4][2][2][6][6][11];
4009 +    } prob_raw;
4010  
4011      // contextual (above) cache
4012      uint8_t *above_partition_ctx;
4013 diff --git a/libavcodec/vp9shared.h b/libavcodec/vp9shared.h
4014 index e54f235..b8fef7d 100644
4015 --- a/libavcodec/vp9shared.h
4016 +++ b/libavcodec/vp9shared.h
4017 @@ -136,6 +136,7 @@ typedef struct VP9BitstreamHeader {
4018          uint8_t temporal;
4019          uint8_t absolute_vals;
4020          uint8_t update_map;
4021 +        uint8_t update_data;
4022          uint8_t prob[7];
4023          uint8_t pred_prob[3];
4024          struct {
4025 -- 
4026 2.44.0
4027
4028
4029 From fdfd56866f020df1e333af7e8beb47b19b1c4ad0 Mon Sep 17 00:00:00 2001
4030 From: Jonas Karlman <jonas@kwiboo.se>
4031 Date: Mon, 29 Apr 2019 22:08:59 +0000
4032 Subject: [PATCH 09/18] HACK: hwcontext_drm: do not require drm device
4033
4034 Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
4035 ---
4036  libavutil/hwcontext_drm.c | 5 +++++
4037  1 file changed, 5 insertions(+)
4038
4039 diff --git a/libavutil/hwcontext_drm.c b/libavutil/hwcontext_drm.c
4040 index 7a9fdbd..6297d1f 100644
4041 --- a/libavutil/hwcontext_drm.c
4042 +++ b/libavutil/hwcontext_drm.c
4043 @@ -53,6 +53,11 @@ static int drm_device_create(AVHWDeviceContext *hwdev, const char *device,
4044      AVDRMDeviceContext *hwctx = hwdev->hwctx;
4045      drmVersionPtr version;
4046  
4047 +    if (device == NULL) {
4048 +      hwctx->fd = -1;
4049 +      return 0;
4050 +    }
4051 +
4052      hwctx->fd = open(device, O_RDWR);
4053      if (hwctx->fd < 0)
4054          return AVERROR(errno);
4055 -- 
4056 2.44.0
4057
4058
4059 From 38d09d83e6131bca6473674bf5979a13c979278b Mon Sep 17 00:00:00 2001
4060 From: Jonas Karlman <jonas@kwiboo.se>
4061 Date: Fri, 15 May 2020 16:54:05 +0000
4062 Subject: [PATCH 10/18] WIP: add NV15 and NV20 support
4063
4064 Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
4065 ---
4066  libavcodec/h264_slice.c   | 9 ++++++---
4067  libavcodec/v4l2_request.c | 7 +++++++
4068  2 files changed, 13 insertions(+), 3 deletions(-)
4069
4070 diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
4071 index 236bdc6..75f8235 100644
4072 --- a/libavcodec/h264_slice.c
4073 +++ b/libavcodec/h264_slice.c
4074 @@ -812,6 +812,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
4075  #endif
4076  #if CONFIG_H264_VULKAN_HWACCEL
4077          *fmt++ = AV_PIX_FMT_VULKAN;
4078 +#endif
4079 +#if CONFIG_H264_V4L2REQUEST_HWACCEL
4080 +        *fmt++ = AV_PIX_FMT_DRM_PRIME;
4081  #endif
4082          if (CHROMA444(h)) {
4083              if (h->avctx->colorspace == AVCOL_SPC_RGB) {
4084 @@ -868,6 +871,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
4085  #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL
4086          if (h->avctx->colorspace != AVCOL_SPC_RGB)
4087              *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
4088 +#endif
4089 +#if CONFIG_H264_V4L2REQUEST_HWACCEL
4090 +        *fmt++ = AV_PIX_FMT_DRM_PRIME;
4091  #endif
4092          if (CHROMA444(h)) {
4093              if (h->avctx->colorspace == AVCOL_SPC_RGB)
4094 @@ -891,9 +897,6 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
4095  #endif
4096  #if CONFIG_H264_VAAPI_HWACCEL
4097              *fmt++ = AV_PIX_FMT_VAAPI;
4098 -#endif
4099 -#if CONFIG_H264_V4L2REQUEST_HWACCEL
4100 -            *fmt++ = AV_PIX_FMT_DRM_PRIME;
4101  #endif
4102              if (h->avctx->color_range == AVCOL_RANGE_JPEG)
4103                  *fmt++ = AV_PIX_FMT_YUVJ420P;
4104 diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
4105 index 595a53e..8d2a248 100644
4106 --- a/libavcodec/v4l2_request.c
4107 +++ b/libavcodec/v4l2_request.c
4108 @@ -196,6 +196,13 @@ static const struct {
4109  } v4l2_request_capture_pixelformats[] = {
4110      { V4L2_PIX_FMT_NV12, AV_PIX_FMT_NV12, DRM_FORMAT_NV12, DRM_FORMAT_MOD_LINEAR },
4111      { V4L2_PIX_FMT_SUNXI_TILED_NV12, AV_PIX_FMT_NV12, DRM_FORMAT_NV12, DRM_FORMAT_MOD_ALLWINNER_TILED },
4112 +#if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15)
4113 +    { V4L2_PIX_FMT_NV15, AV_PIX_FMT_NONE, DRM_FORMAT_NV15, DRM_FORMAT_MOD_LINEAR },
4114 +#endif
4115 +    { V4L2_PIX_FMT_NV16, AV_PIX_FMT_NV16, DRM_FORMAT_NV16, DRM_FORMAT_MOD_LINEAR },
4116 +#if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20)
4117 +    { V4L2_PIX_FMT_NV20, AV_PIX_FMT_NONE, DRM_FORMAT_NV20, DRM_FORMAT_MOD_LINEAR },
4118 +#endif
4119  };
4120  
4121  static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4l2_format *format)
4122 -- 
4123 2.44.0
4124
4125
4126 From 71a1f3f8cb5d81fa8b8239bc302dc27580558550 Mon Sep 17 00:00:00 2001
4127 From: Jernej Skrabec <jernej.skrabec@gmail.com>
4128 Date: Mon, 9 Oct 2023 22:19:18 +0200
4129 Subject: [PATCH 11/18] v4l2 request api: add new codecs
4130
4131 ---
4132  libavcodec/v4l2_request.c | 32 ++++++++++++++++++++++++++++----
4133  1 file changed, 28 insertions(+), 4 deletions(-)
4134
4135 diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
4136 index 8d2a248..813c1b3 100644
4137 --- a/libavcodec/v4l2_request.c
4138 +++ b/libavcodec/v4l2_request.c
4139 @@ -202,6 +202,27 @@ static const struct {
4140      { V4L2_PIX_FMT_NV16, AV_PIX_FMT_NV16, DRM_FORMAT_NV16, DRM_FORMAT_MOD_LINEAR },
4141  #if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20)
4142      { V4L2_PIX_FMT_NV20, AV_PIX_FMT_NONE, DRM_FORMAT_NV20, DRM_FORMAT_MOD_LINEAR },
4143 +#endif
4144 +    { V4L2_PIX_FMT_P010, AV_PIX_FMT_P010, DRM_FORMAT_P010, DRM_FORMAT_MOD_LINEAR },
4145 +#if defined(V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT)
4146 +    {
4147 +        .pixelformat = V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT,
4148 +        .sw_format = AV_PIX_FMT_NONE,
4149 +        .drm_format = DRM_FORMAT_YUV420_10BIT,
4150 +        .format_modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
4151 +                                                   AFBC_FORMAT_MOD_SPARSE |
4152 +                                                   AFBC_FORMAT_MOD_SPLIT),
4153 +    },
4154 +#endif
4155 +#if defined(V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT)
4156 +    {
4157 +        .pixelformat = V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT,
4158 +        .sw_format = AV_PIX_FMT_NONE,
4159 +        .drm_format = DRM_FORMAT_YUV420_8BIT,
4160 +        .format_modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
4161 +                                                   AFBC_FORMAT_MOD_SPARSE |
4162 +                                                   AFBC_FORMAT_MOD_SPLIT),
4163 +    },
4164  #endif
4165  };
4166  
4167 @@ -228,15 +249,18 @@ static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4
4168      desc->objects[0].size = req->capture.size;
4169  
4170      desc->nb_layers = 1;
4171 -    layer->nb_planes = 2;
4172 +    layer->nb_planes = 1;
4173  
4174      layer->planes[0].object_index = 0;
4175      layer->planes[0].offset = 0;
4176      layer->planes[0].pitch = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.plane_fmt[0].bytesperline : format->fmt.pix.bytesperline;
4177  
4178 -    layer->planes[1].object_index = 0;
4179 -    layer->planes[1].offset = layer->planes[0].pitch * (V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.height : format->fmt.pix.height);
4180 -    layer->planes[1].pitch = layer->planes[0].pitch;
4181 +    if (!fourcc_mod_is_vendor(desc->objects[0].format_modifier, ARM)) {
4182 +        layer->nb_planes = 2;
4183 +        layer->planes[1].object_index = 0;
4184 +        layer->planes[1].offset = layer->planes[0].pitch * (V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.height : format->fmt.pix.height);
4185 +        layer->planes[1].pitch = layer->planes[0].pitch;
4186 +    }
4187  
4188      return 0;
4189  }
4190 -- 
4191 2.44.0
4192
4193
4194 From b6ec3a75b3ebaae839257c5a6de8bbdd0fdc237c Mon Sep 17 00:00:00 2001
4195 From: Jonas Karlman <jonas@kwiboo.se>
4196 Date: Sat, 4 Nov 2023 21:14:21 +0000
4197 Subject: [PATCH 12/18] WIP: libavutil: add NV15 and NV20 pix fmt
4198
4199 ---
4200  libavutil/pixdesc.c | 24 ++++++++++++++++++++++++
4201  libavutil/pixfmt.h  |  3 +++
4202  2 files changed, 27 insertions(+)
4203
4204 diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c
4205 index 6ded946..9747b5a 100644
4206 --- a/libavutil/pixdesc.c
4207 +++ b/libavutil/pixdesc.c
4208 @@ -584,6 +584,18 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
4209          },
4210          .flags = AV_PIX_FMT_FLAG_PLANAR,
4211      },
4212 +    [AV_PIX_FMT_NV15] = {
4213 +        .name = "nv15",
4214 +        .nb_components = 3,
4215 +        .log2_chroma_w = 1,
4216 +        .log2_chroma_h = 1,
4217 +        .comp = {
4218 +            { 0, 1, 0, 0, 10 },        /* Y */
4219 +            { 1, 2, 0, 0, 10 },        /* U */
4220 +            { 1, 2, 1, 0, 10 },        /* V */
4221 +        },
4222 +        .flags = AV_PIX_FMT_FLAG_PLANAR,
4223 +    },
4224      [AV_PIX_FMT_ARGB] = {
4225          .name = "argb",
4226          .nb_components = 4,
4227 @@ -2085,6 +2097,18 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
4228          },
4229          .flags = AV_PIX_FMT_FLAG_PLANAR,
4230      },
4231 +    [AV_PIX_FMT_NV20NP] = {
4232 +        .name = "nv20",
4233 +        .nb_components = 3,
4234 +        .log2_chroma_w = 1,
4235 +        .log2_chroma_h = 0,
4236 +        .comp = {
4237 +            { 0, 1, 0, 0, 10 },        /* Y */
4238 +            { 1, 2, 0, 0, 10 },        /* U */
4239 +            { 1, 2, 1, 0, 10 },        /* V */
4240 +        },
4241 +        .flags = AV_PIX_FMT_FLAG_PLANAR,
4242 +    },
4243      [AV_PIX_FMT_NV20LE] = {
4244          .name = "nv20le",
4245          .nb_components = 3,
4246 diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
4247 index a26c72d..08e7aac 100644
4248 --- a/libavutil/pixfmt.h
4249 +++ b/libavutil/pixfmt.h
4250 @@ -429,6 +429,9 @@ enum AVPixelFormat {
4251      AV_PIX_FMT_GBRAP14BE,  ///< planar GBR 4:4:4:4 56bpp, big-endian
4252      AV_PIX_FMT_GBRAP14LE,  ///< planar GBR 4:4:4:4 56bpp, little-endian
4253  
4254 +    AV_PIX_FMT_NV15,        ///< packed planar YUV 4:2:0, 15bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first component U and the following component V), no padding between components
4255 +    AV_PIX_FMT_NV20NP,      ///< packed planar YUV 4:2:2, 20bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first component U and the following component V), no padding between components
4256 +
4257      AV_PIX_FMT_NB         ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
4258  };
4259  
4260 -- 
4261 2.44.0
4262
4263
4264 From 5f3f0bf02e8728a9d36050260055feaabdccf687 Mon Sep 17 00:00:00 2001
4265 From: Jonas Karlman <jonas@kwiboo.se>
4266 Date: Sat, 4 Nov 2023 22:35:38 +0000
4267 Subject: [PATCH 13/18] WIP: libavutil: force NV15 and NV20 linesize
4268
4269 ---
4270  libavutil/imgutils.c | 2 ++
4271  libavutil/pixdesc.c  | 4 ++--
4272  libavutil/pixdesc.h  | 5 +++++
4273  3 files changed, 9 insertions(+), 2 deletions(-)
4274
4275 diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c
4276 index da38126..0cd8d3d 100644
4277 --- a/libavutil/imgutils.c
4278 +++ b/libavutil/imgutils.c
4279 @@ -70,6 +70,8 @@ int image_get_linesize(int width, int plane,
4280  
4281      if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM)
4282          linesize = (linesize + 7) >> 3;
4283 +    if (desc->flags & AV_PIX_FMT_FLAG_10BIT_NO_PADDING)
4284 +        linesize = linesize * 5 / 4;
4285      return linesize;
4286  }
4287  
4288 diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c
4289 index 9747b5a..42c4acd 100644
4290 --- a/libavutil/pixdesc.c
4291 +++ b/libavutil/pixdesc.c
4292 @@ -594,7 +594,7 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
4293              { 1, 2, 0, 0, 10 },        /* U */
4294              { 1, 2, 1, 0, 10 },        /* V */
4295          },
4296 -        .flags = AV_PIX_FMT_FLAG_PLANAR,
4297 +        .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_10BIT_NO_PADDING,
4298      },
4299      [AV_PIX_FMT_ARGB] = {
4300          .name = "argb",
4301 @@ -2107,7 +2107,7 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
4302              { 1, 2, 0, 0, 10 },        /* U */
4303              { 1, 2, 1, 0, 10 },        /* V */
4304          },
4305 -        .flags = AV_PIX_FMT_FLAG_PLANAR,
4306 +        .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_10BIT_NO_PADDING,
4307      },
4308      [AV_PIX_FMT_NV20LE] = {
4309          .name = "nv20le",
4310 diff --git a/libavutil/pixdesc.h b/libavutil/pixdesc.h
4311 index 0df73e6..73714c2 100644
4312 --- a/libavutil/pixdesc.h
4313 +++ b/libavutil/pixdesc.h
4314 @@ -157,6 +157,11 @@ typedef struct AVPixFmtDescriptor {
4315   */
4316  #define AV_PIX_FMT_FLAG_FLOAT        (1 << 9)
4317  
4318 +/**
4319 + * HACK: force use of linesize = linesize * 5 / 4
4320 + */
4321 +#define AV_PIX_FMT_FLAG_10BIT_NO_PADDING        (1 << 10)
4322 +
4323  /**
4324   * Return the number of bits per pixel used by the pixel format
4325   * described by pixdesc. Note that this is not the same as the number
4326 -- 
4327 2.44.0
4328
4329
4330 From c941547fb6068b09140ad618f7cea7fcb2806189 Mon Sep 17 00:00:00 2001
4331 From: Jonas Karlman <jonas@kwiboo.se>
4332 Date: Sat, 4 Nov 2023 21:14:21 +0000
4333 Subject: [PATCH 14/18] WIP: libswscale: add NV15 and NV20 unscaled conversion
4334
4335 ---
4336  libswscale/swscale_unscaled.c | 55 +++++++++++++++++++++++++++++++++++
4337  libswscale/utils.c            |  2 ++
4338  2 files changed, 57 insertions(+)
4339
4340 diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
4341 index a5c9917..5d054c0 100644
4342 --- a/libswscale/swscale_unscaled.c
4343 +++ b/libswscale/swscale_unscaled.c
4344 @@ -221,6 +221,56 @@ static int nv24ToPlanarWrapper(SwsContext *c, const uint8_t *src[],
4345      return srcSliceH;
4346  }
4347  
4348 +static int nv15ToPlanarWrapper(SwsContext *c, const uint8_t *src[],
4349 +                               int srcStride[], int srcSliceY,
4350 +                               int srcSliceH, uint8_t *dstParam[],
4351 +                               int dstStride[])
4352 +{
4353 +    const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat);
4354 +    int vsub = 1 << dst_format->log2_chroma_h;
4355 +    uint16_t *dstY = (uint16_t*)(dstParam[0] + dstStride[0] * srcSliceY);
4356 +    uint16_t *dstU = (uint16_t*)(dstParam[1] + dstStride[1] * srcSliceY / vsub);
4357 +    uint16_t *dstV = (uint16_t*)(dstParam[2] + dstStride[2] * srcSliceY / vsub);
4358 +    int x, y;
4359 +
4360 +    const int shift[3] = {
4361 +        dst_format->comp[0].shift,
4362 +        dst_format->comp[1].shift,
4363 +        dst_format->comp[2].shift,
4364 +    };
4365 +
4366 +    for (y = srcSliceH; y > 0; y--) {
4367 +        const uint8_t *tsrcY = src[0];
4368 +        uint16_t *tdstY = dstY;
4369 +        for (x = c->srcW / 4; x > 0; x--) {
4370 +            *tdstY++ = (((tsrcY[1] & 0x3) << 8) | (tsrcY[0] & 0xff)) << shift[0];
4371 +            *tdstY++ = (((tsrcY[2] & 0xf) << 6) | ((tsrcY[1] >> 2) & 0x3f)) << shift[0];
4372 +            *tdstY++ = (((tsrcY[3] & 0x3f) << 4) | ((tsrcY[2] >> 4) & 0xf)) << shift[0];
4373 +            *tdstY++ = (((tsrcY[4] & 0xff) << 2) | ((tsrcY[3] >> 6) & 0x3)) << shift[0];
4374 +            tsrcY += 5;
4375 +        }
4376 +        src[0] += srcStride[0];
4377 +        dstY += dstStride[0] / sizeof(uint16_t);
4378 +    }
4379 +
4380 +    for (y = srcSliceH / vsub; y > 0; y--) {
4381 +        const uint8_t *tsrcUV = src[1];
4382 +        uint16_t *tdstU = dstU, *tdstV = dstV;
4383 +        for (x = c->chrSrcW / 2; x > 0; x--) {
4384 +            *tdstU++ = (((tsrcUV[1] & 0x3) << 8) | (tsrcUV[0] & 0xff)) << shift[1];
4385 +            *tdstV++ = (((tsrcUV[2] & 0xf) << 6) | ((tsrcUV[1] >> 2) & 0x3f)) << shift[2];
4386 +            *tdstU++ = (((tsrcUV[3] & 0x3f) << 4) | ((tsrcUV[2] >> 4) & 0xf)) << shift[1];
4387 +            *tdstV++ = (((tsrcUV[4] & 0xff) << 2) | ((tsrcUV[3] >> 6) & 0x3)) << shift[2];
4388 +            tsrcUV += 5;
4389 +        }
4390 +        src[1] += srcStride[1];
4391 +        dstU += dstStride[1] / sizeof(uint16_t);
4392 +        dstV += dstStride[2] / sizeof(uint16_t);
4393 +    }
4394 +
4395 +    return srcSliceH;
4396 +}
4397 +
4398  static int planarToP01xWrapper(SwsContext *c, const uint8_t *src8[],
4399                                 int srcStride[], int srcSliceY,
4400                                 int srcSliceH, uint8_t *dstParam8[],
4401 @@ -2004,6 +2054,11 @@ void ff_get_unscaled_swscale(SwsContext *c)
4402          (srcFormat == AV_PIX_FMT_NV24 || srcFormat == AV_PIX_FMT_NV42)) {
4403          c->convert_unscaled = nv24ToPlanarWrapper;
4404      }
4405 +    /* nv15_to_yuv420p10 */
4406 +    if ((dstFormat == AV_PIX_FMT_YUV420P10 && srcFormat == AV_PIX_FMT_NV15) ||
4407 +        (dstFormat == AV_PIX_FMT_YUV422P10 && srcFormat == AV_PIX_FMT_NV20NP)) {
4408 +        c->convert_unscaled = nv15ToPlanarWrapper;
4409 +    }
4410      /* yuv2bgr */
4411      if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P ||
4412           srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) &&
4413 diff --git a/libswscale/utils.c b/libswscale/utils.c
4414 index e1ad685..a878456 100644
4415 --- a/libswscale/utils.c
4416 +++ b/libswscale/utils.c
4417 @@ -267,6 +267,8 @@ static const FormatEntry format_entries[] = {
4418      [AV_PIX_FMT_RGBAF16LE]   = { 1, 0 },
4419      [AV_PIX_FMT_XV30LE]      = { 1, 1 },
4420      [AV_PIX_FMT_XV36LE]      = { 1, 1 },
4421 +    [AV_PIX_FMT_NV15]        = { 1, 0 },
4422 +    [AV_PIX_FMT_NV20NP]      = { 1, 0 },
4423  };
4424  
4425  int ff_shuffle_filter_coefficients(SwsContext *c, int *filterPos,
4426 -- 
4427 2.44.0
4428
4429
4430 From 49ff7fcf6ae1de10007f529c979f7478f2d7a451 Mon Sep 17 00:00:00 2001
4431 From: Jonas Karlman <jonas@kwiboo.se>
4432 Date: Sat, 11 Nov 2023 21:27:42 +0000
4433 Subject: [PATCH 15/18] WIP: v4l2-request: use NV15 and NV20 pix fmt
4434
4435 ---
4436  libavcodec/v4l2_request.c | 4 ++--
4437  1 file changed, 2 insertions(+), 2 deletions(-)
4438
4439 diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
4440 index 813c1b3..bf1e3c4 100644
4441 --- a/libavcodec/v4l2_request.c
4442 +++ b/libavcodec/v4l2_request.c
4443 @@ -197,11 +197,11 @@ static const struct {
4444      { V4L2_PIX_FMT_NV12, AV_PIX_FMT_NV12, DRM_FORMAT_NV12, DRM_FORMAT_MOD_LINEAR },
4445      { V4L2_PIX_FMT_SUNXI_TILED_NV12, AV_PIX_FMT_NV12, DRM_FORMAT_NV12, DRM_FORMAT_MOD_ALLWINNER_TILED },
4446  #if defined(V4L2_PIX_FMT_NV15) && defined(DRM_FORMAT_NV15)
4447 -    { V4L2_PIX_FMT_NV15, AV_PIX_FMT_NONE, DRM_FORMAT_NV15, DRM_FORMAT_MOD_LINEAR },
4448 +    { V4L2_PIX_FMT_NV15, AV_PIX_FMT_NV15, DRM_FORMAT_NV15, DRM_FORMAT_MOD_LINEAR },
4449  #endif
4450      { V4L2_PIX_FMT_NV16, AV_PIX_FMT_NV16, DRM_FORMAT_NV16, DRM_FORMAT_MOD_LINEAR },
4451  #if defined(V4L2_PIX_FMT_NV20) && defined(DRM_FORMAT_NV20)
4452 -    { V4L2_PIX_FMT_NV20, AV_PIX_FMT_NONE, DRM_FORMAT_NV20, DRM_FORMAT_MOD_LINEAR },
4453 +    { V4L2_PIX_FMT_NV20, AV_PIX_FMT_NV20NP, DRM_FORMAT_NV20, DRM_FORMAT_MOD_LINEAR },
4454  #endif
4455      { V4L2_PIX_FMT_P010, AV_PIX_FMT_P010, DRM_FORMAT_P010, DRM_FORMAT_MOD_LINEAR },
4456  #if defined(V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT)
4457 -- 
4458 2.44.0
4459
4460
4461 From 0db39ac91179f6893ecaede6936fb12f3e642306 Mon Sep 17 00:00:00 2001
4462 From: Jonas Karlman <jonas@kwiboo.se>
4463 Date: Sat, 4 Nov 2023 19:13:43 +0000
4464 Subject: [PATCH 16/18] WIP: v4l2-request: change to autodetect
4465
4466 fixes a review note from prior upstreaming attempt
4467 ---
4468  configure | 4 ++--
4469  1 file changed, 2 insertions(+), 2 deletions(-)
4470
4471 diff --git a/configure b/configure
4472 index 810e57c..bde3d46 100755
4473 --- a/configure
4474 +++ b/configure
4475 @@ -348,7 +348,7 @@ External library support:
4476    --enable-omx-rpi         enable OpenMAX IL code for Raspberry Pi [no]
4477    --enable-rkmpp           enable Rockchip Media Process Platform code [no]
4478    --disable-v4l2-m2m       disable V4L2 mem2mem code [autodetect]
4479 -  --enable-v4l2-request    enable V4L2 request API code [no]
4480 +  --disable-v4l2-request   disable V4L2 request API code [autodetect]
4481    --disable-vaapi          disable Video Acceleration API (mainly Unix/Intel) code [autodetect]
4482    --disable-vdpau          disable Nvidia Video Decode and Presentation API for Unix code [autodetect]
4483    --disable-videotoolbox   disable VideoToolbox code [autodetect]
4484 @@ -1934,6 +1934,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST="
4485      videotoolbox
4486      vulkan
4487      v4l2_m2m
4488 +    v4l2_request
4489  "
4490  
4491  # catchall list of things that require external libs to link
4492 @@ -1955,7 +1956,6 @@ HWACCEL_LIBRARY_LIST="
4493      mmal
4494      omx
4495      opencl
4496 -    v4l2_request
4497  "
4498  
4499  DOCUMENT_LIST="
4500 -- 
4501 2.44.0
4502
4503
4504 From 36a27318e0f280b448fb5ab6e59f4151f6001517 Mon Sep 17 00:00:00 2001
4505 From: Jonas Karlman <jonas@kwiboo.se>
4506 Date: Sat, 4 Nov 2023 21:13:27 +0000
4507 Subject: [PATCH 17/18] libswscale: fix NV16 unscaled conversion
4508
4509 ---
4510  libswscale/swscale_unscaled.c | 13 +++++++++++--
4511  1 file changed, 11 insertions(+), 2 deletions(-)
4512
4513 diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
4514 index 5d054c0..833c2c6 100644
4515 --- a/libswscale/swscale_unscaled.c
4516 +++ b/libswscale/swscale_unscaled.c
4517 @@ -190,7 +190,7 @@ static int planarToNv24Wrapper(SwsContext *c, const uint8_t *src[],
4518      copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
4519                dstParam[0], dstStride[0]);
4520  
4521 -    if (c->dstFormat == AV_PIX_FMT_NV24)
4522 +    if (c->dstFormat == AV_PIX_FMT_NV24 || c->dstFormat == AV_PIX_FMT_NV16)
4523          interleaveBytes(src[1], src[2], dst, c->chrSrcW, srcSliceH,
4524                          srcStride[1], srcStride[2], dstStride[1]);
4525      else
4526 @@ -211,7 +211,7 @@ static int nv24ToPlanarWrapper(SwsContext *c, const uint8_t *src[],
4527      copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
4528                dstParam[0], dstStride[0]);
4529  
4530 -    if (c->srcFormat == AV_PIX_FMT_NV24)
4531 +    if (c->srcFormat == AV_PIX_FMT_NV24 || c->srcFormat == AV_PIX_FMT_NV16)
4532          deinterleaveBytes(src[1], dst1, dst2, c->chrSrcW, srcSliceH,
4533                            srcStride[1], dstStride[1], dstStride[2]);
4534      else
4535 @@ -2039,6 +2039,11 @@ void ff_get_unscaled_swscale(SwsContext *c)
4536          (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21)) {
4537          c->convert_unscaled = planarToNv12Wrapper;
4538      }
4539 +    /* yv16_to_nv16 */
4540 +    if ((srcFormat == AV_PIX_FMT_YUV422P || srcFormat == AV_PIX_FMT_YUVA422P) &&
4541 +        dstFormat == AV_PIX_FMT_NV16) {
4542 +        c->convert_unscaled = planarToNv24Wrapper;
4543 +    }
4544      /* yv24_to_nv24 */
4545      if ((srcFormat == AV_PIX_FMT_YUV444P || srcFormat == AV_PIX_FMT_YUVA444P) &&
4546          (dstFormat == AV_PIX_FMT_NV24 || dstFormat == AV_PIX_FMT_NV42)) {
4547 @@ -2049,6 +2054,10 @@ void ff_get_unscaled_swscale(SwsContext *c)
4548          (srcFormat == AV_PIX_FMT_NV12 || srcFormat == AV_PIX_FMT_NV21)) {
4549          c->convert_unscaled = nv12ToPlanarWrapper;
4550      }
4551 +    /* nv16_to_yv16 */
4552 +    if (dstFormat == AV_PIX_FMT_YUV422P && srcFormat == AV_PIX_FMT_NV16) {
4553 +        c->convert_unscaled = nv24ToPlanarWrapper;
4554 +    }
4555      /* nv24_to_yv24 */
4556      if (dstFormat == AV_PIX_FMT_YUV444P &&
4557          (srcFormat == AV_PIX_FMT_NV24 || srcFormat == AV_PIX_FMT_NV42)) {
4558 -- 
4559 2.44.0
4560
4561
4562 From 502d19c9564969538952051c2d395c714e41e567 Mon Sep 17 00:00:00 2001
4563 From: Jonas Karlman <jonas@kwiboo.se>
4564 Date: Sun, 31 Dec 2023 08:56:14 +0000
4565 Subject: [PATCH 18/18] WIP: limit v4l2 udev enum sysname match
4566
4567 ---
4568  libavcodec/v4l2_request.c | 4 ++++
4569  1 file changed, 4 insertions(+)
4570
4571 diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
4572 index bf1e3c4..e249dea 100644
4573 --- a/libavcodec/v4l2_request.c
4574 +++ b/libavcodec/v4l2_request.c
4575 @@ -764,6 +764,7 @@ int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t b
4576      struct udev_list_entry *devices;
4577      struct udev_list_entry *entry;
4578      struct udev_device *device;
4579 +    const char *sysname;
4580  
4581      av_log(avctx, AV_LOG_DEBUG, "%s: ctx=%p hw_device_ctx=%p hw_frames_ctx=%p\n", __func__, ctx, avctx->hw_device_ctx, avctx->hw_frames_ctx);
4582  
4583 @@ -786,6 +787,9 @@ int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t b
4584      }
4585  
4586      udev_enumerate_add_match_subsystem(enumerate, "media");
4587 +    sysname = getenv("V4L2_SYSNAME");
4588 +    if (sysname)
4589 +        udev_enumerate_add_match_sysname(enumerate, sysname);
4590      udev_enumerate_scan_devices(enumerate);
4591  
4592      devices = udev_enumerate_get_list_entry(enumerate);
4593 -- 
4594 2.44.0
4595
This page took 0.398438 seconds and 3 git commands to generate.