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 | 84 | void (*analyze_channel)(AVFilterContext *ctx, ChannelContext *cc, |
| 85 | 85 | const uint8_t *srcp, int nb_samples); |
| 86 | 86 | void (*filter_channels[2])(AVFilterContext *ctx, |
| 87 | − AVFrame *in, int nb_samples); | |
| 87 | + AVFrame *in, AVFrame *out, int nb_samples); | |
| 88 | 88 | } SpeechNormalizerContext; |
| 89 | 89 | |
| 90 | 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 | 296 | #define FILTER_CHANNELS(name, ptype) \ |
| 297 | 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 | 300 | SpeechNormalizerContext *s = ctx->priv; \ |
| 301 | 301 | AVFilterLink *inlink = ctx->inputs[0]; \ |
| 302 | 302 | \ |
| 303 | 303 | for (int ch = 0; ch < inlink->channels; ch++) { \ |
| 304 | 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 | 307 | const int bypass = !(av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels); \ |
| 307 | 308 | int n = 0; \ |
| 308 | 309 | \ |
| @@ -316,7 +317,7 @@ static void filter_channels_## name (AVFilterContext *ctx, · 7 unmodified lines | ||
| 316 | 317 | gain = cc->gain_state; \ |
| 317 | 318 | consume_pi(cc, size); \ |
| 318 | 319 | for (int i = n; !ctx->is_disabled && i < n + size; i++) \ |
| 319 | − dst[i] *= gain; \ | |
| 320 | + dst[i] = src[i] * gain; \ | |
| 320 | 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 | 339 | #define FILTER_LINK_CHANNELS(name, ptype, tlerp) \ |
| 339 | 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 | 344 | SpeechNormalizerContext *s = ctx->priv; \ |
| 343 | 345 | AVFilterLink *inlink = ctx->inputs[0]; \ |
| @@ -369,7 +371,8 @@ static void filter_link_channels_## name (AVFilterContext *ctx, · 25 unmodified lines | ||
| 369 | 371 | \ |
| 370 | 372 | for (int ch = 0; ch < inlink->channels; ch++) { \ |
| 371 | 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 | 377 | consume_pi(cc, min_size); \ |
| 375 | 378 | if (cc->bypass) \ |
| @@ -377,7 +380,7 @@ static void filter_link_channels_## name (AVFilterContext *ctx, · 1 unmodified line | ||
| 377 | 380 | \ |
| 378 | 381 | for (int i = n; !ctx->is_disabled && i < n + min_size; i++) { \ |
| 379 | 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 | 402 | while (s->queue.available > 0) { |
| 400 | 403 | int min_pi_nb_samples; |
| 401 | − AVFrame *in; | |
| 404 | + AVFrame *in, *out; | |
| 402 | 405 | |
| 403 | 406 | in = ff_bufqueue_peek(&s->queue, 0); |
| 404 | 407 | if (!in) |
| @@ -410,16 +413,25 @@ static int filter_frame(AVFilterContext *ctx) · 5 unmodified lines | ||
| 410 | 413 | |
| 411 | 414 | in = ff_bufqueue_get(&s->queue); |
| 412 | 415 | |
| 413 | − ret = av_frame_make_writable(in); | |
| 414 | − if (ret < 0) | |
| 415 | − return ret; | |
| 416 | + if (av_frame_is_writable(in)) { | |
| 417 | + out = in; | |
| 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 | 429 | s->pts = in->pts + av_rescale_q(in->nb_samples, av_make_q(1, outlink->sample_rate), |
| 420 | 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 | 437 | for (int f = 0; f < ff_inlink_queued_frames(inlink); f++) { |