diff --git a/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch b/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch index fdd03f7036..acb070e4d6 100644 --- a/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch +++ b/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch @@ -1,16 +1,16 @@ diff --git a/configure b/configure -index 36713ab658..665d247bf7 100755 +index d7a3f507e8..cfbbb4f27d 100755 --- a/configure +++ b/configure -@@ -274,6 +274,7 @@ External library support: - --enable-libtls enable LibreSSL (via libtls), needed for https support +@@ -279,6 +279,7 @@ External library support: if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] + --enable-libudev enable libudev [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] -@@ -336,12 +337,17 @@ External library support: +@@ -340,12 +341,17 @@ External library support: --enable-libmfx enable Intel MediaSDK (AKA Quick Sync Video) code via libmfx [no] --enable-libnpp enable Nvidia Performance Primitives-based code [no] --enable-mmal enable Broadcom Multi-Media Abstraction Layer (Raspberry Pi) via MMAL [no] @@ -28,7 +28,7 @@ index 36713ab658..665d247bf7 100755 --disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect] --disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect] --disable-videotoolbox disable VideoToolbox code [autodetect] -@@ -1771,6 +1777,7 @@ EXTERNAL_LIBRARY_LIST=" +@@ -1774,6 +1780,7 @@ EXTERNAL_LIBRARY_LIST=" libdav1d libdc1394 libdrm @@ -36,15 +36,15 @@ index 36713ab658..665d247bf7 100755 libflite libfontconfig libfreetype -@@ -1807,6 +1814,7 @@ EXTERNAL_LIBRARY_LIST=" - libtesseract +@@ -1814,6 +1821,7 @@ EXTERNAL_LIBRARY_LIST=" libtheora libtwolame + libuavs3d + libudev libv4l2 + libvmaf libvorbis - libvpx -@@ -1861,7 +1869,10 @@ HWACCEL_LIBRARY_LIST=" +@@ -1868,7 +1876,10 @@ HWACCEL_LIBRARY_LIST=" mmal omx opencl @@ -55,7 +55,7 @@ index 36713ab658..665d247bf7 100755 " DOCUMENT_LIST=" -@@ -1877,12 +1888,16 @@ FEATURE_LIST=" +@@ -1884,12 +1895,16 @@ FEATURE_LIST=" gray hardcoded_tables omx_rpi @@ -72,7 +72,7 @@ index 36713ab658..665d247bf7 100755 " # this list should be kept in linking order -@@ -1923,6 +1938,7 @@ SUBSYSTEM_LIST=" +@@ -1930,6 +1945,7 @@ SUBSYSTEM_LIST=" pixelutils network rdft @@ -80,7 +80,7 @@ index 36713ab658..665d247bf7 100755 " # COMPONENT_LIST needs to come last to ensure correct dependency checking -@@ -2405,9 +2421,11 @@ CONFIG_EXTRA=" +@@ -2416,9 +2432,11 @@ CONFIG_EXTRA=" rangecoder riffdec riffenc @@ -92,16 +92,16 @@ index 36713ab658..665d247bf7 100755 scene_sad sinewin snappy -@@ -2737,6 +2755,8 @@ hap_decoder_select="snappy texturedsp" +@@ -2750,6 +2768,8 @@ hap_decoder_select="snappy texturedsp" hap_encoder_deps="libsnappy" hap_encoder_select="texturedspenc" - hevc_decoder_select="bswapdsp cabac golomb hevcparse videodsp" + hevc_decoder_select="atsc_a53 bswapdsp cabac golomb hevcparse videodsp" +hevc_rpi_decoder_deps="rpi" +hevc_rpi_decoder_select="hevc_decoder sand" huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp" huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llvidencdsp" hymt_decoder_select="huffyuv_decoder" -@@ -2903,6 +2923,7 @@ d3d11va_deps="dxva_h ID3D11VideoDecoder ID3D11VideoContext" +@@ -2919,6 +2939,7 @@ d3d11va_deps="dxva_h ID3D11VideoDecoder ID3D11VideoContext" dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" ffnvcodec_deps_any="libdl LoadLibrary" nvdec_deps="ffnvcodec" @@ -109,7 +109,7 @@ index 36713ab658..665d247bf7 100755 vaapi_x11_deps="xlib" videotoolbox_hwaccel_deps="videotoolbox pthreads" videotoolbox_hwaccel_extralibs="-framework QuartzCore" -@@ -2934,6 +2955,12 @@ hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" +@@ -2960,6 +2981,12 @@ hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" hevc_dxva2_hwaccel_select="hevc_decoder" hevc_nvdec_hwaccel_deps="nvdec" hevc_nvdec_hwaccel_select="hevc_decoder" @@ -122,7 +122,7 @@ index 36713ab658..665d247bf7 100755 hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC" hevc_vaapi_hwaccel_select="hevc_decoder" hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" -@@ -3401,8 +3428,14 @@ sndio_indev_deps="sndio" +@@ -3437,8 +3464,14 @@ sndio_indev_deps="sndio" sndio_outdev_deps="sndio" v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h" v4l2_indev_suggest="libv4l2" @@ -137,7 +137,7 @@ index 36713ab658..665d247bf7 100755 vfwcap_indev_deps="vfw32 vfwcap_defines" xcbgrab_indev_deps="libxcb" xcbgrab_indev_suggest="libxcb_shm libxcb_shape libxcb_xfixes" -@@ -3618,6 +3651,7 @@ tonemap_vaapi_filter_deps="vaapi VAProcFilterParameterBufferHDRToneMapping" +@@ -3657,6 +3690,7 @@ tonemap_vaapi_filter_deps="vaapi VAProcFilterParameterBufferHDRToneMapping" tonemap_opencl_filter_deps="opencl const_nan" transpose_opencl_filter_deps="opencl" transpose_vaapi_filter_deps="vaapi VAProcPipelineCaps_rotation_flags" @@ -145,7 +145,7 @@ index 36713ab658..665d247bf7 100755 unsharp_opencl_filter_deps="opencl" uspp_filter_deps="gpl avcodec" vaguedenoiser_filter_deps="gpl" -@@ -6299,6 +6333,7 @@ enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.4.0" "dav1d +@@ -6357,6 +6391,7 @@ enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.5.0" "dav1d enabled libdavs2 && require_pkg_config libdavs2 "davs2 >= 1.6.0" davs2.h davs2_decoder_open enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new enabled libdrm && require_pkg_config libdrm libdrm xf86drm.h drmGetVersion @@ -153,15 +153,15 @@ index 36713ab658..665d247bf7 100755 enabled libfdk_aac && { check_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen || { require libfdk_aac fdk-aac/aacenc_lib.h aacEncOpen -lfdk-aac && warn "using libfdk without pkg-config"; } } -@@ -6376,6 +6411,7 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur - enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && +@@ -6438,6 +6473,7 @@ enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } + enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode +enabled libudev && require_pkg_config libudev libudev libudev.h udev_new enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit - enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf -@@ -6430,11 +6466,12 @@ enabled mbedtls && { check_pkg_config mbedtls mbedtls mbedtls/x509_crt + enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf +@@ -6491,11 +6527,12 @@ enabled mbedtls && { check_pkg_config mbedtls mbedtls mbedtls/x509_crt check_lib mbedtls mbedtls/ssl.h mbedtls_ssl_init -lmbedtls -lmbedx509 -lmbedcrypto || die "ERROR: mbedTLS not found"; } enabled mediacodec && { enabled jni || die "ERROR: mediacodec requires --enable-jni"; } @@ -176,7 +176,7 @@ index 36713ab658..665d247bf7 100755 die "ERROR: mmal not found" && check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS"; } enabled openal && { { for al_extralibs in "${OPENAL_LIBS}" "-lopenal" "-lOpenAL32"; do -@@ -6475,6 +6512,10 @@ enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/r +@@ -6536,6 +6573,10 @@ enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/r { enabled libdrm || die "ERROR: rkmpp requires --enable-libdrm"; } } @@ -187,7 +187,7 @@ index 36713ab658..665d247bf7 100755 enabled vapoursynth && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init -@@ -6556,6 +6597,8 @@ if enabled v4l2_m2m; then +@@ -6617,6 +6658,8 @@ if enabled v4l2_m2m; then check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;" fi @@ -197,10 +197,10 @@ index 36713ab658..665d247bf7 100755 test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c -index 2e9448ea2b..7d22427b1b 100644 +index 46bb014de8..a29f7d3b5b 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c -@@ -2118,8 +2118,8 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) +@@ -2186,8 +2186,8 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) ifilter->channel_layout != frame->channel_layout; break; case AVMEDIA_TYPE_VIDEO: @@ -211,7 +211,7 @@ index 2e9448ea2b..7d22427b1b 100644 break; } -@@ -2130,6 +2130,9 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) +@@ -2198,6 +2198,9 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data)) need_reinit = 1; @@ -221,7 +221,7 @@ index 2e9448ea2b..7d22427b1b 100644 if (need_reinit) { ret = ifilter_parameters_from_frame(ifilter, frame); if (ret < 0) -@@ -2400,8 +2403,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ +@@ -2466,8 +2469,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ decoded_frame->top_field_first = ist->top_field_first; ist->frames_decoded++; @@ -231,7 +231,7 @@ index 2e9448ea2b..7d22427b1b 100644 err = ist->hwaccel_retrieve_data(ist->dec_ctx, decoded_frame); if (err < 0) goto fail; -@@ -2819,6 +2821,16 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat +@@ -2895,6 +2897,16 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat } else { const HWAccel *hwaccel = NULL; int i; @@ -248,7 +248,7 @@ index 2e9448ea2b..7d22427b1b 100644 for (i = 0; hwaccels[i].name; i++) { if (hwaccels[i].pix_fmt == *p) { hwaccel = &hwaccels[i]; -@@ -2913,6 +2925,15 @@ static int init_input_stream(int ist_index, char *error, int error_len) +@@ -2990,6 +3002,15 @@ static int init_input_stream(int ist_index, char *error, int error_len) return ret; } @@ -265,7 +265,7 @@ index 2e9448ea2b..7d22427b1b 100644 if (ret == AVERROR_EXPERIMENTAL) abort_codec_experimental(codec, 0); diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h -index 828cb2a4ff..f2abea94d7 100644 +index 606f2afe0c..448cd2e009 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -61,6 +61,7 @@ enum HWAccelID { @@ -276,7 +276,7 @@ index 828cb2a4ff..f2abea94d7 100644 }; typedef struct HWAccel { -@@ -590,6 +591,7 @@ extern int video_sync_method; +@@ -611,6 +612,7 @@ extern int video_sync_method; extern float frame_drop_threshold; extern int do_benchmark; extern int do_benchmark_all; @@ -285,10 +285,10 @@ index 828cb2a4ff..f2abea94d7 100644 extern int do_hex_dump; extern int do_pkt_dump; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c -index 422e1268e9..deb89c076d 100644 +index 4ab769c07b..5cdc3a7b6c 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c -@@ -1186,8 +1186,8 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) +@@ -1160,8 +1160,8 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) ifilter->format = frame->format; @@ -313,10 +313,10 @@ index fc4a5d31d6..cc69dce40e 100644 name = av_malloc(index_pos + 4); if (!name) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c -index 2eb4e1c973..ffbfa9accf 100644 +index 807e783422..456d4f349b 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c -@@ -130,12 +130,22 @@ static const char *opt_name_enc_time_bases[] = {"enc_time_base", NULL +@@ -133,12 +133,22 @@ static const char *const opt_name_enc_time_bases[] = {"enc_time_base" }\ } @@ -339,7 +339,7 @@ index 2eb4e1c973..ffbfa9accf 100644 #endif { 0 }, }; -@@ -155,6 +165,7 @@ float frame_drop_threshold = 0; +@@ -158,6 +168,7 @@ float frame_drop_threshold = 0; int do_deinterlace = 0; int do_benchmark = 0; int do_benchmark_all = 0; @@ -347,7 +347,7 @@ index 2eb4e1c973..ffbfa9accf 100644 int do_hex_dump = 0; int do_pkt_dump = 0; int copy_ts = 0; -@@ -3460,6 +3471,8 @@ const OptionDef options[] = { +@@ -3499,6 +3510,8 @@ const OptionDef options[] = { "add timings for benchmarking" }, { "benchmark_all", OPT_BOOL | OPT_EXPERT, { &do_benchmark_all }, "add timings for each task" }, @@ -357,7 +357,7 @@ index 2eb4e1c973..ffbfa9accf 100644 "write program-readable progress information", "url" }, { "stdin", OPT_BOOL | OPT_EXPERT, { &stdin_interaction }, diff --git a/libavcodec/Makefile b/libavcodec/Makefile -index 5a6ea59715..069865ee37 100644 +index 33a280cf69..be3b73e7c4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -19,6 +19,7 @@ HEADERS = ac3_parser.h \ @@ -368,15 +368,15 @@ index 5a6ea59715..069865ee37 100644 vaapi.h \ vdpau.h \ version.h \ -@@ -138,6 +139,7 @@ OBJS-$(CONFIG_QSVDEC) += qsvdec.o +@@ -140,6 +141,7 @@ OBJS-$(CONFIG_QSVDEC) += qsvdec.o OBJS-$(CONFIG_QSVENC) += qsvenc.o OBJS-$(CONFIG_RANGECODER) += rangecoder.o OBJS-$(CONFIG_RDFT) += rdft.o +OBJS-$(CONFIG_RPI) += rpi_qpu.o rpi_mailbox.o rpi_zc.o OBJS-$(CONFIG_RV34DSP) += rv34dsp.o OBJS-$(CONFIG_SHARED) += log2_tab.o reverse.o - OBJS-$(CONFIG_SINEWIN) += sinewin.o sinewin_fixed.o -@@ -152,7 +154,10 @@ OBJS-$(CONFIG_VIDEODSP) += videodsp.o + OBJS-$(CONFIG_SINEWIN) += sinewin.o +@@ -154,7 +156,10 @@ OBJS-$(CONFIG_VIDEODSP) += videodsp.o OBJS-$(CONFIG_VP3DSP) += vp3dsp.o OBJS-$(CONFIG_VP56DSP) += vp56dsp.o OBJS-$(CONFIG_VP8DSP) += vp8dsp.o @@ -388,7 +388,7 @@ index 5a6ea59715..069865ee37 100644 OBJS-$(CONFIG_WMA_FREQS) += wma_freqs.o OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o -@@ -391,6 +396,14 @@ OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o +@@ -403,6 +408,14 @@ OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \ hevc_data.o OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmppdec.o @@ -403,20 +403,20 @@ index 5a6ea59715..069865ee37 100644 OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o h265_profile_level.o OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER) += v4l2_m2m_enc.o -@@ -909,6 +922,10 @@ OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o +@@ -941,6 +954,10 @@ OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o - OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o + OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec.o +OBJS-$(CONFIG_HEVC_RPI4_8_HWACCEL) += rpivid_hevc.o +OBJS-$(CONFIG_HEVC_RPI4_10_HWACCEL) += rpivid_hevc.o +OBJS-$(CONFIG_HEVC_V4L2REQUEST_HWACCEL) += v4l2_request_hevc.o v4l2_req_decode_q.o\ + v4l2_req_hevc_v1.o v4l2_req_hevc_v2.o OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o h265_profile_level.o - OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o + OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o h265_profile_level.o OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o -@@ -1261,3 +1278,31 @@ $(SUBDIR)qdm2.o: $(SUBDIR)qdm2_tables.h +@@ -1297,3 +1314,31 @@ $(SUBDIR)pcm.o: $(SUBDIR)pcm_tables.h + $(SUBDIR)qdm2.o: $(SUBDIR)qdm2_tables.h $(SUBDIR)sinewin.o: $(SUBDIR)sinewin_tables.h - $(SUBDIR)sinewin_fixed.o: $(SUBDIR)sinewin_fixed_tables.h endif + +ifdef CONFIG_HEVC_RPI_DECODER @@ -447,10 +447,10 @@ index 5a6ea59715..069865ee37 100644 +$(SUBDIR)rpi_hevcdec.o $(SUBDIR)rpi_shader_template.o $(SUBDIR)rpi_qpu.o: $(SUBDIR)rpi_hevc_shader.h +endif diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c -index fa0c08d42e..89a25a398d 100644 +index 2e9a3581de..d9571b437f 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c -@@ -149,6 +149,7 @@ extern AVCodec ff_hap_decoder; +@@ -153,6 +153,7 @@ extern AVCodec ff_hap_decoder; extern AVCodec ff_hevc_decoder; extern AVCodec ff_hevc_qsv_decoder; extern AVCodec ff_hevc_rkmpp_decoder; @@ -458,7 +458,7 @@ index fa0c08d42e..89a25a398d 100644 extern AVCodec ff_hevc_v4l2m2m_decoder; extern AVCodec ff_hnm4_video_decoder; extern AVCodec ff_hq_hqa_decoder; -@@ -890,6 +891,41 @@ static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id) +@@ -917,6 +918,41 @@ static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id) } } @@ -501,10 +501,10 @@ index fa0c08d42e..89a25a398d 100644 { const AVCodec *p, *experimental = NULL; diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile -index c6be814153..442d60efe4 100644 +index c4ab93aeeb..cd926f7b33 100644 --- a/libavcodec/arm/Makefile +++ b/libavcodec/arm/Makefile -@@ -40,6 +40,8 @@ OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_init_arm.o \ +@@ -39,6 +39,8 @@ OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_init_arm.o \ arm/sbrdsp_init_arm.o OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_init_arm.o OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_arm.o @@ -513,7 +513,7 @@ index c6be814153..442d60efe4 100644 OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_init_arm.o OBJS-$(CONFIG_RV40_DECODER) += arm/rv40dsp_init_arm.o OBJS-$(CONFIG_SBC_ENCODER) += arm/sbcdsp_init_arm.o -@@ -140,10 +142,24 @@ NEON-OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_neon.o \ +@@ -137,10 +139,24 @@ NEON-OBJS-$(CONFIG_AAC_DECODER) += arm/aacpsdsp_neon.o \ NEON-OBJS-$(CONFIG_LLAUDDSP) += arm/lossless_audiodsp_neon.o NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/synth_filter_neon.o NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_neon.o \ @@ -15290,10 +15290,10 @@ index 0000000000..af8c4c03f0 + +endfunc diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h -index c91b2fd169..003079cdc6 100644 +index 8a71c04230..53644506e5 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h -@@ -2567,6 +2567,17 @@ typedef struct AVHWAccel { +@@ -2595,6 +2595,17 @@ typedef struct AVHWAccel { * that avctx->hwaccel_priv_data is invalid. */ int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); @@ -15312,30 +15312,25 @@ index c91b2fd169..003079cdc6 100644 /** diff --git a/libavcodec/cabac.h b/libavcodec/cabac.h -index 1bf1c620d6..ccfa991f60 100644 +index 38d06b2842..bbf5d70560 100644 --- a/libavcodec/cabac.h +++ b/libavcodec/cabac.h -@@ -43,7 +43,14 @@ extern const uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63]; - typedef struct CABACContext{ - int low; - int range; -- int outstanding_count; -+ union -+ { -+ int outstanding_count; -+ struct { -+ uint16_t bits; -+ uint16_t range; -+ } by22; -+ }; +@@ -44,6 +44,10 @@ typedef struct CABACContext{ const uint8_t *bytestream_start; const uint8_t *bytestream; const uint8_t *bytestream_end; ++ struct { ++ uint16_t bits; ++ uint16_t range; ++ } by22; + }CABACContext; + + int ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size); diff --git a/libavcodec/codec.h b/libavcodec/codec.h -index 1fda619ee7..b4650f9ec9 100644 +index 50a22f6e3c..5acf572ef4 100644 --- a/libavcodec/codec.h +++ b/libavcodec/codec.h -@@ -349,6 +349,17 @@ const AVCodec *av_codec_iterate(void **opaque); +@@ -367,6 +367,17 @@ const AVCodec *av_codec_iterate(void **opaque); */ AVCodec *avcodec_find_decoder(enum AVCodecID id); @@ -15852,7 +15847,7 @@ index 0000000000..7cbbbf055f + +#endif diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c -index 5af4b788d5..c7314a6af8 100644 +index 463d352055..7feff43c28 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -98,6 +98,19 @@ static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal, @@ -15876,10 +15871,10 @@ index 5af4b788d5..c7314a6af8 100644 num = ps->vps->vps_num_units_in_tick; den = ps->vps->vps_time_scale; diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c -index 1eaeaf72f1..b6871ff2e2 100644 +index 2231aed259..6d2d66dfdf 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c -@@ -332,6 +332,19 @@ static void export_stream_params(HEVCContext *s, const HEVCSPS *sps) +@@ -333,6 +333,19 @@ static void export_stream_params(HEVCContext *s, const HEVCSPS *sps) ff_set_sar(avctx, sps->vui.sar); @@ -15899,7 +15894,7 @@ index 1eaeaf72f1..b6871ff2e2 100644 if (sps->vui.video_signal_type_present_flag) avctx->color_range = sps->vui.video_full_range_flag ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; -@@ -372,14 +385,20 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) +@@ -392,14 +405,20 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + \ CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \ CONFIG_HEVC_NVDEC_HWACCEL + \ @@ -15920,7 +15915,7 @@ index 1eaeaf72f1..b6871ff2e2 100644 #if CONFIG_HEVC_DXVA2_HWACCEL *fmt++ = AV_PIX_FMT_DXVA2_VLD; #endif -@@ -398,9 +417,15 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) +@@ -418,9 +437,15 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #endif #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; @@ -15936,7 +15931,7 @@ index 1eaeaf72f1..b6871ff2e2 100644 #if CONFIG_HEVC_DXVA2_HWACCEL *fmt++ = AV_PIX_FMT_DXVA2_VLD; #endif -@@ -416,6 +441,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) +@@ -439,6 +464,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #endif #if CONFIG_HEVC_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; @@ -15946,7 +15941,7 @@ index 1eaeaf72f1..b6871ff2e2 100644 #endif break; case AV_PIX_FMT_YUV444P: -@@ -3230,7 +3258,14 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, +@@ -3327,7 +3355,14 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, s->ref = NULL; ret = decode_nal_units(s, avpkt->data, avpkt->size); if (ret < 0) @@ -15961,7 +15956,7 @@ index 1eaeaf72f1..b6871ff2e2 100644 if (avctx->hwaccel) { if (s->ref && (ret = avctx->hwaccel->end_frame(avctx)) < 0) { -@@ -3585,6 +3620,15 @@ AVCodec ff_hevc_decoder = { +@@ -3697,6 +3732,15 @@ AVCodec ff_hevc_decoder = { #if CONFIG_HEVC_NVDEC_HWACCEL HWACCEL_NVDEC(hevc), #endif @@ -15978,10 +15973,10 @@ index 1eaeaf72f1..b6871ff2e2 100644 HWACCEL_VAAPI(hevc), #endif diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h -index 6109c89bd6..81d200d5ec 100644 +index 8e54cf73f9..2277aadf75 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h -@@ -34,6 +34,9 @@ extern const AVHWAccel ff_hevc_d3d11va_hwaccel; +@@ -39,6 +39,9 @@ extern const AVHWAccel ff_hevc_d3d11va_hwaccel; extern const AVHWAccel ff_hevc_d3d11va2_hwaccel; extern const AVHWAccel ff_hevc_dxva2_hwaccel; extern const AVHWAccel ff_hevc_nvdec_hwaccel; @@ -16017,7 +16012,7 @@ index f421dc909f..f93283b893 100644 HW_CONFIG_HWACCEL(1, 1, 1, VAAPI, VAAPI, ff_ ## codec ## _vaapi_hwaccel) #define HWACCEL_VDPAU(codec) \ diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c -index 547bece576..bfd1083c16 100644 +index cb15ac072a..f6261db962 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -24,6 +24,9 @@ @@ -16039,10 +16034,10 @@ index 547bece576..bfd1083c16 100644 #include "avcodec.h" diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c -index 601f170447..f890f99931 100644 +index 9176027f15..0b0ff03c18 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c -@@ -191,7 +191,8 @@ static attribute_align_arg void *frame_worker_thread(void *arg) +@@ -209,7 +209,8 @@ FF_ENABLE_DEPRECATION_WARNINGS /* if the previous thread uses hwaccel then we take the lock to ensure * the threads don't run concurrently */ @@ -16052,7 +16047,7 @@ index 601f170447..f890f99931 100644 pthread_mutex_lock(&p->parent->hwaccel_mutex); p->hwaccel_serializing = 1; } -@@ -614,7 +615,9 @@ void ff_thread_finish_setup(AVCodecContext *avctx) { +@@ -636,7 +637,9 @@ void ff_thread_finish_setup(AVCodecContext *avctx) { if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return; @@ -16064,10 +16059,10 @@ index 601f170447..f890f99931 100644 p->hwaccel_serializing = 1; } diff --git a/libavcodec/raw.c b/libavcodec/raw.c -index b6fb91c1c6..f3afb6e09a 100644 +index 079d5c5d10..0781f28615 100644 --- a/libavcodec/raw.c +++ b/libavcodec/raw.c -@@ -293,6 +293,12 @@ const PixelFormatTag ff_raw_pix_fmt_tags[] = { +@@ -294,6 +294,12 @@ const PixelFormatTag ff_raw_pix_fmt_tags[] = { { AV_PIX_FMT_RGB565LE,MKTAG( 3 , 0 , 0 , 0 ) }, /* flipped RGB565LE */ { AV_PIX_FMT_YUV444P, MKTAG('Y', 'V', '2', '4') }, /* YUV444P, swapped UV */ @@ -46333,7 +46328,7 @@ index 0000000000..85c5b46d75 +}; + diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c -index 02f23d954b..44ed41481e 100644 +index 4b2679eb38..8b10fd5398 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -21,6 +21,7 @@ @@ -46421,7 +46416,134 @@ index 02f23d954b..44ed41481e 100644 } static enum AVColorPrimaries v4l2_get_color_primaries(V4L2Buffer *buf) -@@ -210,73 +223,159 @@ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf) +@@ -116,6 +129,105 @@ static enum AVColorPrimaries v4l2_get_color_primaries(V4L2Buffer *buf) + return AVCOL_PRI_UNSPECIFIED; + } + ++static void v4l2_set_color(V4L2Buffer *buf, ++ const enum AVColorPrimaries avcp, ++ const enum AVColorSpace avcs, ++ const enum AVColorTransferCharacteristic avxc) ++{ ++ enum v4l2_ycbcr_encoding ycbcr = V4L2_YCBCR_ENC_DEFAULT; ++ enum v4l2_colorspace cs = V4L2_COLORSPACE_DEFAULT; ++ enum v4l2_xfer_func xfer = V4L2_XFER_FUNC_DEFAULT; ++ ++ switch (avcp) { ++ case AVCOL_PRI_BT709: ++ cs = V4L2_COLORSPACE_REC709; ++ ycbcr = V4L2_YCBCR_ENC_709; ++ break; ++ case AVCOL_PRI_BT470M: ++ cs = V4L2_COLORSPACE_470_SYSTEM_M; ++ ycbcr = V4L2_YCBCR_ENC_601; ++ break; ++ case AVCOL_PRI_BT470BG: ++ cs = V4L2_COLORSPACE_470_SYSTEM_BG; ++ break; ++ case AVCOL_PRI_SMPTE170M: ++ cs = V4L2_COLORSPACE_SMPTE170M; ++ break; ++ case AVCOL_PRI_SMPTE240M: ++ cs = V4L2_COLORSPACE_SMPTE240M; ++ break; ++ case AVCOL_PRI_BT2020: ++ cs = V4L2_COLORSPACE_BT2020; ++ break; ++ case AVCOL_PRI_SMPTE428: ++ case AVCOL_PRI_SMPTE431: ++ case AVCOL_PRI_SMPTE432: ++ case AVCOL_PRI_EBU3213: ++ case AVCOL_PRI_RESERVED: ++ case AVCOL_PRI_FILM: ++ case AVCOL_PRI_UNSPECIFIED: ++ default: ++ break; ++ } ++ ++ switch (avcs) { ++ case AVCOL_SPC_RGB: ++ cs = V4L2_COLORSPACE_SRGB; ++ break; ++ case AVCOL_SPC_BT709: ++ cs = V4L2_COLORSPACE_REC709; ++ break; ++ case AVCOL_SPC_FCC: ++ cs = V4L2_COLORSPACE_470_SYSTEM_M; ++ break; ++ case AVCOL_SPC_BT470BG: ++ cs = V4L2_COLORSPACE_470_SYSTEM_BG; ++ break; ++ case AVCOL_SPC_SMPTE170M: ++ cs = V4L2_COLORSPACE_SMPTE170M; ++ break; ++ case AVCOL_SPC_SMPTE240M: ++ cs = V4L2_COLORSPACE_SMPTE240M; ++ break; ++ case AVCOL_SPC_BT2020_CL: ++ cs = V4L2_COLORSPACE_BT2020; ++ ycbcr = V4L2_YCBCR_ENC_BT2020_CONST_LUM; ++ break; ++ case AVCOL_SPC_BT2020_NCL: ++ cs = V4L2_COLORSPACE_BT2020; ++ break; ++ default: ++ break; ++ } ++ ++ switch (xfer) { ++ case AVCOL_TRC_BT709: ++ xfer = V4L2_XFER_FUNC_709; ++ break; ++ case AVCOL_TRC_IEC61966_2_1: ++ xfer = V4L2_XFER_FUNC_SRGB; ++ break; ++ case AVCOL_TRC_SMPTE240M: ++ xfer = V4L2_XFER_FUNC_SMPTE240M; ++ break; ++ case AVCOL_TRC_SMPTE2084: ++ xfer = V4L2_XFER_FUNC_SMPTE2084; ++ break; ++ default: ++ break; ++ } ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type)) { ++ buf->context->format.fmt.pix_mp.colorspace = cs; ++ buf->context->format.fmt.pix_mp.ycbcr_enc = ycbcr; ++ buf->context->format.fmt.pix_mp.xfer_func = xfer; ++ } else { ++ buf->context->format.fmt.pix.colorspace = cs; ++ buf->context->format.fmt.pix.ycbcr_enc = ycbcr; ++ buf->context->format.fmt.pix.xfer_func = xfer; ++ } ++} ++ + static enum AVColorRange v4l2_get_color_range(V4L2Buffer *buf) + { + enum v4l2_quantization qt; +@@ -134,6 +246,20 @@ static enum AVColorRange v4l2_get_color_range(V4L2Buffer *buf) + return AVCOL_RANGE_UNSPECIFIED; + } + ++static void v4l2_set_color_range(V4L2Buffer *buf, const enum AVColorRange avcr) ++{ ++ const enum v4l2_quantization q = ++ avcr == AVCOL_RANGE_MPEG ? V4L2_QUANTIZATION_LIM_RANGE : ++ avcr == AVCOL_RANGE_JPEG ? V4L2_QUANTIZATION_FULL_RANGE : ++ V4L2_QUANTIZATION_DEFAULT; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buf.type)) { ++ buf->context->format.fmt.pix_mp.quantization = q; ++ } else { ++ buf->context->format.fmt.pix.quantization = q; ++ } ++} ++ + static enum AVColorSpace v4l2_get_color_space(V4L2Buffer *buf) + { + enum v4l2_ycbcr_encoding ycbcr; +@@ -210,73 +336,165 @@ static enum AVColorTransferCharacteristic v4l2_get_color_trc(V4L2Buffer *buf) return AVCOL_TRC_UNSPECIFIED; } @@ -46432,19 +46554,14 @@ index 02f23d954b..44ed41481e 100644 - V4L2m2mContext *s = buf_to_m2mctx(avbuf); + return V4L2_FIELD_IS_INTERLACED(buf->buf.field); +} -+ + +- if (atomic_fetch_sub(&avbuf->context_refcount, 1) == 1) { +- atomic_fetch_sub_explicit(&s->refcount, 1, memory_order_acq_rel); +static int v4l2_buf_is_top_first(const V4L2Buffer * const buf) +{ + return buf->buf.field == V4L2_FIELD_INTERLACED_TB; +} -- if (atomic_fetch_sub(&avbuf->context_refcount, 1) == 1) { -- atomic_fetch_sub_explicit(&s->refcount, 1, memory_order_acq_rel); -+static uint8_t * v4l2_get_drm_frame(V4L2Buffer *avbuf) -+{ -+ AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame; -+ AVDRMLayerDescriptor *layer; - - if (s->reinit) { - if (!atomic_load(&s->refcount)) - sem_post(&s->refsync); @@ -46456,6 +46573,17 @@ index 02f23d954b..44ed41481e 100644 - else if (avbuf->context->streamon) - ff_v4l2_buffer_enqueue(avbuf); - } ++static void v4l2_set_interlace(V4L2Buffer * const buf, const int is_interlaced, const int is_tff) ++{ ++ buf->buf.field = !is_interlaced ? V4L2_FIELD_NONE : ++ is_tff ? V4L2_FIELD_INTERLACED_TB : V4L2_FIELD_INTERLACED_BT; ++} ++ ++static uint8_t * v4l2_get_drm_frame(V4L2Buffer *avbuf) ++{ ++ AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame; ++ AVDRMLayerDescriptor *layer; ++ + /* fill the DRM frame descriptor */ + drm_desc->nb_objects = avbuf->num_planes; + drm_desc->nb_layers = 1; @@ -46500,10 +46628,10 @@ index 02f23d954b..44ed41481e 100644 + + if (avbuf->num_planes > 1) + break; ++ ++ layer->nb_planes = 3; - av_buffer_unref(&avbuf->context_ref); -+ layer->nb_planes = 3; -+ + layer->planes[1].object_index = 0; + layer->planes[1].offset = avbuf->plane_info[0].bytesperline * + avbuf->context->format.fmt.pix.height; @@ -46617,15 +46745,14 @@ index 02f23d954b..44ed41481e 100644 + return 0; } --static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset, AVBufferRef* bref) -+static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset) + static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset) { unsigned int bytesused, length; + int rv = 0; if (plane >= out->num_planes) return AVERROR(EINVAL); -@@ -284,32 +383,57 @@ static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, i +@@ -284,32 +502,57 @@ static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, i length = out->plane_info[plane].length; bytesused = FFMIN(size+offset, length); @@ -46698,7 +46825,7 @@ index 02f23d954b..44ed41481e 100644 } /* fixup special cases */ -@@ -318,17 +442,17 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) +@@ -318,17 +561,17 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) case AV_PIX_FMT_NV21: if (avbuf->num_planes > 1) break; @@ -46722,7 +46849,7 @@ index 02f23d954b..44ed41481e 100644 break; default: -@@ -338,68 +462,95 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) +@@ -338,68 +581,95 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) return 0; } @@ -46820,7 +46947,7 @@ index 02f23d954b..44ed41481e 100644 h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); } - size = frame->linesize[i] * h; -- ret = v4l2_bufref_to_buf(out, 0, frame->data[i], size, offset, frame->buf[i]); +- ret = v4l2_bufref_to_buf(out, 0, frame->data[i], size, offset); - if (ret) - return ret; - offset += size; @@ -46859,7 +46986,7 @@ index 02f23d954b..44ed41481e 100644 + } - for (i = 0; i < out->num_planes; i++) { -- ret = v4l2_bufref_to_buf(out, i, frame->buf[i]->data, frame->buf[i]->size, 0, frame->buf[i]); +- ret = v4l2_bufref_to_buf(out, i, frame->buf[i]->data, frame->buf[i]->size, 0); - if (ret) - return ret; + cpy_2d(dst, dst_stride, @@ -46872,12 +46999,19 @@ index 02f23d954b..44ed41481e 100644 return 0; } -@@ -411,14 +562,15 @@ static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) +@@ -411,14 +681,22 @@ static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out) { - v4l2_set_pts(out, frame->pts); ++ out->buf.flags = frame->key_frame ? (out->buf.flags & ~V4L2_BUF_FLAG_KEYFRAME) : (out->buf.flags | V4L2_BUF_FLAG_KEYFRAME); ++ // Beware that colour info is held in format rather than the actual ++ // v4l2 buffer struct so this may not be as useful as you might hope ++ v4l2_set_color(out, frame->color_primaries, frame->colorspace, frame->color_trc); ++ v4l2_set_color_range(out, frame->color_range); ++ // PTS & interlace are buffer vars + v4l2_set_pts(out, frame->pts, 0); ++ v4l2_set_interlace(out, frame->interlaced_frame, frame->top_field_first); return v4l2_buffer_swframe_to_buf(frame, out); } @@ -46890,7 +47024,7 @@ index 02f23d954b..44ed41481e 100644 av_frame_unref(frame); -@@ -433,13 +585,24 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) +@@ -433,13 +711,24 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) frame->colorspace = v4l2_get_color_space(avbuf); frame->color_range = v4l2_get_color_range(avbuf); frame->color_trc = v4l2_get_color_trc(avbuf); @@ -46919,7 +47053,7 @@ index 02f23d954b..44ed41481e 100644 /* 3. report errors upstream */ if (avbuf->buf.flags & V4L2_BUF_FLAG_ERROR) { -@@ -452,15 +615,16 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) +@@ -452,15 +741,16 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) int ff_v4l2_buffer_buf_to_avpkt(AVPacket *pkt, V4L2Buffer *avbuf) { @@ -46941,7 +47075,7 @@ index 02f23d954b..44ed41481e 100644 if (avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME) pkt->flags |= AV_PKT_FLAG_KEY; -@@ -470,36 +634,89 @@ int ff_v4l2_buffer_buf_to_avpkt(AVPacket *pkt, V4L2Buffer *avbuf) +@@ -470,36 +760,89 @@ int ff_v4l2_buffer_buf_to_avpkt(AVPacket *pkt, V4L2Buffer *avbuf) pkt->flags |= AV_PKT_FLAG_CORRUPT; } @@ -46957,7 +47091,7 @@ index 02f23d954b..44ed41481e 100644 { int ret; -- ret = v4l2_bufref_to_buf(out, 0, pkt->data, pkt->size, 0, pkt->buf); +- ret = v4l2_bufref_to_buf(out, 0, pkt->data, pkt->size, 0); - if (ret) + if (extlen) { + ret = v4l2_bufref_to_buf(out, 0, extdata, extlen, 0); @@ -46982,9 +47116,8 @@ index 02f23d954b..44ed41481e 100644 +int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out) +{ + return ff_v4l2_buffer_avpkt_to_buf_ext(pkt, out, NULL, 0, 0); - } - --int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) ++} ++ + +static void v4l2_buffer_buffer_free(void *opaque, uint8_t *data) +{ @@ -47005,8 +47138,9 @@ index 02f23d954b..44ed41481e 100644 + ff_weak_link_unref(&avbuf->context_wl); + + av_free(avbuf); -+} -+ + } + +-int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) + +int ff_v4l2_buffer_initialize(AVBufferRef ** pbufref, int index, V4L2Context *ctx) { @@ -47018,13 +47152,13 @@ index 02f23d954b..44ed41481e 100644 + *pbufref = NULL; + if (avbuf == NULL) + return AVERROR(ENOMEM); -+ + + bufref = av_buffer_create((uint8_t*)avbuf, sizeof(*avbuf), v4l2_buffer_buffer_free, NULL, 0); + if (bufref == NULL) { + av_free(avbuf); + return AVERROR(ENOMEM); + } - ++ + avbuf->context = ctx; avbuf->buf.memory = V4L2_MEMORY_MMAP; avbuf->buf.type = ctx->type; @@ -47039,7 +47173,7 @@ index 02f23d954b..44ed41481e 100644 if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { avbuf->buf.length = VIDEO_MAX_PLANES; avbuf->buf.m.planes = avbuf->planes; -@@ -507,7 +724,7 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) +@@ -507,7 +850,7 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) ret = ioctl(buf_to_m2mctx(avbuf)->fd, VIDIOC_QUERYBUF, &avbuf->buf); if (ret < 0) @@ -47048,7 +47182,7 @@ index 02f23d954b..44ed41481e 100644 if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { avbuf->num_planes = 0; -@@ -527,25 +744,33 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) +@@ -527,25 +870,33 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { avbuf->plane_info[i].length = avbuf->buf.m.planes[i].length; @@ -47093,7 +47227,7 @@ index 02f23d954b..44ed41481e 100644 if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { avbuf->buf.m.planes = avbuf->planes; avbuf->buf.length = avbuf->num_planes; -@@ -555,7 +780,20 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) +@@ -555,7 +906,20 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) avbuf->buf.length = avbuf->planes[0].length; } @@ -47115,7 +47249,7 @@ index 02f23d954b..44ed41481e 100644 } int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf) -@@ -564,9 +802,27 @@ int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf) +@@ -564,9 +928,27 @@ int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf) avbuf->buf.flags = avbuf->flags; @@ -47223,7 +47357,7 @@ index 8dbc7fc104..9909f349bd 100644 /** * Enqueues a V4L2Buffer diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c -index 29b144ed73..10f86913ad 100644 +index ff1ea8e57b..e94e5e4ab4 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -27,11 +27,13 @@ @@ -47868,16 +48002,16 @@ index 29b144ed73..10f86913ad 100644 + { + if (cmd == VIDIOC_STREAMOFF) + flush_all_buffers_status(ctx); - -- ctx->streamon = (cmd == VIDIOC_STREAMON); ++ + ctx->streamon = (cmd == VIDIOC_STREAMON); + av_log(avctx, AV_LOG_DEBUG, "%s set status %d (%s) OK\n", ctx->name, + cmd, (cmd == VIDIOC_STREAMON) ? "ON" : "OFF"); + } -- return 0; +- ctx->streamon = (cmd == VIDIOC_STREAMON); + ff_mutex_unlock(&ctx->lock); -+ + +- return 0; + return ret; } @@ -48191,7 +48325,7 @@ index 22a9532444..70190e3079 100644 /** * Enqueues a buffer to a V4L2Context from an AVFrame diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c -index e48b3a8ccf..4f3bcd3a51 100644 +index cdfd579810..c5a74b3373 100644 --- a/libavcodec/v4l2_m2m.c +++ b/libavcodec/v4l2_m2m.c @@ -215,13 +215,7 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mContext *s) @@ -48208,45 +48342,35 @@ index e48b3a8ccf..4f3bcd3a51 100644 ff_v4l2_context_release(&s->capture); /* 3. get the new capture format */ -@@ -328,7 +322,10 @@ static void v4l2_m2m_destroy_context(void *opaque, uint8_t *context) +@@ -328,11 +322,14 @@ static void v4l2_m2m_destroy_context(void *opaque, uint8_t *context) ff_v4l2_context_release(&s->capture); sem_destroy(&s->refsync); - close(s->fd); + if (s->fd != -1) + close(s->fd); -+ -+ av_log(s->avctx, AV_LOG_DEBUG, "V4L2 Context destroyed\n"); + av_frame_unref(s->frame); + av_frame_free(&s->frame); + av_packet_unref(&s->buf_pkt); ++ av_log(s->avctx, AV_LOG_DEBUG, "V4L2 Context destroyed\n"); ++ av_free(s); } -@@ -338,17 +335,34 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) - V4L2m2mContext *s = priv->context; - int ret; -- ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); -- if (ret) -- av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name); -+ if (!s) -+ return 0; +@@ -344,6 +341,11 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) + if (!s) + return 0; -- ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); -- if (ret) -- av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name); + av_log(s->avctx, AV_LOG_DEBUG, "V4L2 Codec end\n"); + + if (av_codec_is_decoder(s->avctx->codec)) + av_packet_unref(&s->buf_pkt); + -+ if (s->fd >= 0) { -+ ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); -+ if (ret) -+ av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name); -+ -+ ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); -+ if (ret) -+ av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name); -+ } + if (s->fd >= 0) { + ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); + if (ret) +@@ -356,7 +358,14 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) ff_v4l2_context_release(&s->output); @@ -48262,7 +48386,7 @@ index e48b3a8ccf..4f3bcd3a51 100644 return 0; diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h -index 456281f48c..6f2d0d75eb 100644 +index b67b216331..8f054f2f50 100644 --- a/libavcodec/v4l2_m2m.h +++ b/libavcodec/v4l2_m2m.h @@ -30,6 +30,7 @@ @@ -48301,7 +48425,7 @@ index 456281f48c..6f2d0d75eb 100644 /* null frame/packet received */ int draining; -@@ -63,6 +76,23 @@ typedef struct V4L2m2mContext { +@@ -66,6 +79,23 @@ typedef struct V4L2m2mContext { /* reference back to V4L2m2mPriv */ void *priv; @@ -48325,7 +48449,7 @@ index 456281f48c..6f2d0d75eb 100644 } V4L2m2mContext; typedef struct V4L2m2mPriv { -@@ -73,6 +103,7 @@ typedef struct V4L2m2mPriv { +@@ -76,6 +106,7 @@ typedef struct V4L2m2mPriv { int num_output_buffers; int num_capture_buffers; @@ -48333,7 +48457,7 @@ index 456281f48c..6f2d0d75eb 100644 } V4L2m2mPriv; /** -@@ -126,4 +157,16 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mContext *ctx); +@@ -129,4 +160,16 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mContext *ctx); */ int ff_v4l2_m2m_codec_full_reinit(V4L2m2mContext *ctx); @@ -48351,7 +48475,7 @@ index 456281f48c..6f2d0d75eb 100644 + #endif /* AVCODEC_V4L2_M2M_H */ diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c -index 3e17e0fcac..b9f28220a8 100644 +index ab07c0a24a..b9f28220a8 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -23,6 +23,10 @@ @@ -48475,7 +48599,7 @@ index 3e17e0fcac..b9f28220a8 100644 /* 5. start the capture process */ ret = ff_v4l2_context_set_status(capture, VIDIOC_STREAMON); -@@ -133,52 +168,312 @@ static int v4l2_prepare_decoder(V4L2m2mContext *s) +@@ -133,54 +168,325 @@ static int v4l2_prepare_decoder(V4L2m2mContext *s) return 0; } @@ -48592,20 +48716,14 @@ index 3e17e0fcac..b9f28220a8 100644 - V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; - V4L2Context *const capture = &s->capture; - V4L2Context *const output = &s->output; -- AVPacket avpkt = {0}; int ret; -- if (s->buf_pkt.size) { -- avpkt = s->buf_pkt; -- memset(&s->buf_pkt, 0, sizeof(AVPacket)); -- } else { -- ret = ff_decode_get_packet(avctx, &avpkt); -- if (ret < 0 && ret != AVERROR_EOF) + // If we don't already have a coded packet - get a new one + // We will already have a coded pkt if the output Q was full last time we + // tried to Q it -+ if (!s->buf_pkt.size) { -+ ret = ff_decode_get_packet(avctx, &s->buf_pkt); + if (!s->buf_pkt.size) { + ret = ff_decode_get_packet(avctx, &s->buf_pkt); +- if (ret < 0 && ret != AVERROR_EOF) + + if (ret == AVERROR(EAGAIN)) { + if (!stream_started(s)) { @@ -48651,29 +48769,31 @@ index 3e17e0fcac..b9f28220a8 100644 + if ((ret = check_output_streamon(avctx, s)) != 0) + return ret; -- ret = ff_v4l2_context_enqueue_packet(output, &avpkt); -- if (ret < 0) { -- if (ret != AVERROR(EAGAIN)) -- return ret; +- ret = ff_v4l2_context_enqueue_packet(output, &s->buf_pkt); +- if (ret < 0 && ret != AVERROR(EAGAIN)) +- goto fail; + ret = ff_v4l2_context_enqueue_packet(&s->output, &s->buf_pkt, + avctx->extradata, s->extdata_sent ? 0 : avctx->extradata_size, + 1); -- s->buf_pkt = avpkt; -- /* no input buffers available, continue dequeing */ +- /* if EAGAIN don't unref packet and try to enqueue in the next iteration */ +- if (ret != AVERROR(EAGAIN)) + if (ret == AVERROR(EAGAIN)) { + // Out of input buffers - keep packet + ret = NQ_Q_FULL; - } ++ } + else { + // In all other cases we are done with this packet -+ av_packet_unref(&s->buf_pkt); + av_packet_unref(&s->buf_pkt); + s->extdata_sent = 1; -- if (avpkt.size) { +- if (!s->draining) { - ret = v4l2_try_start(avctx); if (ret) { -- av_packet_unref(&avpkt); +- /* cant recover */ +- if (ret != AVERROR(ENOMEM)) +- ret = 0; +- goto fail; + av_log(avctx, AV_LOG_ERROR, "Packet enqueue failure: err=%d\n", ret); + return ret; + } @@ -48685,15 +48805,16 @@ index 3e17e0fcac..b9f28220a8 100644 + if (ret2) { + av_log(avctx, AV_LOG_DEBUG, "Start failure: err=%d\n", ret2); + ret = (ret2 == AVERROR(ENOMEM)) ? ret2 : NQ_DEAD; -+ } -+ } + } + } + +-dequeue: +- return ff_v4l2_context_dequeue_frame(capture, frame, -1); +-fail: +- av_packet_unref(&s->buf_pkt); + return ret; + } -- /* cant recover */ -- if (ret == AVERROR(ENOMEM)) -- return ret; -+ return ret; -+} -+ +static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) +{ + V4L2m2mContext *const s = ((V4L2m2mPriv*)avctx->priv_data)->context; @@ -48737,8 +48858,7 @@ index 3e17e0fcac..b9f28220a8 100644 + // Go again if we got a frame that we need to discard + } while (dst_rv == 0 && xlat_pts_out(avctx, s, frame)); + } - -- return 0; ++ + // Continue trying to enqueue packets if either + // (a) we succeeded last time OR + // (b) enqueue failed due to input Q full AND there is now room @@ -48760,14 +48880,10 @@ index 3e17e0fcac..b9f28220a8 100644 + av_log(avctx, AV_LOG_ERROR, "Streamoff and die?\n"); + ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); + return -1; - } - } ++ } ++ } +#endif - --dequeue: -- if (!s->buf_pkt.size) -- av_packet_unref(&avpkt); -- return ff_v4l2_context_dequeue_frame(capture, frame, -1); ++ + return dst_rv == 0 ? 0 : + src_rv < 0 ? src_rv : + dst_rv < 0 ? dst_rv : @@ -48815,10 +48931,10 @@ index 3e17e0fcac..b9f28220a8 100644 + // Add 64k to allow for any overheads and/or encoder hopefulness + // with small WxH + return size + (1 << 16); - } - ++} ++ static av_cold int v4l2_decode_init(AVCodecContext *avctx) -@@ -186,8 +481,12 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + { V4L2Context *capture, *output; V4L2m2mContext *s; V4L2m2mPriv *priv = avctx->priv_data; @@ -48831,7 +48947,7 @@ index 3e17e0fcac..b9f28220a8 100644 ret = ff_v4l2_m2m_create_context(priv, &s); if (ret < 0) return ret; -@@ -204,17 +503,43 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) +@@ -197,9 +503,38 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) output->av_codec_id = avctx->codec_id; output->av_pix_fmt = AV_PIX_FMT_NONE; @@ -48870,22 +48986,11 @@ index 3e17e0fcac..b9f28220a8 100644 s->avctx = avctx; ret = ff_v4l2_m2m_codec_init(priv); - if (ret) { - av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n"); -- s->self_ref = NULL; -- av_buffer_unref(&priv->context_ref); -- - return ret; - } - -@@ -223,10 +548,53 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) +@@ -213,7 +548,53 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) static av_cold int v4l2_decode_close(AVCodecContext *avctx) { -- V4L2m2mPriv *priv = avctx->priv_data; -- V4L2m2mContext *s = priv->context; -- av_packet_unref(&s->buf_pkt); -- return ff_v4l2_m2m_codec_end(priv); +- return ff_v4l2_m2m_codec_end(avctx->priv_data); + int rv; + av_log(avctx, AV_LOG_TRACE, "<<< %s\n", __func__); + rv = ff_v4l2_m2m_codec_end(avctx->priv_data); @@ -48936,7 +49041,7 @@ index 3e17e0fcac..b9f28220a8 100644 } #define OFFSET(x) offsetof(V4L2m2mPriv, x) -@@ -235,10 +603,16 @@ static av_cold int v4l2_decode_close(AVCodecContext *avctx) +@@ -222,10 +603,16 @@ static av_cold int v4l2_decode_close(AVCodecContext *avctx) static const AVOption options[] = { V4L_M2M_DEFAULT_OPTS, { "num_capture_buffers", "Number of buffers in the capture context", @@ -48954,15 +49059,14 @@ index 3e17e0fcac..b9f28220a8 100644 #define M2MDEC_CLASS(NAME) \ static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \ .class_name = #NAME "_v4l2m2m_decoder", \ -@@ -259,9 +633,15 @@ static const AVOption options[] = { +@@ -246,9 +633,15 @@ static const AVOption options[] = { .init = v4l2_decode_init, \ .receive_frame = v4l2_receive_frame, \ .close = v4l2_decode_close, \ + .flush = v4l2_decode_flush, \ .bsfs = bsf_name, \ .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ -- .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, \ -+ .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \ + .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \ + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ + AV_PIX_FMT_NV12, \ + AV_PIX_FMT_YUV420P, \ @@ -48973,10 +49077,10 @@ index 3e17e0fcac..b9f28220a8 100644 diff --git a/libavcodec/v4l2_req_decode_q.c b/libavcodec/v4l2_req_decode_q.c new file mode 100644 -index 0000000000..2adbd5999b +index 0000000000..5b3fb958fa --- /dev/null +++ b/libavcodec/v4l2_req_decode_q.c -@@ -0,0 +1,86 @@ +@@ -0,0 +1,84 @@ +#include +#include +#include @@ -49024,10 +49128,8 @@ index 0000000000..2adbd5999b + + if (d->next) + d->next->prev = d->prev; -+ else { -+ try_signal = 0; // If we were a singleton then no point signalling ++ else + q->tail = d->prev; -+ } + + // Not strictly needed but makes debug easier + d->next = NULL; @@ -49096,10 +49198,10 @@ index 0000000000..af7bbe1de4 + diff --git a/libavcodec/v4l2_req_devscan.c b/libavcodec/v4l2_req_devscan.c new file mode 100644 -index 0000000000..59724a8104 +index 0000000000..cfa94d55c4 --- /dev/null +++ b/libavcodec/v4l2_req_devscan.c -@@ -0,0 +1,452 @@ +@@ -0,0 +1,449 @@ +#include +#include +#include @@ -49434,9 +49536,6 @@ index 0000000000..59724a8104 + goto fail; + } + -+ free(interfaces); -+ return ret; -+ +fail: + free(interfaces); + if (media_fd != -1) @@ -49581,10 +49680,10 @@ index 0000000000..0baef36535 +#endif diff --git a/libavcodec/v4l2_req_dmabufs.c b/libavcodec/v4l2_req_dmabufs.c new file mode 100644 -index 0000000000..0717279e75 +index 0000000000..ae6c648369 --- /dev/null +++ b/libavcodec/v4l2_req_dmabufs.c -@@ -0,0 +1,241 @@ +@@ -0,0 +1,266 @@ +#include +#include +#include @@ -49604,6 +49703,7 @@ index 0000000000..0717279e75 +#define DMABUF_NAME1 "/dev/dma_heap/linux,cma" +#define DMABUF_NAME2 "/dev/dma_heap/reserved" + ++#define TRACE_ALLOC 0 + +struct dmabufs_ctl { + int fd; @@ -49617,6 +49717,11 @@ index 0000000000..0717279e75 + void * mapptr; +}; + ++#if TRACE_ALLOC ++static unsigned int total_bufs = 0; ++static size_t total_size = 0; ++#endif ++ +struct dmabuf_h * dmabuf_import(int fd, size_t size) +{ + struct dmabuf_h *dh; @@ -49636,6 +49741,13 @@ index 0000000000..0717279e75 + .size = size, + .mapptr = MAP_FAILED + }; ++ ++#if TRACE_ALLOC ++ ++total_bufs; ++ total_size += dh->size; ++ request_log("%s: Import: %zd, total=%zd, bufs=%d\n", __func__, dh->size, total_size, total_bufs); ++#endif ++ + return dh; +} + @@ -49678,6 +49790,12 @@ index 0000000000..0717279e75 + .mapptr = MAP_FAILED + }; + ++#if TRACE_ALLOC ++ ++total_bufs; ++ total_size += dh->size; ++ request_log("%s: Alloc: %zd, total=%zd, bufs=%d\n", __func__, dh->size, total_size, total_bufs); ++#endif ++ + return dh; + +fail: @@ -49773,6 +49891,12 @@ index 0000000000..0717279e75 + if (!dh) + return; + ++#if TRACE_ALLOC ++ --total_bufs; ++ total_size -= dh->size; ++ request_log("%s: Free: %zd, total=%zd, bufs=%d\n", __func__, dh->size, total_size, total_bufs); ++#endif ++ + if (dh->mapptr != MAP_FAILED) + munmap(dh->mapptr, dh->size); + while (close(dh->fd) == -1 && errno == EINTR) @@ -49890,10 +50014,10 @@ index 0000000000..42af98e156 + diff --git a/libavcodec/v4l2_req_hevc_vx.c b/libavcodec/v4l2_req_hevc_vx.c new file mode 100644 -index 0000000000..c628bd5ab4 +index 0000000000..c9a8fa7c87 --- /dev/null +++ b/libavcodec/v4l2_req_hevc_vx.c -@@ -0,0 +1,1189 @@ +@@ -0,0 +1,1188 @@ +// File included by v4l2_req_hevc_v* - not compiled on its own + +#include "decode.h" @@ -50861,13 +50985,12 @@ index 0000000000..c628bd5ab4 + } + } + -+ decode_q_remove(&ctx->decode_q, &rd->decode_ent); -+ + // Set the drm_prime desriptor + drm_from_format(&rd->drm, mediabufs_dst_fmt(ctx->mbufs)); + rd->drm.objects[0].fd = dmabuf_fd(qent_dst_dmabuf(rd->qe_dst, 0)); + rd->drm.objects[0].size = dmabuf_size(qent_dst_dmabuf(rd->qe_dst, 0)); + ++ decode_q_remove(&ctx->decode_q, &rd->decode_ent); + return 0; + +fail: @@ -50983,7 +51106,7 @@ index 0000000000..c628bd5ab4 + + av_log(NULL, AV_LOG_DEBUG, "%s: avctx=%p data=%p\n", __func__, avctx, data); + -+ qent_dst_free(&rd->qe_dst); ++ qent_dst_unref(&rd->qe_dst); + + // We don't expect req or qe_src to be set + if (rd->req || rd->qe_src) @@ -51085,10 +51208,10 @@ index 0000000000..c628bd5ab4 + diff --git a/libavcodec/v4l2_req_media.c b/libavcodec/v4l2_req_media.c new file mode 100644 -index 0000000000..9fb02b1d98 +index 0000000000..10f720f814 --- /dev/null +++ b/libavcodec/v4l2_req_media.c -@@ -0,0 +1,1525 @@ +@@ -0,0 +1,1569 @@ +/* + * Copyright (C) 2018 Paul Kocialkowski + * @@ -51271,8 +51394,6 @@ index 0000000000..9fb02b1d98 + +int media_request_start(struct media_request * const req) +{ -+ struct media_pool * const mp = req->mp; -+ + while (ioctl(req->fd, MEDIA_REQUEST_IOC_QUEUE, NULL) == -1) + { + const int err = errno; @@ -51282,7 +51403,7 @@ index 0000000000..9fb02b1d98 + return -err; + } + -+ pollqueue_add_task(mp->pq, req->pt, 2000); ++ pollqueue_add_task(req->pt, 2000); + return 0; +} + @@ -51322,6 +51443,8 @@ index 0000000000..9fb02b1d98 + while (next) { + struct media_request * const req = next; + next = req->next; ++ if (req->pt) ++ polltask_delete(&req->pt); + if (req->fd != -1) + close(req->fd); + free(req); @@ -51363,7 +51486,7 @@ index 0000000000..9fb02b1d98 + goto fail4; + } + -+ req->pt = polltask_new(req->fd, POLLPRI, media_request_done, req); ++ req->pt = polltask_new(pq, req->fd, POLLPRI, media_request_done, req); + if (!req->pt) + goto fail4; + } @@ -51401,15 +51524,17 @@ index 0000000000..9fb02b1d98 +#define INDEX_UNSET (~(uint32_t)0) + +enum qent_status { -+ QENT_NEW, -+ QENT_PENDING, -+ QENT_WAITING, -+ QENT_DONE, -+ QENT_ERROR, ++ QENT_NEW = 0, // Initial state - shouldn't last ++ QENT_FREE, // On free chain ++ QENT_PENDING, // User has ent ++ QENT_WAITING, // On inuse ++ QENT_DONE, // Frame rx ++ QENT_ERROR, // Error + QENT_IMPORT +}; + +struct qent_base { ++ atomic_int ref_count; + struct qent_base *next; + struct qent_base *prev; + enum qent_status status; @@ -51425,22 +51550,23 @@ index 0000000000..9fb02b1d98 + +struct qent_dst { + struct qent_base base; -+ + bool waiting; + pthread_mutex_t lock; + pthread_cond_t cond; + struct ff_weak_link_client * mbc_wl; +}; + ++struct qe_list_head { ++ struct qent_base *head; ++ struct qent_base *tail; ++}; + +struct buf_pool { + pthread_mutex_t lock; + sem_t free_sem; + enum v4l2_buf_type buf_type; -+ struct qent_base *free_head; -+ struct qent_base *free_tail; -+ struct qent_base *inuse_head; -+ struct qent_base *inuse_tail; ++ struct qe_list_head free; ++ struct qe_list_head inuse; +}; + + @@ -51456,6 +51582,7 @@ index 0000000000..9fb02b1d98 + + +#define QENT_BASE_INITIALIZER {\ ++ .ref_count = ATOMIC_VAR_INIT(0),\ + .status = QENT_NEW,\ + .index = INDEX_UNSET\ +} @@ -51469,7 +51596,7 @@ index 0000000000..9fb02b1d98 + } +} + -+static void qe_src_delete(struct qent_src *const be_src) ++static void qe_src_free(struct qent_src *const be_src) +{ + if (!be_src) + return; @@ -51488,6 +51615,18 @@ index 0000000000..9fb02b1d98 + return be_src; +} + ++static void qe_dst_free(struct qent_dst *const be_dst) ++{ ++ if (!be_dst) ++ return; ++ ++ ff_weak_link_unref(&be_dst->mbc_wl); ++ pthread_cond_destroy(&be_dst->cond); ++ pthread_mutex_destroy(&be_dst->lock); ++ qe_base_uninit(&be_dst->base); ++ free(be_dst); ++} ++ +static struct qent_dst * qe_dst_new(void) +{ + struct qent_dst *const be_dst = malloc(sizeof(*be_dst)); @@ -51501,55 +51640,75 @@ index 0000000000..9fb02b1d98 + return be_dst; +} + ++static void ql_add_tail(struct qe_list_head * const ql, struct qent_base * be) ++{ ++ if (ql->tail) ++ ql->tail->next = be; ++ else ++ ql->head = be; ++ be->prev = ql->tail; ++ be->next = NULL; ++ ql->tail = be; ++} ++ ++static struct qent_base * ql_extract(struct qe_list_head * const ql, struct qent_base * be) ++{ ++ if (!be) ++ return NULL; ++ ++ if (be->next) ++ be->next->prev = be->prev; ++ else ++ ql->tail = be->prev; ++ if (be->prev) ++ be->prev->next = be->next; ++ else ++ ql->head = be->next; ++ be->next = NULL; ++ be->prev = NULL; ++ return be; ++} ++ + +static void bq_put_free(struct buf_pool *const bp, struct qent_base * be) +{ -+ if (bp->free_tail) -+ bp->free_tail->next = be; -+ else -+ bp->free_head = be; -+ be->prev = bp->free_tail; -+ be->next = NULL; -+ bp->free_tail = be; ++ ql_add_tail(&bp->free, be); +} + +static struct qent_base * bq_get_free(struct buf_pool *const bp) +{ -+ struct qent_base *be; -+ -+ be = bp->free_head; -+ if (be) { -+ if (be->next) -+ be->next->prev = be->prev; -+ else -+ bp->free_tail = be->prev; -+ bp->free_head = be->next; -+ be->next = NULL; -+ be->prev = NULL; -+ } -+ return be; ++ return ql_extract(&bp->free, bp->free.head); +} + +static struct qent_base * bq_extract_inuse(struct buf_pool *const bp, struct qent_base *const be) +{ -+ if (be->next) -+ be->next->prev = be->prev; -+ else -+ bp->inuse_tail = be->prev; -+ if (be->prev) -+ be->prev->next = be->next; -+ else -+ bp->inuse_head = be->next; -+ be->next = NULL; -+ be->prev = NULL; -+ return be; ++ return ql_extract(&bp->inuse, be); ++} ++ ++static struct qent_base * bq_get_inuse(struct buf_pool *const bp) ++{ ++ return ql_extract(&bp->inuse, bp->inuse.head); +} + +static void bq_free_all_free_src(struct buf_pool *const bp) +{ + struct qent_base *be; + while ((be = bq_get_free(bp)) != NULL) -+ qe_src_delete(base_to_src(be)); ++ qe_src_free(base_to_src(be)); ++} ++ ++static void bq_free_all_inuse_src(struct buf_pool *const bp) ++{ ++ struct qent_base *be; ++ while ((be = bq_get_inuse(bp)) != NULL) ++ qe_src_free(base_to_src(be)); ++} ++ ++static void bq_free_all_free_dst(struct buf_pool *const bp) ++{ ++ struct qent_base *be; ++ while ((be = bq_get_free(bp)) != NULL) ++ qe_dst_free(base_to_dst(be)); +} + +static void queue_put_free(struct buf_pool *const bp, struct qent_base *be) @@ -51560,6 +51719,7 @@ index 0000000000..9fb02b1d98 + /* Clear out state vars */ + be->timestamp.tv_sec = 0; + be->timestamp.tv_usec = 0; ++ be->status = QENT_FREE; + for (i = 0; i < VIDEO_MAX_PLANES && be->dh[i]; ++i) + dmabuf_len_set(be->dh[i], 0); + bq_put_free(bp, be); @@ -51569,7 +51729,7 @@ index 0000000000..9fb02b1d98 + +static bool queue_is_inuse(const struct buf_pool *const bp) +{ -+ return bp->inuse_tail != NULL; ++ return bp->inuse.tail != NULL; +} + +static void queue_put_inuse(struct buf_pool *const bp, struct qent_base *be) @@ -51577,13 +51737,7 @@ index 0000000000..9fb02b1d98 + if (!be) + return; + pthread_mutex_lock(&bp->lock); -+ if (bp->inuse_tail) -+ bp->inuse_tail->next = be; -+ else -+ bp->inuse_head = be; -+ be->prev = bp->inuse_tail; -+ be->next = NULL; -+ bp->inuse_tail = be; ++ ql_add_tail(&bp->inuse, be); + be->status = QENT_WAITING; + pthread_mutex_unlock(&bp->lock); +} @@ -51618,7 +51772,7 @@ index 0000000000..9fb02b1d98 + + pthread_mutex_lock(&bp->lock); + /* Expect 1st in Q, but allow anywhere */ -+ for (be = bp->inuse_head; be; be = be->next) { ++ for (be = bp->inuse.head; be; be = be->next) { + if (dmabuf_fd(be->dh[0]) == fd) { + bq_extract_inuse(bp, be); + break; @@ -51631,14 +51785,12 @@ index 0000000000..9fb02b1d98 + +static void queue_delete(struct buf_pool *const bp) +{ -+ if (!bp) -+ return; + sem_destroy(&bp->free_sem); + pthread_mutex_destroy(&bp->lock); + free(bp); +} + -+static struct buf_pool* queue_new(const int vfd, struct pollqueue * pq) ++static struct buf_pool* queue_new(const int vfd) +{ + struct buf_pool *bp = calloc(1, sizeof(*bp)); + if (!bp) @@ -51761,12 +51913,14 @@ index 0000000000..9fb02b1d98 + return be; +} + -+static void qe_dst_done(struct qent_dst *const dst_be) ++static void qe_dst_done(struct qent_dst * dst_be) +{ + pthread_mutex_lock(&dst_be->lock); + dst_be->waiting = false; + pthread_cond_broadcast(&dst_be->cond); + pthread_mutex_unlock(&dst_be->lock); ++ ++ qent_dst_unref(&dst_be); +} + +static bool qe_dst_waiting(struct qent_dst *const dst_be) @@ -51790,7 +51944,6 @@ index 0000000000..9fb02b1d98 + struct mediabufs_ctl *mbc = v; + struct qent_src *src_be = NULL; + struct qent_dst *dst_be = NULL; -+ bool qrun = false; + + if (!revents) + request_err(mbc->dc, "%s: Timeout\n", __func__); @@ -51806,8 +51959,7 @@ index 0000000000..9fb02b1d98 + /* Reschedule */ + if (mediabufs_wants_poll(mbc)) { + mbc->polling = true; -+ pollqueue_add_task(mbc->pq, mbc->pt, 2000); -+ qrun = true; ++ pollqueue_add_task(mbc->pt, 2000); + } + pthread_mutex_unlock(&mbc->lock); + @@ -51815,8 +51967,6 @@ index 0000000000..9fb02b1d98 + queue_put_free(mbc->src, &src_be->base); + if (dst_be) + qe_dst_done(dst_be); -+ if (!qrun) -+ mediabufs_ctl_unref(&mbc); +} + +int qent_src_params_set(struct qent_src *const be_src, const struct timeval * timestamp) @@ -51915,6 +52065,8 @@ index 0000000000..9fb02b1d98 + dst_be->base.timestamp = (struct timeval){0,0}; + if (qe_v4l2_queue(&dst_be->base, mbc->vfd, NULL, &mbc->dst_fmt, true, false)) + goto fail1; ++ ++ qent_dst_ref(dst_be); + queue_put_inuse(mbc->dst, &dst_be->base); + } + @@ -51924,8 +52076,7 @@ index 0000000000..9fb02b1d98 + + if (!mbc->polling && mediabufs_wants_poll(mbc)) { + mbc->polling = true; -+ mediabufs_ctl_ref(mbc); -+ pollqueue_add_task(mbc->pq, mbc->pt, 2000); ++ pollqueue_add_task(mbc->pt, 2000); + } + pthread_mutex_unlock(&mbc->lock); + @@ -51940,8 +52091,10 @@ index 0000000000..9fb02b1d98 + queue_put_free(mbc->src, &src_be->base); + +// *** TODO: If src Q fails this doesnt unwind properly - separate dst Q from src Q -+ if (dst_be) ++ if (dst_be) { ++ dst_be->base.status = QENT_ERROR; + qe_dst_done(dst_be); ++ } + pthread_mutex_unlock(&mbc->lock); + return MEDIABUFS_ERROR_OPERATION_FAILED; +} @@ -52110,32 +52263,30 @@ index 0000000000..9fb02b1d98 + return status; +} + -+void qent_dst_delete(struct qent_dst *const be_dst) ++struct qent_dst * qent_dst_ref(struct qent_dst * const be_dst) +{ -+ if (!be_dst) -+ return; -+ -+ ff_weak_link_unref(&be_dst->mbc_wl); -+ pthread_cond_destroy(&be_dst->cond); -+ pthread_mutex_destroy(&be_dst->lock); -+ qe_base_uninit(&be_dst->base); -+ free(be_dst); ++ if (be_dst) ++ atomic_fetch_add(&be_dst->base.ref_count, 1); ++ return be_dst; +} + -+void qent_dst_free(struct qent_dst ** const pbe_dst) ++void qent_dst_unref(struct qent_dst ** const pbe_dst) +{ + struct qent_dst * const be_dst = *pbe_dst; + struct mediabufs_ctl * mbc; + if (!be_dst) + return; -+ + *pbe_dst = NULL; ++ ++ if (atomic_fetch_sub(&be_dst->base.ref_count, 1) != 0) ++ return; ++ + if ((mbc = ff_weak_link_lock(&be_dst->mbc_wl)) != NULL) { + queue_put_free(mbc->dst, &be_dst->base); + ff_weak_link_unlock(be_dst->mbc_wl); + } + else { -+ qent_dst_delete(be_dst); ++ qe_dst_free(be_dst); + } +} + @@ -52196,7 +52347,7 @@ index 0000000000..9fb02b1d98 + + if ((be_dst->mbc_wl = ff_weak_link_ref(mbc->this_wlm)) == NULL || + (index = create_dst_buf(mbc)) < 0) { -+ qent_dst_delete(be_dst); ++ qe_dst_free(be_dst); + return NULL; + } + @@ -52211,6 +52362,8 @@ index 0000000000..9fb02b1d98 + return NULL; + } + ++ be_dst->base.status = QENT_PENDING; ++ atomic_store(&be_dst->base.ref_count, 0); + return be_dst; +} + @@ -52266,7 +52419,7 @@ index 0000000000..9fb02b1d98 + + index = create_dst_buf(mbc); + if (index < 0) { -+ qent_dst_delete(be_dst); ++ qe_dst_free(be_dst); + return MEDIABUFS_ERROR_OPERATION_FAILED; + } + @@ -52280,6 +52433,7 @@ index 0000000000..9fb02b1d98 +struct qent_src *mediabufs_src_qent_get(struct mediabufs_ctl *const mbc) +{ + struct qent_base * buf = queue_get_free(mbc->src); ++ buf->status = QENT_PENDING; + return base_to_src(buf); +} + @@ -52324,7 +52478,7 @@ index 0000000000..9fb02b1d98 + goto fail; + } + if (qe_alloc_from_fmt(&be_src->base, dbsc, &mbc->src_fmt)) { -+ qe_src_delete(be_src); ++ qe_src_free(be_src); + goto fail; + } + be_src->base.index = i; @@ -52382,13 +52536,13 @@ index 0000000000..9fb02b1d98 + if (!mbc->stream_on) + return MEDIABUFS_STATUS_SUCCESS; + -+ if (set_stream(mbc->vfd, mbc->src_fmt.type, false) < 0) { -+ request_log("Failed to set stream off src type %d\n", mbc->src_fmt.type); ++ if (set_stream(mbc->vfd, mbc->dst_fmt.type, false) < 0) { ++ request_log("Failed to set stream off dst type %d\n", mbc->dst_fmt.type); + status = MEDIABUFS_ERROR_OPERATION_FAILED; + } + -+ if (set_stream(mbc->vfd, mbc->dst_fmt.type, false) < 0) { -+ request_log("Failed to set stream off dst type %d\n", mbc->dst_fmt.type); ++ if (set_stream(mbc->vfd, mbc->src_fmt.type, false) < 0) { ++ request_log("Failed to set stream off src type %d\n", mbc->src_fmt.type); + status = MEDIABUFS_ERROR_OPERATION_FAILED; + } + @@ -52490,6 +52644,19 @@ index 0000000000..9fb02b1d98 + request_buffers(mbc->vfd, mbc->src_fmt.type, V4L2_MEMORY_MMAP, 0); + request_buffers(mbc->vfd, mbc->dst_fmt.type, V4L2_MEMORY_MMAP, 0); + ++ bq_free_all_free_src(mbc->src); ++ bq_free_all_inuse_src(mbc->src); ++ bq_free_all_free_dst(mbc->dst); ++ ++ { ++ struct qent_dst *dst_be; ++ while ((dst_be = base_to_dst(bq_get_inuse(mbc->dst))) != NULL) { ++ dst_be->base.timestamp = (struct timeval){0}; ++ dst_be->base.status = QENT_ERROR; ++ qe_dst_done(dst_be); ++ } ++ } ++ + queue_delete(mbc->dst); + queue_delete(mbc->src); + close(mbc->vfd); @@ -52580,13 +52747,13 @@ index 0000000000..9fb02b1d98 + goto fail1; + } + -+ mbc->src = queue_new(mbc->vfd, pq); ++ mbc->src = queue_new(mbc->vfd); + if (!mbc->src) + goto fail1; -+ mbc->dst = queue_new(mbc->vfd, pq); ++ mbc->dst = queue_new(mbc->vfd); + if (!mbc->dst) + goto fail2; -+ mbc->pt = polltask_new(mbc->vfd, POLLIN | POLLOUT, mediabufs_poll_cb, mbc); ++ mbc->pt = polltask_new(pq, mbc->vfd, POLLIN | POLLOUT, mediabufs_poll_cb, mbc); + if (!mbc->pt) + goto fail3; + mbc->this_wlm = ff_weak_link_new(mbc); @@ -52616,10 +52783,10 @@ index 0000000000..9fb02b1d98 + diff --git a/libavcodec/v4l2_req_media.h b/libavcodec/v4l2_req_media.h new file mode 100644 -index 0000000000..e503773b1a +index 0000000000..15a6952748 --- /dev/null +++ b/libavcodec/v4l2_req_media.h -@@ -0,0 +1,147 @@ +@@ -0,0 +1,148 @@ +/* +e.h +* @@ -52704,7 +52871,8 @@ index 0000000000..e503773b1a +MediaBufsStatus qent_dst_wait(struct qent_dst *const be); +void qent_dst_delete(struct qent_dst *const be); +// Returns a qent_dst to its mbc free Q or deletes it if the mbc is dead -+void qent_dst_free(struct qent_dst ** const pbe_dst); ++void qent_dst_unref(struct qent_dst ** const pbe_dst); ++struct qent_dst * qent_dst_ref(struct qent_dst * const be_dst); + +const uint8_t * qent_dst_data(struct qent_dst *const be, unsigned int buf_no); +MediaBufsStatus qent_dst_read_start(struct qent_dst *const be); @@ -52769,14 +52937,16 @@ index 0000000000..e503773b1a +#endif diff --git a/libavcodec/v4l2_req_pollqueue.c b/libavcodec/v4l2_req_pollqueue.c new file mode 100644 -index 0000000000..0f7d9020ee +index 0000000000..5c47c50a6f --- /dev/null +++ b/libavcodec/v4l2_req_pollqueue.c -@@ -0,0 +1,280 @@ +@@ -0,0 +1,363 @@ +#include +#include +#include +#include ++#include ++#include +#include +#include +#include @@ -52791,21 +52961,32 @@ index 0000000000..0f7d9020ee + +struct pollqueue; + ++enum polltask_state { ++ POLLTASK_UNQUEUED = 0, ++ POLLTASK_QUEUED, ++ POLLTASK_RUNNING, ++ POLLTASK_Q_KILL, ++ POLLTASK_RUN_KILL, ++}; ++ +struct polltask { + struct polltask *next; + struct polltask *prev; + struct pollqueue *q; ++ enum polltask_state state; + + int fd; -+ short events; /* 0 => deleted */ ++ short events; + + void (*fn)(void *v, short revents); + void * v; + -+ uint64_t timeout; /* 0 => now */ ++ uint64_t timeout; /* CLOCK_MONOTONIC time, 0 => never */ ++ sem_t kill_sem; +}; + +struct pollqueue { ++ atomic_int ref_count; + pthread_mutex_t lock; + + struct polltask *head; @@ -52818,7 +52999,8 @@ index 0000000000..0f7d9020ee + pthread_t worker; +}; + -+struct polltask *polltask_new(const int fd, const short events, ++struct polltask *polltask_new(struct pollqueue *const pq, ++ const int fd, const short events, + void (*const fn)(void *v, short revents), + void *const v) +{ @@ -52834,11 +53016,15 @@ index 0000000000..0f7d9020ee + *pt = (struct polltask){ + .next = NULL, + .prev = NULL, ++ .q = pollqueue_ref(pq), + .fd = fd, + .events = events, + .fn = fn, + .v = v + }; ++ ++ sem_init(&pt->kill_sem, 0, 0); ++ + return pt; +} + @@ -52856,14 +53042,9 @@ index 0000000000..0f7d9020ee + pt->prev = NULL; +} + -+void polltask_delete(struct polltask **const ppt) ++static void polltask_free(struct polltask * const pt) +{ -+ struct polltask *const pt = *ppt; -+ -+ if (!pt) -+ return; -+ *ppt = NULL; -+ ++ sem_destroy(&pt->kill_sem); + free(pt); +} + @@ -52873,6 +53054,37 @@ index 0000000000..0f7d9020ee + return write(pq->prod_fd, &one, sizeof(one)); +} + ++void polltask_delete(struct polltask **const ppt) ++{ ++ struct polltask *const pt = *ppt; ++ struct pollqueue * pq; ++ enum polltask_state state; ++ bool prodme; ++ ++ if (!pt) ++ return; ++ ++ pq = pt->q; ++ pthread_mutex_lock(&pq->lock); ++ state = pt->state; ++ pt->state = (state == POLLTASK_RUNNING) ? POLLTASK_RUN_KILL : POLLTASK_Q_KILL; ++ prodme = !pq->no_prod; ++ pthread_mutex_unlock(&pq->lock); ++ ++ if (state != POLLTASK_UNQUEUED) { ++ if (prodme) ++ pollqueue_prod(pq); ++ while (sem_wait(&pt->kill_sem) && errno == EINTR) ++ /* loop */; ++ } ++ ++ // Leave zapping the ref until we have DQed the PT as might well be ++ // legitimately used in it ++ *ppt = NULL; ++ polltask_free(pt); ++ pollqueue_unref(&pq); ++} ++ +static uint64_t pollqueue_now(int timeout) +{ + struct timespec now; @@ -52884,21 +53096,24 @@ index 0000000000..0f7d9020ee + return now_ms ? now_ms : (uint64_t)1; +} + -+void pollqueue_add_task(struct pollqueue *const pq, struct polltask *const pt, -+ const int timeout) ++void pollqueue_add_task(struct polltask *const pt, const int timeout) +{ -+ bool prodme; ++ bool prodme = false; ++ struct pollqueue * const pq = pt->q; ++ + pthread_mutex_lock(&pq->lock); -+ if (pq->tail) -+ pq->tail->next = pt; -+ else -+ pq->head = pt; -+ pt->prev = pq->tail; -+ pt->next = NULL; -+ pt->q = pq; -+ pt->timeout = timeout < 0 ? 0 : pollqueue_now(timeout); -+ pq->tail = pt; -+ prodme = !pq->no_prod; ++ if (pt->state != POLLTASK_Q_KILL && pt->state != POLLTASK_RUN_KILL) { ++ if (pq->tail) ++ pq->tail->next = pt; ++ else ++ pq->head = pt; ++ pt->prev = pq->tail; ++ pt->next = NULL; ++ pt->state = POLLTASK_QUEUED; ++ pt->timeout = timeout < 0 ? 0 : pollqueue_now(timeout); ++ pq->tail = pt; ++ prodme = !pq->no_prod; ++ } + pthread_mutex_unlock(&pq->lock); + if (prodme) + pollqueue_prod(pq); @@ -52922,6 +53137,15 @@ index 0000000000..0f7d9020ee + for (pt = pq->head; pt; pt = pt->next) { + int64_t t; + ++ if (pt->state == POLLTASK_Q_KILL) { ++ struct polltask * const prev = pt->prev; ++ pollqueue_rem_task(pq, pt); ++ sem_post(&pt->kill_sem); ++ if ((pt = prev) == NULL) ++ break; ++ continue; ++ } ++ + if (n >= asize) { + asize = asize ? asize * 2 : 4; + a = realloc(a, asize * sizeof(*a)); @@ -52964,6 +53188,10 @@ index 0000000000..0f7d9020ee + if (a[i].revents || + (pt->timeout && (int64_t)(now - pt->timeout) >= 0)) { + pollqueue_rem_task(pq, pt); ++ if (pt->state == POLLTASK_QUEUED) ++ pt->state = POLLTASK_RUNNING; ++ if (pt->state == POLLTASK_Q_KILL) ++ pt->state = POLLTASK_RUN_KILL; + pthread_mutex_unlock(&pq->lock); + + /* This can add new entries to the Q but as @@ -52973,6 +53201,10 @@ index 0000000000..0f7d9020ee + pt->fn(pt->v, a[i].revents); + + pthread_mutex_lock(&pq->lock); ++ if (pt->state == POLLTASK_RUNNING) ++ pt->state = POLLTASK_UNQUEUED; ++ if (pt->state == POLLTASK_RUN_KILL) ++ sem_post(&pt->kill_sem); + } + + pt = pt_next; @@ -52995,7 +53227,7 @@ index 0000000000..0f7d9020ee + if (revents) + read(pq->prod_fd, buf, 8); + if (!pq->kill) -+ pollqueue_add_task(pq, pq->prod_pt, -1); ++ pollqueue_add_task(pq->prod_pt, -1); +} + +struct pollqueue * pollqueue_new(void) @@ -53004,26 +53236,29 @@ index 0000000000..0f7d9020ee + if (!pq) + return NULL; + *pq = (struct pollqueue){ ++ .ref_count = ATOMIC_VAR_INIT(0), ++ .lock = PTHREAD_MUTEX_INITIALIZER, + .head = NULL, + .tail = NULL, + .kill = false, -+ .lock = PTHREAD_MUTEX_INITIALIZER, + .prod_fd = -1 + }; + + pq->prod_fd = eventfd(0, EFD_NONBLOCK); + if (pq->prod_fd == 1) + goto fail1; -+ pq->prod_pt = polltask_new(pq->prod_fd, POLLIN, prod_fn, pq); ++ pq->prod_pt = polltask_new(pq, pq->prod_fd, POLLIN, prod_fn, pq); + if (!pq->prod_pt) + goto fail2; -+ pollqueue_add_task(pq, pq->prod_pt, -1); ++ pollqueue_add_task(pq->prod_pt, -1); + if (pthread_create(&pq->worker, NULL, poll_thread, pq)) + goto fail3; ++ // Reset ref count which will have been inced by the add_task ++ atomic_store(&pq->ref_count, 0); + return pq; + +fail3: -+ polltask_delete(&pq->prod_pt); ++ polltask_free(pq->prod_pt); +fail2: + close(pq->prod_fd); +fail1: @@ -53031,49 +53266,66 @@ index 0000000000..0f7d9020ee + return NULL; +} + -+void pollqueue_delete(struct pollqueue **const ppq) ++static void pollqueue_free(struct pollqueue *const pq) +{ -+ struct pollqueue * pq = *ppq; + void *rv; + -+ if (!pq) -+ return; -+ *ppq = NULL; -+ + pthread_mutex_lock(&pq->lock); + pq->kill = true; + pollqueue_prod(pq); + pthread_mutex_unlock(&pq->lock); + + pthread_join(pq->worker, &rv); -+ polltask_delete(&pq->prod_pt); ++ polltask_free(pq->prod_pt); + pthread_mutex_destroy(&pq->lock); + close(pq->prod_fd); + free(pq); +} + ++struct pollqueue * pollqueue_ref(struct pollqueue *const pq) ++{ ++ atomic_fetch_add(&pq->ref_count, 1); ++ return pq; ++} ++ ++void pollqueue_unref(struct pollqueue **const ppq) ++{ ++ struct pollqueue * const pq = *ppq; ++ ++ if (!pq) ++ return; ++ *ppq = NULL; ++ ++ if (atomic_fetch_sub(&pq->ref_count, 1) != 0) ++ return; ++ ++ pollqueue_free(pq); ++} ++ ++ + diff --git a/libavcodec/v4l2_req_pollqueue.h b/libavcodec/v4l2_req_pollqueue.h new file mode 100644 -index 0000000000..dcb0d80258 +index 0000000000..e1182cb2fc --- /dev/null +++ b/libavcodec/v4l2_req_pollqueue.h -@@ -0,0 +1,17 @@ +@@ -0,0 +1,18 @@ +#ifndef POLLQUEUE_H_ +#define POLLQUEUE_H_ + +struct polltask; +struct pollqueue; + -+struct polltask *polltask_new(const int fd, const short events, ++struct polltask *polltask_new(struct pollqueue *const pq, ++ const int fd, const short events, + void (*const fn)(void *v, short revents), + void *const v); +void polltask_delete(struct polltask **const ppt); + -+void pollqueue_add_task(struct pollqueue *const pq, struct polltask *const pt, -+ const int timeout); ++void pollqueue_add_task(struct polltask *const pt, const int timeout); +struct pollqueue * pollqueue_new(void); -+void pollqueue_delete(struct pollqueue **const ppq); ++void pollqueue_unref(struct pollqueue **const ppq); ++struct pollqueue * pollqueue_ref(struct pollqueue *const pq); + +#endif /* POLLQUEUE_H_ */ diff --git a/libavcodec/v4l2_req_utils.h b/libavcodec/v4l2_req_utils.h @@ -53105,10 +53357,10 @@ index 0000000000..9e9a5f7e39 + diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c new file mode 100644 -index 0000000000..5f287ee75c +index 0000000000..18ff8c0e64 --- /dev/null +++ b/libavcodec/v4l2_request_hevc.c -@@ -0,0 +1,274 @@ +@@ -0,0 +1,280 @@ +/* + * This file is part of FFmpeg. + * @@ -53200,9 +53452,13 @@ index 0000000000..5f287ee75c +{ + V4L2RequestContextHEVC * const ctx = avctx->internal->hwaccel_priv_data; + ++ av_log(avctx, AV_LOG_DEBUG, "<<< %s\n", __func__); ++ ++ decode_q_wait(&ctx->decode_q, NULL); // Wait for all other threads to be out of decode ++ + mediabufs_ctl_unref(&ctx->mbufs); + media_pool_delete(&ctx->mpool); -+ pollqueue_delete(&ctx->pq); ++ pollqueue_unref(&ctx->pq); + dmabufs_ctl_delete(&ctx->dbufs); + devscan_delete(&ctx->devscan); + @@ -53244,6 +53500,8 @@ index 0000000000..5f287ee75c + const uint32_t src_pix_fmt = V2(ff_v4l2_req_hevc, 1).src_pix_fmt_v4l2; // Assuming constant for all APIs but avoiding V4L2 includes + size_t src_size; + ++ av_log(avctx, AV_LOG_DEBUG, "<<< %s\n", __func__); ++ + if ((ret = devscan_build(avctx, &ctx->devscan)) != 0) { + av_log(avctx, AV_LOG_WARNING, "Failed to find any V4L2 devices\n"); + return (AVERROR(-ret)); @@ -53359,7 +53617,7 @@ index 0000000000..5f287ee75c +fail3: + media_pool_delete(&ctx->mpool); +fail2: -+ pollqueue_delete(&ctx->pq); ++ pollqueue_unref(&ctx->pq); +fail1: + dmabufs_ctl_delete(&ctx->dbufs); +fail0: @@ -53625,10 +53883,10 @@ index 0000000000..415b6a27a0 + + diff --git a/libavdevice/Makefile b/libavdevice/Makefile -index 6ea62b914e..a336cbc596 100644 +index 0dfe47a1f4..ec7c7b4147 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile -@@ -46,6 +46,9 @@ OBJS-$(CONFIG_SNDIO_OUTDEV) += sndio_enc.o sndio.o +@@ -47,6 +47,9 @@ OBJS-$(CONFIG_SNDIO_OUTDEV) += sndio_enc.o sndio.o OBJS-$(CONFIG_V4L2_INDEV) += v4l2.o v4l2-common.o timefilter.o OBJS-$(CONFIG_V4L2_OUTDEV) += v4l2enc.o v4l2-common.o OBJS-$(CONFIG_VFWCAP_INDEV) += vfwcap.o @@ -53639,10 +53897,10 @@ index 6ea62b914e..a336cbc596 100644 OBJS-$(CONFIG_XV_OUTDEV) += xv.o diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c -index 8633433254..bc15112a00 100644 +index 92b27a1d14..19d2a9de55 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c -@@ -52,6 +52,9 @@ extern AVOutputFormat ff_sndio_muxer; +@@ -53,6 +53,9 @@ extern AVOutputFormat ff_sndio_muxer; extern AVInputFormat ff_v4l2_demuxer; extern AVOutputFormat ff_v4l2_muxer; extern AVInputFormat ff_vfwcap_demuxer; @@ -53654,10 +53912,10 @@ index 8633433254..bc15112a00 100644 diff --git a/libavdevice/drm_vout.c b/libavdevice/drm_vout.c new file mode 100644 -index 0000000000..d58b8fc7c8 +index 0000000000..064cbf6b08 --- /dev/null +++ b/libavdevice/drm_vout.c -@@ -0,0 +1,633 @@ +@@ -0,0 +1,643 @@ +/* + * Copyright (c) 2020 John Cox for Raspberry Pi Trading + * @@ -53714,6 +53972,7 @@ index 0000000000..d58b8fc7c8 + +typedef struct drm_aux_s { + unsigned int fb_handle; ++ uint32_t bo_handles[AV_DRM_MAX_PLANES]; + AVFrame * frame; +} drm_aux_t; + @@ -53827,6 +54086,13 @@ index 0000000000..d58b8fc7c8 + da->fb_handle = 0; + } + ++ for (unsigned int i = 0; i != AV_DRM_MAX_PLANES; ++i) { ++ if (da->bo_handles[i]) { ++ struct drm_gem_close gem_close = {.handle = da->bo_handles[i]}; ++ drmIoctl(de->drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close); ++ da->bo_handles[i] = 0; ++ } ++ } + av_frame_free(&da->frame); +} + @@ -53872,14 +54138,13 @@ index 0000000000..d58b8fc7c8 + uint32_t pitches[4] = {0}; + uint32_t offsets[4] = {0}; + uint64_t modifiers[4] = {0}; -+ uint32_t bo_object_handles[4] = {0}; + uint32_t bo_handles[4] = {0}; + int i, j, n; + + da->frame = frame; + + for (i = 0; i < desc->nb_objects; ++i) { -+ if (drmPrimeFDToHandle(de->drm_fd, desc->objects[i].fd, bo_object_handles + i) != 0) { ++ if (drmPrimeFDToHandle(de->drm_fd, desc->objects[i].fd, da->bo_handles + i) != 0) { + av_log(s, AV_LOG_WARNING, "drmPrimeFDToHandle[%d](%d) failed: %s\n", i, desc->objects[i].fd, ERRSTR); + return -1; + } @@ -53893,7 +54158,7 @@ index 0000000000..d58b8fc7c8 + pitches[n] = p->pitch; + offsets[n] = p->offset; + modifiers[n] = obj->format_modifier; -+ bo_handles[n] = bo_object_handles[p->object_index]; ++ bo_handles[n] = da->bo_handles[p->object_index]; + ++n; + } + } @@ -54249,6 +54514,9 @@ index 0000000000..d58b8fc7c8 + sem_destroy(&de->q_sem_in); + sem_destroy(&de->q_sem_out); + ++ for (unsigned int i = 0; i != AUX_SIZE; ++i) ++ da_uninit(de, de->aux + i); ++ + av_frame_free(&de->q_next); + + if (de->drm_fd >= 0) { @@ -55663,10 +55931,10 @@ index 0000000000..84723a34ad + .deinit = rpi_vout_deinit, +}; diff --git a/libavfilter/Makefile b/libavfilter/Makefile -index 5123540653..17ccea3150 100644 +index b2c254ea67..2ecd5b3c81 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile -@@ -434,6 +434,7 @@ OBJS-$(CONFIG_TRANSPOSE_OPENCL_FILTER) += vf_transpose_opencl.o opencl.o o +@@ -459,6 +459,7 @@ OBJS-$(CONFIG_TRANSPOSE_OPENCL_FILTER) += vf_transpose_opencl.o opencl.o o OBJS-$(CONFIG_TRANSPOSE_VAAPI_FILTER) += vf_transpose_vaapi.o vaapi_vpp.o OBJS-$(CONFIG_TRIM_FILTER) += trim.o OBJS-$(CONFIG_UNPREMULTIPLY_FILTER) += vf_premultiply.o framesync.o @@ -55675,10 +55943,10 @@ index 5123540653..17ccea3150 100644 OBJS-$(CONFIG_UNSHARP_OPENCL_FILTER) += vf_unsharp_opencl.o opencl.o \ opencl/unsharp.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c -index 1183e40267..2f569057dd 100644 +index 0872c6e0f2..c894cb8bbd 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c -@@ -414,6 +414,7 @@ extern AVFilter ff_vf_transpose_opencl; +@@ -438,6 +438,7 @@ extern AVFilter ff_vf_transpose_opencl; extern AVFilter ff_vf_transpose_vaapi; extern AVFilter ff_vf_trim; extern AVFilter ff_vf_unpremultiply; @@ -55687,7 +55955,7 @@ index 1183e40267..2f569057dd 100644 extern AVFilter ff_vf_unsharp_opencl; extern AVFilter ff_vf_untile; diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c -index 2fe4f0b0f9..5a8e6b3f24 100644 +index f6b572b3de..44fe8b679c 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -32,6 +32,9 @@ @@ -55700,8 +55968,8 @@ index 2fe4f0b0f9..5a8e6b3f24 100644 #define FF_INTERNAL_FIELDS 1 #include "framequeue.h" -@@ -429,6 +432,19 @@ static int can_merge_formats(AVFilterFormats *a_arg, - } +@@ -422,6 +425,19 @@ static int formats_declared(AVFilterContext *f) + return 1; } +#if CONFIG_UNSAND_FILTER @@ -55720,7 +55988,7 @@ index 2fe4f0b0f9..5a8e6b3f24 100644 /** * Perform one round of query_formats() and merging formats lists on the * filter graph. -@@ -469,6 +485,7 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) +@@ -462,6 +478,7 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) for (j = 0; j < filter->nb_inputs; j++) { AVFilterLink *link = filter->inputs[j]; int convert_needed = 0; @@ -55728,8 +55996,8 @@ index 2fe4f0b0f9..5a8e6b3f24 100644 if (!link) continue; -@@ -516,11 +533,14 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) - ) +@@ -504,11 +521,14 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) + link->outcfg.formats, link->type) #undef MERGE_DISPATCH - if (convert_needed) { @@ -55744,7 +56012,7 @@ index 2fe4f0b0f9..5a8e6b3f24 100644 if (graph->disable_auto_convert) { av_log(log_ctx, AV_LOG_ERROR, -@@ -533,19 +553,45 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) +@@ -521,19 +541,45 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) /* couldn't merge format lists. auto-insert conversion filter */ switch (link->type) { case AVMEDIA_TYPE_VIDEO: @@ -55760,7 +56028,7 @@ index 2fe4f0b0f9..5a8e6b3f24 100644 + // Only try each extra conversion once + // The unsand output pad should never trigger has_sand_format + // but it is better to be safe -+ if ((extra_convert_tried & 1) == 0 && has_sand_format(link->in_formats)) { ++ if ((extra_convert_tried & 1) == 0 && has_sand_format(link->incfg.formats)) { + if (!(filter = avfilter_get_by_name("unsand"))) { + av_log(log_ctx, AV_LOG_ERROR, "'unsand' filter " + "not present, cannot convert pixel formats.\n"); @@ -55802,33 +56070,25 @@ index 2fe4f0b0f9..5a8e6b3f24 100644 break; case AVMEDIA_TYPE_AUDIO: if (!(filter = avfilter_get_by_name("aresample"))) { -@@ -587,9 +633,19 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) - av_assert0(outlink-> in_channel_layouts->refcount > 0); - av_assert0(outlink->out_channel_layouts->refcount > 0); - } -- if (!ff_merge_formats( inlink->in_formats, inlink->out_formats, inlink->type) || -- !ff_merge_formats(outlink->in_formats, outlink->out_formats, outlink->type)) -+ // If we have added an extra filter we must merge the input -+ // side but we can have another go at the output -+ if (!ff_merge_formats( inlink->in_formats, inlink->out_formats, inlink->type)) -+ ret = AVERROR(ENOSYS); -+ else if (!ff_merge_formats(outlink->in_formats, outlink->out_formats, outlink->type)) -+ { -+ if (can_retry) { +@@ -589,6 +635,13 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) + outlink->outcfg.samplerates) || + CHECKED_MERGE(channel_layouts, outlink->incfg.channel_layouts, + outlink->outcfg.channel_layouts))) { ++ // Try adding an unsand filter & see if that helps ++ if (ret < 0 && can_retry) { + link = outlink; + convert_needed = 1; + continue; + } - ret = AVERROR(ENOSYS); -+ } - if (inlink->type == AVMEDIA_TYPE_AUDIO && - (!ff_merge_samplerates(inlink->in_samplerates, - inlink->out_samplerates) || ++ + if (ret < 0) + return ret; + av_log(log_ctx, AV_LOG_ERROR, diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c -index bf30f54177..eb5dfa22f8 100644 +index da1cf9941e..c588ed23cb 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c -@@ -210,7 +210,7 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx, +@@ -188,7 +188,7 @@ int attribute_align_arg av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFra switch (ctx->outputs[0]->type) { case AVMEDIA_TYPE_VIDEO: @@ -55839,10 +56099,10 @@ index bf30f54177..eb5dfa22f8 100644 case AVMEDIA_TYPE_AUDIO: diff --git a/libavfilter/vf_unsand.c b/libavfilter/vf_unsand.c new file mode 100644 -index 0000000000..fbea56dd09 +index 0000000000..61c03a385c --- /dev/null +++ b/libavfilter/vf_unsand.c -@@ -0,0 +1,234 @@ +@@ -0,0 +1,229 @@ +/* + * Copyright (c) 2007 Bobby Bingham + * @@ -55956,26 +56216,21 @@ index 0000000000..fbea56dd09 + if (ctx->inputs[0] == NULL || ctx->outputs[0] == NULL) + return 0; + -+// printf("Unsand: %s in: ", __func__); -+// dump_fmts(ctx->inputs[0]->in_formats); -+// printf("Unsand: %s out: ", __func__); -+// dump_fmts(ctx->outputs[0]->out_formats); -+ + // Our output formats depend on our input formats and we can't/don't + // want to convert between bit depths so we need to wait for the source + // to have an opinion before we do -+ if (ctx->inputs[0]->in_formats == NULL) ++ if (ctx->inputs[0]->incfg.formats == NULL) + return AVERROR(EAGAIN); + + // Accept anything -+ if (ctx->inputs[0]->out_formats == NULL && -+ (ret = ff_formats_ref(ctx->inputs[0]->in_formats, &ctx->inputs[0]->out_formats)) < 0) ++ if (ctx->inputs[0]->outcfg.formats == NULL && ++ (ret = ff_formats_ref(ctx->inputs[0]->incfg.formats, &ctx->inputs[0]->outcfg.formats)) < 0) + return ret; + + // Filter out sand formats + + // Generate a container if we don't already have one -+ if (ctx->outputs[0]->in_formats == NULL) ++ if (ctx->outputs[0]->incfg.formats == NULL) + { + // Somewhat rubbish way of ensuring we have a good structure + const static enum AVPixelFormat out_fmts[] = {AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}; @@ -55983,15 +56238,15 @@ index 0000000000..fbea56dd09 + + if (formats == NULL) + return AVERROR(ENOMEM); -+ if ((ret = ff_formats_ref(formats, &ctx->outputs[0]->in_formats)) < 0) ++ if ((ret = ff_formats_ref(formats, &ctx->outputs[0]->incfg.formats)) < 0) + return ret; + } + + // Replace old format list with new filtered list derived from what our + // input says it can do + { -+ const AVFilterFormats * const src_ff = ctx->inputs[0]->out_formats; -+ AVFilterFormats * const dst_ff = ctx->outputs[0]->in_formats; ++ const AVFilterFormats * const src_ff = ctx->inputs[0]->outcfg.formats; ++ AVFilterFormats * const dst_ff = ctx->outputs[0]->incfg.formats; + enum AVPixelFormat *dst_fmts = av_malloc(sizeof(enum AVPixelFormat) * src_ff->nb_formats); + int i; + int n = 0; @@ -56030,7 +56285,7 @@ index 0000000000..fbea56dd09 + } + +// printf("Unsand: %s calc: ", __func__); -+// dump_fmts(ctx->outputs[0]->in_formats); ++// dump_fmts(ctx->outputs[0]->incfg.formats); + + return 0; +} @@ -56078,10 +56333,10 @@ index 0000000000..fbea56dd09 +}; + diff --git a/libavformat/utils.c b/libavformat/utils.c -index 7185fbfd71..c7b0553903 100644 +index 1384b56771..27479e3c40 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c -@@ -3048,6 +3048,40 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr) +@@ -3011,6 +3011,40 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr) return 1; } @@ -56122,8 +56377,8 @@ index 7185fbfd71..c7b0553903 100644 /* returns 1 or 0 if or if not decoded data was returned, or a negative error */ static int try_decode_frame(AVFormatContext *s, AVStream *st, const AVPacket *avpkt, AVDictionary **options) -@@ -3082,7 +3116,11 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, - av_dict_set(options ? options : &thread_opt, "threads", "1", 0); +@@ -3049,7 +3083,11 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, + av_dict_set(options ? options : &thread_opt, "lowres", "0", 0); if (s->codec_whitelist) av_dict_set(options ? options : &thread_opt, "codec_whitelist", s->codec_whitelist, 0); - ret = avcodec_open2(avctx, codec, options ? options : &thread_opt); @@ -56135,7 +56390,7 @@ index 7185fbfd71..c7b0553903 100644 if (!options) av_dict_free(&thread_opt); if (ret < 0) { -@@ -3113,6 +3151,14 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, +@@ -3080,6 +3118,14 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, if (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO) { ret = avcodec_send_packet(avctx, &pkt); @@ -56150,9 +56405,9 @@ index 7185fbfd71..c7b0553903 100644 if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) break; if (ret >= 0) -@@ -3723,9 +3769,20 @@ FF_ENABLE_DEPRECATION_WARNINGS +@@ -3708,9 +3754,20 @@ FF_ENABLE_DEPRECATION_WARNINGS // Try to just open decoders, in case this is enough to get parameters. - if (!has_codec_parameters(st, NULL) && st->request_probe <= 0) { + if (!has_codec_parameters(st, NULL) && st->internal->request_probe <= 0) { if (codec && !avctx->codec) - if (avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt) < 0) - av_log(ic, AV_LOG_WARNING, @@ -56175,7 +56430,7 @@ index 7185fbfd71..c7b0553903 100644 if (!options) av_dict_free(&thread_opt); diff --git a/libavutil/Makefile b/libavutil/Makefile -index 9b08372eb2..c965c2dc85 100644 +index 27bafe9e12..c9075ddf8a 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -68,6 +68,7 @@ HEADERS = adler32.h \ @@ -56186,15 +56441,15 @@ index 9b08372eb2..c965c2dc85 100644 samplefmt.h \ sha.h \ sha512.h \ -@@ -86,6 +87,7 @@ HEADERS = adler32.h \ - tx.h \ +@@ -87,6 +88,7 @@ HEADERS = adler32.h \ + film_grain_params.h \ HEADERS-$(CONFIG_LZO) += lzo.h +HEADERS-$(CONFIG-RPI) += rpi_sand_fn_pw.h ARCH_HEADERS = bswap.h \ intmath.h \ -@@ -180,6 +182,7 @@ OBJS-$(CONFIG_LZO) += lzo.o +@@ -182,6 +184,7 @@ OBJS-$(CONFIG_LZO) += lzo.o OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o OBJS-$(CONFIG_QSV) += hwcontext_qsv.o @@ -57846,7 +58101,7 @@ index 0000000000..447f367bea +#endif // AVUTIL_ARM_SAND_NEON_H + diff --git a/libavutil/frame.c b/libavutil/frame.c -index 2e952edd29..96e8bf5b3e 100644 +index 75e347bf2f..daa6477485 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -16,6 +16,8 @@ @@ -57868,7 +58123,7 @@ index 2e952edd29..96e8bf5b3e 100644 #if FF_API_FRAME_GET_SET MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp) -@@ -902,6 +907,12 @@ int av_frame_apply_cropping(AVFrame *frame, int flags) +@@ -903,6 +908,12 @@ int av_frame_apply_cropping(AVFrame *frame, int flags) (frame->crop_top + frame->crop_bottom) >= frame->height) return AVERROR(ERANGE); @@ -57882,10 +58137,10 @@ index 2e952edd29..96e8bf5b3e 100644 if (!desc) return AVERROR_BUG; diff --git a/libavutil/frame.h b/libavutil/frame.h -index fc67db0f6c..b1a7eb4858 100644 +index 7d1f8e2935..a4e7dc915d 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h -@@ -968,6 +968,16 @@ int av_frame_apply_cropping(AVFrame *frame, int flags); +@@ -990,6 +990,16 @@ int av_frame_apply_cropping(AVFrame *frame, int flags); */ const char *av_frame_side_data_name(enum AVFrameSideDataType type); @@ -57903,116 +58158,58 @@ index fc67db0f6c..b1a7eb4858 100644 * @} */ diff --git a/libavutil/hwcontext_drm.c b/libavutil/hwcontext_drm.c -index 32cbde82eb..c5d0b960af 100644 +index 7a9fdbd263..2a498f9b50 100644 --- a/libavutil/hwcontext_drm.c +++ b/libavutil/hwcontext_drm.c -@@ -19,8 +19,10 @@ +@@ -21,6 +21,7 @@ #include #include #include +#include + /* This was introduced in version 4.6. And may not exist all without an + * optional package. So to prevent a hard dependency on needing the Linux +@@ -31,6 +32,7 @@ + #endif + #include +#include #include #include "avassert.h" -@@ -28,6 +30,11 @@ +@@ -38,7 +40,9 @@ #include "hwcontext_drm.h" #include "hwcontext_internal.h" #include "imgutils.h" +- ++#if CONFIG_SAND +#include "libavutil/rpi_sand_fns.h" -+ -+#include -+#include -+#include - ++#endif static void drm_device_free(AVHWDeviceContext *hwdev) -@@ -43,6 +50,11 @@ static int drm_device_create(AVHWDeviceContext *hwdev, const char *device, + { +@@ -53,6 +57,11 @@ static int drm_device_create(AVHWDeviceContext *hwdev, const char *device, AVDRMDeviceContext *hwctx = hwdev->hwctx; drmVersionPtr version; + if (device == NULL) { -+ hwctx->fd = -1; -+ return 0; ++ hwctx->fd = -1; ++ return 0; + } + hwctx->fd = open(device, O_RDWR); if (hwctx->fd < 0) return AVERROR(errno); -@@ -85,18 +97,37 @@ static int drm_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame) - typedef struct DRMMapping { - // Address and length of each mmap()ed region. - int nb_regions; -+ unsigned int dmaflags; - void *address[AV_DRM_MAX_PLANES]; - size_t length[AV_DRM_MAX_PLANES]; -+ int fds[AV_DRM_MAX_PLANES]; - } DRMMapping; - -+static int dmasync(const int fd, const unsigned int flags) -+{ -+ struct dma_buf_sync sync = { -+ .flags = flags -+ }; -+ while (ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync) == -1) { -+ const int err = errno; -+ if (errno == EINTR) -+ continue; -+ av_log(NULL, AV_LOG_WARNING, "%s: ioctl failed: flags=%#x\n", __func__, flags); -+ return -err; -+ } -+ return 0; -+} -+ - static void drm_unmap_frame(AVHWFramesContext *hwfc, - HWMapDescriptor *hwmap) - { - DRMMapping *map = hwmap->priv; - int i; - -- for (i = 0; i < map->nb_regions; i++) -+ for (i = 0; i < map->nb_regions; i++) { - munmap(map->address[i], map->length[i]); -+ dmasync(map->fds[i], DMA_BUF_SYNC_END | map->dmaflags); -+ } - - av_free(map); - } -@@ -114,15 +145,28 @@ static int drm_map_frame(AVHWFramesContext *hwfc, - if (!map) - return AVERROR(ENOMEM); - -+ for (i = 0; i < AV_DRM_MAX_PLANES; i++) -+ map->fds[i] = -1; -+ - mmap_prot = 0; -- if (flags & AV_HWFRAME_MAP_READ) -+ if (flags & AV_HWFRAME_MAP_READ) { -+ map->dmaflags |= DMA_BUF_SYNC_READ; - mmap_prot |= PROT_READ; -- if (flags & AV_HWFRAME_MAP_WRITE) -+ } -+ if (flags & AV_HWFRAME_MAP_WRITE) { -+ map->dmaflags |= DMA_BUF_SYNC_WRITE; +@@ -139,6 +148,8 @@ static int drm_map_frame(AVHWFramesContext *hwfc, + if (flags & AV_HWFRAME_MAP_WRITE) mmap_prot |= PROT_WRITE; -+ } -+ + + if (dst->format == AV_PIX_FMT_NONE) + dst->format = hwfc->sw_format; - - av_assert0(desc->nb_objects <= AV_DRM_MAX_PLANES); - for (i = 0; i < desc->nb_objects; i++) { -- addr = mmap(NULL, desc->objects[i].size, mmap_prot, MAP_SHARED, -+ dmasync(desc->objects[i].fd, DMA_BUF_SYNC_START | map->dmaflags); -+ map->fds[i] = desc->objects[i].fd; -+ -+ addr = mmap(NULL, desc->objects[i].size, mmap_prot, MAP_SHARED | MAP_POPULATE, - desc->objects[i].fd, 0); - if (addr == MAP_FAILED) { - err = AVERROR(errno); -@@ -151,6 +195,23 @@ static int drm_map_frame(AVHWFramesContext *hwfc, + #if HAVE_LINUX_DMA_BUF_H + if (flags & AV_HWFRAME_MAP_READ) + map->sync_flags |= DMA_BUF_SYNC_READ; +@@ -185,6 +196,23 @@ static int drm_map_frame(AVHWFramesContext *hwfc, dst->width = src->width; dst->height = src->height; @@ -58036,18 +58233,7 @@ index 32cbde82eb..c5d0b960af 100644 err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, &drm_unmap_frame, map); -@@ -160,7 +221,9 @@ static int drm_map_frame(AVHWFramesContext *hwfc, - return 0; - - fail: -- for (i = 0; i < desc->nb_objects; i++) { -+ for (i = 0; i < AV_DRM_MAX_PLANES; i++) { -+ if (map->fds[i] != -1) -+ dmasync(map->fds[i], DMA_BUF_SYNC_END | map->dmaflags); - if (map->address[i]) - munmap(map->address[i], map->length[i]); - } -@@ -178,7 +241,15 @@ static int drm_transfer_get_formats(AVHWFramesContext *ctx, +@@ -212,7 +240,15 @@ static int drm_transfer_get_formats(AVHWFramesContext *ctx, if (!pix_fmts) return AVERROR(ENOMEM); @@ -58064,7 +58250,7 @@ index 32cbde82eb..c5d0b960af 100644 pix_fmts[1] = AV_PIX_FMT_NONE; *formats = pix_fmts; -@@ -197,18 +268,80 @@ static int drm_transfer_data_from(AVHWFramesContext *hwfc, +@@ -231,18 +267,80 @@ static int drm_transfer_data_from(AVHWFramesContext *hwfc, map = av_frame_alloc(); if (!map) return AVERROR(ENOMEM); @@ -58080,7 +58266,7 @@ index 32cbde82eb..c5d0b960af 100644 - map->height = dst->height; +#if 0 + av_log(hwfc, AV_LOG_INFO, "%s: src fmt=%d (%d), dst fmt=%d (%d) s=%dx%d l=%d/%d/%d/%d, d=%dx%d l=%d/%d/%d\n", __func__, -+ map->hwfc_format, AV_PIX_FMT_RPI4_8, dst->format, AV_PIX_FMT_YUV420P10LE, ++ hwfc->sw_format, AV_PIX_FMT_RPI4_8, dst->format, AV_PIX_FMT_YUV420P10LE, + map->width, map->height, + map->linesize[0], + map->linesize[1], @@ -58149,7 +58335,7 @@ index 32cbde82eb..c5d0b960af 100644 err = 0; fail: -@@ -223,7 +356,10 @@ static int drm_transfer_data_to(AVHWFramesContext *hwfc, +@@ -257,7 +355,10 @@ static int drm_transfer_data_to(AVHWFramesContext *hwfc, int err; if (src->width > hwfc->width || src->height > hwfc->height) @@ -58161,10 +58347,10 @@ index 32cbde82eb..c5d0b960af 100644 map = av_frame_alloc(); if (!map) diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c -index 9d61c52567..1cda09f53c 100644 +index 18c7a0efc8..15eafb4c54 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c -@@ -2371,6 +2371,38 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { +@@ -2395,6 +2395,38 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .name = "vulkan", .flags = AV_PIX_FMT_FLAG_HWACCEL, }, @@ -58204,7 +58390,7 @@ index 9d61c52567..1cda09f53c 100644 #if FF_API_PLUS1_MINUS1 FF_ENABLE_DEPRECATION_WARNINGS diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h -index 1c625cfc8a..e7f543b797 100644 +index 46ef211add..84b7c9dd88 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -357,6 +357,12 @@ enum AVPixelFormat { @@ -58218,8 +58404,8 @@ index 1c625cfc8a..e7f543b797 100644 + AV_PIX_FMT_RPI4_8, + AV_PIX_FMT_RPI4_10, - 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 - }; + AV_PIX_FMT_X2RGB10LE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_X2RGB10BE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined diff --git a/libavutil/rpi_sand_fn_pw.h b/libavutil/rpi_sand_fn_pw.h new file mode 100644 index 0000000000..0d5d203dc3 @@ -59788,10 +59974,10 @@ index 0000000000..fc14f2a3c2 +1,WPP_F_ericsson_MAIN_2,WPP_F_ericsson_MAIN_2.bit,WPP_F_ericsson_MAIN_2_yuv.md5 diff --git a/pi-util/conf_native.sh b/pi-util/conf_native.sh new file mode 100755 -index 0000000000..d5240ff388 +index 0000000000..13fae3cf78 --- /dev/null +++ b/pi-util/conf_native.sh -@@ -0,0 +1,76 @@ +@@ -0,0 +1,77 @@ +echo "Configure for native build" + +FFSRC=`pwd` @@ -59823,15 +60009,16 @@ index 0000000000..d5240ff388 + RPIOPTS="--enable-mmal --enable-rpi" +fi +C=`lsb_release -sc` ++V=`cat RELEASE` + +SHARED_LIBS="--enable-shared" +if [ "$1" == "--noshared" ]; then + SHARED_LIBS="--disable-shared" -+ OUT=out/$B-$C-static-rel ++ OUT=out/$B-$C-$V-static-rel + echo Static libs +else + echo Shared libs -+ OUT=out/$B-$C-shared-rel ++ OUT=out/$B-$C-$V-shared-rel +fi + +USR_PREFIX=$FFSRC/$OUT/install