diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index a5b2793859c6a6739e78821ebb92eb871ed2a246..ea263a36c68697e97d8fd830d83910f40f74e03b 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -1206,6 +1206,9 @@ void EncApp::xInitLibCfg()
 #endif
 #if JVET_AG0158_ALF_LUMA_COEFF_PRECISION
   m_cEncLib.setUseAlfPrecision                                   ( m_alfPrecision );
+#endif
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  m_cEncLib.setUseCCALFPrecision                                 ( m_ccalfPrecision );
 #endif
   m_cEncLib.setTestSAODisableAtPictureLevel                      ( m_bTestSAODisableAtPictureLevel );
   m_cEncLib.setSaoEncodingRate                                   ( m_saoEncodingRate );
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index c1dd33f8a37fdfbda38d3d97b8bf4799e849d167..d55f74efba6d61908ffa848fbc627bfa5e774807 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1525,6 +1525,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #endif
 #if JVET_AG0158_ALF_LUMA_COEFF_PRECISION
   ("AlfPrecision",                                    m_alfPrecision,                                    true, "Luma Alf with variable precision coefficients" )
+#endif
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  ("CCALFPrecision",                                  m_ccalfPrecision,                                  true, "Cross-component Alf with variable precision coefficients")
 #endif
   ("TestSAODisableAtPictureLevel",                    m_bTestSAODisableAtPictureLevel,                  false, "Enables the testing of disabling SAO at the picture level after having analysed all blocks")
   ("SaoEncodingRate",                                 m_saoEncodingRate,                                 0.75, "When >0 SAO early picture termination is enabled for luma and chroma")
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 8a5dd011f6e9ba514a2fe5c93f0baa6c94643725..5b2b551ed988340459efa8f0e43d963d729b2cde 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -713,6 +713,9 @@ protected:
 #endif
 #if JVET_AG0158_ALF_LUMA_COEFF_PRECISION
   bool      m_alfPrecision;
+#endif
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  bool      m_ccalfPrecision;
 #endif
   bool      m_bTestSAODisableAtPictureLevel;
   double    m_saoEncodingRate;                                ///< When >0 SAO early picture termination is enabled for luma and chroma
diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp
index caf2b3059444325101fb984f20db88ca447a3c8d..bf6fb92da5570d2f8e396cc8fb6a4657237f53ae 100644
--- a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp
+++ b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp
@@ -393,10 +393,11 @@ const int AdaptiveLoopFilter::m_classToFilterMapping[NUM_FIXED_FILTER_SETS][MAX_
   { 16,  31,  32,  15,  60,  30,   4,  17,  19,  25,  22,  20,   4,  53,  19,  21,  22,  46,  25,  55,  26,  48,  63,  58,  55 },
 };
 #endif
-void AdaptiveLoopFilter::applyCcAlfFilter(CodingStructure &cs, ComponentID compID, const PelBuf &dstBuf,
-                                          const PelUnitBuf &recYuvExt, uint8_t *filterControl,
-                                          const short filterSet[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF],
-                                          const int   selectedFilterIdx)
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+void AdaptiveLoopFilter::applyCcAlfFilter(CodingStructure &cs, ComponentID compID, const PelBuf &dstBuf, const PelUnitBuf &recYuvExt, uint8_t *filterControl, const short filterSet[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], const int   selectedFilterIdx, const int coeffPrec)
+#else
+void AdaptiveLoopFilter::applyCcAlfFilter(CodingStructure &cs, ComponentID compID, const PelBuf &dstBuf, const PelUnitBuf &recYuvExt, uint8_t *filterControl, const short filterSet[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], const int   selectedFilterIdx)
+#endif
 {
   bool clipTop = false, clipBottom = false, clipLeft = false, clipRight = false;
   int  numHorVirBndry = 0, numVerVirBndry = 0;
@@ -496,10 +497,18 @@ void AdaptiveLoopFilter::applyCcAlfFilter(CodingStructure &cs, ComponentID compI
               const Area blkDst(xStart >> chromaScaleX, yStart >> chromaScaleY, w >> chromaScaleX, h >> chromaScaleY);
 #if ALF_IMPROVEMENT
 #if JVET_AF0197_LUMA_RESIDUAL_TAP_IN_CCALF
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+              m_filterCcAlf( dstBuf, buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, bufResi, m_alfClippingValues[CHANNEL_TYPE_LUMA], coeffPrec );
+#else
               m_filterCcAlf( dstBuf, buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, bufResi, m_alfClippingValues[CHANNEL_TYPE_LUMA] );
+#endif
+#else
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+              m_filterCcAlf( dstBuf, buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, coeffPrec );
 #else
               m_filterCcAlf( dstBuf, buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs );
 #endif
+#endif
 #else
               m_filterCcAlf(dstBuf, buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_alfVBLumaCTUHeight, m_alfVBLumaPos);
 #endif
@@ -518,10 +527,18 @@ void AdaptiveLoopFilter::applyCcAlfFilter(CodingStructure &cs, ComponentID compI
           Area blkSrc(xPos, yPos, width, height);
 #if ALF_IMPROVEMENT
 #if JVET_AF0197_LUMA_RESIDUAL_TAP_IN_CCALF
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+          m_filterCcAlf( dstBuf, recYuvExt, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, tmpYuvResi, m_alfClippingValues[CHANNEL_TYPE_LUMA], coeffPrec );
+#else
           m_filterCcAlf( dstBuf, recYuvExt, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, tmpYuvResi, m_alfClippingValues[CHANNEL_TYPE_LUMA] );
+#endif
+#else
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+          m_filterCcAlf( dstBuf, recYuvExt, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, coeffPrec );
 #else
           m_filterCcAlf( dstBuf, recYuvExt, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs );
 #endif
+#endif
 #else
           m_filterCcAlf(dstBuf, recYuvExt, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_alfVBLumaCTUHeight, m_alfVBLumaPos);
 #endif
@@ -1031,10 +1048,18 @@ void AdaptiveLoopFilter::ALFProcess(CodingStructure& cs)
                   const int16_t *filterCoeff = m_ccAlfFilterParam.ccAlfCoeff[compIdx - 1][filterIdx - 1];
 #if ALF_IMPROVEMENT
 #if JVET_AF0197_LUMA_RESIDUAL_TAP_IN_CCALF
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+                  m_filterCcAlf( recYuv.get( compID ), buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, bufResi, m_alfClippingValues[CHANNEL_TYPE_LUMA], m_ccAlfFilterParam.ccAlfCoeffPrec[compIdx - 1] );
+#else
                   m_filterCcAlf( recYuv.get( compID ), buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, bufResi, m_alfClippingValues[CHANNEL_TYPE_LUMA] );
+#endif
+#else
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+                  m_filterCcAlf( recYuv.get( compID ), buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_ccAlfFilterParam.ccAlfCoeffPrec[compIdx - 1] );
 #else
                   m_filterCcAlf( recYuv.get( compID ), buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs );
 #endif
+#endif
 #else
                   m_filterCcAlf(recYuv.get(compID), buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_alfVBLumaCTUHeight, m_alfVBLumaPos);
 #endif
@@ -1303,10 +1328,18 @@ void AdaptiveLoopFilter::ALFProcess(CodingStructure& cs)
 
 #if ALF_IMPROVEMENT
 #if JVET_AF0197_LUMA_RESIDUAL_TAP_IN_CCALF
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+              m_filterCcAlf( recYuv.get( compID ), tmpYuv, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, tmpYuvResi, m_alfClippingValues[CHANNEL_TYPE_LUMA], m_ccAlfFilterParam.ccAlfCoeffPrec[compIdx - 1] );
+#else
               m_filterCcAlf( recYuv.get( compID ), tmpYuv, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, tmpYuvResi, m_alfClippingValues[CHANNEL_TYPE_LUMA] );
+#endif
+#else
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+              m_filterCcAlf( recYuv.get( compID ), tmpYuv, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_ccAlfFilterParam.ccAlfCoeffPrec[compIdx - 1] );
 #else
               m_filterCcAlf( recYuv.get( compID ), tmpYuv, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs );
 #endif
+#endif
 #else
               m_filterCcAlf(recYuv.get(compID), tmpYuv, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_alfVBLumaCTUHeight, m_alfVBLumaPos);
 #endif
@@ -5715,10 +5748,18 @@ void AdaptiveLoopFilter::filterBlk(AlfClassifier **classifier, const PelUnitBuf
 template<AlfFilterType filtTypeCcAlf>
 #if ALF_IMPROVEMENT
 #if JVET_AF0197_LUMA_RESIDUAL_TAP_IN_CCALF
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+void AdaptiveLoopFilter::filterBlkCcAlf(const PelBuf &dstBuf, const CPelUnitBuf &recSrc, const Area &blkDst, const Area &blkSrc, const ComponentID compId, const int16_t *filterCoeff, const ClpRngs &clpRngs, CodingStructure &cs, const CPelUnitBuf &resiSrc, const Pel clippingValues[4], const int coeffPrec )
+#else
 void AdaptiveLoopFilter::filterBlkCcAlf(const PelBuf &dstBuf, const CPelUnitBuf &recSrc, const Area &blkDst, const Area &blkSrc, const ComponentID compId, const int16_t *filterCoeff, const ClpRngs &clpRngs, CodingStructure &cs, const CPelUnitBuf &resiSrc, const Pel clippingValues[4] )
+#endif
+#else
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+void AdaptiveLoopFilter::filterBlkCcAlf(const PelBuf &dstBuf, const CPelUnitBuf &recSrc, const Area &blkDst, const Area &blkSrc, const ComponentID compId, const int16_t *filterCoeff, const ClpRngs &clpRngs, CodingStructure &cs, const int coeffPrec)
 #else
 void AdaptiveLoopFilter::filterBlkCcAlf(const PelBuf &dstBuf, const CPelUnitBuf &recSrc, const Area &blkDst, const Area &blkSrc, const ComponentID compId, const int16_t *filterCoeff, const ClpRngs &clpRngs, CodingStructure &cs)
 #endif
+#endif
 #else
 void AdaptiveLoopFilter::filterBlkCcAlf(const PelBuf &dstBuf, const CPelUnitBuf &recSrc, const Area &blkDst, const Area &blkSrc, const ComponentID compId, const int16_t *filterCoeff, const ClpRngs &clpRngs, CodingStructure &cs, int vbCTUHeight, int vbPos)
 #endif
@@ -5884,7 +5925,11 @@ void AdaptiveLoopFilter::filterBlkCcAlf(const PelBuf &dstBuf, const CPelUnitBuf
           sum += filterCoeff[5] * (srcCross[offset1 + jj2 + 1] - currSrcCross);
           sum += filterCoeff[6] * (srcCross[offset3 + jj2    ] - currSrcCross);
 #endif
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+          sum = (sum + ((1 << coeffPrec) >> 1)) >> coeffPrec;
+#else
           sum = (sum + ((1 << m_scaleBits ) >> 1)) >> m_scaleBits;
+#endif
           const int offset = 1 << clpRngs.comp[compId].bd >> 1;
           sum = ClipPel(sum + offset, clpRngs.comp[compId]) - offset;
           sum += srcSelf[jj];
diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.h b/source/Lib/CommonLib/AdaptiveLoopFilter.h
index 339346fd5d08d7fb4899961804ff0f8db74ec639..c008829a46a91f96327aa5fb2854231d74cfb5c2 100644
--- a/source/Lib/CommonLib/AdaptiveLoopFilter.h
+++ b/source/Lib/CommonLib/AdaptiveLoopFilter.h
@@ -237,10 +237,18 @@ public:
 #endif
   template<AlfFilterType filtTypeCcAlf>
 #if JVET_AF0197_LUMA_RESIDUAL_TAP_IN_CCALF
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  static void filterBlkCcAlf(const PelBuf& dstBuf, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blkSrc, const ComponentID compId, const int16_t* filterCoeff, const ClpRngs& clpRngs, CodingStructure& cs, const CPelUnitBuf& resiSrc, const Pel clippingValues[4], const int coeffPrec );
+#else
   static void filterBlkCcAlf(const PelBuf& dstBuf, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blkSrc, const ComponentID compId, const int16_t* filterCoeff, const ClpRngs& clpRngs, CodingStructure& cs, const CPelUnitBuf& resiSrc, const Pel clippingValues[4] );
+#endif
+#else
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  static void filterBlkCcAlf(const PelBuf& dstBuf, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blkSrc, const ComponentID compId, const int16_t* filterCoeff, const ClpRngs& clpRngs, CodingStructure& cs, const int coeffPrec);
 #else
   static void filterBlkCcAlf(const PelBuf& dstBuf, const CPelUnitBuf& recSrc, const Area& blkDst, const Area& blkSrc, const ComponentID compId, const int16_t* filterCoeff, const ClpRngs& clpRngs, CodingStructure& cs);
 #endif
+#endif
 #else
   static void deriveClassificationBlk(AlfClassifier **classifier, int **laplacian[NUM_DIRECTIONS], const CPelBuf &srcLuma, const Area &blkDst, const Area &blk, const int shift, const int vbCTUHeight, int vbPos);
     template<AlfFilterType filtTypeCcAlf>
@@ -304,9 +312,17 @@ public:
 #endif
 #endif
 #if JVET_AF0197_LUMA_RESIDUAL_TAP_IN_CCALF
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  void(*m_filterCcAlf)(const PelBuf &dstBuf, const CPelUnitBuf &recSrc, const Area &blkDst, const Area &blkSrc, const ComponentID compId, const int16_t *filterCoeff, const ClpRngs &clpRngs, CodingStructure &cs, const CPelUnitBuf &resiSrc, const Pel clippingValues[4], const int coeffPrec );
+#else
   void(*m_filterCcAlf)(const PelBuf &dstBuf, const CPelUnitBuf &recSrc, const Area &blkDst, const Area &blkSrc, const ComponentID compId, const int16_t *filterCoeff, const ClpRngs &clpRngs, CodingStructure &cs, const CPelUnitBuf &resiSrc, const Pel clippingValues[4] );
+#endif
+#else
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  void(*m_filterCcAlf)(const PelBuf &dstBuf, const CPelUnitBuf &recSrc, const Area &blkDst, const Area &blkSrc, const ComponentID compId, const int16_t *filterCoeff, const ClpRngs &clpRngs, CodingStructure &cs, const int coeffPrec);
 #else
   void(*m_filterCcAlf)(const PelBuf &dstBuf, const CPelUnitBuf &recSrc, const Area &blkDst, const Area &blkSrc, const ComponentID compId, const int16_t *filterCoeff, const ClpRngs &clpRngs, CodingStructure &cs);
+#endif
 #endif
   template<AlfFilterType filtType>
   static void filterBlk(AlfClassifier **classifier, const PelUnitBuf &recDst,
@@ -663,7 +679,11 @@ public:
   void (*m_filter7x7Blk)(AlfClassifier **classifier, const PelUnitBuf &recDst, const CPelUnitBuf &recSrc, const Area &blkDst, const Area &blk, const ComponentID compId, const short *filterSet, const short *fClipSet, const ClpRng &clpRng, CodingStructure &cs, const int vbCTUHeight, int vbPos);
 #endif
 #endif
-  void applyCcAlfFilter(CodingStructure &cs, ComponentID compID, const PelBuf &dstBuf, const PelUnitBuf &recYuvExt, uint8_t *   filterControl, const short filterSet[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], const int   selectedFilterIdx);
+#if JVET_AH0057_CCALF_COEFF_PRECISION  
+  void applyCcAlfFilter(CodingStructure &cs, ComponentID compID, const PelBuf &dstBuf, const PelUnitBuf &recYuvExt, uint8_t *filterControl, const short filterSet[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], const int   selectedFilterIdx, const int coeffPrec);
+#else
+  void applyCcAlfFilter(CodingStructure &cs, ComponentID compID, const PelBuf &dstBuf, const PelUnitBuf &recYuvExt, uint8_t *filterControl, const short filterSet[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], const int   selectedFilterIdx);
+#endif
   CcAlfFilterParam &getCcAlfFilterParam() { return m_ccAlfFilterParam; }
   uint8_t* getCcAlfControlIdc(const ComponentID compID)   { return m_ccAlfFilterControl[compID-1]; }
 
@@ -675,7 +695,9 @@ public:
 
 protected:
   bool isCrossedByVirtualBoundaries( const CodingStructure& cs, const int xPos, const int yPos, const int width, const int height, bool& clipTop, bool& clipBottom, bool& clipLeft, bool& clipRight, int& numHorVirBndry, int& numVerVirBndry, int horVirBndryPos[], int verVirBndryPos[], int& rasterSliceAlfPad );
+#if !JVET_AH0057_CCALF_COEFF_PRECISION
   static constexpr int   m_scaleBits = 7; // 8-bits
+#endif
   CcAlfFilterParam       m_ccAlfFilterParam;
   uint8_t*               m_ccAlfFilterControl[2];
 #if !ALF_IMPROVEMENT
diff --git a/source/Lib/CommonLib/AlfParameters.h b/source/Lib/CommonLib/AlfParameters.h
index 89dc29a99c4ef12649ccbdbf8ab9630bd821da1d..915ed53d0e0e9bdccd89910bc1285daa52538fd1 100644
--- a/source/Lib/CommonLib/AlfParameters.h
+++ b/source/Lib/CommonLib/AlfParameters.h
@@ -727,6 +727,9 @@ struct CcAlfFilterParam
   bool    ccAlfFilterEnabled[2];
   bool    ccAlfFilterIdxEnabled[2][MAX_NUM_CC_ALF_FILTERS];
   uint8_t ccAlfFilterCount[2];
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  int     ccAlfCoeffPrec[2];
+#endif
   short   ccAlfCoeff[2][MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF];
   int     newCcAlfFilter[2];
   int     numberValidComponents;
@@ -739,6 +742,9 @@ struct CcAlfFilterParam
     std::memset( ccAlfFilterEnabled, false, sizeof( ccAlfFilterEnabled ) );
     std::memset( ccAlfFilterIdxEnabled, false, sizeof( ccAlfFilterIdxEnabled ) );
     std::memset( ccAlfCoeff, 0, sizeof( ccAlfCoeff ) );
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+    ccAlfCoeffPrec[0] = ccAlfCoeffPrec[1] = 0;
+#endif
     ccAlfFilterCount[0] = ccAlfFilterCount[1] = MAX_NUM_CC_ALF_FILTERS;
     numberValidComponents = 3;
     newCcAlfFilter[0] = newCcAlfFilter[1] = 0;
@@ -753,6 +759,10 @@ struct CcAlfFilterParam
     numberValidComponents = src.numberValidComponents;
     newCcAlfFilter[0] = src.newCcAlfFilter[0];
     newCcAlfFilter[1] = src.newCcAlfFilter[1];
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+    ccAlfCoeffPrec[0] = src.ccAlfCoeffPrec[0];
+    ccAlfCoeffPrec[1] = src.ccAlfCoeffPrec[1];
+#endif
     return *this;
   }
 };
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index f648cfcf7c79e0dfa62b5b179aeafa8d9bb55378..03f4a55ab0b4cf650bc2ef122b3a127d76fb7119 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -434,6 +434,10 @@ static const int MAX_NUM_ALF_CHROMA_COEFF    =                     21 + 5;
 #else
 static const int MAX_NUM_ALF_CHROMA_COEFF    =                     21;
 #endif
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+static const int MAX_NUM_CCALF_PREC          =                     4;
+static const int MIN_CCALF_PREC              =                     7;
+#endif
 #else
 static const int MAX_NUM_ALF_LUMA_COEFF      =                     13;
 static const int MAX_NUM_ALF_CHROMA_COEFF    =                      7;
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 73b38bf22ce4b87b89b16daaaa1a016c2c0dafa4..5fcc7203fc153bb88ca8cc4bb071afddd0aae0df 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -1719,6 +1719,9 @@ private:
 #endif
 #if JVET_AG0158_ALF_LUMA_COEFF_PRECISION
   bool              m_alfPrecisionFlag;
+#endif
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  bool              m_ccalfPrecisionFlag;
 #endif
   bool              m_bTemporalIdNestingFlag; // temporal_id_nesting_flag
 
@@ -2172,6 +2175,10 @@ public:
 #if JVET_AG0158_ALF_LUMA_COEFF_PRECISION
   bool                    getAlfPrecisionFlag() const                                                 { return m_alfPrecisionFlag; }
   void                    setAlfPrecisionFlag( bool b )                                               { m_alfPrecisionFlag = b;    }
+#endif
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  bool                    getCCALFPrecisionFlag() const                                                   { return m_ccalfPrecisionFlag; }
+  void                    setCCALFPrecisionFlag( bool b )                                                 { m_ccalfPrecisionFlag = b; }
 #endif
   bool                    getALFEnabledFlag() const                                                       { return m_alfEnabledFlag; }
   void                    setALFEnabledFlag( bool b )                                                     { m_alfEnabledFlag = b; }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 72561986a327096f54127dc6c7f34461ab7cccd9..c4541c3d796e5db61f41031acf360042ec2a0a0a 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -436,6 +436,7 @@
 #define JVET_AG0157_ALF_CHROMA_FIXED_FILTER               1 // JVET-AG0157: Fixed filter for chroma ALF
 #define JVET_AG0158_ALF_LUMA_COEFF_PRECISION              1 // JVET-AG0158: adaptive precision for luma ALF coefficients
 #define JVET_AG0145_ADAPTIVE_CLIPPING                     1 // JVET-AG0145: Adaptive clipping with signalled lower and upper bounds
+#define JVET_AH0057_CCALF_COEFF_PRECISION                 1 // JVET-AH0057: adaptive precision for CCALF coefficients
 
 // SIMD optimizations
 #if IF_12TAP
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index d77bb14fc74d90ec7ceec65c611a5f677c6f64aa..f08ef6a7639fe7599536597ad3eedbc7660ad411 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -1714,7 +1714,9 @@ void activateAPS(PicHeader* picHeader, Slice* pSlice, ParameterSetManager& param
 
       CHECK( aps->getTemporalId() > pSlice->getTLayer(), "TemporalId shall be less than or equal to the TemporalId of the coded slice NAL unit" );
       //ToDO: APS NAL unit containing the APS RBSP shall have nuh_layer_id either equal to the nuh_layer_id of a coded slice NAL unit that referrs it, or equal to the nuh_layer_id of a direct dependent layer of the layer containing a coded slice NAL unit that referrs it.
-
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+      filterParam.ccAlfCoeffPrec[COMPONENT_Cb - 1] = aps->getCcAlfAPSParam().ccAlfCoeffPrec[COMPONENT_Cb - 1];
+#endif
       filterParam.ccAlfFilterCount[COMPONENT_Cb - 1] = aps->getCcAlfAPSParam().ccAlfFilterCount[COMPONENT_Cb - 1];
       for (int filterIdx=0; filterIdx < filterParam.ccAlfFilterCount[COMPONENT_Cb - 1]; filterIdx++ )
       {
@@ -1742,7 +1744,9 @@ void activateAPS(PicHeader* picHeader, Slice* pSlice, ParameterSetManager& param
 
       CHECK( aps->getTemporalId() > pSlice->getTLayer(), "TemporalId shall be less than or equal to the TemporalId of the coded slice NAL unit" );
       //ToDO: APS NAL unit containing the APS RBSP shall have nuh_layer_id either equal to the nuh_layer_id of a coded slice NAL unit that referrs it, or equal to the nuh_layer_id of a direct dependent layer of the layer containing a coded slice NAL unit that referrs it.
-
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+      filterParam.ccAlfCoeffPrec[COMPONENT_Cr - 1] = aps->getCcAlfAPSParam().ccAlfCoeffPrec[COMPONENT_Cr - 1];
+#endif
       filterParam.ccAlfFilterCount[COMPONENT_Cr - 1] = aps->getCcAlfAPSParam().ccAlfFilterCount[COMPONENT_Cr - 1];
       for (int filterIdx=0; filterIdx < filterParam.ccAlfFilterCount[COMPONENT_Cr - 1]; filterIdx++ )
       {
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 208049f3b4566df4d214c5d0c8c71b1852e82ad0..db2922cde01247c85f2add41f654c107327867a5 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -1242,6 +1242,11 @@ void HLSyntaxReader::parseAlfAps( APS* aps )
   {
     if (ccAlfParam.newCcAlfFilter[ccIdx])
     {
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+      READ_CODE(2, code,
+        ccIdx == 0 ? "alf_cc_cb_frame_precision_idx" : "alf_cc_cr_frame_precision_idx");
+      ccAlfParam.ccAlfCoeffPrec[ccIdx] = code + MIN_CCALF_PREC;
+#endif
       if (MAX_NUM_CC_ALF_FILTERS > 1)
       {
         READ_UVLC(code, ccIdx == 0 ? "alf_cc_cb_filters_signalled_minus1" : "alf_cc_cr_filters_signalled_minus1");
@@ -2145,7 +2150,16 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   {
     pcSPS->setCCALFEnabledFlag(false);
   }
-
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  if (pcSPS->getCCALFEnabledFlag())
+  {
+    READ_FLAG(uiCode, "sps_ccalf_precision_flag");                  pcSPS->setCCALFPrecisionFlag(uiCode ? true : false);
+  }
+  else
+  {
+    pcSPS->setCCALFPrecisionFlag(false);
+  }
+#endif
 #if SIGN_PREDICTION
   READ_CODE(4, uiCode, "num_predicted_coef_signs");
   pcSPS->setNumPredSigns(uiCode);
diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
index 7e9000650b66cf7a8feb270b33fdc91ab90cdd7c..81f0b2674c968c554943e282134a44b2481bd28b 100644
--- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
+++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
@@ -1219,6 +1219,9 @@ void EncAdaptiveLoopFilter::xSetupCcAlfAPS( CodingStructure &cs )
       aps->setTemporalId(cs.slice->getTLayer());
     }
     aps->getCcAlfAPSParam().ccAlfFilterEnabled[COMPONENT_Cb - 1] = 1;
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+    aps->getCcAlfAPSParam().ccAlfCoeffPrec[COMPONENT_Cb - 1] = m_ccAlfFilterParam.ccAlfCoeffPrec[COMPONENT_Cb - 1];
+#endif
     aps->getCcAlfAPSParam().ccAlfFilterCount[COMPONENT_Cb - 1] = m_ccAlfFilterParam.ccAlfFilterCount[COMPONENT_Cb - 1];
     for ( int filterIdx = 0; filterIdx < MAX_NUM_CC_ALF_FILTERS; filterIdx++ )
     {
@@ -1251,6 +1254,9 @@ void EncAdaptiveLoopFilter::xSetupCcAlfAPS( CodingStructure &cs )
       aps->setTemporalId(cs.slice->getTLayer());
     }
     aps->getCcAlfAPSParam().ccAlfFilterEnabled[COMPONENT_Cr - 1] = 1;
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+    aps->getCcAlfAPSParam().ccAlfCoeffPrec[COMPONENT_Cr - 1] = m_ccAlfFilterParam.ccAlfCoeffPrec[COMPONENT_Cr - 1];
+#endif
     aps->getCcAlfAPSParam().ccAlfFilterCount[COMPONENT_Cr - 1] = m_ccAlfFilterParam.ccAlfFilterCount[COMPONENT_Cr - 1];
     for ( int filterIdx = 0; filterIdx < MAX_NUM_CC_ALF_FILTERS; filterIdx++ )
     {
@@ -1772,7 +1778,11 @@ void EncAdaptiveLoopFilter::ALFProcess( CodingStructure& cs, const double *lambd
     ComponentID compID     = ComponentID(compIdx);
     if (m_ccAlfFilterParam.ccAlfFilterEnabled[compIdx - 1])
     {
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+      applyCcAlfFilter(cs, compID, cs.getRecoBuf().get(compID), recYuv, m_ccAlfFilterControl[compIdx - 1], m_ccAlfFilterParam.ccAlfCoeff[compIdx - 1], -1, m_ccAlfFilterParam.ccAlfCoeffPrec[compIdx - 1]);
+#else
       applyCcAlfFilter(cs, compID, cs.getRecoBuf().get(compID), recYuv, m_ccAlfFilterControl[compIdx - 1], m_ccAlfFilterParam.ccAlfCoeff[compIdx - 1], -1);
+#endif
     }
   }
 }
@@ -7397,7 +7407,11 @@ int EncAdaptiveLoopFilter::getCoeffRateCcAlf(short chromaCoeff[MAX_NUM_CC_ALF_FI
   return bits;
 }
 
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+void EncAdaptiveLoopFilter::deriveCcAlfFilterCoeff( ComponentID compID, const PelUnitBuf& recYuv, const PelUnitBuf& recYuvExt, short filterCoeff[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], const uint8_t filterIdx, int coeffPrec )
+#else
 void EncAdaptiveLoopFilter::deriveCcAlfFilterCoeff( ComponentID compID, const PelUnitBuf& recYuv, const PelUnitBuf& recYuvExt, short filterCoeff[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], const uint8_t filterIdx )
+#endif
 {
   int forward_tab[CCALF_CANDS_COEFF_NR * 2 - 1] = {0};
   for (int i = 0; i < CCALF_CANDS_COEFF_NR; i++)
@@ -7447,7 +7461,11 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilterCoeff( ComponentID compID, const Pe
   }
 
   m_alfCovarianceFrameCcAlf[0].gnsSolveByChol(kE, ky, filterCoeffDbl, size);
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  roundFiltCoeffCCALF(filterCoeffInt, filterCoeffDbl, size, (1 << coeffPrec));
+#else
   roundFiltCoeffCCALF(filterCoeffInt, filterCoeffDbl, size, (1 << m_scaleBits));
+#endif
 
   for (int k = 0; k < size; k++)
   {
@@ -7457,7 +7475,11 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilterCoeff( ComponentID compID, const Pe
 
   // Refine quanitzation
   int modified       = 1;
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  double errRef      = m_alfCovarianceFrameCcAlf[0].calcErrorForCcAlfCoeffs(filterCoeffInt, size, (coeffPrec + 1));
+#else
   double errRef      = m_alfCovarianceFrameCcAlf[0].calcErrorForCcAlfCoeffs(filterCoeffInt, size, (m_scaleBits+1));
+#endif
 
   while (modified)
   {
@@ -7484,7 +7506,11 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilterCoeff( ComponentID compID, const Pe
           continue;
 
         filterCoeffInt[k] = forward_tab[org_idx - delta];
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+        double error = m_alfCovarianceFrameCcAlf[0].calcErrorForCcAlfCoeffs(filterCoeffInt, size, (coeffPrec + 1));
+#else
         double error = m_alfCovarianceFrameCcAlf[0].calcErrorForCcAlfCoeffs(filterCoeffInt, size, (m_scaleBits+1));
+#endif
         if( error < errMin )
         {
           errMin = error;
@@ -7806,6 +7832,10 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID
   double bestUnfilteredTotalCost = 1 * m_lambda[compID] + unfilteredDistortion;   // 1 bit is for gating flag
 
   bool             ccAlfFilterIdxEnabled[MAX_NUM_CC_ALF_FILTERS];
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  int              ccAlfCoeffPrec = MIN_CCALF_PREC;
+  int              bestCoeffPrec = MIN_CCALF_PREC;
+#endif
   short            ccAlfFilterCoeff[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF];
   uint8_t          ccAlfFilterCount             = MAX_NUM_CC_ALF_FILTERS;
   double bestFilteredTotalCost        = MAX_DOUBLE;
@@ -7842,6 +7872,9 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID
       }
 
       // initialize filters
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+      ccAlfCoeffPrec = MIN_CCALF_PREC;
+#endif
       for ( int filterIdx = 0; filterIdx < MAX_NUM_CC_ALF_FILTERS; filterIdx++ )
       {
         ccAlfFilterIdxEnabled[filterIdx] = false;
@@ -7857,6 +7890,9 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID
           memcpy(ccAlfFilterCoeff[filterIdx], m_ccAlfFilterParam.ccAlfCoeff[compID - 1][filterIdx],sizeof(ccAlfFilterCoeff[filterIdx]));
         }
         memcpy( ccAlfFilterCoeff, m_apsMap->getPS((apsIds[testFilterIdx] << NUM_APS_TYPE_LEN) + ALF_APS)->getCcAlfAPSParam().ccAlfCoeff[compID - 1], sizeof(ccAlfFilterCoeff) );
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+        ccAlfCoeffPrec = m_apsMap->getPS((apsIds[testFilterIdx] << NUM_APS_TYPE_LEN) + ALF_APS)->getCcAlfAPSParam().ccAlfCoeffPrec[compID - 1];
+#endif
       }
       else
       {
@@ -7879,11 +7915,19 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID
         }
       }
 
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+      const int coeffPrecNum = ( m_encCfg->getUseCCALFPrecision() && ( !referencingExistingAps ) )  ? MAX_NUM_CCALF_PREC : 1;
+      for (int coeffPrecTest = MIN_CCALF_PREC; coeffPrecTest < coeffPrecNum + MIN_CCALF_PREC; coeffPrecTest++)
+      {
+#endif
       // compute cost of filtering
       int    trainingIterCount = 0;
       bool   keepTraining      = true;
       bool   improvement       = false;
       double prevTotalCost     = MAX_DOUBLE;
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+      int coeffPrec = referencingExistingAps ? ccAlfCoeffPrec : coeffPrecTest;
+#endif
       while (keepTraining)
       {
         improvement = false;
@@ -7894,7 +7938,11 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID
             if (!referencingExistingAps)
             {
               getFrameStatsCcalf(compID, (filterIdx + 1));
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+              deriveCcAlfFilterCoeff(compID, dstYuv, tempDecYuvBuf, ccAlfFilterCoeff, filterIdx, coeffPrec);
+#else
               deriveCcAlfFilterCoeff(compID, dstYuv, tempDecYuvBuf, ccAlfFilterCoeff, filterIdx);
+#endif
             }
             const int numCoeff  = m_filterShapesCcAlf[0].numCoeff - 1;
             int log2BlockWidth  = cs.pcv->maxCUWidthLog2 - scaleX;
@@ -7904,7 +7952,11 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID
               for (int x = 0; x < m_buf->width; x += (1 << log2BlockWidth))
               {
                 int ctuIdx = (y >> log2BlockHeight) * m_numCTUsInWidth + (x >> log2BlockWidth);
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+                m_trainingDistortion[filterIdx][ctuIdx] = int(m_ctbDistortionUnfilter[compID][ctuIdx] + m_alfCovarianceCcAlf[0][ctuIdx].calcErrorForCcAlfCoeffs(ccAlfFilterCoeff[filterIdx], numCoeff, coeffPrec + 1));
+#else
                 m_trainingDistortion[filterIdx][ctuIdx] = int(m_ctbDistortionUnfilter[compID][ctuIdx] + m_alfCovarianceCcAlf[0][ctuIdx].calcErrorForCcAlfCoeffs(ccAlfFilterCoeff[filterIdx], numCoeff, m_scaleBits + 1));
+#endif
               }
             }
           }
@@ -7931,10 +7983,15 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID
           }
           else
           {
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+            curTotalRate += getCoeffRateCcAlf(ccAlfFilterCoeff, ccAlfFilterIdxEnabled, ccAlfFilterCount, compID) + 1
+              + 9 + 2;
+#else
             curTotalRate += getCoeffRateCcAlf(ccAlfFilterCoeff, ccAlfFilterIdxEnabled, ccAlfFilterCount, compID) + 1
             + 9;   // +1 for the enable flag, +9 3-bit for APS ID in slice header, 5-bit for APS ID in APS, a 1-bit
             // new filter flags (ignore shared cost such as other new-filter flags/NALU header/RBSP
             // terminating bit/byte alignment bits)
+#endif
           }
 #if JVET_AF0197_LUMA_RESIDUAL_TAP_IN_CCALF
           double curTotalCost = curTotalRate * m_lambda[compID] * chromaFactor + curTotalDistortion;
@@ -7950,6 +8007,9 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID
           if (curTotalCost < bestFilteredTotalCost)
           {
             bestFilteredTotalCost = curTotalCost;
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+            bestCoeffPrec = coeffPrec;
+#endif
             memcpy(m_bestFilterIdxEnabled, ccAlfFilterIdxEnabled, sizeof(ccAlfFilterIdxEnabled));
             memcpy(m_bestFilterCoeffSet, ccAlfFilterCoeff, sizeof(ccAlfFilterCoeff));
             memcpy(m_bestFilterControl, m_filterControl, sizeof(uint8_t) * m_numCTUsInPic);
@@ -7965,6 +8025,9 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID
           keepTraining = false;
         }
       }
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+      }
+#endif
     }
   }
 
@@ -8019,6 +8082,9 @@ void EncAdaptiveLoopFilter::deriveCcAlfFilter( CodingStructure& cs, ComponentID
     }
 
     m_ccAlfFilterParam.ccAlfFilterCount[compID - 1] = m_bestFilterCount;
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+    m_ccAlfFilterParam.ccAlfCoeffPrec[compID - 1] = bestCoeffPrec;
+#endif
     // cleanup before copying
     memset(m_ccAlfFilterControl[compID - 1], 0, sizeof(uint8_t) * m_numCTUsInPic);
     for ( int filterIdx = 0; filterIdx < MAX_NUM_CC_ALF_FILTERS; filterIdx++ )
diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
index 4415240ee7162cbc54348f51cc837d1700969be1..a4f2270aaa4236d5c0f80037bc46ee58a2dad6d1 100644
--- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
+++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
@@ -699,7 +699,11 @@ private:
   void copyCtuAlternativeChroma( uint8_t* ctuAltsDst[MAX_NUM_COMPONENT], uint8_t* ctuAltsSrc[MAX_NUM_COMPONENT] );
   int getMaxNumAlternativesChroma( );
   int  getCoeffRateCcAlf(short chromaCoeff[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], bool filterEnabled[MAX_NUM_CC_ALF_FILTERS], uint8_t filterCount, ComponentID compID);
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  void deriveCcAlfFilterCoeff( ComponentID compID, const PelUnitBuf& recYuv, const PelUnitBuf& recYuvExt, short filterCoeff[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], const uint8_t filterIdx, int coeffPrec );
+#else
   void deriveCcAlfFilterCoeff( ComponentID compID, const PelUnitBuf& recYuv, const PelUnitBuf& recYuvExt, short filterCoeff[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], const uint8_t filterIdx );
+#endif
   void determineControlIdcValues(CodingStructure &cs, const ComponentID compID, const PelBuf *buf, const int ctuWidthC,
                                  const int ctuHeightC, const int picWidthC, const int picHeightC,
                                  double **unfilteredDistortion, uint64_t *trainingDistortion[MAX_NUM_CC_ALF_FILTERS],
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 2f0ffbe9d31b0552f63284ba51328a6a811885e2..17eafd18adb86fc9d773709221b8bcbdecd6bbf1 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -674,6 +674,9 @@ protected:
 #endif
 #if JVET_AG0158_ALF_LUMA_COEFF_PRECISION
   bool      m_alfPrecision;
+#endif
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  bool      m_ccalfPrecision;
 #endif
   bool      m_bTestSAODisableAtPictureLevel;
   double    m_saoEncodingRate;       // When non-0 SAO early picture termination is enabled for luma and chroma
@@ -2279,6 +2282,10 @@ public:
 #if JVET_AG0158_ALF_LUMA_COEFF_PRECISION
   void      setUseAlfPrecision( bool b )                             { m_alfPrecision = b; }
   bool      getUseAlfPrecision()                               const { return m_alfPrecision; }
+#endif
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  void      setUseCCALFPrecision(bool b)                             { m_ccalfPrecision = b; }
+  bool      getUseCCALFPrecision()                             const { return m_ccalfPrecision; }
 #endif
   void  setTestSAODisableAtPictureLevel (bool bVal)                  { m_bTestSAODisableAtPictureLevel = bVal; }
   bool  getTestSAODisableAtPictureLevel ( ) const                    { return m_bTestSAODisableAtPictureLevel; }
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 6b3710387e36930393b0921dc65befc8e9fa322f..fe0594c14f5ac281cc451c13462f4e4d79a1f1b8 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -2140,6 +2140,9 @@ void EncLib::xInitSPS( SPS& sps )
 #endif
 #if JVET_AG0158_ALF_LUMA_COEFF_PRECISION
   sps.setAlfPrecisionFlag( m_alfPrecision );
+#endif
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  sps.setCCALFPrecisionFlag( m_ccalfPrecision );
 #endif
   sps.setJointCbCrEnabledFlag( m_JointCbCrMode );
   sps.setMaxTLayers( m_maxTempLayer );
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index c907da30b76e4b5f2b80548af275a0e4aaba5503..16f386e9256b350281f51a5b3f3cf25cdaa94da6 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -776,6 +776,10 @@ void HLSWriter::codeAlfAps( APS* pcAPS )
   {
     if (paramCcAlf.newCcAlfFilter[ccIdx])
     {
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+      WRITE_CODE(paramCcAlf.ccAlfCoeffPrec[ccIdx] - MIN_CCALF_PREC, 2,
+        ccIdx == 0 ? "alf_cc_cb_frame_precision_idx" : "alf_cc_cr_frame_precision_idx");
+#endif
       const int filterCount = paramCcAlf.ccAlfFilterCount[ccIdx];
       CHECK(filterCount > MAX_NUM_CC_ALF_FILTERS, "CC ALF Filter count is too large");
       CHECK(filterCount == 0, "CC ALF Filter count is too small");
@@ -1312,7 +1316,12 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   {
     WRITE_FLAG( pcSPS->getCCALFEnabledFlag(),                                            "sps_ccalf_enabled_flag" );
   }
-
+#if JVET_AH0057_CCALF_COEFF_PRECISION
+  if (pcSPS->getCCALFEnabledFlag())
+  {
+    WRITE_FLAG(pcSPS->getCCALFPrecisionFlag(),                                           "sps_ccalf_precision_flag" );
+  }
+#endif
 #if SIGN_PREDICTION
   WRITE_CODE(pcSPS->getNumPredSigns(), 4, "num_predicted_coef_signs");
 #if JVET_Y0141_SIGN_PRED_IMPROVE