[PR] swresample/rematrix: Avoid repeated calls to av_channel_layout* funcs (PR #24039)

mkver via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178609762526.59.17413125557489603769@29965ddac10e>
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]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.