]> git.sesse.net Git - ffmpeg/blobdiff - libswresample/rematrix.c
swresample: make .class_name more descriptive
[ffmpeg] / libswresample / rematrix.c
index 44319792ea6118f110ad76843880b00309fc0dfe..3784111854b0beb8a5e597c33b96c8f685f86cdc 100644 (file)
@@ -26,6 +26,7 @@
 #define R(x) x
 #define SAMPLE float
 #define COEFF float
+#define INTER float
 #define RENAME(x) x ## _float
 #include "rematrix_template.c"
 #undef SAMPLE
 #undef R
 #undef ONE
 #undef COEFF
+#undef INTER
+
+#define ONE (1.0)
+#define R(x) x
+#define SAMPLE double
+#define COEFF double
+#define INTER double
+#define RENAME(x) x ## _double
+#include "rematrix_template.c"
+#undef SAMPLE
+#undef RENAME
+#undef R
+#undef ONE
+#undef COEFF
+#undef INTER
 
 #define ONE (-32768)
 #define R(x) (((x) + 16384)>>15)
 #define SAMPLE int16_t
 #define COEFF int
+#define INTER int
 #define RENAME(x) x ## _s16
 #include "rematrix_template.c"
 
@@ -108,6 +125,7 @@ static int auto_matrix(SwrContext *s)
     double matrix[64][64]={{0}};
     int64_t unaccounted= s->in_ch_layout & ~s->out_ch_layout;
     double maxcoef=0;
+    char buf[128];
 
     memset(s->matrix, 0, sizeof(s->matrix));
     for(i=0; i<64; i++){
@@ -116,11 +134,13 @@ static int auto_matrix(SwrContext *s)
     }
 
     if(!sane_layout(s->in_ch_layout)){
-        av_log(s, AV_LOG_ERROR, "Input channel layout isnt supported\n");
+        av_get_channel_layout_string(buf, sizeof(buf), -1, s->in_ch_layout);
+        av_log(s, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
         return AVERROR(EINVAL);
     }
     if(!sane_layout(s->out_ch_layout)){
-        av_log(s, AV_LOG_ERROR, "Output channel layout isnt supported\n");
+        av_get_channel_layout_string(buf, sizeof(buf), -1, s->out_ch_layout);
+        av_log(s, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
         return AVERROR(EINVAL);
     }
 
@@ -184,8 +204,15 @@ static int auto_matrix(SwrContext *s)
 
     if(unaccounted & AV_CH_SIDE_LEFT){
         if(s->out_ch_layout & AV_CH_BACK_LEFT){
-            matrix[ BACK_LEFT][ SIDE_LEFT]+= 1.0;
-            matrix[BACK_RIGHT][SIDE_RIGHT]+= 1.0;
+            /* if back channels do not exist in the input, just copy side
+               channels to back channels, otherwise mix side into back */
+            if (s->in_ch_layout & 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(s->out_ch_layout & AV_CH_BACK_CENTER){
             matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
             matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
@@ -209,6 +236,17 @@ static int auto_matrix(SwrContext *s)
         }else
             av_assert0(0);
     }
+    /* mix LFE into front left/right or center */
+    if (unaccounted & AV_CH_LOW_FREQUENCY) {
+        if (s->out_ch_layout & AV_CH_FRONT_CENTER) {
+            matrix[FRONT_CENTER][LOW_FREQUENCY] += s->lfe_mix_level;
+        } else if (s->out_ch_layout & AV_CH_FRONT_LEFT) {
+            matrix[FRONT_LEFT ][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2;
+            matrix[FRONT_RIGHT][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2;
+        } else
+            av_assert0(0);
+    }
+
     for(out_i=i=0; i<64; i++){
         double sum=0;
         int in_i=0;
@@ -227,8 +265,8 @@ static int auto_matrix(SwrContext *s)
     if(s->rematrix_volume  < 0)
         maxcoef = -s->rematrix_volume;
 
-    if((   s->out_sample_fmt < AV_SAMPLE_FMT_FLT
-        || s->int_sample_fmt < AV_SAMPLE_FMT_FLT) && maxcoef > 1.0){
+    if((   av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT
+        || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) && maxcoef > 1.0){
         for(i=0; i<SWR_CH_MAX; i++)
             for(j=0; j<SWR_CH_MAX; j++){
                 s->matrix[i][j] /= maxcoef;
@@ -253,12 +291,48 @@ static int auto_matrix(SwrContext *s)
 
 int swri_rematrix_init(SwrContext *s){
     int i, j;
+    int nb_in  = av_get_channel_layout_nb_channels(s->in_ch_layout);
+    int nb_out = av_get_channel_layout_nb_channels(s->out_ch_layout);
+
+    s->mix_any_f = NULL;
 
     if (!s->rematrix_custom) {
         int r = auto_matrix(s);
         if (r)
             return r;
     }
+    if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){
+        s->native_matrix = av_mallocz(nb_in * nb_out * sizeof(int));
+        s->native_one    = av_mallocz(sizeof(int));
+        for (i = 0; i < nb_out; i++)
+            for (j = 0; j < nb_in; j++)
+                ((int*)s->native_matrix)[i * nb_in + j] = lrintf(s->matrix[i][j] * 32768);
+        *((int*)s->native_one) = 32768;
+        s->mix_1_1_f = copy_s16;
+        s->mix_2_1_f = sum2_s16;
+        s->mix_any_f = get_mix_any_func_s16(s);
+    }else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){
+        s->native_matrix = av_mallocz(nb_in * nb_out * sizeof(float));
+        s->native_one    = av_mallocz(sizeof(float));
+        for (i = 0; i < nb_out; i++)
+            for (j = 0; j < nb_in; j++)
+                ((float*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
+        *((float*)s->native_one) = 1.0;
+        s->mix_1_1_f = copy_float;
+        s->mix_2_1_f = sum2_float;
+        s->mix_any_f = get_mix_any_func_float(s);
+    }else if(s->midbuf.fmt == AV_SAMPLE_FMT_DBLP){
+        s->native_matrix = av_mallocz(nb_in * nb_out * sizeof(double));
+        s->native_one    = av_mallocz(sizeof(double));
+        for (i = 0; i < nb_out; i++)
+            for (j = 0; j < nb_in; j++)
+                ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
+        *((double*)s->native_one) = 1.0;
+        s->mix_1_1_f = copy_double;
+        s->mix_2_1_f = sum2_double;
+        s->mix_any_f = get_mix_any_func_double(s);
+    }else
+        av_assert0(0);
     //FIXME quantize for integeres
     for (i = 0; i < SWR_CH_MAX; i++) {
         int ch_in=0;
@@ -269,20 +343,32 @@ int swri_rematrix_init(SwrContext *s){
         }
         s->matrix_ch[i][0]= ch_in;
     }
+
+    if(HAVE_YASM && HAVE_MMX) swri_rematrix_init_x86(s);
+
     return 0;
 }
 
-void swri_sum2(enum AVSampleFormat format, void *dst, const void *src0, const void *src1, float coef0, float coef1, int len){
-    if(format == AV_SAMPLE_FMT_FLT){
-        sum2_float((float  *)dst, (const float  *)src0, (const float  *)src1, coef0, coef1, len);
-    }else{
-        av_assert1(format == AV_SAMPLE_FMT_S16);
-        sum2_s16  ((int16_t*)dst, (const int16_t*)src0, (const int16_t*)src1, lrintf(coef0 * 32768), lrintf(coef1 * 32768), len);
-    }
+void swri_rematrix_free(SwrContext *s){
+    av_freep(&s->native_matrix);
+    av_freep(&s->native_one);
+    av_freep(&s->native_simd_matrix);
 }
 
 int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
     int out_i, in_i, i, j;
+    int len1 = 0;
+    int off = 0;
+
+    if(s->mix_any_f) {
+        s->mix_any_f(out->ch, in->ch, s->native_matrix, len);
+        return 0;
+    }
+
+    if(s->mix_2_1_simd || s->mix_1_1_simd){
+        len1= len&~15;
+        off = len1 * out->bps;
+    }
 
     av_assert0(out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
     av_assert0(in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));
@@ -290,25 +376,34 @@ int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus
     for(out_i=0; out_i<out->ch_count; out_i++){
         switch(s->matrix_ch[out_i][0]){
         case 0:
-            memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt));
+            if(mustcopy)
+                memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt));
             break;
         case 1:
             in_i= s->matrix_ch[out_i][1];
-            if(mustcopy || s->matrix[out_i][in_i]!=1.0){
-                if(s->int_sample_fmt == AV_SAMPLE_FMT_FLT){
-                    copy_float((float  *)out->ch[out_i], (const float  *)in->ch[in_i], s->matrix  [out_i][in_i], len);
-                }else
-                    copy_s16  ((int16_t*)out->ch[out_i], (const int16_t*)in->ch[in_i], s->matrix32[out_i][in_i], len);
+            if(s->matrix[out_i][in_i]!=1.0){
+                if(s->mix_1_1_simd && len1)
+                    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);
+                if(len != len1)
+                    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);
+            }else if(mustcopy){
+                memcpy(out->ch[out_i], in->ch[in_i], len*out->bps);
             }else{
                 out->ch[out_i]= in->ch[in_i];
             }
             break;
-        case 2:
-            swri_sum2(s->int_sample_fmt, out->ch[out_i], in->ch[ s->matrix_ch[out_i][1] ],           in->ch[ s->matrix_ch[out_i][2] ],
-                        s->matrix[out_i][ s->matrix_ch[out_i][1] ], s->matrix[out_i][ s->matrix_ch[out_i][2] ], len);
-            break;
+        case 2: {
+            int in_i1 = s->matrix_ch[out_i][1];
+            int in_i2 = s->matrix_ch[out_i][2];
+            if(s->mix_2_1_simd && len1)
+                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);
+            else
+                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);
+            if(len != len1)
+                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);
+            break;}
         default:
-            if(s->int_sample_fmt == AV_SAMPLE_FMT_FLT){
+            if(s->int_sample_fmt == AV_SAMPLE_FMT_FLTP){
                 for(i=0; i<len; i++){
                     float v=0;
                     for(j=0; j<s->matrix_ch[out_i][0]; j++){
@@ -317,6 +412,15 @@ int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus
                     }
                     ((float*)out->ch[out_i])[i]= v;
                 }
+            }else if(s->int_sample_fmt == AV_SAMPLE_FMT_DBLP){
+                for(i=0; i<len; i++){
+                    double v=0;
+                    for(j=0; j<s->matrix_ch[out_i][0]; j++){
+                        in_i= s->matrix_ch[out_i][1+j];
+                        v+= ((double*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
+                    }
+                    ((double*)out->ch[out_i])[i]= v;
+                }
             }else{
                 for(i=0; i<len; i++){
                     int v=0;