You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
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:
@@ -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
|
|||||||
|
|
||||||
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
|
|||||||
}
|
}
|
||||||
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,
|
|||||||
// 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,
|
|||||||
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);
|
||||||
|
Reference in New Issue
Block a user