avcodec: add a get_encode_buffer() callback to AVCodecContext

This callback is functionally the same as get_buffer2() is for decoders, and
implements for the new encode API the functionality of the old encode API had
where the user could provide their own buffers.

Reviewed-by: Lynne <dev@lynne.ee>
Reviewed-by: Michael Niedermayer <michael@niedermayer.cc>
Reviewed-by: Mark Thompson <sw@jkqxz.net>
Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer
2021-02-20 16:01:52 -03:00
parent 2c96e6cb95
commit 6e7e3a3820
7 changed files with 131 additions and 4 deletions

View File

@@ -56,6 +56,59 @@ int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64
return 0;
}
int avcodec_default_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int flags)
{
int ret;
if (avpkt->size < 0 || avpkt->size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
return AVERROR(EINVAL);
if (avpkt->data || avpkt->buf) {
av_log(avctx, AV_LOG_ERROR, "avpkt->{data,buf} != NULL in avcodec_default_get_encode_buffer()\n");
return AVERROR(EINVAL);
}
ret = av_buffer_realloc(&avpkt->buf, avpkt->size + AV_INPUT_BUFFER_PADDING_SIZE);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Failed to allocate packet of size %d\n", avpkt->size);
return ret;
}
avpkt->data = avpkt->buf->data;
memset(avpkt->data + avpkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
return 0;
}
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
{
int ret;
if (size < 0 || size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
return AVERROR(EINVAL);
av_assert0(!avpkt->data && !avpkt->buf);
avpkt->size = size;
ret = avctx->get_encode_buffer(avctx, avpkt, flags);
if (ret < 0)
goto fail;
if (!avpkt->data || !avpkt->buf) {
av_log(avctx, AV_LOG_ERROR, "No buffer returned by get_encode_buffer()\n");
ret = AVERROR(EINVAL);
goto fail;
}
ret = 0;
fail:
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "get_encode_buffer() failed\n");
av_packet_unref(avpkt);
}
return ret;
}
/**
* Pad last frame with silence.
*/
@@ -377,6 +430,12 @@ static int compat_encode(AVCodecContext *avctx, AVPacket *avpkt,
av_log(avctx, AV_LOG_WARNING, "AVFrame.width or height is not set\n");
}
if (avctx->codec->capabilities & AV_CODEC_CAP_DR1) {
av_log(avctx, AV_LOG_WARNING, "The deprecated avcodec_encode_* API does not support "
"AV_CODEC_CAP_DR1 encoders\n");
return AVERROR(ENOSYS);
}
ret = avcodec_send_frame(avctx, frame);
if (ret == AVERROR_EOF)
ret = 0;