The current code stores a pointer to the packet passed to the decoder, which is then used during get_buffer() for timestamps and side data passthrough. However, since this is a pointer to user data which we do not own, storing it is potentially dangerous. It is also ill defined for the new decoding API with split input/output. Fix this problem by making an explicit internally owned copy of the packet properties.tags/n3.4
@@ -99,6 +99,14 @@ fail2: | |||||
return 0; | return 0; | ||||
} | } | ||||
static int extract_packet_props(AVCodecInternal *avci, const AVPacket *pkt) | |||||
{ | |||||
av_packet_unref(avci->last_pkt_props); | |||||
if (pkt) | |||||
return av_packet_copy_props(avci->last_pkt_props, pkt); | |||||
return 0; | |||||
} | |||||
static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame) | static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame) | ||||
{ | { | ||||
int ret; | int ret; | ||||
@@ -304,7 +312,10 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi | |||||
return AVERROR(ENOSYS); | return AVERROR(ENOSYS); | ||||
} | } | ||||
avctx->internal->pkt = avpkt; | |||||
ret = extract_packet_props(avci, avpkt); | |||||
if (ret < 0) | |||||
return ret; | |||||
ret = apply_param_change(avctx, avpkt); | ret = apply_param_change(avctx, avpkt); | ||||
if (ret < 0) | if (ret < 0) | ||||
return ret; | return ret; | ||||
@@ -368,7 +379,9 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, | |||||
return AVERROR(ENOSYS); | return AVERROR(ENOSYS); | ||||
} | } | ||||
avctx->internal->pkt = avpkt; | |||||
ret = extract_packet_props(avci, avpkt); | |||||
if (ret < 0) | |||||
return ret; | |||||
if (!avpkt->data && avpkt->size) { | if (!avpkt->data && avpkt->size) { | ||||
av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n"); | av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n"); | ||||
@@ -408,7 +421,10 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, | |||||
{ | { | ||||
int ret; | int ret; | ||||
avctx->internal->pkt = avpkt; | |||||
ret = extract_packet_props(avctx->internal, avpkt); | |||||
if (ret < 0) | |||||
return ret; | |||||
*got_sub_ptr = 0; | *got_sub_ptr = 0; | ||||
ret = avctx->codec->decode(avctx, sub, got_sub_ptr, avpkt); | ret = avctx->codec->decode(avctx, sub, got_sub_ptr, avpkt); | ||||
if (*got_sub_ptr) | if (*got_sub_ptr) | ||||
@@ -739,7 +755,7 @@ int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags | |||||
int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) | int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) | ||||
{ | { | ||||
AVPacket *pkt = avctx->internal->pkt; | |||||
AVPacket *pkt = avctx->internal->last_pkt_props; | |||||
int i; | int i; | ||||
struct { | struct { | ||||
enum AVPacketSideDataType packet; | enum AVPacketSideDataType packet; | ||||
@@ -759,15 +775,6 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) | |||||
frame->chroma_location = avctx->chroma_sample_location; | frame->chroma_location = avctx->chroma_sample_location; | ||||
frame->reordered_opaque = avctx->reordered_opaque; | frame->reordered_opaque = avctx->reordered_opaque; | ||||
if (!pkt) { | |||||
#if FF_API_PKT_PTS | |||||
FF_DISABLE_DEPRECATION_WARNINGS | |||||
frame->pkt_pts = AV_NOPTS_VALUE; | |||||
FF_ENABLE_DEPRECATION_WARNINGS | |||||
#endif | |||||
frame->pts = AV_NOPTS_VALUE; | |||||
return 0; | |||||
} | |||||
#if FF_API_PKT_PTS | #if FF_API_PKT_PTS | ||||
FF_DISABLE_DEPRECATION_WARNINGS | FF_DISABLE_DEPRECATION_WARNINGS | ||||
@@ -131,10 +131,10 @@ typedef struct AVCodecInternal { | |||||
void *thread_ctx; | void *thread_ctx; | ||||
/** | /** | ||||
* Current packet as passed into the decoder, to avoid having to pass the | |||||
* packet into every function. | |||||
* Properties (timestamps+side data) extracted from the last packet passed | |||||
* for decoding. | |||||
*/ | */ | ||||
AVPacket *pkt; | |||||
AVPacket *last_pkt_props; | |||||
/** | /** | ||||
* hwaccel-specific private data | * hwaccel-specific private data | ||||
@@ -656,7 +656,7 @@ int ff_frame_thread_init(AVCodecContext *avctx) | |||||
} | } | ||||
*copy->internal = *src->internal; | *copy->internal = *src->internal; | ||||
copy->internal->thread_ctx = p; | copy->internal->thread_ctx = p; | ||||
copy->internal->pkt = &p->avpkt; | |||||
copy->internal->last_pkt_props = &p->avpkt; | |||||
if (!i) { | if (!i) { | ||||
src = copy; | src = copy; | ||||
@@ -433,6 +433,12 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code | |||||
goto free_and_end; | goto free_and_end; | ||||
} | } | ||||
avctx->internal->last_pkt_props = av_packet_alloc(); | |||||
if (!avctx->internal->last_pkt_props) { | |||||
ret = AVERROR(ENOMEM); | |||||
goto free_and_end; | |||||
} | |||||
if (codec->priv_data_size > 0) { | if (codec->priv_data_size > 0) { | ||||
if (!avctx->priv_data) { | if (!avctx->priv_data) { | ||||
avctx->priv_data = av_mallocz(codec->priv_data_size); | avctx->priv_data = av_mallocz(codec->priv_data_size); | ||||
@@ -713,6 +719,7 @@ FF_ENABLE_DEPRECATION_WARNINGS | |||||
av_frame_free(&avctx->internal->to_free); | av_frame_free(&avctx->internal->to_free); | ||||
av_frame_free(&avctx->internal->buffer_frame); | av_frame_free(&avctx->internal->buffer_frame); | ||||
av_packet_free(&avctx->internal->buffer_pkt); | av_packet_free(&avctx->internal->buffer_pkt); | ||||
av_packet_free(&avctx->internal->last_pkt_props); | |||||
av_freep(&avctx->internal->pool); | av_freep(&avctx->internal->pool); | ||||
} | } | ||||
av_freep(&avctx->internal); | av_freep(&avctx->internal); | ||||
@@ -753,6 +760,7 @@ av_cold int avcodec_close(AVCodecContext *avctx) | |||||
av_frame_free(&avctx->internal->to_free); | av_frame_free(&avctx->internal->to_free); | ||||
av_frame_free(&avctx->internal->buffer_frame); | av_frame_free(&avctx->internal->buffer_frame); | ||||
av_packet_free(&avctx->internal->buffer_pkt); | av_packet_free(&avctx->internal->buffer_pkt); | ||||
av_packet_free(&avctx->internal->last_pkt_props); | |||||
for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++) | for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++) | ||||
av_buffer_pool_uninit(&pool->pools[i]); | av_buffer_pool_uninit(&pool->pools[i]); | ||||
av_freep(&avctx->internal->pool); | av_freep(&avctx->internal->pool); | ||||