Fix this by adding support for non-writable frames.
Showing the changes to libavfilter (1 of 1 file). Show all
Unified · Split
| @@ -84,7 +84,7 @@ typedef struct SpeechNormalizerContext { · 83 unmodified lines | |||
| 84 | void (*analyze_channel)(AVFilterContext *ctx, ChannelContext *cc, | 84 | void (*analyze_channel)(AVFilterContext *ctx, ChannelContext *cc, |
| 85 | const uint8_t *srcp, int nb_samples); | 85 | const uint8_t *srcp, int nb_samples); |
| 86 | void (*filter_channels[2])(AVFilterContext *ctx, | 86 | void (*filter_channels[2])(AVFilterContext *ctx, |
| 87 | AVFrame *in, int nb_samples); | 87 | AVFrame *in, AVFrame *out, int nb_samples); |
| 88 | } SpeechNormalizerContext; | 88 | } SpeechNormalizerContext; |
| 89 | 89 | ||
| 90 | #define OFFSET(x) offsetof(SpeechNormalizerContext, x) | 90 | #define OFFSET(x) offsetof(SpeechNormalizerContext, x) |
| @@ -295,14 +295,15 @@ ANALYZE_CHANNEL(flt, float, 0.f, (float)MIN_PEAK) · 204 unmodified lines | |||
| 295 | 295 | ||
| 296 | #define FILTER_CHANNELS(name, ptype) \ | 296 | #define FILTER_CHANNELS(name, ptype) \ |
| 297 | static void filter_channels_## name (AVFilterContext *ctx, \ | 297 | static void filter_channels_## name (AVFilterContext *ctx, \ |
| 298 | AVFrame *in, int nb_samples) \ | 298 | AVFrame *in, AVFrame *out, int nb_samples) \ |
| 299 | { \ | 299 | { \ |
| 300 | SpeechNormalizerContext *s = ctx->priv; \ | 300 | SpeechNormalizerContext *s = ctx->priv; \ |
| 301 | AVFilterLink *inlink = ctx->inputs[0]; \ | 301 | AVFilterLink *inlink = ctx->inputs[0]; \ |
| 302 | \ | 302 | \ |
| 303 | for (int ch = 0; ch < inlink->channels; ch++) { \ | 303 | for (int ch = 0; ch < inlink->channels; ch++) { \ |
| 304 | ChannelContext *cc = &s->cc[ch]; \ | 304 | ChannelContext *cc = &s->cc[ch]; \ |
| 305 | ptype *dst = (ptype *)in->extended_data[ch]; \ | 305 | const ptype *src = (const ptype *)in->extended_data[ch]; \ |
| 306 | ptype *dst = (ptype *)out->extended_data[ch]; \ | ||
| 306 | const int bypass = !(av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels); \ | 307 | const int bypass = !(av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels); \ |
| 307 | int n = 0; \ | 308 | int n = 0; \ |
| 308 | \ | 309 | \ |
| @@ -316,7 +317,7 @@ static void filter_channels_## name (AVFilterContext *ctx, · 7 unmodified lines | |||
| 316 | gain = cc->gain_state; \ | 317 | gain = cc->gain_state; \ |
| 317 | consume_pi(cc, size); \ | 318 | consume_pi(cc, size); \ |
| 318 | for (int i = n; !ctx->is_disabled && i < n + size; i++) \ | 319 | for (int i = n; !ctx->is_disabled && i < n + size; i++) \ |
| 319 | dst[i] *= gain; \ | 320 | dst[i] = src[i] * gain; \ |
| 320 | n += size; \ | 321 | n += size; \ |
| 321 | } \ | 322 | } \ |
| 322 | } \ | 323 | } \ |
| @@ -337,7 +338,8 @@ static float flerp(float min, float max, float mix) · 14 unmodified lines | |||
| 337 | 338 | ||
| 338 | #define FILTER_LINK_CHANNELS(name, ptype, tlerp) \ | 339 | #define FILTER_LINK_CHANNELS(name, ptype, tlerp) \ |
| 339 | static void filter_link_channels_## name (AVFilterContext *ctx, \ | 340 | static void filter_link_channels_## name (AVFilterContext *ctx, \ |
| 340 | AVFrame *in, int nb_samples) \ | 341 | AVFrame *in, AVFrame *out, \ |
| 342 | int nb_samples) \ | ||
| 341 | { \ | 343 | { \ |
| 342 | SpeechNormalizerContext *s = ctx->priv; \ | 344 | SpeechNormalizerContext *s = ctx->priv; \ |
| 343 | AVFilterLink *inlink = ctx->inputs[0]; \ | 345 | AVFilterLink *inlink = ctx->inputs[0]; \ |
| @@ -369,7 +371,8 @@ static void filter_link_channels_## name (AVFilterContext *ctx, · 25 unmodified lines | |||
| 369 | \ | 371 | \ |
| 370 | for (int ch = 0; ch < inlink->channels; ch++) { \ | 372 | for (int ch = 0; ch < inlink->channels; ch++) { \ |
| 371 | ChannelContext *cc = &s->cc[ch]; \ | 373 | ChannelContext *cc = &s->cc[ch]; \ |
| 372 | ptype *dst = (ptype *)in->extended_data[ch]; \ | 374 | const ptype *src = (const ptype *)in->extended_data[ch]; \ |
| 375 | ptype *dst = (ptype *)out->extended_data[ch]; \ | ||
| 373 | \ | 376 | \ |
| 374 | consume_pi(cc, min_size); \ | 377 | consume_pi(cc, min_size); \ |
| 375 | if (cc->bypass) \ | 378 | if (cc->bypass) \ |
| @@ -377,7 +380,7 @@ static void filter_link_channels_## name (AVFilterContext *ctx, · 1 unmodified line | |||
| 377 | \ | 380 | \ |
| 378 | for (int i = n; !ctx->is_disabled && i < n + min_size; i++) { \ | 381 | for (int i = n; !ctx->is_disabled && i < n + min_size; i++) { \ |
| 379 | ptype g = tlerp(s->prev_gain, gain, (i - n) / (ptype)min_size); \ | 382 | ptype g = tlerp(s->prev_gain, gain, (i - n) / (ptype)min_size); \ |
| 380 | dst[i] *= g; \ | 383 | dst[i] = src[i] * g; \ |
| 381 | } \ | 384 | } \ |
| 382 | } \ | 385 | } \ |
| 383 | \ | 386 | \ |
| @@ -398,7 +401,7 @@ static int filter_frame(AVFilterContext *ctx) · 14 unmodified lines | |||
| 398 | 401 | ||
| 399 | while (s->queue.available > 0) { | 402 | while (s->queue.available > 0) { |
| 400 | int min_pi_nb_samples; | 403 | int min_pi_nb_samples; |
| 401 | AVFrame *in; | 404 | AVFrame *in, *out; |
| 402 | 405 | ||
| 403 | in = ff_bufqueue_peek(&s->queue, 0); | 406 | in = ff_bufqueue_peek(&s->queue, 0); |
| 404 | if (!in) | 407 | if (!in) |
| @@ -410,16 +413,25 @@ static int filter_frame(AVFilterContext *ctx) · 5 unmodified lines | |||
| 410 | 413 | ||
| 411 | in = ff_bufqueue_get(&s->queue); | 414 | in = ff_bufqueue_get(&s->queue); |
| 412 | 415 | ||
| 413 | ret = av_frame_make_writable(in); | 416 | if (av_frame_is_writable(in)) { |
| 414 | if (ret < 0) | 417 | out = in; |
| 415 | return ret; | 418 | } else { |
| 419 | out = ff_get_audio_buffer(outlink, in->nb_samples); | ||
| 420 | if (!out) { | ||
| 421 | av_frame_free(&in); | ||
| 422 | return AVERROR(ENOMEM); | ||
| 423 | } | ||
| 424 | av_frame_copy_props(out, in); | ||
| 425 | } | ||
| 416 | 426 | ||
| 417 | s->filter_channels[s->link](ctx, in, in->nb_samples); | 427 | s->filter_channels[s->link](ctx, in, out, in->nb_samples); |
| 418 | 428 | ||
| 419 | s->pts = in->pts + av_rescale_q(in->nb_samples, av_make_q(1, outlink->sample_rate), | 429 | s->pts = in->pts + av_rescale_q(in->nb_samples, av_make_q(1, outlink->sample_rate), |
| 420 | outlink->time_base); | 430 | outlink->time_base); |
| 421 | 431 | ||
| 422 | return ff_filter_frame(outlink, in); | 432 | if (out != in) |
| 433 | av_frame_free(&in); | ||
| 434 | return ff_filter_frame(outlink, out); | ||
| 423 | } | 435 | } |
| 424 | 436 | ||
| 425 | for (int f = 0; f < ff_inlink_queued_frames(inlink); f++) { | 437 | for (int f = 0; f < ff_inlink_queued_frames(inlink); f++) { |