PR #24039 opened by mkver
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24039
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24039.patch


>From f351bb5584a2296271a52ba8e6eb4d8ff37583d3 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Fri, 7 Aug 2026 12:10:01 +0200
Subject: [PATCH] swresample/rematrix: Avoid repeated calls to
 av_channel_layout* funcs

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libswresample/rematrix.c | 101 +++++++++++++++++++--------------------
 1 file changed, 50 insertions(+), 51 deletions(-)

diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c
index 269849a427..bcdb71ce4f 100644
--- a/libswresample/rematrix.c
+++ b/libswresample/rematrix.c
@@ -115,19 +115,20 @@ static int sane_layout(AVChannelLayout *ch_layout) {
         }
     else if (ch_layout->order != AV_CHANNEL_ORDER_NATIVE)
         return 0;
-    if(!av_channel_layout_subset(ch_layout, AV_CH_LAYOUT_SURROUND)) // at 
least 1 front speaker
+    uint64_t mask = av_channel_layout_subset(ch_layout, ~(uint64_t)0);
+    if(!(mask & AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
         return 0;
-    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT | 
AV_CH_FRONT_RIGHT)))) // no asymmetric front
+    if (!even(mask & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymmetric 
front
         return 0;
-    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_SIDE_LEFT | 
AV_CH_SIDE_RIGHT))))   // no asymmetric side
+    if (!even(mask & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))   // no asymmetric 
side
         return 0;
-    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_BACK_LEFT | 
AV_CH_BACK_RIGHT))))
+    if (!even(mask & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))
         return 0;
-    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT_OF_CENTER | 
AV_CH_FRONT_RIGHT_OF_CENTER))))
+    if (!even(mask & (AV_CH_FRONT_LEFT_OF_CENTER | 
AV_CH_FRONT_RIGHT_OF_CENTER)))
         return 0;
-    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_TOP_FRONT_LEFT | 
AV_CH_TOP_FRONT_RIGHT))))
+    if (!even(mask & (AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT)))
         return 0;
-    if(!even(av_channel_layout_subset(ch_layout, (AV_CH_TOP_BACK_LEFT | 
AV_CH_TOP_BACK_RIGHT))))
+    if (!even(mask & (AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT)))
         return 0;
 
     return 1;
@@ -139,14 +140,14 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
                          ptrdiff_t stride, enum AVMatrixEncoding 
matrix_encoding)
 {
     double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}};
-    uint64_t unaccounted =  av_channel_layout_subset(in_ch_layout,  
UINT64_MAX) &
-                           ~av_channel_layout_subset(out_ch_layout, 
UINT64_MAX);
+    uint64_t in_mask  = av_channel_layout_subset(in_ch_layout,  ~(uint64_t)0);
+    uint64_t out_mask = av_channel_layout_subset(out_ch_layout, ~(uint64_t)0);
+    uint64_t unaccounted =  in_mask & ~out_mask;
     double maxcoef=0;
     int i, j;
 
     for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){
-        if(   av_channel_layout_index_from_channel(in_ch_layout, i) >= 0
-           && av_channel_layout_index_from_channel(out_ch_layout, i) >= 0)
+        if (in_mask & out_mask & (1ULL << i))
             matrix[i][i]= 1.0;
     }
 
@@ -154,8 +155,8 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
 //FIXME implement full ac3
 
     if(unaccounted & AV_CH_FRONT_CENTER){
-        if (av_channel_layout_subset(out_ch_layout, AV_CH_LAYOUT_STEREO) == 
AV_CH_LAYOUT_STEREO) {
-            if (av_channel_layout_subset(in_ch_layout, AV_CH_LAYOUT_STEREO)) {
+        if ((out_mask & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) {
+            if (in_mask & AV_CH_LAYOUT_STEREO) {
                 matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level;
                 matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level;
             } else {
@@ -166,23 +167,23 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
             av_assert0(0);
     }
     if(unaccounted & AV_CH_LAYOUT_STEREO){
-        if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_CENTER) >= 0) {
+        if (out_mask & AV_CH_FRONT_CENTER) {
             matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2;
             matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2;
-            if (av_channel_layout_index_from_channel(in_ch_layout, 
AV_CHAN_FRONT_CENTER) >= 0)
+            if (in_mask & AV_CH_FRONT_CENTER)
                 matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2);
         }else
             av_assert0(0);
     }
 
     if(unaccounted & AV_CH_BACK_CENTER){
-        if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_BACK_LEFT) >= 0) {
+        if (out_mask & AV_CH_BACK_LEFT) {
             matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2;
             matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_SIDE_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_SIDE_LEFT) {
             matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2;
             matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_LEFT) {
             if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
                 matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
                 if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
@@ -196,24 +197,24 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
                 matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * 
M_SQRT1_2;
                 matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * 
M_SQRT1_2;
             }
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_CENTER) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_CENTER) {
             matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * 
M_SQRT1_2;
         }else
             av_assert0(0);
     }
     if(unaccounted & AV_CH_BACK_LEFT){
-        if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_BACK_CENTER) >= 0) {
+        if (out_mask & AV_CH_BACK_CENTER) {
             matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2;
             matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_SIDE_LEFT) >= 0) {
-            if (av_channel_layout_index_from_channel(in_ch_layout, 
AV_CHAN_SIDE_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_SIDE_LEFT) {
+            if (in_mask & AV_CH_SIDE_LEFT) {
                 matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2;
                 matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2;
             }else{
             matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
             matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
             }
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_LEFT) {
             if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
                 matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * 
M_SQRT1_2;
                 matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * 
M_SQRT1_2;
@@ -228,7 +229,7 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
                 matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level;
                 matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
             }
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_CENTER) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_CENTER) {
             matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2;
             matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2;
         }else
@@ -236,20 +237,20 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
     }
 
     if(unaccounted & AV_CH_SIDE_LEFT){
-        if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_BACK_LEFT) >= 0) {
+        if (out_mask & AV_CH_BACK_LEFT) {
             /* if back channels do not exist in the input, just copy side
                channels to back channels, otherwise mix side into back */
-            if (av_channel_layout_index_from_channel(in_ch_layout, 
AV_CHAN_BACK_LEFT) >= 0) {
+            if (in_mask & AV_CH_BACK_LEFT) {
                 matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
                 matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
             } else {
                 matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
                 matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
             }
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_BACK_CENTER) >= 0) {
+        } else if (out_mask & AV_CH_BACK_CENTER) {
             matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
             matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_LEFT) {
             if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
                 matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * 
M_SQRT1_2;
                 matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * 
M_SQRT1_2;
@@ -264,7 +265,7 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
                 matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level;
                 matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
             }
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_CENTER) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_CENTER) {
             matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2;
             matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2;
         }else
@@ -272,10 +273,10 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
     }
 
     if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
-        if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_LEFT) >= 0) {
+        if (out_mask & AV_CH_FRONT_LEFT) {
             matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
             matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_CENTER) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_CENTER) {
             matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2;
             matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2;
         }else
@@ -283,16 +284,16 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
     }
 
     if (unaccounted & AV_CH_TOP_FRONT_LEFT) {
-        if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_TOP_FRONT_CENTER) >= 0) {
+        if (out_mask & AV_CH_TOP_FRONT_CENTER) {
             matrix[TOP_FRONT_CENTER][TOP_FRONT_LEFT ] += M_SQRT1_2;
             matrix[TOP_FRONT_CENTER][TOP_FRONT_RIGHT] += M_SQRT1_2;
-            if (av_channel_layout_index_from_channel(in_ch_layout, 
AV_CHAN_TOP_FRONT_CENTER) >= 0)
+            if (in_mask & AV_CH_TOP_FRONT_CENTER)
                 matrix[TOP_FRONT_CENTER][TOP_FRONT_CENTER] = center_mix_level 
* sqrt(2);
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_LEFT) {
             /* U+030 -> M+030 in ITU-R BS.2127-1, Table 16. */
             matrix[FRONT_LEFT ][TOP_FRONT_LEFT ] += 1.0;
             matrix[FRONT_RIGHT][TOP_FRONT_RIGHT] += 1.0;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_CENTER) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_CENTER) {
             matrix[FRONT_CENTER][TOP_FRONT_LEFT ] += M_SQRT1_2;
             matrix[FRONT_CENTER][TOP_FRONT_RIGHT] += M_SQRT1_2;
         } else
@@ -300,23 +301,23 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
     }
 
     if (unaccounted & AV_CH_TOP_BACK_LEFT) {
-        if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_TOP_BACK_CENTER) >= 0) {
+        if (out_mask & AV_CH_TOP_BACK_CENTER) {
             matrix[TOP_BACK_CENTER][TOP_BACK_LEFT ] += M_SQRT1_2;
             matrix[TOP_BACK_CENTER][TOP_BACK_RIGHT] += M_SQRT1_2;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_TOP_FRONT_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_TOP_FRONT_LEFT) {
             /* IAMF v1.1.0, Section 7.3.2.1.1. */
             matrix[TOP_FRONT_LEFT ][TOP_BACK_LEFT ] += M_SQRT1_2;
             matrix[TOP_FRONT_RIGHT][TOP_BACK_RIGHT] += M_SQRT1_2;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_BACK_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_BACK_LEFT) {
             matrix[BACK_LEFT ][TOP_BACK_LEFT ] += 1.0;
             matrix[BACK_RIGHT][TOP_BACK_RIGHT] += 1.0;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_SIDE_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_SIDE_LEFT) {
             matrix[SIDE_LEFT ][TOP_BACK_LEFT ] += 1.0;
             matrix[SIDE_RIGHT][TOP_BACK_RIGHT] += 1.0;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_LEFT) {
             matrix[FRONT_LEFT ][TOP_BACK_LEFT ] += surround_mix_level;
             matrix[FRONT_RIGHT][TOP_BACK_RIGHT] += surround_mix_level;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_CENTER) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_CENTER) {
             matrix[FRONT_CENTER][TOP_BACK_LEFT ] += M_SQRT1_2;
             matrix[FRONT_CENTER][TOP_BACK_RIGHT] += M_SQRT1_2;
         } else
@@ -325,19 +326,19 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
 
     /* BS.2127-1 maps U+180 to rear outputs before front outputs. */
     if (unaccounted & AV_CH_TOP_BACK_CENTER) {
-        if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_TOP_BACK_LEFT) >= 0) {
+        if (out_mask & AV_CH_TOP_BACK_LEFT) {
             matrix[TOP_BACK_LEFT ][TOP_BACK_CENTER] += M_SQRT1_2;
             matrix[TOP_BACK_RIGHT][TOP_BACK_CENTER] += M_SQRT1_2;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_BACK_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_BACK_LEFT) {
             matrix[BACK_LEFT ][TOP_BACK_CENTER] += M_SQRT1_2;
             matrix[BACK_RIGHT][TOP_BACK_CENTER] += M_SQRT1_2;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_SIDE_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_SIDE_LEFT) {
             matrix[SIDE_LEFT ][TOP_BACK_CENTER] += M_SQRT1_2;
             matrix[SIDE_RIGHT][TOP_BACK_CENTER] += M_SQRT1_2;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_LEFT) {
             matrix[FRONT_LEFT ][TOP_BACK_CENTER] += 0.5;
             matrix[FRONT_RIGHT][TOP_BACK_CENTER] += 0.5;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_CENTER) >= 0)
+        } else if (out_mask & AV_CH_FRONT_CENTER)
             matrix[FRONT_CENTER][TOP_BACK_CENTER] += 0.5;
         else
             av_assert0(0);
@@ -345,9 +346,9 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
 
     /* mix LFE into front left/right or center */
     if (unaccounted & AV_CH_LOW_FREQUENCY) {
-        if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_CENTER) >= 0) {
+        if (out_mask & AV_CH_FRONT_CENTER) {
             matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
-        } else if (av_channel_layout_index_from_channel(out_ch_layout, 
AV_CHAN_FRONT_LEFT) >= 0) {
+        } else if (out_mask & AV_CH_FRONT_LEFT) {
             matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
             matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
         } else
@@ -367,9 +368,7 @@ static void build_matrix(const AVChannelLayout 
*in_ch_layout, const AVChannelLay
             if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0]))
                 matrix_param[stride*out_i + in_i] = matrix[i][j];
             else
-                matrix_param[stride*out_i + in_i] = i == j &&
-                (   av_channel_layout_index_from_channel(in_ch_layout, i) >= 0
-                 && av_channel_layout_index_from_channel(out_ch_layout, i) >= 
0);
+                matrix_param[stride*out_i + in_i] = i == j && (in_mask & 
out_mask & (1ULL << i));
             sum += fabs(matrix_param[stride*out_i + in_i]);
         }
         maxcoef= FFMAX(maxcoef, sum);
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to