From 34badba6d106467d63ee2578662fd5f30276736c Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sun, 20 Oct 2019 17:10:07 +0000
Subject: [PATCH 1/7] WIP: DVDVideoCodecDRMPRIME: add support for filters

---
 .../DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp | 62 +++++++++++++++++--
 .../DVDCodecs/Video/DVDVideoCodecDRMPRIME.h   | 10 +++
 2 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
index ab65c4ecd4..4cf36f83e6 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
@@ -28,6 +28,8 @@
 extern "C"
 {
 #include <libavcodec/avcodec.h>
+#include <libavfilter/buffersink.h>
+#include <libavfilter/buffersrc.h>
 #include <libavutil/error.h>
 #include <libavutil/imgutils.h>
 #include <libavutil/opt.h>
@@ -595,12 +597,30 @@ void CDVDVideoCodecDRMPRIME::SetPictureParams(VideoPicture* pVideoPicture)
   pVideoPicture->dts = DVD_NOPTS_VALUE;
 }
 
-CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::GetPicture(VideoPicture* pVideoPicture)
+CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::ProcessFilterIn()
 {
-  if (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)
-    Drain();
+  if (!m_pFilterIn)
+    return VC_PICTURE;
+
+  int ret = av_buffersrc_add_frame(m_pFilterIn, m_pFrame);
+  if (ret < 0)
+  {
+    char err[AV_ERROR_MAX_STRING_SIZE] = {};
+    av_strerror(ret, err, AV_ERROR_MAX_STRING_SIZE);
+    CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - buffersrc add frame failed: {} ({})",
+              __FUNCTION__, err, ret);
+    return VC_ERROR;
+  }
 
-  int ret = avcodec_receive_frame(m_pCodecContext, m_pFrame);
+  return ProcessFilterOut();
+}
+
+CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::ProcessFilterOut()
+{
+  if (!m_pFilterOut)
+    return VC_EOF;
+
+  int ret = av_buffersink_get_frame(m_pFilterOut, m_pFrame);
   if (ret == AVERROR(EAGAIN))
     return VC_BUFFER;
   else if (ret == AVERROR_EOF)
@@ -617,11 +637,41 @@ CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::GetPicture(VideoPicture* pVideo
   {
     char err[AV_ERROR_MAX_STRING_SIZE] = {};
     av_strerror(ret, err, AV_ERROR_MAX_STRING_SIZE);
-    CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - receive frame failed: {} ({})", __FUNCTION__,
-              err, ret);
+    CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - buffersink get frame failed: {} ({})",
+              __FUNCTION__, err, ret);
     return VC_ERROR;
   }
 
+  return VC_PICTURE;
+}
+
+CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::GetPicture(VideoPicture* pVideoPicture)
+{
+  if (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)
+    Drain();
+
+  auto result = ProcessFilterOut();
+  if (result != VC_PICTURE)
+  {
+    int ret = avcodec_receive_frame(m_pCodecContext, m_pFrame);
+    if (ret == AVERROR(EAGAIN))
+      return VC_BUFFER;
+    else if (ret == AVERROR_EOF)
+      return VC_EOF;
+    else if (ret)
+    {
+      char err[AV_ERROR_MAX_STRING_SIZE] = {};
+      av_strerror(ret, err, AV_ERROR_MAX_STRING_SIZE);
+      CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - receive frame failed: {} ({})",
+                __FUNCTION__, err, ret);
+      return VC_ERROR;
+    }
+
+    result = ProcessFilterIn();
+    if (result != VC_PICTURE)
+      return result;
+  }
+
   SetPictureParams(pVideoPicture);
 
   if (pVideoPicture->videoBuffer)
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h
index db49d165e7..b5cacf1a3c 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h
@@ -14,6 +14,11 @@
 
 #include <memory>
 
+extern "C"
+{
+#include <libavfilter/avfilter.h>
+}
+
 class CDVDVideoCodecDRMPRIME : public CDVDVideoCodec
 {
 public:
@@ -35,6 +40,8 @@ protected:
   void Drain();
   void SetPictureParams(VideoPicture* pVideoPicture);
   void UpdateProcessInfo(struct AVCodecContext* avctx, const enum AVPixelFormat fmt);
+  CDVDVideoCodec::VCReturn ProcessFilterIn();
+  CDVDVideoCodec::VCReturn ProcessFilterOut();
   static enum AVPixelFormat GetFormat(struct AVCodecContext* avctx, const enum AVPixelFormat* fmt);
   static int GetBuffer(struct AVCodecContext* avctx, AVFrame* frame, int flags);
 
@@ -44,5 +51,8 @@ protected:
   double m_DAR = 1.0;
   AVCodecContext* m_pCodecContext = nullptr;
   AVFrame* m_pFrame = nullptr;
+  AVFilterGraph* m_pFilterGraph = nullptr;
+  AVFilterContext* m_pFilterIn = nullptr;
+  AVFilterContext* m_pFilterOut = nullptr;
   std::shared_ptr<IVideoBufferPool> m_videoBufferPool;
 };
-- 
2.39.2

