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.
Unified · Split
| @@ -43,7 +43,6 @@ typedef struct AResampleContext { · 42 unmodified lines | ||
| 43 | 43 | struct SwrContext *swr; |
| 44 | 44 | int64_t next_pts; |
| 45 | 45 | int more_data; |
| 46 | − int eof; | |
| 47 | 46 | } AResampleContext; |
| 48 | 47 | |
| 49 | 48 | static av_cold int preinit(AVFilterContext *ctx) |
| @@ -209,7 +208,7 @@ static int config_output(AVFilterLink *outlink) · 159 unmodified lines | ||
| 209 | 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 | 213 | AVFilterContext *ctx = inlink->dst; |
| 215 | 214 | AResampleContext *aresample = ctx->priv; |
| @@ -220,23 +219,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) · 4 unmodified lines | ||
| 220 | 219 | AVFrame *outsamplesref; |
| 221 | 220 | int ret; |
| 222 | 221 | |
| 222 | + *outsamplesref_ret = NULL; | |
| 223 | 223 | delay = swr_get_delay(aresample->swr, outlink->sample_rate); |
| 224 | 224 | if (delay > 0) |
| 225 | 225 | n_out += FFMIN(delay, FFMAX(4096, n_out)); |
| 226 | 226 | |
| 227 | 227 | outsamplesref = ff_get_audio_buffer(outlink, n_out); |
| 228 | − | |
| 229 | − if(!outsamplesref) { | |
| 230 | − av_frame_free(&insamplesref); | |
| 228 | + if (!outsamplesref) | |
| 231 | 229 | return AVERROR(ENOMEM); |
| 232 | − } | |
| 233 | 230 | |
| 234 | 231 | av_frame_copy_props(outsamplesref, insamplesref); |
| 235 | 232 | outsamplesref->format = outlink->format; |
| 236 | 233 | ret = av_channel_layout_copy(&outsamplesref->ch_layout, &outlink->ch_layout); |
| 237 | 234 | if (ret < 0) { |
| 238 | 235 | av_frame_free(&outsamplesref); |
| 239 | − av_frame_free(&insamplesref); | |
| 240 | 236 | return ret; |
| 241 | 237 | } |
| 242 | 238 | outsamplesref->sample_rate = outlink->sample_rate; |
| @@ -257,8 +253,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) · 14 unmodified lines | ||
| 257 | 253 | (void *)insamplesref->extended_data, n_in); |
| 258 | 254 | if (n_out <= 0) { |
| 259 | 255 | av_frame_free(&outsamplesref); |
| 260 | − av_frame_free(&insamplesref); | |
| 261 | − ff_inlink_request_frame(inlink); | |
| 262 | 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 | 261 | outsamplesref->nb_samples = n_out; |
| 268 | 262 | |
| 269 | − ret = ff_filter_frame(outlink, outsamplesref); | |
| 270 | − av_frame_free(&insamplesref); | |
| 271 | − return ret; | |
| 263 | + *outsamplesref_ret = outsamplesref; | |
| 264 | + return 1; | |
| 272 | 265 | } |
| 273 | 266 | |
| 274 | 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 | 284 | n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, final ? NULL : (void*)outsamplesref->extended_data, 0); |
| 292 | 285 | if (n_out <= 0) { |
| 293 | 286 | av_frame_free(&outsamplesref); |
| 294 | − return (n_out == 0) ? AVERROR_EOF : n_out; | |
| 287 | + return n_out; | |
| 295 | 288 | } |
| 296 | 289 | |
| 297 | 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 | 293 | outsamplesref->pts = pts; |
| 301 | 294 | |
| 302 | − return 0; | |
| 295 | + return 1; | |
| 303 | 296 | } |
| 304 | 297 | |
| 305 | 298 | static int activate(AVFilterContext *ctx) |
| @@ -307,53 +300,54 @@ static int activate(AVFilterContext *ctx) · 1 unmodified line | ||
| 307 | 300 | AVFilterLink *inlink = ctx->inputs[0]; |
| 308 | 301 | AVFilterLink *outlink = ctx->outputs[0]; |
| 309 | 302 | AResampleContext *aresample = ctx->priv; |
| 303 | + AVFrame *frame; | |
| 310 | 304 | int ret = 0, status; |
| 311 | 305 | int64_t pts; |
| 312 | 306 | |
| 313 | 307 | FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); |
| 314 | 308 | |
| 315 | − if (!aresample->eof && ff_inlink_queued_frames(inlink)) { | |
| 316 | − AVFrame *frame = NULL; | |
| 309 | + // First try to get data from the internal buffers | |
| 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 | 314 | if (ret < 0) |
| 320 | 315 | return ret; |
| 321 | 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 | |
| 326 | − if (aresample->more_data) { | |
| 321 | + // Then consume frames from inlink | |
| 322 | + while ((ret = ff_inlink_consume_frame(inlink, &frame))) { | |
| 327 | 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 | 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 | |
| 343 | − if (aresample->eof) { | |
| 335 | + // If we hit the end flush | |
| 336 | + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { | |
| 344 | 337 | AVFrame *outsamplesref; |
| 345 | 338 | |
| 346 | − if ((ret = flush_frame(outlink, 1, &outsamplesref)) < 0) { | |
| 347 | − if (ret == AVERROR_EOF) { | |
| 348 | − ff_outlink_set_status(outlink, AVERROR_EOF, aresample->next_pts); | |
| 349 | − return 0; | |
| 350 | − } | |
| 339 | + ret = flush_frame(outlink, 1, &outsamplesref); | |
| 340 | + if (ret < 0) | |
| 351 | 341 | return ret; |
| 352 | − } | |
| 353 | − | |
| 354 | − return ff_filter_frame(outlink, outsamplesref); | |
| 342 | + if (ret > 0) | |
| 343 | + 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 | 351 | return FFERROR_NOT_READY; |
| 358 | 352 | } |
| 359 | 353 | |