mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-28 20:53:54 +02:00
lavfi: implement samples framing on links.
Links can be set up to group samples into buffers of specified minimum and maximum size.
This commit is contained in:
parent
c9c4835f51
commit
0689d5e17a
@ -156,7 +156,8 @@ static void default_filter_samples(AVFilterLink *link,
|
||||
ff_filter_samples(link->dst->outputs[0], samplesref);
|
||||
}
|
||||
|
||||
void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
|
||||
void ff_filter_samples_framed(AVFilterLink *link,
|
||||
AVFilterBufferRef *samplesref)
|
||||
{
|
||||
void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
|
||||
AVFilterPad *dst = link->dstpad;
|
||||
@ -195,3 +196,48 @@ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
|
||||
filter_samples(link, buf_out);
|
||||
ff_update_link_current_pts(link, pts);
|
||||
}
|
||||
|
||||
void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
|
||||
{
|
||||
int insamples = samplesref->audio->nb_samples, inpos = 0, nb_samples;
|
||||
AVFilterBufferRef *pbuf = link->partial_buf;
|
||||
int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
|
||||
|
||||
if (!link->min_samples ||
|
||||
(!pbuf &&
|
||||
insamples >= link->min_samples && insamples <= link->max_samples)) {
|
||||
ff_filter_samples_framed(link, samplesref);
|
||||
return;
|
||||
}
|
||||
/* Handle framing (min_samples, max_samples) */
|
||||
while (insamples) {
|
||||
if (!pbuf) {
|
||||
AVRational samples_tb = { 1, link->sample_rate };
|
||||
int perms = link->dstpad->min_perms | AV_PERM_WRITE;
|
||||
pbuf = ff_get_audio_buffer(link, perms, link->partial_buf_size);
|
||||
if (!pbuf) {
|
||||
av_log(link->dst, AV_LOG_WARNING,
|
||||
"Samples dropped due to memory allocation failure.\n");
|
||||
return;
|
||||
}
|
||||
avfilter_copy_buffer_ref_props(pbuf, samplesref);
|
||||
pbuf->pts = samplesref->pts +
|
||||
av_rescale_q(inpos, samples_tb, link->time_base);
|
||||
pbuf->audio->nb_samples = 0;
|
||||
}
|
||||
nb_samples = FFMIN(insamples,
|
||||
link->partial_buf_size - pbuf->audio->nb_samples);
|
||||
av_samples_copy(pbuf->extended_data, samplesref->extended_data,
|
||||
pbuf->audio->nb_samples, inpos,
|
||||
nb_samples, nb_channels, link->format);
|
||||
inpos += nb_samples;
|
||||
insamples -= nb_samples;
|
||||
pbuf->audio->nb_samples += nb_samples;
|
||||
if (pbuf->audio->nb_samples >= link->min_samples) {
|
||||
ff_filter_samples_framed(link, pbuf);
|
||||
pbuf = NULL;
|
||||
}
|
||||
}
|
||||
avfilter_unref_buffer(samplesref);
|
||||
link->partial_buf = pbuf;
|
||||
}
|
||||
|
@ -73,4 +73,11 @@ AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
|
||||
*/
|
||||
void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
|
||||
|
||||
/**
|
||||
* Send a buffer of audio samples to the next link, without checking
|
||||
* min_samples.
|
||||
*/
|
||||
void ff_filter_samples_framed(AVFilterLink *link,
|
||||
AVFilterBufferRef *samplesref);
|
||||
|
||||
#endif /* AVFILTER_AUDIO_H */
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "avfilter.h"
|
||||
#include "formats.h"
|
||||
#include "internal.h"
|
||||
#include "audio.h"
|
||||
|
||||
char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms)
|
||||
{
|
||||
@ -320,13 +321,20 @@ void ff_tlog_link(void *ctx, AVFilterLink *link, int end)
|
||||
|
||||
int ff_request_frame(AVFilterLink *link)
|
||||
{
|
||||
int ret = -1;
|
||||
FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1);
|
||||
|
||||
if (link->srcpad->request_frame)
|
||||
return link->srcpad->request_frame(link);
|
||||
ret = link->srcpad->request_frame(link);
|
||||
else if (link->src->inputs[0])
|
||||
return ff_request_frame(link->src->inputs[0]);
|
||||
else return -1;
|
||||
ret = ff_request_frame(link->src->inputs[0]);
|
||||
if (ret == AVERROR_EOF && link->partial_buf) {
|
||||
AVFilterBufferRef *pbuf = link->partial_buf;
|
||||
link->partial_buf = NULL;
|
||||
ff_filter_samples_framed(link, pbuf);
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ff_poll_frame(AVFilterLink *link)
|
||||
|
@ -590,6 +590,32 @@ struct AVFilterLink {
|
||||
* It is similar to the r_frae_rate field in AVStream.
|
||||
*/
|
||||
AVRational frame_rate;
|
||||
|
||||
/**
|
||||
* Buffer partially filled with samples to achieve a fixed/minimum size.
|
||||
*/
|
||||
AVFilterBufferRef *partial_buf;
|
||||
|
||||
/**
|
||||
* Size of the partial buffer to allocate.
|
||||
* Must be between min_samples and max_samples.
|
||||
*/
|
||||
int partial_buf_size;
|
||||
|
||||
/**
|
||||
* Minimum number of samples to filter at once. If filter_samples() is
|
||||
* called with fewer samples, it will accumulate them in partial_buf.
|
||||
* This field and the related ones must not be changed after filtering
|
||||
* has started.
|
||||
* If 0, all related fields are ignored.
|
||||
*/
|
||||
int min_samples;
|
||||
|
||||
/**
|
||||
* Maximum number of samples to filter at once. If filter_samples() is
|
||||
* called with more samples, it will split them.
|
||||
*/
|
||||
int max_samples;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user