diff options
author | Anton Khirnov <anton@khirnov.net> | 2012-05-07 13:55:03 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2012-05-09 17:46:54 +0200 |
commit | a5117a2444f3e636ff824ea467bc828d482c68fc (patch) | |
tree | 5987200061f5c74ce5b35af47cbcf81a88f8583f /libavcodec/utils.c | |
parent | 6d7f61770094cc80ca2d93c4784c0091411d8242 (diff) | |
download | ffmpeg-a5117a2444f3e636ff824ea467bc828d482c68fc.tar.gz |
lavc: pad last audio frame with silence when needed.
Diffstat (limited to 'libavcodec/utils.c')
-rw-r--r-- | libavcodec/utils.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/libavcodec/utils.c b/libavcodec/utils.c index ca386646c3..9631c99899 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -857,11 +857,58 @@ int ff_alloc_packet(AVPacket *avpkt, int size) } } +/** + * Pad last frame with silence. + */ +static int pad_last_frame(AVCodecContext *s, AVFrame **dst, const AVFrame *src) +{ + AVFrame *frame = NULL; + uint8_t *buf = NULL; + int ret; + + if (!(frame = avcodec_alloc_frame())) + return AVERROR(ENOMEM); + *frame = *src; + + if ((ret = av_samples_get_buffer_size(&frame->linesize[0], s->channels, + s->frame_size, s->sample_fmt, 0)) < 0) + goto fail; + + if (!(buf = av_malloc(ret))) { + ret = AVERROR(ENOMEM); + goto fail; + } + + frame->nb_samples = s->frame_size; + if ((ret = avcodec_fill_audio_frame(frame, s->channels, s->sample_fmt, + buf, ret, 0)) < 0) + goto fail; + if ((ret = av_samples_copy(frame->extended_data, src->extended_data, 0, 0, + src->nb_samples, s->channels, s->sample_fmt)) < 0) + goto fail; + if ((ret = av_samples_set_silence(frame->extended_data, src->nb_samples, + frame->nb_samples - src->nb_samples, + s->channels, s->sample_fmt)) < 0) + goto fail; + + *dst = frame; + + return 0; + +fail: + if (frame->extended_data != frame->data) + av_freep(&frame->extended_data); + av_freep(&buf); + av_freep(&frame); + return ret; +} + int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { + AVFrame *padded_frame = NULL; int ret; int user_packet = !!avpkt->data; @@ -879,6 +926,16 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, if (frame->nb_samples > avctx->frame_size) return AVERROR(EINVAL); } else if (!(avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) { + if (frame->nb_samples < avctx->frame_size && + !avctx->internal->last_audio_frame) { + ret = pad_last_frame(avctx, &padded_frame, frame); + if (ret < 0) + return ret; + + frame = padded_frame; + avctx->internal->last_audio_frame = 1; + } + if (frame->nb_samples != avctx->frame_size) return AVERROR(EINVAL); } @@ -919,6 +976,13 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, here to simplify things */ avpkt->flags |= AV_PKT_FLAG_KEY; + if (padded_frame) { + av_freep(&padded_frame->data[0]); + if (padded_frame->extended_data != padded_frame->data) + av_freep(&padded_frame->extended_data); + av_freep(&padded_frame); + } + return ret; } |