Commit 558784f1 authored by Michael Niedermayer's avatar Michael Niedermayer

Merge commit 'b9589f5a'

* commit 'b9589f5a':
  lavc: add error checking to apply_param_change.

Conflicts:
	libavcodec/utils.c
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents 4427fe7e b9589f5a
...@@ -1954,46 +1954,59 @@ static int64_t guess_correct_pts(AVCodecContext *ctx, ...@@ -1954,46 +1954,59 @@ static int64_t guess_correct_pts(AVCodecContext *ctx,
return pts; return pts;
} }
static void apply_param_change(AVCodecContext *avctx, AVPacket *avpkt) static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
{ {
int size = 0; int size = 0;
const uint8_t *data; const uint8_t *data;
uint32_t flags; uint32_t flags;
if (!(avctx->codec->capabilities & CODEC_CAP_PARAM_CHANGE))
return;
data = av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, &size); data = av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, &size);
if (!data || size < 4) if (!data)
return; return 0;
if (!(avctx->codec->capabilities & CODEC_CAP_PARAM_CHANGE)) {
av_log(avctx, AV_LOG_ERROR, "This decoder does not support parameter "
"changes, but PARAM_CHANGE side data was sent to it.\n");
return AVERROR(EINVAL);
}
if (size < 4)
goto fail;
flags = bytestream_get_le32(&data); flags = bytestream_get_le32(&data);
size -= 4; size -= 4;
if (size < 4) /* Required for any of the changes */
return;
if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) { if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) {
if (size < 4)
goto fail;
avctx->channels = bytestream_get_le32(&data); avctx->channels = bytestream_get_le32(&data);
size -= 4; size -= 4;
} }
if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) { if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) {
if (size < 8) if (size < 8)
return; goto fail;
avctx->channel_layout = bytestream_get_le64(&data); avctx->channel_layout = bytestream_get_le64(&data);
size -= 8; size -= 8;
} }
if (size < 4)
return;
if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) { if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) {
if (size < 4)
goto fail;
avctx->sample_rate = bytestream_get_le32(&data); avctx->sample_rate = bytestream_get_le32(&data);
size -= 4; size -= 4;
} }
if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) { if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) {
if (size < 8) if (size < 8)
return; goto fail;
avctx->width = bytestream_get_le32(&data); avctx->width = bytestream_get_le32(&data);
avctx->height = bytestream_get_le32(&data); avctx->height = bytestream_get_le32(&data);
avcodec_set_dimensions(avctx, avctx->width, avctx->height); avcodec_set_dimensions(avctx, avctx->width, avctx->height);
size -= 8; size -= 8;
} }
return 0;
fail:
av_log(avctx, AV_LOG_ERROR, "PARAM_CHANGE side data too small.\n");
return AVERROR_INVALIDDATA;
} }
static int add_metadata_from_side_data(AVCodecContext *avctx, AVFrame *frame) static int add_metadata_from_side_data(AVCodecContext *avctx, AVFrame *frame)
...@@ -2053,7 +2066,13 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi ...@@ -2053,7 +2066,13 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type & FF_THREAD_FRAME)) { if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type & FF_THREAD_FRAME)) {
int did_split = av_packet_split_side_data(&tmp); int did_split = av_packet_split_side_data(&tmp);
apply_param_change(avctx, &tmp); ret = apply_param_change(avctx, &tmp);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n");
if (avctx->err_recognition & AV_EF_EXPLODE)
goto fail;
}
avctx->pkt = &tmp; avctx->pkt = &tmp;
if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr, ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
...@@ -2077,6 +2096,7 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi ...@@ -2077,6 +2096,7 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
} }
add_metadata_from_side_data(avctx, picture); add_metadata_from_side_data(avctx, picture);
fail:
emms_c(); //needed to avoid an emms_c() call before every return; emms_c(); //needed to avoid an emms_c() call before every return;
avctx->pkt = NULL; avctx->pkt = NULL;
...@@ -2195,7 +2215,12 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, ...@@ -2195,7 +2215,12 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
// copy to ensure we do not change avpkt // copy to ensure we do not change avpkt
AVPacket tmp = *avpkt; AVPacket tmp = *avpkt;
int did_split = av_packet_split_side_data(&tmp); int did_split = av_packet_split_side_data(&tmp);
apply_param_change(avctx, &tmp); ret = apply_param_change(avctx, &tmp);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n");
if (avctx->err_recognition & AV_EF_EXPLODE)
goto fail;
}
avctx->pkt = &tmp; avctx->pkt = &tmp;
if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
...@@ -2275,7 +2300,7 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, ...@@ -2275,7 +2300,7 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
frame->nb_samples -= discard_padding; frame->nb_samples -= discard_padding;
} }
} }
fail:
avctx->pkt = NULL; avctx->pkt = NULL;
if (did_split) { if (did_split) {
av_packet_free_side_data(&tmp); av_packet_free_side_data(&tmp);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment