[x265] [PATCH] fix for crf and vbv issue in abr-ladder

Shanmathi Paramanandam shanmathi.paramanandam at multicorewareinc.com
Mon Jul 7 04:19:47 UTC 2025


>From ec4f8524fcd420cc12fab18e17072a06659fd92b Mon Sep 17 00:00:00 2001
From: Shanmathi Paramanandam <shanmathi.paramanandam at multicorewareinc.com>
Date: Wed, 2 Jul 2025 18:10:42 +0530
Subject: [PATCH] fix for crf and vbv issue in abr-ladder

---
 source/encoder/slicetype.cpp | 431 ++++++++++++++++++-----------------
 1 file changed, 226 insertions(+), 205 deletions(-)

diff --git a/source/encoder/slicetype.cpp b/source/encoder/slicetype.cpp
index edf2b00d9..ee31972ba 100644
--- a/source/encoder/slicetype.cpp
+++ b/source/encoder/slicetype.cpp
@@ -2758,27 +2758,33 @@ void Lookahead::slicetypeAnalyse(Lowres **frames, bool bKeyframe)
             break;
     }

-    if (!framecnt)
+    if (!framecnt && m_param->analysisLoadReuseLevel != 1)
     {
         if (m_param->rc.cuTree)
             cuTree(frames, 0, bKeyframe);
         return;
     }
-    frames[framecnt + 1] = NULL;

-    if (m_param->bResetZoneConfig)
+    if (framecnt)
     {
-        for (int i = 0; i < m_param->rc.zonefileCount; i++)
+
+        frames[framecnt + 1] = NULL;
+
+        if (m_param->bResetZoneConfig)
         {
-            int curZoneStart = m_param->rc.zones[i].startFrame, nextZoneStart = 0;
-            curZoneStart += curZoneStart ? m_param->rc.zones[i].zoneParam->radl : 0;
-            nextZoneStart += (i + 1 < m_param->rc.zonefileCount) ? m_param->rc.zones[i + 1].startFrame + m_param->rc.zones[i + 1].zoneParam->radl : m_param->totalFrames;
-            if (curZoneStart <= frames[0]->frameNum && nextZoneStart > frames[0]->frameNum)
-                m_param->keyframeMax = nextZoneStart - curZoneStart;
-            if (m_param->rc.zones[m_param->rc.zonefileCount - 1].startFrame <= frames[0]->frameNum && nextZoneStart == 0)
-                m_param->keyframeMax = m_param->rc.zones[0].keyframeMax;
+            for (int i = 0; i < m_param->rc.zonefileCount; i++)
+            {
+                int curZoneStart = m_param->rc.zones[i].startFrame, nextZoneStart = 0;
+                curZoneStart += curZoneStart ? m_param->rc.zones[i].zoneParam->radl : 0;
+                nextZoneStart += (i + 1 < m_param->rc.zonefileCount) ? m_param->rc.zones[i + 1].startFrame + m_param->rc.zones[i + 1].zoneParam->radl : m_param->totalFrames;
+                if (curZoneStart <= frames[0]->frameNum && nextZoneStart > frames[0]->frameNum)
+                    m_param->keyframeMax = nextZoneStart - curZoneStart;
+                if (m_param->rc.zones[m_param->rc.zonefileCount - 1].startFrame <= frames[0]->frameNum && nextZoneStart == 0)
+                    m_param->keyframeMax = m_param->rc.zones[0].keyframeMax;
+            }
         }
     }
+
     int keylimit = m_param->keyframeMax;
     if (frames[0]->frameNum < m_param->chunkEnd)
     {
@@ -2797,266 +2803,281 @@ void Lookahead::slicetypeAnalyse(Lowres **frames, bool bKeyframe)
         keyintLimit = keyFrameLimit;

     origNumFrames = numFrames = m_param->bIntraRefresh ? framecnt : X265_MIN(framecnt, keyintLimit);
-    if (bIsVbvLookahead)
-        numFrames = framecnt;
-    else if (m_param->bOpenGOP && numFrames < framecnt)
-        numFrames++;
-    else if (numFrames == 0)
-    {
-        frames[1]->sliceType = X265_TYPE_I;
-        return;
-    }

-    if (m_bBatchMotionSearch)
+    if (framecnt)
     {
-        /* pre-calculate all motion searches, using many worker threads */
-        CostEstimateGroup estGroup(*this, frames);
-        for (int b = 2; b < numFrames; b++)
+        if (bIsVbvLookahead)
+            numFrames = framecnt;
+        else if (m_param->bOpenGOP && numFrames < framecnt)
+            numFrames++;
+        else if (numFrames == 0)
         {
-            for (int i = 1; i <= m_param->bframes + 1; i++)
-            {
-                int p0 = b - i;
-                if (p0 < 0)
-                    continue;
-
-                /* Skip search if already done */
-                if (frames[b]->lowresMvs[0][i][0].x != 0x7FFF)
-                    continue;
-
-                /* perform search to p1 at same distance, if possible */
-                int p1 = b + i;
-                if (p1 >= numFrames || frames[b]->lowresMvs[1][i][0].x != 0x7FFF)
-                    p1 = b;
-
-                estGroup.add(p0, p1, b);
-            }
+            frames[1]->sliceType = X265_TYPE_I;
+            return;
         }
-        /* auto-disable after the first batch if pool is small */
-        m_bBatchMotionSearch &= m_pool->m_numWorkers >= 4;
-        estGroup.finishBatch();

-        if (m_bBatchFrameCosts)
+        if (m_bBatchMotionSearch)
         {
-            /* pre-calculate all frame cost estimates, using many worker threads */
+            /* pre-calculate all motion searches, using many worker threads */
+            CostEstimateGroup estGroup(*this, frames);
             for (int b = 2; b < numFrames; b++)
             {
                 for (int i = 1; i <= m_param->bframes + 1; i++)
                 {
-                    if (b < i)
+                    int p0 = b - i;
+                    if (p0 < 0)
                         continue;

-                    /* only measure frame cost in this pass if motion searches
-                     * are already done */
-                    if (frames[b]->lowresMvs[0][i][0].x == 0x7FFF)
+                    /* Skip search if already done */
+                    if (frames[b]->lowresMvs[0][i][0].x != 0x7FFF)
                         continue;

-                    int p0 = b - i;
+                    /* perform search to p1 at same distance, if possible */
+                    int p1 = b + i;
+                    if (p1 >= numFrames || frames[b]->lowresMvs[1][i][0].x != 0x7FFF)
+                        p1 = b;

-                    for (int j = 0; j <= m_param->bframes; j++)
-                    {
-                        int p1 = b + j;
-                        if (p1 >= numFrames)
-                            break;
+                    estGroup.add(p0, p1, b);
+                }
+            }
+            /* auto-disable after the first batch if pool is small */
+            m_bBatchMotionSearch &= m_pool->m_numWorkers >= 4;
+            estGroup.finishBatch();

-                        /* ensure P1 search is done */
-                        if (j && frames[b]->lowresMvs[1][j][0].x == 0x7FFF)
+            if (m_bBatchFrameCosts)
+            {
+                /* pre-calculate all frame cost estimates, using many worker threads */
+                for (int b = 2; b < numFrames; b++)
+                {
+                    for (int i = 1; i <= m_param->bframes + 1; i++)
+                    {
+                        if (b < i)
                             continue;

-                        /* ensure frame cost is not done */
-                        if (frames[b]->costEst[i][j] >= 0)
+                        /* only measure frame cost in this pass if motion searches
+                         * are already done */
+                        if (frames[b]->lowresMvs[0][i][0].x == 0x7FFF)
                             continue;

-                        estGroup.add(p0, p1, b);
+                        int p0 = b - i;
+
+                        for (int j = 0; j <= m_param->bframes; j++)
+                        {
+                            int p1 = b + j;
+                            if (p1 >= numFrames)
+                                break;
+
+                            /* ensure P1 search is done */
+                            if (j && frames[b]->lowresMvs[1][j][0].x == 0x7FFF)
+                                continue;
+
+                            /* ensure frame cost is not done */
+                            if (frames[b]->costEst[i][j] >= 0)
+                                continue;
+
+                            estGroup.add(p0, p1, b);
+                        }
                     }
                 }
-            }

-            /* auto-disable after the first batch if the pool is not large */
-            m_bBatchFrameCosts &= m_pool->m_numWorkers > 12;
-            estGroup.finishBatch();
+                /* auto-disable after the first batch if the pool is not large */
+                m_bBatchFrameCosts &= m_pool->m_numWorkers > 12;
+                estGroup.finishBatch();
+            }
         }
-    }

-    int numBFrames = 0;
-    int numAnalyzed = numFrames;
-    bool isScenecut = false;
+        int numBFrames = 0;
+        int numAnalyzed = numFrames;
+        bool isScenecut = false;

-    if (m_param->bHistBasedSceneCut)
-        isScenecut = histBasedScenecut(frames, 0, 1, origNumFrames);
-    else
-        isScenecut = scenecut(frames, 0, 1, true, origNumFrames);
+        if (m_param->bHistBasedSceneCut)
+            isScenecut = histBasedScenecut(frames, 0, 1, origNumFrames);
+        else
+            isScenecut = scenecut(frames, 0, 1, true, origNumFrames);

-    /* When scenecut threshold is set, use scenecut detection for I frame placements */
-    if (m_param->scenecutThreshold && isScenecut)
-    {
-        frames[1]->sliceType = X265_TYPE_I;
-        return;
-    }
-    if (m_param->gopLookahead && (keyFrameLimit >= 0) && (keyFrameLimit <= m_param->bframes + 1))
-    {
-        bool sceneTransition = m_isSceneTransition;
-        m_extendGopBoundary = false;
-        for (int i = m_param->bframes + 1; i < origNumFrames; i += m_param->bframes + 1)
+        /* When scenecut threshold is set, use scenecut detection for I frame placements */
+        if (m_param->scenecutThreshold && isScenecut)
         {
-            scenecut(frames, i, i + 1, true, origNumFrames);
-
-            for (int j = i + 1; j <= X265_MIN(i + m_param->bframes + 1, origNumFrames); j++)
+            frames[1]->sliceType = X265_TYPE_I;
+            return;
+        }
+        if (m_param->gopLookahead && (keyFrameLimit >= 0) && (keyFrameLimit <= m_param->bframes + 1))
+        {
+            bool sceneTransition = m_isSceneTransition;
+            m_extendGopBoundary = false;
+            for (int i = m_param->bframes + 1; i < origNumFrames; i += m_param->bframes + 1)
             {
-                if (frames[j]->bScenecut && scenecutInternal(frames, j - 1, j, true))
+                scenecut(frames, i, i + 1, true, origNumFrames);
+
+                for (int j = i + 1; j <= X265_MIN(i + m_param->bframes + 1, origNumFrames); j++)
                 {
-                    m_extendGopBoundary = true;
-                    break;
+                    if (frames[j]->bScenecut && scenecutInternal(frames, j - 1, j, true))
+                    {
+                        m_extendGopBoundary = true;
+                        break;
+                    }
                 }
+                if (m_extendGopBoundary)
+                    break;
             }
-            if (m_extendGopBoundary)
-                break;
+            m_isSceneTransition = sceneTransition;
         }
-        m_isSceneTransition = sceneTransition;
-    }
-    if (m_param->bframes)
-    {
-        if (m_param->bFrameAdaptive == X265_B_ADAPT_TRELLIS)
+        if (m_param->bframes)
         {
-            if (numFrames > 1)
+            if (m_param->bFrameAdaptive == X265_B_ADAPT_TRELLIS)
             {
-                char best_paths[X265_BFRAME_MAX + 1][X265_LOOKAHEAD_MAX + 1] = { "", "P" };
-                int best_path_index = numFrames % (X265_BFRAME_MAX + 1);
+                if (numFrames > 1)
+                {
+                    char best_paths[X265_BFRAME_MAX + 1][X265_LOOKAHEAD_MAX + 1] = { "", "P" };
+                    int best_path_index = numFrames % (X265_BFRAME_MAX + 1);

-                /* Perform the frame type analysis. */
-                for (int j = 2; j <= numFrames; j++)
-                    slicetypePath(frames, j, best_paths);
+                    /* Perform the frame type analysis. */
+                    for (int j = 2; j <= numFrames; j++)
+                        slicetypePath(frames, j, best_paths);

-                numBFrames = (int)strspn(best_paths[best_path_index], "B");
+                    numBFrames = (int)strspn(best_paths[best_path_index], "B");

-                /* Load the results of the analysis into the frame types. */
-                for (int j = 1; j < numFrames; j++)
-                    frames[j]->sliceType = best_paths[best_path_index][j - 1] == 'B' ? X265_TYPE_B : X265_TYPE_P;
+                    /* Load the results of the analysis into the frame types. */
+                    for (int j = 1; j < numFrames; j++)
+                        frames[j]->sliceType = best_paths[best_path_index][j - 1] == 'B' ? X265_TYPE_B : X265_TYPE_P;
+                }
+                frames[numFrames]->sliceType = X265_TYPE_P;
             }
-            frames[numFrames]->sliceType = X265_TYPE_P;
-        }
-        else if (m_param->bFrameAdaptive == X265_B_ADAPT_FAST)
-        {
-            CostEstimateGroup estGroup(*this, frames);
+            else if (m_param->bFrameAdaptive == X265_B_ADAPT_FAST)
+            {
+                CostEstimateGroup estGroup(*this, frames);

-            int64_t cost1p0, cost2p0, cost1b1, cost2p1;
+                int64_t cost1p0, cost2p0, cost1b1, cost2p1;

-            for (int i = 0; i <= numFrames - 2; )
-            {
-                cost2p1 = estGroup.singleCost(i + 0, i + 2, i + 2, true);
-                if (frames[i + 2]->intraMbs[2] > cuCount / 2)
+                for (int i = 0; i <= numFrames - 2; )
                 {
-                    frames[i + 1]->sliceType = X265_TYPE_P;
-                    frames[i + 2]->sliceType = X265_TYPE_P;
-                    i += 2;
-                    continue;
-                }
+                    cost2p1 = estGroup.singleCost(i + 0, i + 2, i + 2, true);
+                    if (frames[i + 2]->intraMbs[2] > cuCount / 2)
+                    {
+                        frames[i + 1]->sliceType = X265_TYPE_P;
+                        frames[i + 2]->sliceType = X265_TYPE_P;
+                        i += 2;
+                        continue;
+                    }

-                cost1b1 = estGroup.singleCost(i + 0, i + 2, i + 1);
-                cost1p0 = estGroup.singleCost(i + 0, i + 1, i + 1);
-                cost2p0 = estGroup.singleCost(i + 1, i + 2, i + 2);
+                    cost1b1 = estGroup.singleCost(i + 0, i + 2, i + 1);
+                    cost1p0 = estGroup.singleCost(i + 0, i + 1, i + 1);
+                    cost2p0 = estGroup.singleCost(i + 1, i + 2, i + 2);

-                if (cost1p0 + cost2p0 < cost1b1 + cost2p1)
-                {
-                    frames[i + 1]->sliceType = X265_TYPE_P;
-                    i += 1;
-                    continue;
-                }
+                    if (cost1p0 + cost2p0 < cost1b1 + cost2p1)
+                    {
+                        frames[i + 1]->sliceType = X265_TYPE_P;
+                        i += 1;
+                        continue;
+                    }

-// arbitrary and untuned
+                    // arbitrary and untuned
 #define INTER_THRESH 300
 #define P_SENS_BIAS (50 - m_param->bFrameBias)
-                frames[i + 1]->sliceType = X265_TYPE_B;
+                    frames[i + 1]->sliceType = X265_TYPE_B;
+
+                    int j;
+                    for (j = i + 2; j <= X265_MIN(i + m_param->bframes, numFrames - 1); j++)
+                    {
+                        int64_t pthresh = X265_MAX(INTER_THRESH - P_SENS_BIAS * (j - i - 1), INTER_THRESH / 10);
+                        int64_t pcost = estGroup.singleCost(i + 0, j + 1, j + 1, true);
+                        if (pcost > pthresh * cuCount || frames[j + 1]->intraMbs[j - i + 1] > cuCount / 3)
+                            break;
+                        frames[j]->sliceType = X265_TYPE_B;
+                    }
+
+                    frames[j]->sliceType = X265_TYPE_P;
+                    i = j;
+                }
+                frames[numFrames]->sliceType = X265_TYPE_P;
+                numBFrames = 0;
+                while (numBFrames < numFrames && frames[numBFrames + 1]->sliceType == X265_TYPE_B)
+                    numBFrames++;
+            }
+            else
+            {
+                numBFrames = X265_MIN(numFrames - 1, m_param->bframes);
+                for (int j = 1; j < numFrames; j++)
+                    frames[j]->sliceType = (j % (numBFrames + 1)) ? X265_TYPE_B : X265_TYPE_P;
+
+                frames[numFrames]->sliceType = X265_TYPE_P;
+            }

-                int j;
-                for (j = i + 2; j <= X265_MIN(i + m_param->bframes, numFrames - 1); j++)
+            int zoneRadl = m_param->rc.zonefileCount && m_param->bResetZoneConfig ? m_param->rc.zones->zoneParam->radl : 0;
+            bool bForceRADL = zoneRadl || (m_param->radl && (m_param->keyframeMax == m_param->keyframeMin));
+            bool bLastMiniGop = (framecnt >= m_param->bframes + 1) ? false : true;
+            int radl = m_param->radl ? m_param->radl : zoneRadl;
+            int preRADL = m_lastKeyframe + m_param->keyframeMax - radl - 1; /*Frame preceeding RADL in POC order*/
+            if (bForceRADL && (frames[0]->frameNum == preRADL) && !bLastMiniGop)
+            {
+                int j = 1;
+                numBFrames = m_param->radl ? m_param->radl : zoneRadl;
+                for (; j <= numBFrames; j++)
+                    frames[j]->sliceType = X265_TYPE_B;
+                frames[j]->sliceType = X265_TYPE_I;
+            }
+            else /* Check scenecut and RADL on the first minigop. */
+            {
+                for (int j = 1; j < numBFrames + 1; j++)
                 {
-                    int64_t pthresh = X265_MAX(INTER_THRESH - P_SENS_BIAS * (j - i - 1), INTER_THRESH / 10);
-                    int64_t pcost = estGroup.singleCost(i + 0, j + 1, j + 1, true);
-                    if (pcost > pthresh * cuCount || frames[j + 1]->intraMbs[j - i + 1] > cuCount / 3)
+                    if (scenecut(frames, j, j + 1, false, origNumFrames) ||
+                        (bForceRADL && (frames[j]->frameNum == preRADL)))
+                    {
+                        frames[j]->sliceType = X265_TYPE_P;
+                        numAnalyzed = j;
                         break;
-                    frames[j]->sliceType = X265_TYPE_B;
+                    }
                 }
-
-                frames[j]->sliceType = X265_TYPE_P;
-                i = j;
             }
-            frames[numFrames]->sliceType = X265_TYPE_P;
-            numBFrames = 0;
-            while (numBFrames < numFrames && frames[numBFrames + 1]->sliceType == X265_TYPE_B)
-                numBFrames++;
+            resetStart = bKeyframe ? 1 : X265_MIN(numBFrames + 2, numAnalyzed + 1);
         }
         else
         {
-            numBFrames = X265_MIN(numFrames - 1, m_param->bframes);
-            for (int j = 1; j < numFrames; j++)
-                frames[j]->sliceType = (j % (numBFrames + 1)) ? X265_TYPE_B : X265_TYPE_P;
+            for (int j = 1; j <= numFrames; j++)
+                frames[j]->sliceType = X265_TYPE_P;

-            frames[numFrames]->sliceType = X265_TYPE_P;
+            resetStart = bKeyframe ? 1 : 2;
         }
+        if (m_param->bAQMotion)
+            aqMotion(frames, bKeyframe);

-        int zoneRadl = m_param->rc.zonefileCount && m_param->bResetZoneConfig ? m_param->rc.zones->zoneParam->radl : 0;
-        bool bForceRADL = zoneRadl || (m_param->radl && (m_param->keyframeMax == m_param->keyframeMin));
-        bool bLastMiniGop = (framecnt >= m_param->bframes + 1) ? false : true;
-        int radl = m_param->radl ? m_param->radl : zoneRadl;
-        int preRADL = m_lastKeyframe + m_param->keyframeMax - radl - 1; /*Frame preceeding RADL in POC order*/
-        if (bForceRADL && (frames[0]->frameNum == preRADL) && !bLastMiniGop)
-        {
-            int j = 1;
-            numBFrames = m_param->radl ? m_param->radl : zoneRadl;
-            for (; j <= numBFrames; j++)
-                frames[j]->sliceType = X265_TYPE_B;
-            frames[j]->sliceType = X265_TYPE_I;
-        }
-        else /* Check scenecut and RADL on the first minigop. */
-        {
-            for (int j = 1; j < numBFrames + 1; j++)
-            {
-                if (scenecut(frames, j, j + 1, false, origNumFrames) ||
-                    (bForceRADL && (frames[j]->frameNum == preRADL)))
-                {
-                    frames[j]->sliceType = X265_TYPE_P;
-                    numAnalyzed = j;
-                    break;
-                }
-            }
-        }
-        resetStart = bKeyframe ? 1 : X265_MIN(numBFrames + 2, numAnalyzed + 1);
-    }
-    else
-    {
-        for (int j = 1; j <= numFrames; j++)
-            frames[j]->sliceType = X265_TYPE_P;
+        if (m_param->rc.cuTree)
+            cuTree(frames, X265_MIN(numFrames, m_param->keyframeMax), bKeyframe);

-        resetStart = bKeyframe ? 1 : 2;
-    }
-    if (m_param->bAQMotion)
-        aqMotion(frames, bKeyframe);
+        if (m_param->gopLookahead && (keyFrameLimit >= 0) && (keyFrameLimit <= m_param->bframes + 1) && !m_extendGopBoundary)
+            keyintLimit = keyFrameLimit;

-    if (m_param->rc.cuTree)
-        cuTree(frames, X265_MIN(numFrames, m_param->keyframeMax), bKeyframe);
+        if (!m_param->bIntraRefresh)
+            for (int j = keyintLimit + 1; j <= numFrames; j += m_param->keyframeMax)
+            {
+                frames[j]->sliceType = X265_TYPE_I;
+                resetStart = X265_MIN(resetStart, j + 1);
+            }

-    if (m_param->gopLookahead && (keyFrameLimit >= 0) && (keyFrameLimit <= m_param->bframes + 1) && !m_extendGopBoundary)
-        keyintLimit = keyFrameLimit;
+        if (bIsVbvLookahead)
+            vbvLookahead(frames, numFrames, bKeyframe);
+        int maxp1 = X265_MIN(m_param->bframes + 1, origNumFrames);

-    if (!m_param->bIntraRefresh)
-        for (int j = keyintLimit + 1; j <= numFrames; j += m_param->keyframeMax)
+        /* Restore frame types for all frames that haven't actually been decided yet. */
+        for (int j = resetStart; j <= numFrames; j++)
         {
-            frames[j]->sliceType = X265_TYPE_I;
-            resetStart = X265_MIN(resetStart, j + 1);
+            frames[j]->sliceType = X265_TYPE_AUTO;
+            /* If any frame marked as scenecut is being restarted for sliceDecision,
+             * undo scene Transition flag */
+            if (j <= maxp1 && frames[j]->bScenecut && m_isSceneTransition)
+                m_isSceneTransition = false;
         }
+    }

-    if (bIsVbvLookahead)
-        vbvLookahead(frames, numFrames, bKeyframe);
-    int maxp1 = X265_MIN(m_param->bframes + 1, origNumFrames);
-
-    /* Restore frame types for all frames that haven't actually been decided yet. */
-    for (int j = resetStart; j <= numFrames; j++)
+    if (m_param->rc.cuTree && !framecnt)
     {
-        frames[j]->sliceType = X265_TYPE_AUTO;
-        /* If any frame marked as scenecut is being restarted for sliceDecision,
-         * undo scene Transition flag */
-        if (j <= maxp1 && frames[j]->bScenecut && m_isSceneTransition)
-            m_isSceneTransition = false;
+        for (framecnt = 0; framecnt < maxSearch; framecnt++)
+        {
+            Lowres* shhh = frames[framecnt + 1];
+            if (!shhh)
+                break;
+        }
+        cuTree(frames, X265_MIN(framecnt, m_param->keyframeMax), bKeyframe);
     }
 }

--
2.47.0.windows.1



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20250707/6fdd10e7/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-fix-for-crf-and-vbv-issue-in-abr-ladder.patch
Type: application/octet-stream
Size: 23448 bytes
Desc: 0001-fix-for-crf-and-vbv-issue-in-abr-ladder.patch
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20250707/6fdd10e7/attachment-0001.obj>


More information about the x265-devel mailing list