From c1fd8cdbe6bd6ff5f6fb41292131fc68d256211f Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Tue, 21 Mar 2023 17:46:17 +0100 Subject: [PATCH] kodi (RPi): add patches to support arbitrary pixel formats Signed-off-by: Matthias Reichl --- ...DRMPRIME-Also-support-YUV420-buffers.patch | 4 +- ...et-max-bpc-for-high-bit-depth-videos.patch | 4 +- ...eDRMPRIME-add-colourspace-connector-.patch | 4 +- ...MPRIME-Adjust-av-formats-to-match-re.patch | 4 +- ...PRIME-Support-YUV422-and-YUV444-form.patch | 93 +++++ ...A-Support-exporting-YCbCr444-buffers.patch | 55 +++ ...PRIME-Add-support-for-arbitrary-outp.patch | 332 ++++++++++++++++++ 7 files changed, 488 insertions(+), 8 deletions(-) create mode 100644 projects/RPi/patches/kodi/0005-DVDVideoCodecDRMPRIME-Support-YUV422-and-YUV444-form.patch create mode 100644 projects/RPi/patches/kodi/0006-VideoBufferDMA-Support-exporting-YCbCr444-buffers.patch create mode 100644 projects/RPi/patches/kodi/0007-DVDVideoCodecDRMPRIME-Add-support-for-arbitrary-outp.patch diff --git a/projects/RPi/patches/kodi/0001-CDVDVideoCodecDRMPRIME-Also-support-YUV420-buffers.patch b/projects/RPi/patches/kodi/0001-CDVDVideoCodecDRMPRIME-Also-support-YUV420-buffers.patch index 0f2c93f4c2..c4b3d66cb3 100644 --- a/projects/RPi/patches/kodi/0001-CDVDVideoCodecDRMPRIME-Also-support-YUV420-buffers.patch +++ b/projects/RPi/patches/kodi/0001-CDVDVideoCodecDRMPRIME-Also-support-YUV420-buffers.patch @@ -1,7 +1,7 @@ From 97d39a46091b65e4355ce7e545bdec46ff2f87de Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 11 Sep 2021 14:03:05 +0100 -Subject: [PATCH 1/4] CDVDVideoCodecDRMPRIME: Also support YUV420 buffers +Subject: [PATCH 1/7] CDVDVideoCodecDRMPRIME: Also support YUV420 buffers CDVDVideoCodecDRMPRIME: Add support for deinterlace of sw decoded buffers @@ -50,5 +50,5 @@ index 20a5c24f53..a36107c515 100644 if (ret < 0) { -- -2.39.0 +2.39.2 diff --git a/projects/RPi/patches/kodi/0002-gbm-Set-max-bpc-for-high-bit-depth-videos.patch b/projects/RPi/patches/kodi/0002-gbm-Set-max-bpc-for-high-bit-depth-videos.patch index b0abba97ed..6e4b0e8da5 100644 --- a/projects/RPi/patches/kodi/0002-gbm-Set-max-bpc-for-high-bit-depth-videos.patch +++ b/projects/RPi/patches/kodi/0002-gbm-Set-max-bpc-for-high-bit-depth-videos.patch @@ -1,7 +1,7 @@ From 42b30508bfe5451d4dc2884acfde9e0ec2d58c92 Mon Sep 17 00:00:00 2001 From: Dom Cobley Date: Fri, 3 Dec 2021 16:00:50 +0000 -Subject: [PATCH 2/4] gbm: Set max bpc for high bit depth videos +Subject: [PATCH 2/7] gbm: Set max bpc for high bit depth videos --- .../HwDecRender/VideoLayerBridgeDRMPRIME.cpp | 16 ++++++++++++++++ @@ -42,5 +42,5 @@ index 4b8ee5afbb..bd6623e8d1 100644 void CVideoLayerBridgeDRMPRIME::SetVideoPlane(CVideoBufferDRMPRIME* buffer, const CRect& destRect) -- -2.39.0 +2.39.2 diff --git a/projects/RPi/patches/kodi/0003-CVideoLayerBridgeDRMPRIME-add-colourspace-connector-.patch b/projects/RPi/patches/kodi/0003-CVideoLayerBridgeDRMPRIME-add-colourspace-connector-.patch index 7fe34c3654..12b7d57cf4 100644 --- a/projects/RPi/patches/kodi/0003-CVideoLayerBridgeDRMPRIME-add-colourspace-connector-.patch +++ b/projects/RPi/patches/kodi/0003-CVideoLayerBridgeDRMPRIME-add-colourspace-connector-.patch @@ -1,7 +1,7 @@ From 0b9b204c6560f3aff39697f92616b48102840dfe Mon Sep 17 00:00:00 2001 From: Lukas Rusak Date: Mon, 29 Apr 2019 18:48:45 -0700 -Subject: [PATCH 3/4] CVideoLayerBridgeDRMPRIME add colourspace connector +Subject: [PATCH 3/7] CVideoLayerBridgeDRMPRIME add colourspace connector property --- @@ -83,5 +83,5 @@ index bd6623e8d1..a1342595c6 100644 void CVideoLayerBridgeDRMPRIME::SetVideoPlane(CVideoBufferDRMPRIME* buffer, const CRect& destRect) -- -2.39.0 +2.39.2 diff --git a/projects/RPi/patches/kodi/0004-CDVDVideoCodecDRMPRIME-Adjust-av-formats-to-match-re.patch b/projects/RPi/patches/kodi/0004-CDVDVideoCodecDRMPRIME-Adjust-av-formats-to-match-re.patch index 94e221e1a6..c996f21873 100644 --- a/projects/RPi/patches/kodi/0004-CDVDVideoCodecDRMPRIME-Adjust-av-formats-to-match-re.patch +++ b/projects/RPi/patches/kodi/0004-CDVDVideoCodecDRMPRIME-Adjust-av-formats-to-match-re.patch @@ -1,7 +1,7 @@ From 518d8487d090af854fb72a7d0e5efc075d97228c Mon Sep 17 00:00:00 2001 From: Dom Cobley Date: Wed, 18 Jan 2023 16:41:00 +0000 -Subject: [PATCH 4/4] CDVDVideoCodecDRMPRIME: Adjust av formats to match recent +Subject: [PATCH 4/7] CDVDVideoCodecDRMPRIME: Adjust av formats to match recent ffmpeg changes --- @@ -45,5 +45,5 @@ index a36107c515..d5b3289680 100644 if (ret < 0) { -- -2.39.0 +2.39.2 diff --git a/projects/RPi/patches/kodi/0005-DVDVideoCodecDRMPRIME-Support-YUV422-and-YUV444-form.patch b/projects/RPi/patches/kodi/0005-DVDVideoCodecDRMPRIME-Support-YUV422-and-YUV444-form.patch new file mode 100644 index 0000000000..b36915dbd4 --- /dev/null +++ b/projects/RPi/patches/kodi/0005-DVDVideoCodecDRMPRIME-Support-YUV422-and-YUV444-form.patch @@ -0,0 +1,93 @@ +From a11461db2d442e0648ebb9255a2399a647d8f5be Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Wed, 25 Jan 2023 18:42:24 +0000 +Subject: [PATCH 5/7] DVDVideoCodecDRMPRIME: Support YUV422 and YUV444 formats + +See: https://github.com/xbmc/xbmc/issues/20017 + +We currently can't play YUV422 and YUV444 videos with drm +but they can be made to work with straightforward plumbing +--- + .../Buffers/VideoBufferPoolDMA.cpp | 6 +++++ + .../DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp | 27 +++++++++++++++---- + 2 files changed, 28 insertions(+), 5 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/Buffers/VideoBufferPoolDMA.cpp b/xbmc/cores/VideoPlayer/Buffers/VideoBufferPoolDMA.cpp +index fb2dfc6c78..e6b071117e 100644 +--- a/xbmc/cores/VideoPlayer/Buffers/VideoBufferPoolDMA.cpp ++++ b/xbmc/cores/VideoPlayer/Buffers/VideoBufferPoolDMA.cpp +@@ -123,6 +123,12 @@ uint32_t CVideoBufferPoolDMA::TranslateFormat(AVPixelFormat format) + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUVJ420P: + return DRM_FORMAT_YUV420; ++ case AV_PIX_FMT_YUV422P: ++ case AV_PIX_FMT_YUVJ422P: ++ return DRM_FORMAT_YUV422; ++ case AV_PIX_FMT_YUV444P: ++ case AV_PIX_FMT_YUVJ444P: ++ return DRM_FORMAT_YUV444; + default: + return 0; + } +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp +index d5b3289680..4af903ecf5 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp +@@ -142,7 +142,8 @@ static bool IsSupportedHwFormat(const enum AVPixelFormat fmt) + + static bool IsSupportedSwFormat(const enum AVPixelFormat fmt) + { +- return fmt == AV_PIX_FMT_YUV420P || fmt == AV_PIX_FMT_YUVJ420P; ++ return fmt == AV_PIX_FMT_YUV420P || fmt == AV_PIX_FMT_YUVJ420P || fmt == AV_PIX_FMT_YUV422P || ++ fmt == AV_PIX_FMT_YUVJ422P || fmt == AV_PIX_FMT_YUV444P || fmt == AV_PIX_FMT_YUVJ444P; + } + + static const AVCodecHWConfig* FindHWConfig(const AVCodec* codec) +@@ -206,7 +207,14 @@ enum AVPixelFormat CDVDVideoCodecDRMPRIME::GetFormat(struct AVCodecContext* avct + } + } + +- CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - unsupported pixel format", __FUNCTION__); ++ std::vector formats; ++ for (int n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) ++ { ++ formats.emplace_back(av_get_pix_fmt_name(fmt[n])); ++ } ++ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - no supported pixel formats: {}", __FUNCTION__, ++ StringUtils::Join(formats, ", ")); ++ + return AV_PIX_FMT_NONE; + } + +@@ -226,6 +234,14 @@ int CDVDVideoCodecDRMPRIME::GetBuffer(struct AVCodecContext* avctx, AVFrame* fra + case AV_PIX_FMT_YUVJ420P: + size = width * height * 3 / 2; + break; ++ case AV_PIX_FMT_YUV422P: ++ case AV_PIX_FMT_YUVJ422P: ++ size = width * height * 2; ++ break; ++ case AV_PIX_FMT_YUV444P: ++ case AV_PIX_FMT_YUVJ444P: ++ size = width * height * 3; ++ break; + default: + return -1; + } +@@ -512,9 +528,10 @@ bool CDVDVideoCodecDRMPRIME::SetPictureParams(VideoPicture* pVideoPicture) + (static_cast(lrint(pVideoPicture->iWidth / aspect_ratio))) & -3; + } + +- pVideoPicture->color_range = m_pFrame->color_range == AVCOL_RANGE_JPEG || +- m_pFrame->format == AV_PIX_FMT_YUVJ420P || +- m_hints.colorRange == AVCOL_RANGE_JPEG; ++ pVideoPicture->color_range = ++ m_pFrame->color_range == AVCOL_RANGE_JPEG || m_pFrame->format == AV_PIX_FMT_YUVJ420P || ++ m_pFrame->format == AV_PIX_FMT_YUVJ422P || m_pFrame->format == AV_PIX_FMT_YUVJ444P || ++ m_hints.colorRange == AVCOL_RANGE_JPEG; + pVideoPicture->color_primaries = m_pFrame->color_primaries == AVCOL_PRI_UNSPECIFIED + ? m_hints.colorPrimaries + : m_pFrame->color_primaries; +-- +2.39.2 + diff --git a/projects/RPi/patches/kodi/0006-VideoBufferDMA-Support-exporting-YCbCr444-buffers.patch b/projects/RPi/patches/kodi/0006-VideoBufferDMA-Support-exporting-YCbCr444-buffers.patch new file mode 100644 index 0000000000..a76667adef --- /dev/null +++ b/projects/RPi/patches/kodi/0006-VideoBufferDMA-Support-exporting-YCbCr444-buffers.patch @@ -0,0 +1,55 @@ +From 7b820fa6812e8389613238c6ab3a12fc1dee0276 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Tue, 31 Jan 2023 14:13:00 +0000 +Subject: [PATCH 6/7] VideoBufferDMA: Support exporting YCbCr444 buffers + +The current code assumes chroma is decimated by two, but that is not necessarily the case. +DRMPRIME decode with EGL rendering of YCbCr444 video will have corrupted colours. + +Ask ffmpeg what the chroma decimation is. +--- + .../VideoPlayer/Buffers/VideoBufferDMA.cpp | 21 ++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/Buffers/VideoBufferDMA.cpp b/xbmc/cores/VideoPlayer/Buffers/VideoBufferDMA.cpp +index 2dd7c1341d..3e6bf0dc7a 100644 +--- a/xbmc/cores/VideoPlayer/Buffers/VideoBufferDMA.cpp ++++ b/xbmc/cores/VideoPlayer/Buffers/VideoBufferDMA.cpp +@@ -119,20 +119,27 @@ bool CVideoBufferDMA::Alloc() + + void CVideoBufferDMA::Export(AVFrame* frame, uint32_t width, uint32_t height) + { +- m_planes = av_pix_fmt_count_planes(static_cast(frame->format)); ++ AVPixelFormat pix_fmt = static_cast(frame->format); ++ m_planes = av_pix_fmt_count_planes(pix_fmt); ++ int h_shift; ++ int v_shift; + +- if (m_planes < 2) +- throw std::runtime_error( +- "non-planar formats not supported: " + +- std::string(av_get_pix_fmt_name(static_cast(frame->format)))); ++ if (av_pix_fmt_get_chroma_sub_sample(pix_fmt, &h_shift, &v_shift)) ++ throw std::runtime_error("unable to determine chroma_sub_sample: " + ++ std::string(av_get_pix_fmt_name(pix_fmt))); ++ ++ if (m_planes < 2 || m_planes > 3) ++ throw std::runtime_error("only 2 or 3 plane formats supported: " + ++ std::string(av_get_pix_fmt_name(pix_fmt))); + + for (uint32_t plane = 0; plane < m_planes; plane++) + { + m_strides[plane] = + av_image_get_linesize(static_cast(frame->format), width, plane); +- m_offsets[plane] = +- plane == 0 ? 0 : (m_offsets[plane - 1] + m_strides[plane - 1] * (height >> (plane - 1))); + } ++ m_offsets[0] = 0; ++ m_offsets[1] = m_strides[0] * height; ++ m_offsets[2] = m_offsets[1] + (m_strides[1] * height >> v_shift); + + if (CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) + { +-- +2.39.2 + diff --git a/projects/RPi/patches/kodi/0007-DVDVideoCodecDRMPRIME-Add-support-for-arbitrary-outp.patch b/projects/RPi/patches/kodi/0007-DVDVideoCodecDRMPRIME-Add-support-for-arbitrary-outp.patch new file mode 100644 index 0000000000..219c7f5974 --- /dev/null +++ b/projects/RPi/patches/kodi/0007-DVDVideoCodecDRMPRIME-Add-support-for-arbitrary-outp.patch @@ -0,0 +1,332 @@ +From ae91030c1a84693fd0d34b919f9f8434b08e00c9 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Mon, 6 Feb 2023 15:19:51 +0000 +Subject: [PATCH 7/7] DVDVideoCodecDRMPRIME: Add support for arbitrary output + pixel formats + +This enables any ffmpeg pixel formats to be supported by DRMPRIME decoder +by creating a scale ffmpeg filter to convert it to a supported format. + +This allows formats like h264 Hi10P and hevc 12-bit 444 to be software decoded, +converted and displayed through DRM. + +This will be a cheaper path than disabling DRMPRIME, which is also +software decode, convert, but then needs convert to texture and display through GL. + +And it happens automatically without requiring user video settings +--- + .../DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp | 124 +++++++++++------- + .../DVDCodecs/Video/DVDVideoCodecDRMPRIME.h | 3 +- + 2 files changed, 77 insertions(+), 50 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp +index 4af903ecf5..92a182608d 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp +@@ -199,7 +199,7 @@ enum AVPixelFormat CDVDVideoCodecDRMPRIME::GetFormat(struct AVCodecContext* avct + { + for (int n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) + { +- if (IsSupportedHwFormat(fmt[n]) || IsSupportedSwFormat(fmt[n])) ++ //if (IsSupportedHwFormat(fmt[n]) || IsSupportedSwFormat(fmt[n])) + { + CDVDVideoCodecDRMPRIME* ctx = static_cast(avctx->opaque); + ctx->UpdateProcessInfo(avctx, fmt[n]); +@@ -220,7 +220,8 @@ enum AVPixelFormat CDVDVideoCodecDRMPRIME::GetFormat(struct AVCodecContext* avct + + int CDVDVideoCodecDRMPRIME::GetBuffer(struct AVCodecContext* avctx, AVFrame* frame, int flags) + { +- if (IsSupportedSwFormat(static_cast(frame->format))) ++ AVPixelFormat pix_fmt = static_cast(frame->format); ++ if (IsSupportedSwFormat(pix_fmt)) + { + int width = frame->width; + int height = frame->height; +@@ -228,7 +229,7 @@ int CDVDVideoCodecDRMPRIME::GetBuffer(struct AVCodecContext* avctx, AVFrame* fra + AlignedSize(avctx, width, height); + + int size; +- switch (avctx->pix_fmt) ++ switch (pix_fmt) + { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUVJ420P: +@@ -248,13 +249,12 @@ int CDVDVideoCodecDRMPRIME::GetBuffer(struct AVCodecContext* avctx, AVFrame* fra + + CDVDVideoCodecDRMPRIME* ctx = static_cast(avctx->opaque); + auto buffer = dynamic_cast( +- ctx->m_processInfo.GetVideoBufferManager().Get(avctx->pix_fmt, size, nullptr)); ++ ctx->m_processInfo.GetVideoBufferManager().Get(pix_fmt, size, nullptr)); + if (!buffer) + return -1; + +- frame->opaque = static_cast(buffer); + frame->opaque_ref = +- av_buffer_create(nullptr, 0, ReleaseBuffer, frame->opaque, AV_BUFFER_FLAG_READONLY); ++ av_buffer_create(nullptr, 0, ReleaseBuffer, static_cast(buffer), AV_BUFFER_FLAG_READONLY); + + buffer->Export(frame, width, height); + buffer->SyncStart(); +@@ -608,9 +608,9 @@ bool CDVDVideoCodecDRMPRIME::SetPictureParams(VideoPicture* pVideoPicture) + buffer->SetRef(m_pFrame); + pVideoPicture->videoBuffer = buffer; + } +- else if (m_pFrame->opaque) ++ else if (IsSupportedSwFormat(static_cast(m_pFrame->format))) + { +- CVideoBufferDMA* buffer = static_cast(m_pFrame->opaque); ++ CVideoBufferDMA* buffer = static_cast(av_buffer_get_opaque(m_pFrame->buf[0])); + buffer->SetPictureParams(*pVideoPicture); + buffer->Acquire(); + buffer->SyncEnd(); +@@ -644,13 +644,13 @@ void CDVDVideoCodecDRMPRIME::FilterTest() + + if (name.find("deinterlace") != std::string::npos) + { +- if (FilterOpen(name, true)) ++ bool ret = FilterOpen(name, false, true); ++ FilterClose(); ++ if (ret) + { + m_deintFilterName = name; +- + CLog::Log(LOGDEBUG, "CDVDVideoCodecDRMPRIME::{} - found deinterlacing filter {}", + __FUNCTION__, name); +- + return; + } + } +@@ -660,14 +660,31 @@ void CDVDVideoCodecDRMPRIME::FilterTest() + __FUNCTION__); + } + +-bool CDVDVideoCodecDRMPRIME::FilterOpen(const std::string& filters, bool test) ++AVFrame *CDVDVideoCodecDRMPRIME::alloc_filter_frame(AVFilterContext * ctx, void * v, int w, int h) ++{ ++ int result; ++ CDVDVideoCodecDRMPRIME* me = static_cast(v); ++ AVFrame *frame = av_frame_alloc(); ++ frame->width = w; ++ frame->height = h; ++ frame->format = AV_PIX_FMT_YUV420P; ++ ++ if ((result = CDVDVideoCodecDRMPRIME::GetBuffer(me->m_pCodecContext, frame, 0)) < 0) ++ { ++ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::alloc_filter_frame - failed to GetBuffer ({})", result); ++ return nullptr; ++ } ++ return frame; ++} ++ ++bool CDVDVideoCodecDRMPRIME::FilterOpen(const std::string& filters, bool scale, bool test) + { + int result; + + if (m_pFilterGraph) + FilterClose(); + +- if (filters.empty()) ++ if (filters.empty() && !scale) + return true; + + if (!(m_pFilterGraph = avfilter_graph_alloc())) +@@ -678,13 +695,13 @@ bool CDVDVideoCodecDRMPRIME::FilterOpen(const std::string& filters, bool test) + + const AVFilter* srcFilter = avfilter_get_by_name("buffer"); + const AVFilter* outFilter = avfilter_get_by_name("buffersink"); +- enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_DRM_PRIME, AV_PIX_FMT_NONE }; ++ enum AVPixelFormat pix_fmts[] = { scale ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_DRM_PRIME, AV_PIX_FMT_NONE }; + + std::string args = StringUtils::Format("video_size={}x{}:pix_fmt={}:time_base={}/{}:" + "pixel_aspect={}/{}", + m_pCodecContext->width, + m_pCodecContext->height, +- AV_PIX_FMT_DRM_PRIME, ++ scale ? m_pCodecContext->pix_fmt : AV_PIX_FMT_DRM_PRIME, + m_pCodecContext->time_base.num ? + m_pCodecContext->time_base.num : 1, + m_pCodecContext->time_base.num ? +@@ -703,7 +720,6 @@ bool CDVDVideoCodecDRMPRIME::FilterOpen(const std::string& filters, bool test) + CLog::Log(LOGERROR, + "CDVDVideoCodecDRMPRIME::FilterOpen - avfilter_graph_create_filter: src: {} ({})", + err, result); +- FilterClose(); + return false; + } + +@@ -711,7 +727,6 @@ bool CDVDVideoCodecDRMPRIME::FilterOpen(const std::string& filters, bool test) + if (!par) + { + CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::FilterOpen - unable to alloc buffersrc"); +- FilterClose(); + return false; + } + +@@ -727,7 +742,6 @@ bool CDVDVideoCodecDRMPRIME::FilterOpen(const std::string& filters, bool test) + CLog::Log(LOGERROR, + "CDVDVideoCodecDRMPRIME::FilterOpen - av_buffersrc_parameters_set: {} ({})", + err, result); +- FilterClose(); + return false; + } + av_freep(&par); +@@ -741,7 +755,6 @@ bool CDVDVideoCodecDRMPRIME::FilterOpen(const std::string& filters, bool test) + CLog::Log(LOGERROR, + "CDVDVideoCodecDRMPRIME::FilterOpen - avfilter_graph_create_filter: out: {} ({})", + err, result); +- FilterClose(); + return false; + } + +@@ -750,32 +763,46 @@ bool CDVDVideoCodecDRMPRIME::FilterOpen(const std::string& filters, bool test) + if (result < 0) + { + CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::FilterOpen - failed settings pix formats"); +- FilterClose(); + return false; + } + +- AVFilterInOut* outputs = avfilter_inout_alloc(); +- AVFilterInOut* inputs = avfilter_inout_alloc(); ++ if (!filters.empty()) ++ { ++ AVFilterInOut* outputs = avfilter_inout_alloc(); ++ AVFilterInOut* inputs = avfilter_inout_alloc(); + +- outputs->name = av_strdup("in"); +- outputs->filter_ctx = m_pFilterIn; +- outputs->pad_idx = 0; +- outputs->next = nullptr; ++ outputs->name = av_strdup("in"); ++ outputs->filter_ctx = m_pFilterIn; ++ outputs->pad_idx = 0; ++ outputs->next = nullptr; + +- inputs->name = av_strdup("out"); +- inputs->filter_ctx = m_pFilterOut; +- inputs->pad_idx = 0; +- inputs->next = nullptr; ++ inputs->name = av_strdup("out"); ++ inputs->filter_ctx = m_pFilterOut; ++ inputs->pad_idx = 0; ++ inputs->next = nullptr; + +- result = avfilter_graph_parse_ptr(m_pFilterGraph, filters.c_str(), &inputs, &outputs, NULL); +- avfilter_inout_free(&outputs); +- avfilter_inout_free(&inputs); ++ result = avfilter_graph_parse_ptr(m_pFilterGraph, filters.c_str(), &inputs, &outputs, NULL); ++ avfilter_inout_free(&outputs); ++ avfilter_inout_free(&inputs); + +- if (result < 0) ++ if (result < 0) ++ { ++ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::FilterOpen - avfilter_graph_parse"); ++ return false; ++ } ++ } ++ else + { +- CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::FilterOpen - avfilter_graph_parse"); +- FilterClose(); +- return false; ++ if ((result = av_buffersink_set_alloc_video_frame(m_pFilterOut, alloc_filter_frame, static_cast(this))) < 0) ++ { ++ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::FilterOpen - av_buffersink_set_alloc_video_frame = {}", result); ++ return result; ++ } ++ if ((result = avfilter_link(m_pFilterIn, 0, m_pFilterOut, 0)) < 0) ++ { ++ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::FilterOpen - avfilter_link"); ++ return false; ++ } + } + + if ((result = avfilter_graph_config(m_pFilterGraph, nullptr)) < 0) +@@ -784,15 +811,11 @@ bool CDVDVideoCodecDRMPRIME::FilterOpen(const std::string& filters, bool test) + av_strerror(result, err, AV_ERROR_MAX_STRING_SIZE); + CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::FilterOpen - avfilter_graph_config: {} ({})", + err, result); +- FilterClose(); + return false; + } + + if (test) +- { +- FilterClose(); + return true; +- } + + m_processInfo.SetVideoDeintMethod(filters); + +@@ -827,16 +850,16 @@ void CDVDVideoCodecDRMPRIME::FilterClose() + CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::ProcessFilterIn() + { + // sw decoded buffers need cache flush and for descripter to be set +- if (!IsSupportedHwFormat(static_cast(m_pFrame->format)) && m_pFrame->opaque != nullptr) ++ if (!IsSupportedHwFormat(static_cast(m_pFrame->format)) && IsSupportedSwFormat(static_cast(m_pFrame->format))) + { +- CVideoBufferDMA* buffer = static_cast(m_pFrame->opaque); ++ CVideoBufferDMA* buffer = static_cast(av_buffer_get_opaque(m_pFrame->buf[0])); + buffer->SetDimensions(m_pFrame->width, m_pFrame->height); + buffer->SyncEnd(); + auto descriptor = buffer->GetDescriptor(); + m_pFrame->data[0] = reinterpret_cast(descriptor); ++ m_pFrame->format = AV_PIX_FMT_DRM_PRIME; + } + +- m_pFrame->format = AV_PIX_FMT_DRM_PRIME; + int ret = av_buffersrc_add_frame(m_pFilterIn, m_pFrame); + if (ret < 0) + { +@@ -929,25 +952,28 @@ CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::GetPicture(VideoPicture* pVideo + return VC_ERROR; + } + ++ // we need to scale if the buffer isn't in DRM_PRIME format ++ bool need_scale = !IsSupportedSwFormat(static_cast(m_pFrame->format)) && !IsSupportedHwFormat(static_cast(m_pFrame->format)); ++ + if (!m_processInfo.GetVideoInterlaced() && m_pFrame->interlaced_frame) + m_processInfo.SetVideoInterlaced(true); + + std::string filterChain = GetFilterChain(m_pFrame->interlaced_frame); +- if (!filterChain.empty()) ++ if (!filterChain.empty() || need_scale) + { + bool reopenFilter = false; + if (m_filters != filterChain) + reopenFilter = true; + + if (m_pFilterGraph && +- (m_pFilterIn->outputs[0]->w != m_pCodecContext->width || +- m_pFilterIn->outputs[0]->h != m_pCodecContext->height)) ++ (m_pFilterIn->outputs[0]->w != m_pFrame->width || ++ m_pFilterIn->outputs[0]->h != m_pFrame->height)) + reopenFilter = true; + +- if (reopenFilter) ++ if (reopenFilter || (need_scale && m_pFilterGraph == nullptr)) + { + m_filters = filterChain; +- if (!FilterOpen(filterChain, false)) ++ if (!FilterOpen(filterChain, need_scale, false)) + FilterClose(); + } + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h +index fab3431d40..bb88fde1f9 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h +@@ -44,7 +44,8 @@ protected: + CDVDVideoCodec::VCReturn ProcessFilterOut(); + static enum AVPixelFormat GetFormat(struct AVCodecContext* avctx, const enum AVPixelFormat* fmt); + static int GetBuffer(struct AVCodecContext* avctx, AVFrame* frame, int flags); +- bool FilterOpen(const std::string& filters, bool test); ++ static AVFrame *alloc_filter_frame(AVFilterContext * ctx, void * v, int w, int h); ++ bool FilterOpen(const std::string& filters, bool scale, bool test); + void FilterClose(); + void FilterTest(); + std::string GetFilterChain(bool interlaced); +-- +2.39.2 +