LCOV - code coverage report
Current view: top level - libswresample - rematrix.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 191 365 52.3 %
Date: 2018-04-21 10:11:13 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2011-2012 Michael Niedermayer (michaelni@gmx.at)
       3             :  *
       4             :  * This file is part of libswresample
       5             :  *
       6             :  * libswresample is free software; you can redistribute it and/or
       7             :  * modify it under the terms of the GNU Lesser General Public
       8             :  * License as published by the Free Software Foundation; either
       9             :  * version 2.1 of the License, or (at your option) any later version.
      10             :  *
      11             :  * libswresample is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with libswresample; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include "swresample_internal.h"
      22             : #include "libavutil/avassert.h"
      23             : #include "libavutil/channel_layout.h"
      24             : 
      25             : #define TEMPLATE_REMATRIX_FLT
      26             : #include "rematrix_template.c"
      27             : #undef TEMPLATE_REMATRIX_FLT
      28             : 
      29             : #define TEMPLATE_REMATRIX_DBL
      30             : #include "rematrix_template.c"
      31             : #undef TEMPLATE_REMATRIX_DBL
      32             : 
      33             : #define TEMPLATE_REMATRIX_S16
      34             : #include "rematrix_template.c"
      35             : #define TEMPLATE_CLIP
      36             : #include "rematrix_template.c"
      37             : #undef TEMPLATE_CLIP
      38             : #undef TEMPLATE_REMATRIX_S16
      39             : 
      40             : #define TEMPLATE_REMATRIX_S32
      41             : #include "rematrix_template.c"
      42             : #undef TEMPLATE_REMATRIX_S32
      43             : 
      44             : #define FRONT_LEFT             0
      45             : #define FRONT_RIGHT            1
      46             : #define FRONT_CENTER           2
      47             : #define LOW_FREQUENCY          3
      48             : #define BACK_LEFT              4
      49             : #define BACK_RIGHT             5
      50             : #define FRONT_LEFT_OF_CENTER   6
      51             : #define FRONT_RIGHT_OF_CENTER  7
      52             : #define BACK_CENTER            8
      53             : #define SIDE_LEFT              9
      54             : #define SIDE_RIGHT             10
      55             : #define TOP_CENTER             11
      56             : #define TOP_FRONT_LEFT         12
      57             : #define TOP_FRONT_CENTER       13
      58             : #define TOP_FRONT_RIGHT        14
      59             : #define TOP_BACK_LEFT          15
      60             : #define TOP_BACK_CENTER        16
      61             : #define TOP_BACK_RIGHT         17
      62             : #define NUM_NAMED_CHANNELS     18
      63             : 
      64           4 : int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride)
      65             : {
      66             :     int nb_in, nb_out, in, out;
      67             : 
      68           4 :     if (!s || s->in_convert) // s needs to be allocated but not initialized
      69           0 :         return AVERROR(EINVAL);
      70           4 :     memset(s->matrix, 0, sizeof(s->matrix));
      71           4 :     memset(s->matrix_flt, 0, sizeof(s->matrix_flt));
      72           4 :     nb_in = (s->user_in_ch_count > 0) ? s->user_in_ch_count :
      73           0 :         av_get_channel_layout_nb_channels(s->user_in_ch_layout);
      74           4 :     nb_out = (s->user_out_ch_count > 0) ? s->user_out_ch_count :
      75           0 :         av_get_channel_layout_nb_channels(s->user_out_ch_layout);
      76          13 :     for (out = 0; out < nb_out; out++) {
      77          29 :         for (in = 0; in < nb_in; in++)
      78          20 :             s->matrix_flt[out][in] = s->matrix[out][in] = matrix[in];
      79           9 :         matrix += stride;
      80             :     }
      81           4 :     s->rematrix_custom = 1;
      82           4 :     return 0;
      83             : }
      84             : 
      85          80 : static int even(int64_t layout){
      86          80 :     if(!layout) return 1;
      87          12 :     if(layout&(layout-1)) return 1;
      88           0 :     return 0;
      89             : }
      90             : 
      91          20 : static int clean_layout(void *s, int64_t layout){
      92          20 :     if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) {
      93             :         char buf[128];
      94           0 :         av_get_channel_layout_string(buf, sizeof(buf), -1, layout);
      95           0 :         av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf);
      96           0 :         return AV_CH_FRONT_CENTER;
      97             :     }
      98             : 
      99          20 :     return layout;
     100             : }
     101             : 
     102          20 : static int sane_layout(int64_t layout){
     103          20 :     if(!(layout & AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
     104           0 :         return 0;
     105          20 :     if(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymetric front
     106           0 :         return 0;
     107          20 :     if(!even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))   // no asymetric side
     108           0 :         return 0;
     109          20 :     if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))
     110           0 :         return 0;
     111          20 :     if(!even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)))
     112           0 :         return 0;
     113          20 :     if(av_get_channel_layout_nb_channels(layout) >= SWR_CH_MAX)
     114           0 :         return 0;
     115             : 
     116          20 :     return 1;
     117             : }
     118             : 
     119          10 : av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout_param,
     120             :                              double center_mix_level, double surround_mix_level,
     121             :                              double lfe_mix_level, double maxval,
     122             :                              double rematrix_volume, double *matrix_param,
     123             :                              int stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
     124             : {
     125             :     int i, j, out_i;
     126          10 :     double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}};
     127             :     int64_t unaccounted, in_ch_layout, out_ch_layout;
     128          10 :     double maxcoef=0;
     129             :     char buf[128];
     130             : 
     131          10 :      in_ch_layout = clean_layout(log_context,  in_ch_layout_param);
     132          10 :     out_ch_layout = clean_layout(log_context, out_ch_layout_param);
     133             : 
     134          10 :     if(   out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
     135           0 :        && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
     136             :     )
     137           0 :         out_ch_layout = AV_CH_LAYOUT_STEREO;
     138             : 
     139          10 :     if(    in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
     140           0 :        && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
     141             :     )
     142           0 :         in_ch_layout = AV_CH_LAYOUT_STEREO;
     143             : 
     144          10 :     if(!sane_layout(in_ch_layout)){
     145           0 :         av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param);
     146           0 :         av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
     147           0 :         return AVERROR(EINVAL);
     148             :     }
     149             : 
     150          10 :     if(!sane_layout(out_ch_layout)){
     151           0 :         av_get_channel_layout_string(buf, sizeof(buf), -1, out_ch_layout_param);
     152           0 :         av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
     153           0 :         return AVERROR(EINVAL);
     154             :     }
     155             : 
     156         190 :     for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){
     157         180 :         if(in_ch_layout & out_ch_layout & (1ULL<<i))
     158           2 :             matrix[i][i]= 1.0;
     159             :     }
     160             : 
     161          10 :     unaccounted= in_ch_layout & ~out_ch_layout;
     162             : 
     163             : //FIXME implement dolby surround
     164             : //FIXME implement full ac3
     165             : 
     166             : 
     167          10 :     if(unaccounted & AV_CH_FRONT_CENTER){
     168           3 :         if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
     169           3 :             if(in_ch_layout & AV_CH_LAYOUT_STEREO) {
     170           0 :                 matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level;
     171           0 :                 matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level;
     172             :             } else {
     173           3 :                 matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2;
     174           3 :                 matrix[FRONT_RIGHT][FRONT_CENTER]+= M_SQRT1_2;
     175             :             }
     176             :         }else
     177           0 :             av_assert0(0);
     178             :     }
     179          10 :     if(unaccounted & AV_CH_LAYOUT_STEREO){
     180           6 :         if(out_ch_layout & AV_CH_FRONT_CENTER){
     181           6 :             matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2;
     182           6 :             matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2;
     183           6 :             if(in_ch_layout & AV_CH_FRONT_CENTER)
     184           0 :                 matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2);
     185             :         }else
     186           0 :             av_assert0(0);
     187             :     }
     188             : 
     189          10 :     if(unaccounted & AV_CH_BACK_CENTER){
     190           0 :         if(out_ch_layout & AV_CH_BACK_LEFT){
     191           0 :             matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2;
     192           0 :             matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2;
     193           0 :         }else if(out_ch_layout & AV_CH_SIDE_LEFT){
     194           0 :             matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2;
     195           0 :             matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2;
     196           0 :         }else if(out_ch_layout & AV_CH_FRONT_LEFT){
     197           0 :             if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
     198             :                 matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
     199           0 :                 if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
     200           0 :                     matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2;
     201           0 :                     matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
     202             :                 } else {
     203           0 :                     matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level;
     204           0 :                     matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level;
     205             :                 }
     206             :             } else {
     207           0 :                 matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
     208           0 :                 matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
     209             :             }
     210           0 :         }else if(out_ch_layout & AV_CH_FRONT_CENTER){
     211           0 :             matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
     212             :         }else
     213           0 :             av_assert0(0);
     214             :     }
     215          10 :     if(unaccounted & AV_CH_BACK_LEFT){
     216           0 :         if(out_ch_layout & AV_CH_BACK_CENTER){
     217           0 :             matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2;
     218           0 :             matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2;
     219           0 :         }else if(out_ch_layout & AV_CH_SIDE_LEFT){
     220           0 :             if(in_ch_layout & AV_CH_SIDE_LEFT){
     221           0 :                 matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2;
     222           0 :                 matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2;
     223             :             }else{
     224           0 :             matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
     225           0 :             matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
     226             :             }
     227           0 :         }else if(out_ch_layout & AV_CH_FRONT_LEFT){
     228           0 :             if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
     229           0 :                 matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
     230           0 :                 matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
     231           0 :                 matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
     232           0 :                 matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
     233           0 :             } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
     234           0 :                 matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2;
     235           0 :                 matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
     236           0 :                 matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
     237           0 :                 matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2;
     238             :             } else {
     239           0 :                 matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level;
     240           0 :                 matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
     241             :             }
     242           0 :         }else if(out_ch_layout & AV_CH_FRONT_CENTER){
     243           0 :             matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2;
     244           0 :             matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2;
     245             :         }else
     246           0 :             av_assert0(0);
     247             :     }
     248             : 
     249          10 :     if(unaccounted & AV_CH_SIDE_LEFT){
     250           0 :         if(out_ch_layout & AV_CH_BACK_LEFT){
     251             :             /* if back channels do not exist in the input, just copy side
     252             :                channels to back channels, otherwise mix side into back */
     253           0 :             if (in_ch_layout & AV_CH_BACK_LEFT) {
     254           0 :                 matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
     255           0 :                 matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
     256             :             } else {
     257           0 :                 matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
     258           0 :                 matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
     259             :             }
     260           0 :         }else if(out_ch_layout & AV_CH_BACK_CENTER){
     261           0 :             matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
     262           0 :             matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
     263           0 :         }else if(out_ch_layout & AV_CH_FRONT_LEFT){
     264           0 :             if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
     265           0 :                 matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
     266           0 :                 matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
     267           0 :                 matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
     268           0 :                 matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
     269           0 :             } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
     270           0 :                 matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2;
     271           0 :                 matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
     272           0 :                 matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
     273           0 :                 matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2;
     274             :             } else {
     275           0 :                 matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level;
     276           0 :                 matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
     277             :             }
     278           0 :         }else if(out_ch_layout & AV_CH_FRONT_CENTER){
     279           0 :             matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2;
     280           0 :             matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2;
     281             :         }else
     282           0 :             av_assert0(0);
     283             :     }
     284             : 
     285          10 :     if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
     286           0 :         if(out_ch_layout & AV_CH_FRONT_LEFT){
     287           0 :             matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
     288           0 :             matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
     289           0 :         }else if(out_ch_layout & AV_CH_FRONT_CENTER){
     290           0 :             matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2;
     291           0 :             matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2;
     292             :         }else
     293           0 :             av_assert0(0);
     294             :     }
     295             :     /* mix LFE into front left/right or center */
     296          10 :     if (unaccounted & AV_CH_LOW_FREQUENCY) {
     297           0 :         if (out_ch_layout & AV_CH_FRONT_CENTER) {
     298           0 :             matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
     299           0 :         } else if (out_ch_layout & AV_CH_FRONT_LEFT) {
     300           0 :             matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
     301           0 :             matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
     302             :         } else
     303           0 :             av_assert0(0);
     304             :     }
     305             : 
     306         650 :     for(out_i=i=0; i<64; i++){
     307         640 :         double sum=0;
     308         640 :         int in_i=0;
     309         640 :         if((out_ch_layout & (1ULL<<i)) == 0)
     310         622 :             continue;
     311        1170 :         for(j=0; j<64; j++){
     312        1152 :             if((in_ch_layout & (1ULL<<j)) == 0)
     313        1122 :                continue;
     314          30 :             if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0]))
     315          30 :                 matrix_param[stride*out_i + in_i] = matrix[i][j];
     316             :             else
     317           0 :                 matrix_param[stride*out_i + in_i] = i == j && (in_ch_layout & out_ch_layout & (1ULL<<i));
     318          30 :             sum += fabs(matrix_param[stride*out_i + in_i]);
     319          30 :             in_i++;
     320             :         }
     321          18 :         maxcoef= FFMAX(maxcoef, sum);
     322          18 :         out_i++;
     323             :     }
     324          10 :     if(rematrix_volume  < 0)
     325           0 :         maxcoef = -rematrix_volume;
     326             : 
     327          10 :     if(maxcoef > maxval || rematrix_volume  < 0){
     328           6 :         maxcoef /= maxval;
     329         390 :         for(i=0; i<SWR_CH_MAX; i++)
     330       24960 :             for(j=0; j<SWR_CH_MAX; j++){
     331       24576 :                 matrix_param[stride*i + j] /= maxcoef;
     332             :             }
     333             :     }
     334             : 
     335          10 :     if(rematrix_volume > 0){
     336         650 :         for(i=0; i<SWR_CH_MAX; i++)
     337       41600 :             for(j=0; j<SWR_CH_MAX; j++){
     338       40960 :                 matrix_param[stride*i + j] *= rematrix_volume;
     339             :             }
     340             :     }
     341             : 
     342          10 :     av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n");
     343          28 :     for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){
     344          18 :         const char *c =
     345          18 :             av_get_channel_name(av_channel_layout_extract_channel(out_ch_layout, i));
     346          18 :         av_log(log_context, AV_LOG_DEBUG, "%s: ", c ? c : "?");
     347          48 :         for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){
     348          30 :             c = av_get_channel_name(av_channel_layout_extract_channel(in_ch_layout, j));
     349          30 :             av_log(log_context, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", matrix_param[stride*i + j]);
     350             :         }
     351          18 :         av_log(log_context, AV_LOG_DEBUG, "\n");
     352             :     }
     353          10 :     return 0;
     354             : }
     355             : 
     356          10 : av_cold static int auto_matrix(SwrContext *s)
     357             : {
     358             :     double maxval;
     359             :     int ret;
     360             : 
     361          10 :     if (s->rematrix_maxval > 0) {
     362           0 :         maxval = s->rematrix_maxval;
     363          10 :     } else if (   av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT
     364           1 :                || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) {
     365           9 :         maxval = 1.0;
     366             :     } else
     367           1 :         maxval = INT_MAX;
     368             : 
     369          10 :     memset(s->matrix, 0, sizeof(s->matrix));
     370          50 :     ret = swr_build_matrix(s->in_ch_layout, s->out_ch_layout,
     371          30 :                            s->clev, s->slev, s->lfe_mix_level,
     372          10 :                            maxval, s->rematrix_volume, (double*)s->matrix,
     373          10 :                            s->matrix[1] - s->matrix[0], s->matrix_encoding, s);
     374             : 
     375          10 :     if (ret >= 0 && s->int_sample_fmt == AV_SAMPLE_FMT_FLTP) {
     376             :         int i, j;
     377         455 :         for (i = 0; i < FF_ARRAY_ELEMS(s->matrix[0]); i++)
     378       29120 :             for (j = 0; j < FF_ARRAY_ELEMS(s->matrix[0]); j++)
     379       28672 :                 s->matrix_flt[i][j] = s->matrix[i][j];
     380             :     }
     381             : 
     382          10 :     return ret;
     383             : }
     384             : 
     385          14 : av_cold int swri_rematrix_init(SwrContext *s){
     386             :     int i, j;
     387          14 :     int nb_in  = av_get_channel_layout_nb_channels(s->in_ch_layout);
     388          14 :     int nb_out = av_get_channel_layout_nb_channels(s->out_ch_layout);
     389             : 
     390          14 :     s->mix_any_f = NULL;
     391             : 
     392          14 :     if (!s->rematrix_custom) {
     393          10 :         int r = auto_matrix(s);
     394          10 :         if (r)
     395           0 :             return r;
     396             :     }
     397          14 :     if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){
     398           7 :         int maxsum = 0;
     399           7 :         s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int));
     400           7 :         s->native_one    = av_mallocz(sizeof(int));
     401           7 :         if (!s->native_matrix || !s->native_one)
     402           0 :             return AVERROR(ENOMEM);
     403          21 :         for (i = 0; i < nb_out; i++) {
     404          14 :             double rem = 0;
     405          14 :             int sum = 0;
     406             : 
     407          40 :             for (j = 0; j < nb_in; j++) {
     408          26 :                 double target = s->matrix[i][j] * 32768 + rem;
     409          26 :                 ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target);
     410          26 :                 rem += target - ((int*)s->native_matrix)[i * nb_in + j];
     411          26 :                 sum += FFABS(((int*)s->native_matrix)[i * nb_in + j]);
     412             :             }
     413          14 :             maxsum = FFMAX(maxsum, sum);
     414             :         }
     415           7 :         *((int*)s->native_one) = 32768;
     416           7 :         if (maxsum <= 32768) {
     417           4 :             s->mix_1_1_f = (mix_1_1_func_type*)copy_s16;
     418           4 :             s->mix_2_1_f = (mix_2_1_func_type*)sum2_s16;
     419           4 :             s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s16(s);
     420             :         } else {
     421           3 :             s->mix_1_1_f = (mix_1_1_func_type*)copy_clip_s16;
     422           3 :             s->mix_2_1_f = (mix_2_1_func_type*)sum2_clip_s16;
     423           3 :             s->mix_any_f = (mix_any_func_type*)get_mix_any_func_clip_s16(s);
     424             :         }
     425           7 :     }else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){
     426           7 :         s->native_matrix = av_calloc(nb_in * nb_out, sizeof(float));
     427           7 :         s->native_one    = av_mallocz(sizeof(float));
     428           7 :         if (!s->native_matrix || !s->native_one)
     429           0 :             return AVERROR(ENOMEM);
     430          20 :         for (i = 0; i < nb_out; i++)
     431          37 :             for (j = 0; j < nb_in; j++)
     432          24 :                 ((float*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
     433           7 :         *((float*)s->native_one) = 1.0;
     434           7 :         s->mix_1_1_f = (mix_1_1_func_type*)copy_float;
     435           7 :         s->mix_2_1_f = (mix_2_1_func_type*)sum2_float;
     436           7 :         s->mix_any_f = (mix_any_func_type*)get_mix_any_func_float(s);
     437           0 :     }else if(s->midbuf.fmt == AV_SAMPLE_FMT_DBLP){
     438           0 :         s->native_matrix = av_calloc(nb_in * nb_out, sizeof(double));
     439           0 :         s->native_one    = av_mallocz(sizeof(double));
     440           0 :         if (!s->native_matrix || !s->native_one)
     441           0 :             return AVERROR(ENOMEM);
     442           0 :         for (i = 0; i < nb_out; i++)
     443           0 :             for (j = 0; j < nb_in; j++)
     444           0 :                 ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
     445           0 :         *((double*)s->native_one) = 1.0;
     446           0 :         s->mix_1_1_f = (mix_1_1_func_type*)copy_double;
     447           0 :         s->mix_2_1_f = (mix_2_1_func_type*)sum2_double;
     448           0 :         s->mix_any_f = (mix_any_func_type*)get_mix_any_func_double(s);
     449           0 :     }else if(s->midbuf.fmt == AV_SAMPLE_FMT_S32P){
     450           0 :         s->native_one    = av_mallocz(sizeof(int));
     451           0 :         if (!s->native_one)
     452           0 :             return AVERROR(ENOMEM);
     453           0 :         s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int));
     454           0 :         if (!s->native_matrix) {
     455           0 :             av_freep(&s->native_one);
     456           0 :             return AVERROR(ENOMEM);
     457             :         }
     458           0 :         for (i = 0; i < nb_out; i++) {
     459           0 :             double rem = 0;
     460             : 
     461           0 :             for (j = 0; j < nb_in; j++) {
     462           0 :                 double target = s->matrix[i][j] * 32768 + rem;
     463           0 :                 ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target);
     464           0 :                 rem += target - ((int*)s->native_matrix)[i * nb_in + j];
     465             :             }
     466             :         }
     467           0 :         *((int*)s->native_one) = 32768;
     468           0 :         s->mix_1_1_f = (mix_1_1_func_type*)copy_s32;
     469           0 :         s->mix_2_1_f = (mix_2_1_func_type*)sum2_s32;
     470           0 :         s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s32(s);
     471             :     }else
     472           0 :         av_assert0(0);
     473             :     //FIXME quantize for integeres
     474         910 :     for (i = 0; i < SWR_CH_MAX; i++) {
     475         896 :         int ch_in=0;
     476       58240 :         for (j = 0; j < SWR_CH_MAX; j++) {
     477       57344 :             s->matrix32[i][j]= lrintf(s->matrix[i][j] * 32768);
     478       57344 :             if(s->matrix[i][j])
     479          34 :                 s->matrix_ch[i][++ch_in]= j;
     480             :         }
     481         896 :         s->matrix_ch[i][0]= ch_in;
     482             :     }
     483             : 
     484             :     if(HAVE_X86ASM && HAVE_MMX)
     485          14 :         return swri_rematrix_init_x86(s);
     486             : 
     487             :     return 0;
     488             : }
     489             : 
     490        2432 : av_cold void swri_rematrix_free(SwrContext *s){
     491        2432 :     av_freep(&s->native_matrix);
     492        2432 :     av_freep(&s->native_one);
     493        2432 :     av_freep(&s->native_simd_matrix);
     494        2432 :     av_freep(&s->native_simd_one);
     495        2432 : }
     496             : 
     497         935 : int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
     498             :     int out_i, in_i, i, j;
     499         935 :     int len1 = 0;
     500         935 :     int off = 0;
     501             : 
     502         935 :     if(s->mix_any_f) {
     503           0 :         s->mix_any_f(out->ch, (const uint8_t **)in->ch, s->native_matrix, len);
     504           0 :         return 0;
     505             :     }
     506             : 
     507         935 :     if(s->mix_2_1_simd || s->mix_1_1_simd){
     508          47 :         len1= len&~15;
     509          47 :         off = len1 * out->bps;
     510             :     }
     511             : 
     512         935 :     av_assert0(!s->out_ch_layout || out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
     513         935 :     av_assert0(!s-> in_ch_layout || in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));
     514             : 
     515        2724 :     for(out_i=0; out_i<out->ch_count; out_i++){
     516        1789 :         switch(s->matrix_ch[out_i][0]){
     517         532 :         case 0:
     518         532 :             if(mustcopy)
     519           0 :                 memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt));
     520         532 :             break;
     521         524 :         case 1:
     522         524 :             in_i= s->matrix_ch[out_i][1];
     523         524 :             if(s->matrix[out_i][in_i]!=1.0){
     524         278 :                 if(s->mix_1_1_simd && len1)
     525          94 :                     s->mix_1_1_simd(out->ch[out_i]    , in->ch[in_i]    , s->native_simd_matrix, in->ch_count*out_i + in_i, len1);
     526         278 :                 if(len != len1)
     527         180 :                     s->mix_1_1_f   (out->ch[out_i]+off, in->ch[in_i]+off, s->native_matrix, in->ch_count*out_i + in_i, len-len1);
     528         246 :             }else if(mustcopy){
     529           0 :                 memcpy(out->ch[out_i], in->ch[in_i], len*out->bps);
     530             :             }else{
     531         246 :                 out->ch[out_i]= in->ch[in_i];
     532             :             }
     533         524 :             break;
     534         733 :         case 2: {
     535         733 :             int in_i1 = s->matrix_ch[out_i][1];
     536         733 :             int in_i2 = s->matrix_ch[out_i][2];
     537         733 :             if(s->mix_2_1_simd && len1)
     538           0 :                 s->mix_2_1_simd(out->ch[out_i]    , in->ch[in_i1]    , in->ch[in_i2]    , s->native_simd_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len1);
     539             :             else
     540         733 :                 s->mix_2_1_f   (out->ch[out_i]    , in->ch[in_i1]    , in->ch[in_i2]    , s->native_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len1);
     541         733 :             if(len != len1)
     542         731 :                 s->mix_2_1_f   (out->ch[out_i]+off, in->ch[in_i1]+off, in->ch[in_i2]+off, s->native_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len-len1);
     543         733 :             break;}
     544           0 :         default:
     545           0 :             if(s->int_sample_fmt == AV_SAMPLE_FMT_FLTP){
     546           0 :                 for(i=0; i<len; i++){
     547           0 :                     float v=0;
     548           0 :                     for(j=0; j<s->matrix_ch[out_i][0]; j++){
     549           0 :                         in_i= s->matrix_ch[out_i][1+j];
     550           0 :                         v+= ((float*)in->ch[in_i])[i] * s->matrix_flt[out_i][in_i];
     551             :                     }
     552           0 :                     ((float*)out->ch[out_i])[i]= v;
     553             :                 }
     554           0 :             }else if(s->int_sample_fmt == AV_SAMPLE_FMT_DBLP){
     555           0 :                 for(i=0; i<len; i++){
     556           0 :                     double v=0;
     557           0 :                     for(j=0; j<s->matrix_ch[out_i][0]; j++){
     558           0 :                         in_i= s->matrix_ch[out_i][1+j];
     559           0 :                         v+= ((double*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
     560             :                     }
     561           0 :                     ((double*)out->ch[out_i])[i]= v;
     562             :                 }
     563             :             }else{
     564           0 :                 for(i=0; i<len; i++){
     565           0 :                     int v=0;
     566           0 :                     for(j=0; j<s->matrix_ch[out_i][0]; j++){
     567           0 :                         in_i= s->matrix_ch[out_i][1+j];
     568           0 :                         v+= ((int16_t*)in->ch[in_i])[i] * s->matrix32[out_i][in_i];
     569             :                     }
     570           0 :                     ((int16_t*)out->ch[out_i])[i]= (v + 16384)>>15;
     571             :                 }
     572             :             }
     573             :         }
     574             :     }
     575         935 :     return 0;
     576             : }

Generated by: LCOV version 1.13