diff options
author | Martin Storsjö <martin@martin.st> | 2011-12-16 14:59:26 +0400 |
---|---|---|
committer | Martin Storsjö <martin@martin.st> | 2011-12-22 00:52:42 +0400 |
commit | f13db94d0aadc4f27aea715383a18df461ed9b5d (patch) | |
tree | 4d4d0fb9c06050334cdd87c9f10937d8c572a5f3 /libavcodec/utils.c | |
parent | 2215c39e94e01f57b3191a29e0e51d7e230daf49 (diff) |
libavcodec: Apply parameter change side data when decoding audio
Signed-off-by: Martin Storsjö <martin@martin.st>
Diffstat (limited to 'libavcodec/utils.c')
-rw-r--r-- | libavcodec/utils.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 20b01f5df4..7e9ddb2e35 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -40,6 +40,7 @@ #include "thread.h" #include "audioconvert.h" #include "internal.h" +#include "bytestream.h" #include <stdlib.h> #include <stdarg.h> #include <limits.h> @@ -914,6 +915,47 @@ int attribute_align_arg avcodec_decode_audio3(AVCodecContext *avctx, int16_t *sa } #endif +static void 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; + 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) { + avctx->channels = bytestream_get_le32(&data); + size -= 4; + } + if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) { + if (size < 8) + return; + avctx->channel_layout = bytestream_get_le64(&data); + size -= 8; + } + if (size < 4) + return; + if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) { + avctx->sample_rate = bytestream_get_le32(&data); + size -= 4; + } + if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) { + if (size < 8) + return; + avctx->width = bytestream_get_le32(&data); + avctx->height = bytestream_get_le32(&data); + size -= 8; + } +} + int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, @@ -930,6 +972,8 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, return AVERROR(EINVAL); } + apply_param_change(avctx, avpkt); + if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) { ret = avctx->codec->decode(avctx, frame, got_frame_ptr, avpkt); if (ret >= 0 && *got_frame_ptr) { |