From 2861e1313114ac2d4bdea3f0aa193c40767dadec Mon Sep 17 00:00:00 2001
From: charles Salmon-Legagneur <charles.salmon-legagneur@interdigital.com>
Date: Wed, 1 Feb 2023 22:53:35 +0000
Subject: [PATCH] add options --SourceScalingRatio to rescale source video

---
 doc/software-manual.tex             | 10 ++++++
 source/App/EncoderApp/EncApp.cpp    | 56 ++++++++++++++++++++++++++---
 source/App/EncoderApp/EncApp.h      |  2 ++
 source/App/EncoderApp/EncAppCfg.cpp | 15 ++++++++
 source/App/EncoderApp/EncAppCfg.h   |  4 +++
 5 files changed, 83 insertions(+), 4 deletions(-)

diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index 58ace85d79..6be5b18bd6 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -639,6 +639,16 @@ Specifies the output locally reconstructed video file. If more than one layer is
 Specifies the width and height of the input video in luma samples.
 \\
 
+
+\Option{SourceScalingRatioHor}%
+\Option{SourceScalingRatioVer} &
+\Default{1.0}%
+\Default{1.0} &
+Specifies a scaling ratio to apply in hor and vert direction to the pictures read from input video file.
+Note: The SourceWidth and SourceHeight are multiplied by these scaling factors. This option is useful for spatial scalability in a multi layer scenario to use enhancement layer source when base layer source is not available. 
+\\
+
+
 \Option{InputBitDepth}
  &
 %\ShortOption{\None} &
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index a0e9349b77..c72accaaad 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -1403,8 +1403,16 @@ void EncApp::xCreateLib( std::list<PelUnitBuf*>& recBufList, const int layerId )
   m_cVideoIOYuvInputFile.skipFrames(m_frameSkip, m_inputFileWidth, m_inputFileHeight, m_inputChromaFormatIDC);
 #else
   const int sourceHeight = m_isField ? m_iSourceHeightOrg : m_sourceHeight;
-  m_cVideoIOYuvInputFile.skipFrames(m_frameSkip, m_sourceWidth - m_sourcePadding[0], sourceHeight - m_sourcePadding[1],
-                                    m_inputChromaFormatIDC);
+  if (m_sourceScalingRatioHor != 1.0 || m_sourceScalingRatioVer != 1.0)
+  {
+    m_cVideoIOYuvInputFile.skipFrames(m_frameSkip, m_sourceWidthBeforeScale, m_sourceHeightBeforeScale,
+                                      m_inputChromaFormatIDC);
+  }
+  else
+  {
+    m_cVideoIOYuvInputFile.skipFrames(m_frameSkip, m_sourceWidth - m_sourcePadding[0],
+                                      sourceHeight - m_sourcePadding[1], m_inputChromaFormatIDC);
+  }
 #endif
   if (!m_reconFileName.empty())
   {
@@ -1497,6 +1505,14 @@ void EncApp::createLib( const int layerIdx )
   m_trueOrgPic = new PelStorage;
   m_orgPic->create( unitArea );
   m_trueOrgPic->create( unitArea );
+  if (m_sourceScalingRatioHor != 1.0 || m_sourceScalingRatioVer != 1.0)
+  {
+    UnitArea unitAreaPrescale( m_chromaFormatIDC, Area( 0, 0, m_sourceWidthBeforeScale, m_sourceHeightBeforeScale) );
+    m_orgPicBeforeScale = new PelStorage;
+    m_trueOrgPicBeforeScale = new PelStorage;
+    m_orgPicBeforeScale->create( unitAreaPrescale );
+    m_trueOrgPicBeforeScale->create( unitAreaPrescale );
+  }
   if ( m_gopBasedTemporalFilterEnabled || m_bimEnabled )
   {
     m_filteredOrgPic = new PelStorage;
@@ -1588,6 +1604,15 @@ void EncApp::destroyLib()
   m_trueOrgPic->destroy();
   delete m_trueOrgPic;
   delete m_orgPic;
+
+  if (m_sourceScalingRatioHor != 1.0 || m_sourceScalingRatioVer != 1.0)
+  {
+    m_orgPicBeforeScale->destroy();
+    m_trueOrgPicBeforeScale->destroy();
+    delete m_trueOrgPicBeforeScale;
+    delete m_orgPicBeforeScale;
+  }
+
   if (m_resChangeInClvsEnabled && m_gopBasedRPREnabledFlag)
   {
     for (int i = 0; i < 2; i++)
@@ -1641,8 +1666,31 @@ bool EncApp::encodePrep( bool& eos )
                                 m_clipInputVideoToRec709Range);
   }
 #else
-  m_cVideoIOYuvInputFile.read(*m_orgPic, *m_trueOrgPic, ipCSC, m_sourcePadding, m_inputChromaFormatIDC,
-                              m_clipInputVideoToRec709Range);
+  if (m_sourceScalingRatioHor != 1.0 || m_sourceScalingRatioVer != 1.0)
+  {
+    int noPadding[2] = { 0 };
+    m_cVideoIOYuvInputFile.read(*m_orgPicBeforeScale, *m_trueOrgPicBeforeScale, ipCSC, noPadding, m_inputChromaFormatIDC,
+                                m_clipInputVideoToRec709Range);
+    int w0 = m_sourceWidthBeforeScale;
+    int h0 = m_sourceHeightBeforeScale;
+    int w1 = m_orgPic->get(COMPONENT_Y).width - SPS::getWinUnitX(m_chromaFormatIDC) * (m_confWinLeft + m_confWinRight);
+    int h1 = m_orgPic->get(COMPONENT_Y).height - SPS::getWinUnitY(m_chromaFormatIDC) * (m_confWinTop + m_confWinBottom);
+    int xScale = ((w0 << ScalingRatio::BITS) + (w1 >> 1)) / w1;
+    int yScale = ((h0 << ScalingRatio::BITS) + (h1 >> 1)) / h1;
+    ScalingRatio scalingRatio = { xScale, yScale };
+    Window conformanceWindow1;
+    conformanceWindow1.setWindow(m_confWinLeft, m_confWinRight, m_confWinTop, m_confWinBottom);
+    
+    bool downsampling = (m_sourceWidthBeforeScale > m_sourceWidth) || (m_sourceHeightBeforeScale > m_sourceHeight);
+    bool useLumaFilter = downsampling;
+    Picture::rescalePicture(scalingRatio, *m_orgPicBeforeScale, Window(), *m_orgPic, conformanceWindow1, m_inputChromaFormatIDC , m_internalBitDepth,useLumaFilter,downsampling,m_horCollocatedChromaFlag,m_verCollocatedChromaFlag );
+    m_trueOrgPic->copyFrom(*m_orgPic);
+  }
+  else
+  {
+    m_cVideoIOYuvInputFile.read(*m_orgPic, *m_trueOrgPic, ipCSC, m_sourcePadding, m_inputChromaFormatIDC,
+                                m_clipInputVideoToRec709Range);
+  }
 #endif
 
   if (m_fgcSEIAnalysisEnabled && m_fgcSEIExternalDenoised.empty())
diff --git a/source/App/EncoderApp/EncApp.h b/source/App/EncoderApp/EncApp.h
index e48ce07b6c..3b63cf63c4 100644
--- a/source/App/EncoderApp/EncApp.h
+++ b/source/App/EncoderApp/EncApp.h
@@ -99,6 +99,8 @@ private:
   int                    m_numEncoded;
   PelStorage*            m_trueOrgPic;
   PelStorage*            m_orgPic;
+  PelStorage*            m_trueOrgPicBeforeScale;
+  PelStorage*            m_orgPicBeforeScale;
   PelStorage*            m_filteredOrgPic;
   PelStorage*            m_rprPic[2];
 #if EXTENSION_360_VIDEO
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 331399be2e..bc6e11f1d0 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -772,6 +772,8 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #endif
   ("SourceWidth,-wdt",                                m_sourceWidth,                                       0, "Source picture width")
   ("SourceHeight,-hgt",                               m_sourceHeight,                                      0, "Source picture height")
+  ("SourceScalingRatioHor",                           m_sourceScalingRatioHor,                           1.0, "Source picture  horizontal scaling ratio")
+  ("SourceScalingRatioVer",                           m_sourceScalingRatioVer,                           1.0, "Source picture vertical scaling ratio")
   ("InputBitDepth",                                   m_inputBitDepth[ChannelType::LUMA],                   8, "Bit-depth of input file")
   ("OutputBitDepth",                                  m_outputBitDepth[ChannelType::LUMA],                  0, "Bit-depth of output file (default:InternalBitDepth)")
   ("MSBExtendedBitDepth",                             m_msbExtendedBitDepth[ChannelType::LUMA],             0, "bit depth of luma component after addition of MSBs of value 0 (used for synthesising High Dynamic Range source material). (default:InputBitDepth)")
@@ -2112,6 +2114,19 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   /*
    * Set any derived parameters
    */
+
+  if ( m_sourceScalingRatioHor != 1.0 || m_sourceScalingRatioVer != 1.0 ) 
+  {
+    m_sourceWidthBeforeScale = m_sourceWidth;
+    m_sourceHeightBeforeScale = m_sourceHeight;
+    m_sourceWidth    = int(round(m_sourceWidth*m_sourceScalingRatioHor));
+    m_sourceHeight   = int(round(m_sourceHeight*m_sourceScalingRatioVer));
+  }
+  else 
+  {
+    m_sourceWidthBeforeScale = 0;
+    m_sourceHeightBeforeScale = 0;
+  }
 #if EXTENSION_360_VIDEO
   m_inputFileWidth = m_sourceWidth;
   m_inputFileHeight = m_sourceHeight;
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index e6b82a3aee..275c85c0f3 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -95,6 +95,10 @@ protected:
   uint32_t      m_temporalSubsampleRatio;                         ///< temporal subsample ratio, 2 means code every two frames
   int       m_sourceWidth;                                   ///< source width in pixel
   int       m_sourceHeight;                                  ///< source height in pixel (when interlaced = field height)
+  double    m_sourceScalingRatioHor;                          ////< source scaling ratio Horizontal
+  double    m_sourceScalingRatioVer;                          ////< source scaling ratio Vertical
+  int       m_sourceWidthBeforeScale;                         ///< source width in pixel before applying source scaling ratio Horizontal 
+  int       m_sourceHeightBeforeScale;                        ///< source height in pixel before applying source scaling ratio Vertical (when interlaced = field height)
 #if EXTENSION_360_VIDEO
   int       m_inputFileWidth;                                 ///< width of image in input file  (this is equivalent to sourceWidth,  if sourceWidth  is not subsequently altered due to padding)
   int       m_inputFileHeight;                                ///< height of image in input file (this is equivalent to sourceHeight, if sourceHeight is not subsequently altered due to padding)
-- 
GitLab