static int return_audio_frame(AVFilterContext *ctx) { AVFilterLink *link = ctx->outputs[0]; FifoContext *s = ctx->priv; AVFrame *head = s->root.next ? s->root.next->frame : NULL; AVFrame *out; int ret; /* if head is NULL then we're flushing the remaining samples in out */ if (!head && !s->out) return AVERROR_EOF; if (!s->out && head->nb_samples >= link->request_samples && calc_ptr_alignment(head) >= 32) { if (head->nb_samples == link->request_samples) { out = head; queue_pop(s); } else { out = av_frame_clone(head); if (!out) return AVERROR(ENOMEM); out->nb_samples = link->request_samples; buffer_offset(link, head, link->request_samples); } } else { int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout); if (!s->out) { s->out = ff_get_audio_buffer(link, link->request_samples); if (!s->out) return AVERROR(ENOMEM); s->out->nb_samples = 0; s->out->pts = head->pts; s->allocated_samples = link->request_samples; } else if (link->request_samples != s->allocated_samples) { av_log(ctx, AV_LOG_ERROR, "request_samples changed before the " "buffer was returned.\n"); return AVERROR(EINVAL); } while (s->out->nb_samples < s->allocated_samples) { int len; if (!s->root.next) { ret = ff_request_frame(ctx->inputs[0]); if (ret == AVERROR_EOF) { av_samples_set_silence(s->out->extended_data, s->out->nb_samples, s->allocated_samples - s->out->nb_samples, nb_channels, link->format); s->out->nb_samples = s->allocated_samples; break; } else if (ret < 0) return ret; if (!s->root.next) return 0; } head = s->root.next->frame; len = FFMIN(s->allocated_samples - s->out->nb_samples, head->nb_samples); av_samples_copy(s->out->extended_data, head->extended_data, s->out->nb_samples, 0, len, nb_channels, link->format); s->out->nb_samples += len; if (len == head->nb_samples) { av_frame_free(&head); queue_pop(s); } else { buffer_offset(link, head, len); } } out = s->out; s->out = NULL; } return ff_filter_frame(link, out); }
static int return_audio_frame(AVFilterContext *ctx) { AVFilterLink *link = ctx->outputs[0]; FifoContext *s = ctx->priv; AVFilterBufferRef *head = s->root.next->buf; AVFilterBufferRef *buf_out; int ret; if (!s->buf_out && head->audio->nb_samples >= link->request_samples && calc_ptr_alignment(head) >= 32) { if (head->audio->nb_samples == link->request_samples) { buf_out = head; queue_pop(s); } else { buf_out = avfilter_ref_buffer(head, AV_PERM_READ); if (!buf_out) return AVERROR(ENOMEM); buf_out->audio->nb_samples = link->request_samples; buffer_offset(link, head, link->request_samples); } } else { int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout); if (!s->buf_out) { s->buf_out = ff_get_audio_buffer(link, AV_PERM_WRITE, link->request_samples); if (!s->buf_out) return AVERROR(ENOMEM); s->buf_out->audio->nb_samples = 0; s->buf_out->pts = head->pts; s->allocated_samples = link->request_samples; } else if (link->request_samples != s->allocated_samples) { av_log(ctx, AV_LOG_ERROR, "request_samples changed before the " "buffer was returned.\n"); return AVERROR(EINVAL); } while (s->buf_out->audio->nb_samples < s->allocated_samples) { int len = FFMIN(s->allocated_samples - s->buf_out->audio->nb_samples, head->audio->nb_samples); av_samples_copy(s->buf_out->extended_data, head->extended_data, s->buf_out->audio->nb_samples, 0, len, nb_channels, link->format); s->buf_out->audio->nb_samples += len; if (len == head->audio->nb_samples) { avfilter_unref_buffer(head); queue_pop(s); if (!s->root.next && (ret = ff_request_frame(ctx->inputs[0])) < 0) { if (ret == AVERROR_EOF) { av_samples_set_silence(s->buf_out->extended_data, s->buf_out->audio->nb_samples, s->allocated_samples - s->buf_out->audio->nb_samples, nb_channels, link->format); s->buf_out->audio->nb_samples = s->allocated_samples; break; } return ret; } head = s->root.next->buf; } else { buffer_offset(link, head, len); } } buf_out = s->buf_out; s->buf_out = NULL; } return ff_filter_samples(link, buf_out); }