libswresample takes care of that now.
Unified · Split
| @@ -37,11 +37,7 @@ · 36 unmodified lines | |||
| 37 | 37 | ||
| 38 | typedef struct PanContext { | 38 | typedef struct PanContext { |
| 39 | int64_t out_channel_layout; | 39 | int64_t out_channel_layout; |
| 40 | union { | 40 | double gain[MAX_CHANNELS][MAX_CHANNELS]; |
| 41 | double d[MAX_CHANNELS][MAX_CHANNELS]; | ||
| 42 | // i is 1:7:8 fixed-point, i.e. in [-128*256; +128*256[ | ||
| 43 | int i[MAX_CHANNELS][MAX_CHANNELS]; | ||
| 44 | } gain; | ||
| 45 | int64_t need_renorm; | 41 | int64_t need_renorm; |
| 46 | int need_renumber; | 42 | int need_renumber; |
| 47 | int nb_input_channels; | 43 | int nb_input_channels; |
| @@ -171,7 +167,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args0, void *opaque) · 123 unmodified lines | |||
| 171 | "Can not mix named and numbered channels\n"); | 167 | "Can not mix named and numbered channels\n"); |
| 172 | return AVERROR(EINVAL); | 168 | return AVERROR(EINVAL); |
| 173 | } | 169 | } |
| 174 | pan->gain.d[out_ch_id][in_ch_id] = gain; | 170 | pan->gain[out_ch_id][in_ch_id] = gain; |
| 175 | if (!*arg) | 171 | if (!*arg) |
| 176 | break; | 172 | break; |
| 177 | if (*arg != '+') { | 173 | if (*arg != '+') { |
| @@ -196,7 +192,7 @@ static int are_gains_pure(const PanContext *pan) · 18 unmodified lines | |||
| 196 | int nb_gain = 0; | 192 | int nb_gain = 0; |
| 197 | 193 | ||
| 198 | for (j = 0; j < MAX_CHANNELS; j++) { | 194 | for (j = 0; j < MAX_CHANNELS; j++) { |
| 199 | double gain = pan->gain.d[i][j]; | 195 | double gain = pan->gain[i][j]; |
| 200 | 196 | ||
| 201 | /* channel mapping is effective only if 0% or 100% of a channel is | 197 | /* channel mapping is effective only if 0% or 100% of a channel is |
| 202 | * selected... */ | 198 | * selected... */ |
| @@ -247,7 +243,7 @@ static int config_props(AVFilterLink *link) · 44 unmodified lines | |||
| 247 | for (i = j = 0; i < MAX_CHANNELS; i++) { | 243 | for (i = j = 0; i < MAX_CHANNELS; i++) { |
| 248 | if ((link->channel_layout >> i) & 1) { | 244 | if ((link->channel_layout >> i) & 1) { |
| 249 | for (k = 0; k < pan->nb_output_channels; k++) | 245 | for (k = 0; k < pan->nb_output_channels; k++) |
| 250 | pan->gain.d[k][j] = pan->gain.d[k][i]; | 246 | pan->gain[k][j] = pan->gain[k][i]; |
| 251 | j++; | 247 | j++; |
| 252 | } | 248 | } |
| 253 | } | 249 | } |
| @@ -278,7 +274,7 @@ static int config_props(AVFilterLink *link) · 24 unmodified lines | |||
| 278 | for (i = 0; i < pan->nb_output_channels; i++) { | 274 | for (i = 0; i < pan->nb_output_channels; i++) { |
| 279 | int ch_id = -1; | 275 | int ch_id = -1; |
| 280 | for (j = 0; j < pan->nb_input_channels; j++) { | 276 | for (j = 0; j < pan->nb_input_channels; j++) { |
| 281 | if (pan->gain.d[i][j]) { | 277 | if (pan->gain[i][j]) { |
| 282 | ch_id = j; | 278 | ch_id = j; |
| 283 | break; | 279 | break; |
| 284 | } | 280 | } |
| @@ -296,7 +292,7 @@ static int config_props(AVFilterLink *link) · 11 unmodified lines | |||
| 296 | continue; | 292 | continue; |
| 297 | t = 0; | 293 | t = 0; |
| 298 | for (j = 0; j < pan->nb_input_channels; j++) | 294 | for (j = 0; j < pan->nb_input_channels; j++) |
| 299 | t += pan->gain.d[i][j]; | 295 | t += pan->gain[i][j]; |
| 300 | if (t > -1E-5 && t < 1E-5) { | 296 | if (t > -1E-5 && t < 1E-5) { |
| 301 | // t is almost 0 but not exactly, this is probably a mistake | 297 | // t is almost 0 but not exactly, this is probably a mistake |
| 302 | if (t) | 298 | if (t) |
| @@ -305,12 +301,11 @@ static int config_props(AVFilterLink *link) · 2 unmodified lines | |||
| 305 | continue; | 301 | continue; |
| 306 | } | 302 | } |
| 307 | for (j = 0; j < pan->nb_input_channels; j++) | 303 | for (j = 0; j < pan->nb_input_channels; j++) |
| 308 | pan->gain.d[i][j] /= t; | 304 | pan->gain[i][j] /= t; |
| 309 | } | 305 | } |
| 310 | av_opt_set_int(pan->swr, "icl", link->channel_layout, 0); | 306 | av_opt_set_int(pan->swr, "icl", link->channel_layout, 0); |
| 311 | av_opt_set_int(pan->swr, "ocl", pan->out_channel_layout, 0); | 307 | av_opt_set_int(pan->swr, "ocl", pan->out_channel_layout, 0); |
| 312 | swr_set_matrix(pan->swr, pan->gain.d[0], | 308 | swr_set_matrix(pan->swr, pan->gain[0], pan->gain[1] - pan->gain[0]); |
| 313 | pan->gain.d[1] - pan->gain.d[0]); | ||
| 314 | } | 309 | } |
| 315 | 310 | ||
| 316 | r = swr_init(pan->swr); | 311 | r = swr_init(pan->swr); |
| @@ -322,7 +317,7 @@ static int config_props(AVFilterLink *link) · 5 unmodified lines | |||
| 322 | cur = buf; | 317 | cur = buf; |
| 323 | for (j = 0; j < pan->nb_input_channels; j++) { | 318 | for (j = 0; j < pan->nb_input_channels; j++) { |
| 324 | r = snprintf(cur, buf + sizeof(buf) - cur, "%s%.3g i%d", | 319 | r = snprintf(cur, buf + sizeof(buf) - cur, "%s%.3g i%d", |
| 325 | j ? " + " : "", pan->gain.d[i][j], j); | 320 | j ? " + " : "", pan->gain[i][j], j); |
| 326 | cur += FFMIN(buf + sizeof(buf) - cur, r); | 321 | cur += FFMIN(buf + sizeof(buf) - cur, r); |
| 327 | } | 322 | } |
| 328 | av_log(ctx, AV_LOG_INFO, "o%d = %s\n", i, buf); | 323 | av_log(ctx, AV_LOG_INFO, "o%d = %s\n", i, buf); |
| @@ -338,15 +333,6 @@ static int config_props(AVFilterLink *link) · 9 unmodified lines | |||
| 338 | av_log(ctx, AV_LOG_INFO, "\n"); | 333 | av_log(ctx, AV_LOG_INFO, "\n"); |
| 339 | return 0; | 334 | return 0; |
| 340 | } | 335 | } |
| 341 | // convert to integer | ||
| 342 | for (i = 0; i < pan->nb_output_channels; i++) { | ||
| 343 | for (j = 0; j < pan->nb_input_channels; j++) { | ||
| 344 | if (pan->gain.d[i][j] < -128 || pan->gain.d[i][j] > 128) | ||
| 345 | av_log(ctx, AV_LOG_WARNING, | ||
| 346 | "Gain #%d->#%d too large, clamped\n", j, i); | ||
| 347 | pan->gain.i[i][j] = av_clipf(pan->gain.d[i][j], -128, 128) * 256.0; | ||
| 348 | } | ||
| 349 | } | ||
| 350 | return 0; | 336 | return 0; |
| 351 | } | 337 | } |
| 352 | 338 | ||