Merge commit 'b9589f5a770ec2357ab7920a5fabe8510b8601f9'

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

Conflicts:
	libavcodec/utils.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2013-10-30 10:13:23 +01:00
commit 558784f113

View File

@ -1954,46 +1954,59 @@ static int64_t guess_correct_pts(AVCodecContext *ctx,
return pts;
}
static void apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
{
int size = 0;
const uint8_t *data;
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);
if (!data || size < 4)
return;
if (!data)
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);
size -= 4;
if (size < 4) /* Required for any of the changes */
return;
if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) {
if (size < 4)
goto fail;
avctx->channels = bytestream_get_le32(&data);
size -= 4;
}
if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) {
if (size < 8)
return;
goto fail;
avctx->channel_layout = bytestream_get_le64(&data);
size -= 8;
}
if (size < 4)
return;
if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) {
if (size < 4)
goto fail;
avctx->sample_rate = bytestream_get_le32(&data);
size -= 4;
}
if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) {
if (size < 8)
return;
goto fail;
avctx->width = bytestream_get_le32(&data);
avctx->height = bytestream_get_le32(&data);
avcodec_set_dimensions(avctx, avctx->width, avctx->height);
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)
@ -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)) {
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;
if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
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
}
add_metadata_from_side_data(avctx, picture);
fail:
emms_c(); //needed to avoid an emms_c() call before every return;
avctx->pkt = NULL;
@ -2195,7 +2215,12 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
// copy to ensure we do not change avpkt
AVPacket tmp = *avpkt;
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;
if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
@ -2275,7 +2300,7 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
frame->nb_samples -= discard_padding;
}
}
fail:
avctx->pkt = NULL;
if (did_split) {
av_packet_free_side_data(&tmp);