This should prevent the possibility of audio data accumulating. The commit also cleans up and simplifies the code a bit so all frame producers (filter_frame(), flush_frame()) functions follow similar logic as ff_inlink_consume_frame() for the return code.
Showing the changes to libavfilter (1 of 1 file). Show all
Unified · Split
| @@ -43,7 +43,6 @@ typedef struct AResampleContext { · 42 unmodified lines | |||
| 43 | struct SwrContext *swr; | 43 | struct SwrContext *swr; |
| 44 | int64_t next_pts; | 44 | int64_t next_pts; |
| 45 | int more_data; | 45 | int more_data; |
| 46 | int eof; | ||
| 47 | } AResampleContext; | 46 | } AResampleContext; |
| 48 | 47 | ||
| 49 | static av_cold int preinit(AVFilterContext *ctx) | 48 | static av_cold int preinit(AVFilterContext *ctx) |
| @@ -209,7 +208,7 @@ static int config_output(AVFilterLink *outlink) · 159 unmodified lines | |||
| 209 | return 0; | 208 | return 0; |
| 210 | } | 209 | } |
| 211 | 210 | ||
| 212 | static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) | 211 | static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref, AVFrame **outsamplesref_ret) |
| 213 | { | 212 | { |
| 214 | AVFilterContext *ctx = inlink->dst; | 213 | AVFilterContext *ctx = inlink->dst; |
| 215 | AResampleContext *aresample = ctx->priv; | 214 | AResampleContext *aresample = ctx->priv; |
| @@ -220,23 +219,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) · 4 unmodified lines | |||
| 220 | AVFrame *outsamplesref; | 219 | AVFrame *outsamplesref; |
| 221 | int ret; | 220 | int ret; |
| 222 | 221 | ||
| 222 | *outsamplesref_ret = NULL; | ||
| 223 | delay = swr_get_delay(aresample->swr, outlink->sample_rate); | 223 | delay = swr_get_delay(aresample->swr, outlink->sample_rate); |
| 224 | if (delay > 0) | 224 | if (delay > 0) |
| 225 | n_out += FFMIN(delay, FFMAX(4096, n_out)); | 225 | n_out += FFMIN(delay, FFMAX(4096, n_out)); |
| 226 | 226 | ||
| 227 | outsamplesref = ff_get_audio_buffer(outlink, n_out); | 227 | outsamplesref = ff_get_audio_buffer(outlink, n_out); |
| 228 | 228 | if (!outsamplesref) | |
| 229 | if(!outsamplesref) { | ||
| 230 | av_frame_free(&insamplesref); | ||
| 231 | return AVERROR(ENOMEM); | 229 | return AVERROR(ENOMEM); |
| 232 | } | ||
| 233 | 230 | ||
| 234 | av_frame_copy_props(outsamplesref, insamplesref); | 231 | av_frame_copy_props(outsamplesref, insamplesref); |
| 235 | outsamplesref->format = outlink->format; | 232 | outsamplesref->format = outlink->format; |
| 236 | ret = av_channel_layout_copy(&outsamplesref->ch_layout, &outlink->ch_layout); | 233 | ret = av_channel_layout_copy(&outsamplesref->ch_layout, &outlink->ch_layout); |
| 237 | if (ret < 0) { | 234 | if (ret < 0) { |
| 238 | av_frame_free(&outsamplesref); | 235 | av_frame_free(&outsamplesref); |
| 239 | av_frame_free(&insamplesref); | ||
| 240 | return ret; | 236 | return ret; |
| 241 | } | 237 | } |
| 242 | outsamplesref->sample_rate = outlink->sample_rate; | 238 | outsamplesref->sample_rate = outlink->sample_rate; |
| @@ -257,8 +253,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) · 14 unmodified lines | |||
| 257 | (void *)insamplesref->extended_data, n_in); | 253 | (void *)insamplesref->extended_data, n_in); |
| 258 | if (n_out <= 0) { | 254 | if (n_out <= 0) { |
| 259 | av_frame_free(&outsamplesref); | 255 | av_frame_free(&outsamplesref); |
| 260 | av_frame_free(&insamplesref); | ||
| 261 | ff_inlink_request_frame(inlink); | ||
| 262 | return 0; | 256 | return 0; |
| 263 | } | 257 | } |
| 264 | 258 | ||
| @@ -266,9 +260,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) · 1 unmodified line | |||
| 266 | 260 | ||
| 267 | outsamplesref->nb_samples = n_out; | 261 | outsamplesref->nb_samples = n_out; |
| 268 | 262 | ||
| 269 | ret = ff_filter_frame(outlink, outsamplesref); | 263 | *outsamplesref_ret = outsamplesref; |
| 270 | av_frame_free(&insamplesref); | 264 | return 1; |
| 271 | return ret; | ||
| 272 | } | 265 | } |
| 273 | 266 | ||
| 274 | static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref_ret) | 267 | static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref_ret) |
| @@ -291,7 +284,7 @@ static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref · 16 unmodified lines | |||
| 291 | n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, final ? NULL : (void*)outsamplesref->extended_data, 0); | 284 | n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, final ? NULL : (void*)outsamplesref->extended_data, 0); |
| 292 | if (n_out <= 0) { | 285 | if (n_out <= 0) { |
| 293 | av_frame_free(&outsamplesref); | 286 | av_frame_free(&outsamplesref); |
| 294 | return (n_out == 0) ? AVERROR_EOF : n_out; | 287 | return n_out; |
| 295 | } | 288 | } |
| 296 | 289 | ||
| 297 | outsamplesref->sample_rate = outlink->sample_rate; | 290 | outsamplesref->sample_rate = outlink->sample_rate; |
| @@ -299,7 +292,7 @@ static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref · 1 unmodified line | |||
| 299 | 292 | ||
| 300 | outsamplesref->pts = pts; | 293 | outsamplesref->pts = pts; |
| 301 | 294 | ||
| 302 | return 0; | 295 | return 1; |
| 303 | } | 296 | } |
| 304 | 297 | ||
| 305 | static int activate(AVFilterContext *ctx) | 298 | static int activate(AVFilterContext *ctx) |
| @@ -307,53 +300,54 @@ static int activate(AVFilterContext *ctx) · 1 unmodified line | |||
| 307 | AVFilterLink *inlink = ctx->inputs[0]; | 300 | AVFilterLink *inlink = ctx->inputs[0]; |
| 308 | AVFilterLink *outlink = ctx->outputs[0]; | 301 | AVFilterLink *outlink = ctx->outputs[0]; |
| 309 | AResampleContext *aresample = ctx->priv; | 302 | AResampleContext *aresample = ctx->priv; |
| 303 | AVFrame *frame; | ||
| 310 | int ret = 0, status; | 304 | int ret = 0, status; |
| 311 | int64_t pts; | 305 | int64_t pts; |
| 312 | 306 | ||
| 313 | FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); | 307 | FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); |
| 314 | 308 | ||
| 315 | if (!aresample->eof && ff_inlink_queued_frames(inlink)) { | 309 | // First try to get data from the internal buffers |
| 316 | AVFrame *frame = NULL; | 310 | if (aresample->more_data) { |
| 311 | AVFrame *outsamplesref; | ||
| 317 | 312 | ||
| 318 | ret = ff_inlink_consume_frame(inlink, &frame); | 313 | ret = flush_frame(outlink, 0, &outsamplesref); |
| 319 | if (ret < 0) | 314 | if (ret < 0) |
| 320 | return ret; | 315 | return ret; |
| 321 | if (ret > 0) | 316 | if (ret > 0) |
| 322 | return filter_frame(inlink, frame); | 317 | return ff_filter_frame(outlink, outsamplesref); |
| 323 | } | 318 | } |
| 319 | aresample->more_data = 0; | ||
| 324 | 320 | ||
| 325 | // First try to get data from the internal buffers | 321 | // Then consume frames from inlink |
| 326 | if (aresample->more_data) { | 322 | while ((ret = ff_inlink_consume_frame(inlink, &frame))) { |
| 327 | AVFrame *outsamplesref; | 323 | AVFrame *outsamplesref; |
| 324 | if (ret < 0) | ||
| 325 | return ret; | ||
| 328 | 326 | ||
| 329 | if (flush_frame(outlink, 0, &outsamplesref) >= 0) { | 327 | ret = filter_frame(inlink, frame, &outsamplesref); |
| 328 | av_frame_free(&frame); | ||
| 329 | if (ret < 0) | ||
| 330 | return ret; | ||
| 331 | if (ret > 0) | ||
| 330 | return ff_filter_frame(outlink, outsamplesref); | 332 | return ff_filter_frame(outlink, outsamplesref); |
| 331 | } | ||
| 332 | } | 333 | } |
| 333 | aresample->more_data = 0; | ||
| 334 | |||
| 335 | if (!aresample->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) | ||
| 336 | aresample->eof = 1; | ||
| 337 | |||
| 338 | // Second request more data from the input | ||
| 339 | if (!aresample->eof) | ||
| 340 | FF_FILTER_FORWARD_WANTED(outlink, inlink); | ||
| 341 | 334 | ||
| 342 | // Third if we hit the end flush | 335 | // If we hit the end flush |
| 343 | if (aresample->eof) { | 336 | if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { |
| 344 | AVFrame *outsamplesref; | 337 | AVFrame *outsamplesref; |
| 345 | 338 | ||
| 346 | if ((ret = flush_frame(outlink, 1, &outsamplesref)) < 0) { | 339 | ret = flush_frame(outlink, 1, &outsamplesref); |
| 347 | if (ret == AVERROR_EOF) { | 340 | if (ret < 0) |
| 348 | ff_outlink_set_status(outlink, AVERROR_EOF, aresample->next_pts); | ||
| 349 | return 0; | ||
| 350 | } | ||
| 351 | return ret; | 341 | return ret; |
| 352 | } | 342 | if (ret > 0) |
| 353 | 343 | return ff_filter_frame(outlink, outsamplesref); | |
| 354 | return ff_filter_frame(outlink, outsamplesref); | 344 | ff_outlink_set_status(outlink, status, aresample->next_pts); |
| 345 | return 0; | ||
| 355 | } | 346 | } |
| 356 | 347 | ||
| 348 | // If not, request more data from the input | ||
| 349 | FF_FILTER_FORWARD_WANTED(outlink, inlink); | ||
| 350 | |||
| 357 | return FFERROR_NOT_READY; | 351 | return FFERROR_NOT_READY; |
| 358 | } | 352 | } |
| 359 | 353 | ||