[FFmpeg-devel] [PATCH] Use AVBufferPool in MOV
Arnaud Masserann
arnaud1602 at gmail.com
Fri Nov 22 20:07:41 EET 2024
A few questions:
- Should the pools be per-stream (in MOVStreamContext) or per file (in
MOVContext) ?
- I added an av_get_pooled_packet(AVBufferPool*) function in the
avformat API. This might be undesirable. Possible alternatives:
- Adding a av_get_pooled_packet(AVBufferPool*[32]) function
instead; this matches the way mpegts uses the pool, but is probably
too restrictive since it forces all future users to have this array of
32 pools.
- Duplicating av_get_packet in mov.c; but then
append_packet_chunked needs to be duplicated too.
Feedback is welcome.
On Fri, Nov 22, 2024 at 6:46 PM Arnaud Masserann <arnaud1602 at gmail.com> wrote:
>
> Most demuxers allocate a new buffer for each packet.
> For MOV, this can be problematic, because of some high-bitrate
> codecs like ProRes/HAPQ/NotchLC.
>
> Use pools of buffer instead.
>
> For some test media, demuxing goes from 20ms/frame to 11ms/frame,
> close to the perf of ReadFile (10ms/frame), making it possible
> to read the media at 60Hz.
>
> Signed-off-by: Arnaud Masserann <Arnaud1602 at gmail.com>
> ---
> libavformat/avformat.h | 12 ++++++++++++
> libavformat/isom.h | 2 ++
> libavformat/mov.c | 20 ++++++++++++++++++--
> libavformat/utils.c | 29 +++++++++++++++++++++++++++++
> 4 files changed, 61 insertions(+), 2 deletions(-)
>
> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 56c1c80289..25f2e59b22 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -440,6 +440,18 @@ int av_get_packet(AVIOContext *s, AVPacket *pkt, int size);
> */
> int av_append_packet(AVIOContext *s, AVPacket *pkt, int size);
>
> +
> +/**
> + * Like av_get_packet, but allocates the AVPacket's buffer from a pool.
> + *
> + * @param s associated IO context
> + * @param pool the pool of buffers; must be initialized with a sufficient size
> + * @param pkt packet
> + * @param size desired payload size
> + * @return >0 (read size) if OK, AVERROR_xxx otherwise
> + */
> +int av_get_pooled_packet(AVIOContext *s, AVBufferPool* pool, AVPacket *pkt, int size);
> +
> /*************************************************/
> /* input/output formats */
>
> diff --git a/libavformat/isom.h b/libavformat/isom.h
> index 4723397048..c608f30e04 100644
> --- a/libavformat/isom.h
> +++ b/libavformat/isom.h
> @@ -273,6 +273,8 @@ typedef struct MOVStreamContext {
> } cenc;
>
> struct IAMFDemuxContext *iamf;
> +
> + AVBufferPool* pools[32];
> } MOVStreamContext;
>
> typedef struct HEIFItem {
> diff --git a/libavformat/mov.c b/libavformat/mov.c
> index a2333ac1fd..2668bdf78f 100644
> --- a/libavformat/mov.c
> +++ b/libavformat/mov.c
> @@ -9583,6 +9583,7 @@ static void mov_free_encryption_index(MOVEncryptionIndex **index) {
> static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
> {
> MOVStreamContext *sc = st->priv_data;
> + int i;
>
> if (!sc || --sc->refcount) {
> st->priv_data = NULL;
> @@ -9639,6 +9640,9 @@ static void mov_free_stream_context(AVFormatContext *s, AVStream *st)
> ff_iamf_read_deinit(sc->iamf);
> #endif
> av_freep(&sc->iamf);
> +
> + for (i = 0; i < FF_ARRAY_ELEMS(sc->pools); i++)
> + av_buffer_pool_uninit(&sc->pools[i]);
> }
>
> static int mov_read_close(AVFormatContext *s)
> @@ -10544,6 +10548,16 @@ static int mov_finalize_packet(AVFormatContext *s, AVStream *st, AVIndexEntry *s
> return 0;
> }
>
> +static AVBufferPool *mov_pool_get(AVBufferPool* pools[32], int size)
> +{
> + int index = av_log2(size + AV_INPUT_BUFFER_PADDING_SIZE);
> + if (!pools[index]) {
> + int pool_size = 2 << index;
> + pools[index] = av_buffer_pool_init(pool_size, NULL);
> + }
> + return pools[index];
> +}
> +
> static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
> {
> MOVContext *mov = s->priv_data;
> @@ -10617,8 +10631,10 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
> return FFERROR_REDO;
> }
> #endif
> - else
> - ret = av_get_packet(sc->pb, pkt, sample->size);
> + else{
> + AVBufferPool* pool = mov_pool_get(sc->pools, sample->size);
> + ret = av_get_pooled_packet(sc->pb, pool, pkt, sample->size);
> + }
> if (ret < 0) {
> if (should_retry(sc->pb, ret)) {
> mov_current_sample_dec(sc);
> diff --git a/libavformat/utils.c b/libavformat/utils.c
> index e9ded627ad..869e97c089 100644
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -104,6 +104,35 @@ FF_ENABLE_DEPRECATION_WARNINGS
> return append_packet_chunked(s, pkt, size);
> }
>
> +int av_get_pooled_packet(AVIOContext *s, AVBufferPool* pool, AVPacket *pkt, int size)
> +{
> +#if FF_API_INIT_PACKET
> +FF_DISABLE_DEPRECATION_WARNINGS
> + av_init_packet(pkt);
> + pkt->data = NULL;
> + pkt->size = 0;
> +FF_ENABLE_DEPRECATION_WARNINGS
> +#else
> + av_packet_unref(pkt);
> +#endif
> + pkt->pos = avio_tell(s);
> +
> + if(!pool)
> + return AVERROR(ENOMEM);
> +
> + pkt->buf = av_buffer_pool_get(pool);;
> + if(!pkt->buf)
> + return AVERROR(ENOMEM);
> +
> + if(pkt->buf->size < size){
> + av_packet_unref(pkt); // TODO test this
> + return AVERROR(ENOMEM);
> + }
> +
> + return append_packet_chunked(s, pkt, size);
> +}
> +
> +
> int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)
> {
> if (!pkt->size)
> --
> 2.38.1.windows.1
>
More information about the ffmpeg-devel
mailing list