lavc: pad last audio frame with silence when needed.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user