@@ -612,7 +612,7 @@ static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx,
err = ff_h2645_packet_split(&priv->read_packet,
frag->data + start, end - start,
- ctx->log_ctx, 1, 2, AV_CODEC_ID_H264, 1);
+ ctx->log_ctx, 1, 2, AV_CODEC_ID_H264, 1, 0);
if (err < 0) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC SPS array.\n");
return err;
@@ -636,7 +636,7 @@ static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx,
err = ff_h2645_packet_split(&priv->read_packet,
frag->data + start, end - start,
- ctx->log_ctx, 1, 2, AV_CODEC_ID_H264, 1);
+ ctx->log_ctx, 1, 2, AV_CODEC_ID_H264, 1, 0);
if (err < 0) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split AVCC PPS array.\n");
return err;
@@ -690,7 +690,7 @@ static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx,
err = ff_h2645_packet_split(&priv->read_packet,
frag->data + start, end - start,
- ctx->log_ctx, 1, 2, AV_CODEC_ID_HEVC, 1);
+ ctx->log_ctx, 1, 2, AV_CODEC_ID_HEVC, 1, 0);
if (err < 0) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to split "
"HVCC array %d (%d NAL units of type %d).\n",
@@ -709,7 +709,7 @@ static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx,
frag->data, frag->data_size,
ctx->log_ctx,
priv->mp4, priv->nal_length_size,
- codec_id, 1);
+ codec_id, 1, 0);
if (err < 0)
return err;
@@ -157,7 +157,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt,
}
ret = ff_h2645_packet_split(&s->h2645_pkt, pkt->data, pkt->size,
- ctx, 0, 0, ctx->par_in->codec_id, 1);
+ ctx, 0, 0, ctx->par_in->codec_id, 1, 0);
if (ret < 0)
return ret;
@@ -343,9 +343,51 @@ static int find_next_start_code(const uint8_t *buf, const uint8_t *next_avc)
return i + 3;
}
+static void alloc_rbsp_buffer(H2645RBSP *rbsp, unsigned int size, int use_ref)
+{
+ if (size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
+ goto fail;
+ size += AV_INPUT_BUFFER_PADDING_SIZE;
+
+ if (rbsp->rbsp_buffer_alloc_size >= size &&
+ (!rbsp->rbsp_buffer_ref || av_buffer_is_writable(rbsp->rbsp_buffer_ref)))
+ return;
+
+ size = FFMIN(size + size / 16 + 32, INT_MAX);
+
+ if (rbsp->rbsp_buffer_ref)
+ av_buffer_unref(&rbsp->rbsp_buffer_ref);
+ else
+ av_free(rbsp->rbsp_buffer);
+
+ rbsp->rbsp_buffer = av_malloc(size);
+ if (!rbsp->rbsp_buffer)
+ goto fail;
+ rbsp->rbsp_buffer_alloc_size = size;
+
+ if (use_ref) {
+ rbsp->rbsp_buffer_ref = av_buffer_create(rbsp->rbsp_buffer, size,
+ NULL, NULL, 0);
+ if (!rbsp->rbsp_buffer_ref)
+ goto fail;
+ }
+
+ return;
+
+fail:
+ rbsp->rbsp_buffer_alloc_size = 0;
+ if (rbsp->rbsp_buffer_ref) {
+ av_buffer_unref(&rbsp->rbsp_buffer_ref);
+ rbsp->rbsp_buffer = NULL;
+ } else
+ av_freep(&rbsp->rbsp_buffer);
+
+ return;
+}
+
int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
void *logctx, int is_nalff, int nal_length_size,
- enum AVCodecID codec_id, int small_padding)
+ enum AVCodecID codec_id, int small_padding, int use_ref)
{
GetByteContext bc;
int consumed, ret = 0;
@@ -353,7 +395,8 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
int64_t padding = small_padding ? 0 : MAX_MBPAIR_SIZE;
bytestream2_init(&bc, buf, length);
- av_fast_padded_malloc(&pkt->rbsp.rbsp_buffer, &pkt->rbsp.rbsp_buffer_alloc_size, length + padding);
+ alloc_rbsp_buffer(&pkt->rbsp, length + padding, use_ref);
+
if (!pkt->rbsp.rbsp_buffer)
return AVERROR(ENOMEM);
@@ -474,6 +517,10 @@ void ff_h2645_packet_uninit(H2645Packet *pkt)
}
av_freep(&pkt->nals);
pkt->nals_allocated = 0;
- av_freep(&pkt->rbsp.rbsp_buffer);
+ if (pkt->rbsp.rbsp_buffer_ref) {
+ av_buffer_unref(&pkt->rbsp.rbsp_buffer_ref);
+ pkt->rbsp.rbsp_buffer = NULL;
+ } else
+ av_freep(&pkt->rbsp.rbsp_buffer);
pkt->rbsp.rbsp_buffer_alloc_size = pkt->rbsp.rbsp_buffer_size = 0;
}
@@ -23,6 +23,7 @@
#include <stdint.h>
+#include "libavutil/buffer.h"
#include "avcodec.h"
#include "get_bits.h"
@@ -66,6 +67,7 @@ typedef struct H2645NAL {
typedef struct H2645RBSP {
uint8_t *rbsp_buffer;
+ AVBufferRef *rbsp_buffer_ref;
int rbsp_buffer_alloc_size;
int rbsp_buffer_size;
} H2645RBSP;
@@ -92,10 +94,15 @@ int ff_h2645_extract_rbsp(const uint8_t *src, int length, H2645RBSP *rbsp,
* the data is contained in the input buffer pointed to by buf.
* Otherwise, the unescaped data is part of the rbsp_buffer described by the
* packet's H2645RBSP.
+ *
+ * If the packet's rbsp_buffer_ref is not NULL, the underlying AVBuffer must
+ * own rbsp_buffer. If not and rbsp_buffer is not NULL, use_ref must be 0.
+ * If use_ref is set, rbsp_buffer will be reference-counted and owned by
+ * the underlying AVBuffer of rbsp_buffer_ref.
*/
int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
void *logctx, int is_nalff, int nal_length_size,
- enum AVCodecID codec_id, int small_padding);
+ enum AVCodecID codec_id, int small_padding, int use_ref);
/**
* Free all the allocated memory in the packet.
@@ -359,7 +359,7 @@ static int decode_extradata_ps(const uint8_t *data, int size, H264ParamSets *ps,
H2645Packet pkt = { 0 };
int i, ret = 0;
- ret = ff_h2645_packet_split(&pkt, data, size, logctx, is_avc, 2, AV_CODEC_ID_H264, 1);
+ ret = ff_h2645_packet_split(&pkt, data, size, logctx, is_avc, 2, AV_CODEC_ID_H264, 1, 0);
if (ret < 0) {
ret = 0;
goto fail;
@@ -622,8 +622,8 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
h->is_avc = 1;
}
- ret = ff_h2645_packet_split(&h->pkt, buf, buf_size, avctx, h->is_avc,
- h->nal_length_size, avctx->codec_id, avctx->flags2 & AV_CODEC_FLAG2_FAST);
+ ret = ff_h2645_packet_split(&h->pkt, buf, buf_size, avctx, h->is_avc, h->nal_length_size,
+ avctx->codec_id, avctx->flags2 & AV_CODEC_FLAG2_FAST, 0);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR,
"Error splitting the input into NAL units.\n");
@@ -29,7 +29,8 @@ static int hevc_decode_nal_units(const uint8_t *buf, int buf_size, HEVCParamSets
int ret = 0;
H2645Packet pkt = { 0 };
- ret = ff_h2645_packet_split(&pkt, buf, buf_size, logctx, is_nalff, nal_length_size, AV_CODEC_ID_HEVC, 1);
+ ret = ff_h2645_packet_split(&pkt, buf, buf_size, logctx, is_nalff,
+ nal_length_size, AV_CODEC_ID_HEVC, 1, 0);
if (ret < 0) {
goto done;
}
@@ -194,7 +194,7 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
ff_hevc_reset_sei(sei);
ret = ff_h2645_packet_split(&ctx->pkt, buf, buf_size, avctx, ctx->is_avc,
- ctx->nal_length_size, AV_CODEC_ID_HEVC, 1);
+ ctx->nal_length_size, AV_CODEC_ID_HEVC, 1, 0);
if (ret < 0)
return ret;
@@ -3024,7 +3024,7 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
/* split the input packet into NAL units, so we know the upper bound on the
* number of slices in the frame */
ret = ff_h2645_packet_split(&s->pkt, buf, length, s->avctx, s->is_nalff,
- s->nal_length_size, s->avctx->codec_id, 1);
+ s->nal_length_size, s->avctx->codec_id, 1, 0);
if (ret < 0) {
av_log(s->avctx, AV_LOG_ERROR,
"Error splitting the input into NAL units.\n");
This is in preparation for a patch for cbs_h2645. Now the packet's rbsp_buffer can be owned by an AVBuffer. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@googlemail.com> --- libavcodec/cbs_h2645.c | 8 ++--- libavcodec/extract_extradata_bsf.c | 2 +- libavcodec/h2645_parse.c | 53 ++++++++++++++++++++++++++++-- libavcodec/h2645_parse.h | 9 ++++- libavcodec/h264_parse.c | 2 +- libavcodec/h264dec.c | 4 +-- libavcodec/hevc_parse.c | 3 +- libavcodec/hevc_parser.c | 2 +- libavcodec/hevcdec.c | 2 +- 9 files changed, 70 insertions(+), 15 deletions(-)