lavfi: make ff_framequeue_skip_samples() more useful.
Instead of just updating statistics and leaving the work to the call site, have it actually do the work. Also: skip the samples by updating the frame data pointers instead of moving the samples. More efficient and avoid writing into shared frames. Found-By: Muhammad Faiz <mfcc64@gmail.com>
This commit is contained in:
parent
e05d2dd86a
commit
383057f8e7
@ -1235,13 +1235,7 @@ static int take_samples(AVFilterLink *link, unsigned min, unsigned max,
|
|||||||
frame = ff_framequeue_peek(&link->fifo, 0);
|
frame = ff_framequeue_peek(&link->fifo, 0);
|
||||||
av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n,
|
av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n,
|
||||||
link->channels, link->format);
|
link->channels, link->format);
|
||||||
frame->nb_samples -= n;
|
ff_framequeue_skip_samples(&link->fifo, n, link->time_base);
|
||||||
av_samples_copy(frame->extended_data, frame->extended_data, 0, n,
|
|
||||||
frame->nb_samples, link->channels, link->format);
|
|
||||||
if (frame->pts != AV_NOPTS_VALUE)
|
|
||||||
frame->pts += av_rescale_q(n, av_make_q(1, link->sample_rate), link->time_base);
|
|
||||||
ff_framequeue_update_peeked(&link->fifo, 0);
|
|
||||||
ff_framequeue_skip_samples(&link->fifo, n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*rframe = buf;
|
*rframe = buf;
|
||||||
|
@ -121,3 +121,30 @@ AVFrame *ff_framequeue_peek(FFFrameQueue *fq, size_t idx)
|
|||||||
check_consistency(fq);
|
check_consistency(fq);
|
||||||
return b->frame;
|
return b->frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ff_framequeue_skip_samples(FFFrameQueue *fq, size_t samples, AVRational time_base)
|
||||||
|
{
|
||||||
|
FFFrameBucket *b;
|
||||||
|
size_t bytes;
|
||||||
|
int planar, planes, i;
|
||||||
|
|
||||||
|
check_consistency(fq);
|
||||||
|
av_assert1(fq->queued);
|
||||||
|
b = bucket(fq, 0);
|
||||||
|
av_assert1(samples < b->frame->nb_samples);
|
||||||
|
planar = av_sample_fmt_is_planar(b->frame->format);
|
||||||
|
planes = planar ? b->frame->channels : 1;
|
||||||
|
bytes = samples * av_get_bytes_per_sample(b->frame->format);
|
||||||
|
if (!planar)
|
||||||
|
bytes *= b->frame->channels;
|
||||||
|
if (b->frame->pts != AV_NOPTS_VALUE)
|
||||||
|
b->frame->pts += av_rescale_q(samples, av_make_q(1, b->frame->sample_rate), time_base);
|
||||||
|
b->frame->nb_samples -= samples;
|
||||||
|
b->frame->linesize[0] -= bytes;
|
||||||
|
for (i = 0; i < planes; i++)
|
||||||
|
b->frame->extended_data[i] += bytes;
|
||||||
|
for (i = 0; i < planes && i < AV_NUM_DATA_POINTERS; i++)
|
||||||
|
b->frame->data[i] = b->frame->extended_data[i];
|
||||||
|
fq->total_samples_tail += samples;
|
||||||
|
ff_framequeue_update_peeked(fq, 0);
|
||||||
|
}
|
||||||
|
@ -161,14 +161,13 @@ static inline void ff_framequeue_update_peeked(FFFrameQueue *fq, size_t idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the sample count in the queue.
|
* Skip samples from the first frame in the queue.
|
||||||
*
|
*
|
||||||
* This function must be used when the first frame was accessed using
|
* This function must be used when the first frame was accessed using
|
||||||
* ff_framequeue_peek() and samples were removed from it.
|
* ff_framequeue_peek() and samples were consumed from it.
|
||||||
|
* It adapts the data pointers and timestamps of the head frame to account
|
||||||
|
* for the skipped samples.
|
||||||
*/
|
*/
|
||||||
static inline void ff_framequeue_skip_samples(FFFrameQueue *fq, size_t n)
|
void ff_framequeue_skip_samples(FFFrameQueue *fq, size_t samples, AVRational time_base);
|
||||||
{
|
|
||||||
fq->total_samples_tail += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* AVFILTER_FRAMEQUEUE_H */
|
#endif /* AVFILTER_FRAMEQUEUE_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user