From 560b224f53fd553262790216d18c64665ebf436d Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Thu, 16 Feb 2012 11:26:32 +0100 Subject: [PATCH] libswr: allow to set custom matrices. --- doc/APIchanges | 3 ++ libswresample/rematrix.c | 51 ++++++++++++++++++++++++----- libswresample/swresample.c | 3 +- libswresample/swresample.h | 13 +++++++- libswresample/swresample_internal.h | 1 + 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 87e1aab865..1e94be42b2 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2011-04-18 API changes, most recent first: +2012-02-16 - xxxxxxx - libswr 0.7.100 + Add swr_set_matrix() function. + 2012-02-09 - xxxxxxx - lavu 51.39.100 Add a new installed header libavutil/timestamp.h with timestamp utilities. diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c index 0e4d9630c8..da817e1455 100644 --- a/libswresample/rematrix.c +++ b/libswresample/rematrix.c @@ -61,6 +61,24 @@ #define TOP_BACK_CENTER 16 #define TOP_BACK_RIGHT 17 +int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride) +{ + int nb_in, nb_out, in, out; + + if (!s || s->in_convert) // s needs to be allocated but not initialized + return AVERROR(EINVAL); + memset(s->matrix, 0, sizeof(s->matrix)); + nb_in = av_get_channel_layout_nb_channels(s->in_ch_layout); + nb_out = av_get_channel_layout_nb_channels(s->out_ch_layout); + for (out = 0; out < nb_out; out++) { + for (in = 0; in < nb_in; in++) + s->matrix[out][in] = matrix[in]; + matrix += stride; + } + s->rematrix_custom = 1; + return 0; +} + static int even(int64_t layout){ if(!layout) return 1; if(layout&(layout-1)) return 1; @@ -84,12 +102,14 @@ static int sane_layout(int64_t layout){ return 1; } -int swri_rematrix_init(SwrContext *s){ +static int auto_matrix(SwrContext *s) +{ int i, j, out_i; double matrix[64][64]={{0}}; int64_t unaccounted= s->in_ch_layout & ~s->out_ch_layout; double maxcoef=0; + memset(s->matrix, 0, sizeof(s->matrix)); for(i=0; i<64; i++){ if(s->in_ch_layout & s->out_ch_layout & (1LL<matrix[out_i][in_i]= matrix[i][j]; - s->matrix32[out_i][in_i]= lrintf(matrix[i][j] * 32768); if(matrix[i][j]){ - s->matrix_ch[out_i][++ch_in]= in_i; sum += fabs(matrix[i][j]); } if(s->in_ch_layout & (1ULL<matrix_ch[out_i][0]= ch_in; maxcoef= FFMAX(maxcoef, sum); if(s->out_ch_layout & (1ULL<matrix[i][j] /= maxcoef; - s->matrix32[i][j]= lrintf(s->matrix[i][j] * 32768); } } @@ -226,7 +239,6 @@ int swri_rematrix_init(SwrContext *s){ for(i=0; imatrix[i][j] *= s->rematrix_volume; - s->matrix32[i][j]= lrintf(s->matrix[i][j] * 32768); } } @@ -239,6 +251,27 @@ int swri_rematrix_init(SwrContext *s){ return 0; } +int swri_rematrix_init(SwrContext *s){ + int i, j; + + if (!s->rematrix_custom) { + int r = auto_matrix(s); + if (r) + return r; + } + //FIXME quantize for integeres + for (i = 0; i < SWR_CH_MAX; i++) { + int ch_in=0; + for (j = 0; j < SWR_CH_MAX; j++) { + s->matrix32[i][j]= lrintf(s->matrix[i][j] * 32768); + if(s->matrix[i][j]) + s->matrix_ch[i][++ch_in]= j; + } + s->matrix_ch[i][0]= ch_in; + } + return 0; +} + int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){ int out_i, in_i, i, j; diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 84d0f40232..7fb1ee8c2c 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -209,7 +209,8 @@ int swr_init(struct SwrContext *s){ if(!s->out_ch_layout) s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count); - s->rematrix= s->out_ch_layout !=s->in_ch_layout || s->rematrix_volume!=1.0; + s->rematrix= s->out_ch_layout !=s->in_ch_layout || s->rematrix_volume!=1.0 || + s->rematrix_custom; #define RSC 1 //FIXME finetune if(!s-> in.ch_count) diff --git a/libswresample/swresample.h b/libswresample/swresample.h index 8dc4e1f348..4a3f451aba 100644 --- a/libswresample/swresample.h +++ b/libswresample/swresample.h @@ -30,7 +30,7 @@ #include "libavutil/samplefmt.h" #define LIBSWRESAMPLE_VERSION_MAJOR 0 -#define LIBSWRESAMPLE_VERSION_MINOR 6 +#define LIBSWRESAMPLE_VERSION_MINOR 7 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ @@ -126,6 +126,17 @@ int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensatio */ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); +/** + * Set a customized remix matrix. + * + * @param s allocated Swr context, not yet initialized + * @param matrix remix coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o + * @param stride offset between lines of the matrix + * @return AVERROR error code in case of failure. + */ +int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride); + /** * Return the LIBSWRESAMPLE_VERSION_INT constant. */ diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h index 0fc1c6b6a6..f53ccd76fe 100644 --- a/libswresample/swresample_internal.h +++ b/libswresample/swresample_internal.h @@ -53,6 +53,7 @@ typedef struct SwrContext { int int_bps; ///< internal bytes per sample int resample_first; ///< 1 if resampling must come first, 0 if rematrixing int rematrix; ///< flag to indicate if rematrixing is needed (basically if input and output layouts mismatch) + int rematrix_custom; ///< flag to indicate that a custom matrix has been defined AudioData in; ///< input audio data AudioData postin; ///< post-input audio data: used for rematrix/resample