[FFmpeg-devel] [PATCH 23/36] avcodec/utils: Add utility functions for bsf
Andreas Rheinhardt
andreas.rheinhardt at gmail.com
Sat May 30 19:05:28 EEST 2020
Several bitstream filters (e.g. dump_extradata, imxdump, mjpeg2jpeg,
mjpegadump, mp3decomp, ...) don't buffer packets; instead, they just
modify the buffer of one packet and don't change any other of the
packet's non-buffer properties. The usual approach of these bitstream
filters is to use separate packets for in- and output as follows:
1. Get the input packet via ff_bsf_get_packet() which entails an allocation.
2. Use av_new_packet() to allocate a big enough buffer in the output
packet.
3. Perform the actual work of the bitstream filter, i.e. fill the output
buffer.
4. Use av_packet_copy_props() to copy the non-buffer fields of the input
packet to the output packet.
5. Free the input packet and return.
This commit adds two utility functions that allow a different approach:
A function to (re)allocate a refcounted buffer with zeroed padding and a
function to replace a packet's buffer and the buffer-related fields with
information from an AVBufferRef. This allows to modify the bitstream
filters as follows:
1. Get the packet via ff_bsf_get_packet_ref().
2. Use ff_buffer_padded_realloc() to get a big enough refcounted buffer.
3. Perform the actual work of the bitstream filter.
4. Use ff_packet_replace_buffer() to replace the old data in the packet
with the modified one and return.
The first of these functions is just packet_alloc() from avpacket.c which
has been made non-static.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
---
An earlier version put the declarations to internal.h, but James
suggested putting them into bsf_internal.h (or actually, into bsf.h
because bsf_internal.h didn't exist back then), so I went with this.
There is currently no user that actually makes use of the reallocation
feature; it was initially thought for hevc_mp4toannexb, but then I
decided to make it no longer reallocate the output buffer at all any
more. But I kept this functionality. Might be useful some day.
libavcodec/avpacket.c | 21 ++++++++++++++++-----
libavcodec/bsf_internal.h | 27 +++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index 033f2d8f26..c8f3b0cf7a 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -27,6 +27,7 @@
#include "libavutil/mathematics.h"
#include "libavutil/mem.h"
+#include "bsf_internal.h"
#include "bytestream.h"
#include "internal.h"
#include "packet.h"
@@ -69,7 +70,7 @@ void av_packet_free(AVPacket **pkt)
av_freep(pkt);
}
-static int packet_alloc(AVBufferRef **buf, int size)
+int ff_buffer_padded_realloc(AVBufferRef **buf, int size)
{
int ret;
if (size < 0 || size >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
@@ -87,7 +88,7 @@ static int packet_alloc(AVBufferRef **buf, int size)
int av_new_packet(AVPacket *pkt, int size)
{
AVBufferRef *buf = NULL;
- int ret = packet_alloc(&buf, size);
+ int ret = ff_buffer_padded_realloc(&buf, size);
if (ret < 0)
return ret;
@@ -621,7 +622,7 @@ int av_packet_ref(AVPacket *dst, const AVPacket *src)
goto fail;
if (!src->buf) {
- ret = packet_alloc(&dst->buf, src->size);
+ ret = ff_buffer_padded_realloc(&dst->buf, src->size);
if (ret < 0)
goto fail;
av_assert1(!src->size || src->data);
@@ -674,7 +675,7 @@ int av_packet_make_refcounted(AVPacket *pkt)
if (pkt->buf)
return 0;
- ret = packet_alloc(&pkt->buf, pkt->size);
+ ret = ff_buffer_padded_realloc(&pkt->buf, pkt->size);
if (ret < 0)
return ret;
av_assert1(!pkt->size || pkt->data);
@@ -694,7 +695,7 @@ int av_packet_make_writable(AVPacket *pkt)
if (pkt->buf && av_buffer_is_writable(pkt->buf))
return 0;
- ret = packet_alloc(&buf, pkt->size);
+ ret = ff_buffer_padded_realloc(&buf, pkt->size);
if (ret < 0)
return ret;
av_assert1(!pkt->size || pkt->data);
@@ -770,3 +771,13 @@ int ff_side_data_set_prft(AVPacket *pkt, int64_t timestamp)
return 0;
}
+
+void ff_packet_replace_buffer(AVPacket *pkt, AVBufferRef *buf)
+{
+ av_buffer_unref(&pkt->buf);
+
+ pkt->buf = buf;
+ pkt->data = buf->data;
+ av_assert1(buf->size >= AV_INPUT_BUFFER_PADDING_SIZE);
+ pkt->size = buf->size - AV_INPUT_BUFFER_PADDING_SIZE;
+}
diff --git a/libavcodec/bsf_internal.h b/libavcodec/bsf_internal.h
index fefd5b8905..edaacaa2dd 100644
--- a/libavcodec/bsf_internal.h
+++ b/libavcodec/bsf_internal.h
@@ -19,6 +19,7 @@
#ifndef AVCODEC_BSF_INTERNAL_H
#define AVCODEC_BSF_INTERNAL_H
+#include "libavutil/buffer.h"
#include "libavutil/log.h"
#include "bsf.h"
@@ -42,6 +43,32 @@ int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt);
*/
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt);
+/**
+ * (Re)allocate an AVBufferRef to an effective size of size. In addition,
+ * the buffer will have AV_BUFFER_INPUT_PADDING_SIZE bytes of zeroed padding
+ * at the end.
+ *
+ * @param buf Pointer to pointer to an AVBufferRef. Must not be NULL;
+ * *buf will be reallocated to the desired size; if *buf is NULL,
+ * it will be allocated, otherwise it must be writable.
+ * @param size Desired usable size.
+ * @return Zero on success, negative error code on failure.
+ * *buf is unchanged on error.
+ */
+int ff_buffer_padded_realloc(AVBufferRef **buf, int size);
+
+/**
+ * Unreference the packet's buf and replace it with the given buf.
+ * The packet's data and size fields will be updated with the information
+ * from buf, too.
+ *
+ * @param pkt Pointer to a packet to modify. Must not be NULL.
+ * @param buf Pointer to an AVBufferRef. Must not be NULL.
+ * buf will be owned by pkt afterwards. Its size must include
+ * AV_INPUT_BUFFER_PADDING_SIZE bytes of padding at the end.
+ */
+void ff_packet_replace_buffer(AVPacket *pkt, AVBufferRef *buf);
+
const AVClass *ff_bsf_child_class_next(const AVClass *prev);
#endif /* AVCODEC_BSF_INTERNAL_H */
--
2.20.1
More information about the ffmpeg-devel
mailing list