libavcodec/hevc_mp4toannexb_bsf.c: Optional argument "private_spspps_buf" to avoid extradata modification.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Ivan Uskov 2015-07-28 09:33:43 -04:00 committed by Michael Niedermayer
parent 07558ad582
commit 0b8b18b4fb

View File

@ -35,9 +35,21 @@ typedef struct HEVCBSFContext {
int extradata_parsed;
int logged_nonmp4_warning;
/* When private_spspps is zero then spspps_buf points to global extradata
and bsf does replace a global extradata to own-allocated version (default
behaviour).
When private_spspps is non-zero the bsf uses a private version of spspps buf.
This mode necessary when bsf uses in decoder, else bsf has issues after
decoder re-initialization. Use the "private_spspps_buf" argument to
activate this mode.
*/
int private_spspps;
uint8_t *spspps_buf;
uint32_t spspps_size;
} HEVCBSFContext;
static int hevc_extradata_to_annexb(AVCodecContext *avctx)
static int hevc_extradata_to_annexb(HEVCBSFContext* ctx, AVCodecContext *avctx)
{
GetByteContext gb;
int length_size, num_arrays, i, j;
@ -82,9 +94,13 @@ static int hevc_extradata_to_annexb(AVCodecContext *avctx)
}
}
av_freep(&avctx->extradata);
avctx->extradata = new_extradata;
avctx->extradata_size = new_extradata_size;
if (!ctx->private_spspps) {
av_freep(&avctx->extradata);
avctx->extradata = new_extradata;
avctx->extradata_size = new_extradata_size;
}
ctx->spspps_buf = new_extradata;
ctx->spspps_size = new_extradata_size;
if (!new_extradata_size)
av_log(avctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
@ -122,8 +138,10 @@ static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
*poutbuf_size = buf_size;
return 0;
}
if (args && strstr(args, "private_spspps_buf"))
ctx->private_spspps = 1;
ret = hevc_extradata_to_annexb(avctx);
ret = hevc_extradata_to_annexb(ctx, avctx);
if (ret < 0)
return ret;
ctx->length_size = ret;
@ -148,7 +166,7 @@ static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
/* prepend extradata to IRAP frames */
is_irap = nalu_type >= 16 && nalu_type <= 23;
add_extradata = is_irap && !got_irap;
extra_size = add_extradata * avctx->extradata_size;
extra_size = add_extradata * ctx->spspps_size;
got_irap |= is_irap;
if (SIZE_MAX - out_size < 4 ||
@ -163,7 +181,7 @@ static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
goto fail;
if (add_extradata)
memcpy(out + out_size, avctx->extradata, extra_size);
memcpy(out + out_size, ctx->spspps_buf, extra_size);
AV_WB32(out + out_size + extra_size, 1);
bytestream2_get_buffer(&gb, out + out_size + 4 + extra_size, nalu_size);
out_size += 4 + nalu_size + extra_size;
@ -179,8 +197,16 @@ fail:
return ret;
}
static void hevc_mp4toannexb_close(AVBitStreamFilterContext *bsfc)
{
HEVCBSFContext *ctx = bsfc->priv_data;
if (ctx->private_spspps)
av_freep(&ctx->spspps_buf);
}
AVBitStreamFilter ff_hevc_mp4toannexb_bsf = {
"hevc_mp4toannexb",
sizeof(HEVCBSFContext),
hevc_mp4toannexb_filter,
hevc_mp4toannexb_close,
};