mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
lavc: pad last audio frame with silence when needed.
This commit is contained in:
parent
6d7f617700
commit
a5117a2444
8
avconv.c
8
avconv.c
@ -2048,14 +2048,6 @@ static void flush_encoders(void)
|
||||
|
||||
av_fifo_generic_read(ost->fifo, audio_buf, fifo_bytes, NULL);
|
||||
|
||||
/* pad last frame with silence if needed */
|
||||
if (!(enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME)) {
|
||||
frame_bytes = enc->frame_size * enc->channels *
|
||||
av_get_bytes_per_sample(enc->sample_fmt);
|
||||
if (allocated_audio_buf_size < frame_bytes)
|
||||
exit_program(1);
|
||||
generate_silence(audio_buf+fifo_bytes, enc->sample_fmt, frame_bytes - fifo_bytes);
|
||||
}
|
||||
encode_audio_frame(os, ost, audio_buf, frame_bytes);
|
||||
} else {
|
||||
/* flush encoder with NULL frames until it is done
|
||||
|
@ -13,6 +13,12 @@ libavutil: 2011-04-18
|
||||
|
||||
API changes, most recent first:
|
||||
|
||||
2012-xx-xx - xxxxxxx - lavc 54.13.1
|
||||
For audio formats with fixed frame size, the last frame
|
||||
no longer needs to be padded with silence, libavcodec
|
||||
will handle this internally (effectively all encoders
|
||||
behave as if they had CODEC_CAP_SMALL_LAST_FRAME set).
|
||||
|
||||
2012-xx-xx - xxxxxxx - lavc 54.13.0 - avcodec.h
|
||||
Add sample_rate and channel_layout fields to AVFrame.
|
||||
|
||||
|
@ -3860,15 +3860,11 @@ int attribute_deprecated avcodec_encode_audio(AVCodecContext *avctx,
|
||||
* @param[in] frame AVFrame containing the raw audio data to be encoded.
|
||||
* May be NULL when flushing an encoder that has the
|
||||
* CODEC_CAP_DELAY capability set.
|
||||
* There are 2 codec capabilities that affect the allowed
|
||||
* values of frame->nb_samples.
|
||||
* If CODEC_CAP_SMALL_LAST_FRAME is set, then only the final
|
||||
* frame may be smaller than avctx->frame_size, and all other
|
||||
* frames must be equal to avctx->frame_size.
|
||||
* If CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame
|
||||
* can have any number of samples.
|
||||
* If neither is set, frame->nb_samples must be equal to
|
||||
* avctx->frame_size for all frames.
|
||||
* If it is not set, frame->nb_samples must be equal to
|
||||
* avctx->frame_size for all frames except the last.
|
||||
* The final frame may be smaller than avctx->frame_size.
|
||||
* @param[out] got_packet_ptr This field is set to 1 by libavcodec if the
|
||||
* output packet is non-empty, and to 0 if it is
|
||||
* empty. If the function returns an error, the
|
||||
|
@ -70,6 +70,12 @@ typedef struct AVCodecInternal {
|
||||
*/
|
||||
int sample_count;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* An audio frame with less than required samples has been submitted and
|
||||
* padded with silence. Reject all subsequent frames.
|
||||
*/
|
||||
int last_audio_frame;
|
||||
} AVCodecInternal;
|
||||
|
||||
struct AVCodecDefault {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#define LIBAVCODEC_VERSION_MAJOR 54
|
||||
#define LIBAVCODEC_VERSION_MINOR 13
|
||||
#define LIBAVCODEC_VERSION_MICRO 0
|
||||
#define LIBAVCODEC_VERSION_MICRO 1
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||
LIBAVCODEC_VERSION_MINOR, \
|
||||
|
Loading…
Reference in New Issue
Block a user