On 11/24/2024 2:31 PM, James Almer wrote:
On 11/22/2024 2:46 PM, Arnaud Masserann 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 <arnaud1...@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);This doesn't need to be public. It can be internal to lavf just fine.+ /*************************************************/ /* 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];Like you argued, this can be in MovContext instead, since the pools are fixed size and can be used by any stream.} 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 *sreturn 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);;Extra ;+ if(!pkt->buf) + return AVERROR(ENOMEM); + + if(pkt->buf->size < size){ + av_packet_unref(pkt); // TODO test this + return AVERROR(ENOMEM);Maybe EINVAL instead. Also, you're not setting pkt->data to pkt->buf->data.
Actually, disregard this part. It's fine as is.
+ } + + return append_packet_chunked(s, pkt, size); +} + + int av_append_packet(AVIOContext *s, AVPacket *pkt, int size) { if (!pkt->size)
OpenPGP_signature.asc
Description: OpenPGP digital signature
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".