Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
avcodec/utils: Add utility functions for bsf
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.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
  • Loading branch information
mkver committed Aug 2, 2019
1 parent eb29fd8 commit a119e05
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
26 changes: 26 additions & 0 deletions libavcodec/internal.h
Expand Up @@ -424,6 +424,32 @@ int64_t ff_guess_coded_bitrate(AVCodecContext *avctx);
int ff_int_from_list_or_default(void *ctx, const char * val_name, int val,
const int * array_valid_values, int default_value);

/**
* Reallocate an AVBufferRef of effective size size + grow_by. In addition,
* the buffer will have AV_BUFFER_INPUT_PADDING_SIZE bytes of zeroed padding
* at the end. The addition is checked for overflow and the size restrictions
* are checked, too.
*
* @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.
* @param size Must be >= 0.
* @param grow_by Must be so that size + grow_by >= 0.
* @return Zero on success, negative error code on failure
*/
int ff_buffer_padded_realloc(AVBufferRef **buf, int size, int grow_by);

/**
* 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. The
* reference will be owned by pkt afterwards.
*/
void ff_packet_replace_buffer(AVPacket *pkt, AVBufferRef *buf);

#if defined(_WIN32) && CONFIG_SHARED && !defined(BUILDING_avcodec)
# define av_export_avcodec __declspec(dllimport)
#else
Expand Down
25 changes: 25 additions & 0 deletions libavcodec/utils.c
Expand Up @@ -2232,3 +2232,28 @@ int ff_int_from_list_or_default(void *ctx, const char * val_name, int val,
"%s %d are not supported. Set to default value : %d\n", val_name, val, default_value);
return default_value;
}

int ff_buffer_padded_realloc(AVBufferRef **buf, int size, int grow_by)
{
int err;

if (size < 0 || (unsigned)size + grow_by > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
return AVERROR(EINVAL);

err = av_buffer_realloc(buf, size + grow_by + AV_INPUT_BUFFER_PADDING_SIZE);
if (err < 0)
return err;
memset((*buf)->data + size + grow_by, 0, AV_INPUT_BUFFER_PADDING_SIZE);
(*buf)->size -= AV_INPUT_BUFFER_PADDING_SIZE;

return 0;
}

void ff_packet_replace_buffer(AVPacket *pkt, AVBufferRef *buf)
{
av_buffer_unref(&pkt->buf);

pkt->buf = buf;
pkt->data = buf->data;
pkt->size = buf->size;
}

0 comments on commit a119e05

Please sign in to comment.