Commit 5ee5fa02 authored by Justin Ruggles's avatar Justin Ruggles

avcodec: add a public function, avcodec_fill_audio_frame().

This is a convenience function for the user to fill audio AVFrame information.
parent d7806238
...@@ -4238,6 +4238,26 @@ void avsubtitle_free(AVSubtitle *sub); ...@@ -4238,6 +4238,26 @@ void avsubtitle_free(AVSubtitle *sub);
int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size,
const short *samples); const short *samples);
/**
* Fill audio frame data and linesize.
* AVFrame extended_data channel pointers are allocated if necessary for
* planar audio.
*
* @param frame the AVFrame
* frame->nb_samples must be set prior to calling the
* function. This function fills in frame->data,
* frame->extended_data, frame->linesize[0].
* @param nb_channels channel count
* @param sample_fmt sample format
* @param buf buffer to use for frame data
* @param buf_size size of buffer
* @param align plane size sample alignment
* @return 0 on success, negative error code on failure
*/
int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels,
enum AVSampleFormat sample_fmt, const uint8_t *buf,
int buf_size, int align);
/** /**
* Encode a video frame from pict into buf. * Encode a video frame from pict into buf.
* The input picture should be * The input picture should be
......
...@@ -239,11 +239,47 @@ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){ ...@@ -239,11 +239,47 @@ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){
*width=FFALIGN(*width, align); *width=FFALIGN(*width, align);
} }
int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels,
enum AVSampleFormat sample_fmt, const uint8_t *buf,
int buf_size, int align)
{
int ch, planar, needed_size, ret = 0;
needed_size = av_samples_get_buffer_size(NULL, nb_channels,
frame->nb_samples, sample_fmt,
align);
if (buf_size < needed_size)
return AVERROR(EINVAL);
planar = av_sample_fmt_is_planar(sample_fmt);
if (planar && nb_channels > AV_NUM_DATA_POINTERS) {
if (!(frame->extended_data = av_mallocz(nb_channels *
sizeof(*frame->extended_data))))
return AVERROR(ENOMEM);
} else {
frame->extended_data = frame->data;
}
if ((ret = av_samples_fill_arrays(frame->extended_data, &frame->linesize[0],
buf, nb_channels, frame->nb_samples,
sample_fmt, align)) < 0) {
if (frame->extended_data != frame->data)
av_free(frame->extended_data);
return ret;
}
if (frame->extended_data != frame->data) {
for (ch = 0; ch < AV_NUM_DATA_POINTERS; ch++)
frame->data[ch] = frame->extended_data[ch];
}
return ret;
}
static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
{ {
AVCodecInternal *avci = avctx->internal; AVCodecInternal *avci = avctx->internal;
InternalBuffer *buf; InternalBuffer *buf;
int buf_size, ret, i, needs_extended_data; int buf_size, ret;
buf_size = av_samples_get_buffer_size(NULL, avctx->channels, buf_size = av_samples_get_buffer_size(NULL, avctx->channels,
frame->nb_samples, avctx->sample_fmt, frame->nb_samples, avctx->sample_fmt,
...@@ -251,9 +287,6 @@ static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) ...@@ -251,9 +287,6 @@ static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
if (buf_size < 0) if (buf_size < 0)
return AVERROR(EINVAL); return AVERROR(EINVAL);
needs_extended_data = av_sample_fmt_is_planar(avctx->sample_fmt) &&
avctx->channels > AV_NUM_DATA_POINTERS;
/* allocate InternalBuffer if needed */ /* allocate InternalBuffer if needed */
if (!avci->buffer) { if (!avci->buffer) {
avci->buffer = av_mallocz(sizeof(InternalBuffer)); avci->buffer = av_mallocz(sizeof(InternalBuffer));
...@@ -285,48 +318,31 @@ static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) ...@@ -285,48 +318,31 @@ static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
/* if there is no previous buffer or the previous buffer cannot be used /* if there is no previous buffer or the previous buffer cannot be used
as-is, allocate a new buffer and/or rearrange the channel pointers */ as-is, allocate a new buffer and/or rearrange the channel pointers */
if (!buf->extended_data) { if (!buf->extended_data) {
/* if the channel pointers will fit, just set extended_data to data, if (!buf->data[0]) {
otherwise allocate the extended_data channel pointers */ if (!(buf->data[0] = av_mallocz(buf_size)))
if (needs_extended_data) {
buf->extended_data = av_mallocz(avctx->channels *
sizeof(*buf->extended_data));
if (!buf->extended_data)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
} else { buf->audio_data_size = buf_size;
buf->extended_data = buf->data;
}
/* if there is a previous buffer and it is large enough, reuse it and
just fill-in new channel pointers and linesize, otherwise allocate
a new buffer */
if (buf->extended_data[0]) {
ret = av_samples_fill_arrays(buf->extended_data, &buf->linesize[0],
buf->extended_data[0], avctx->channels,
frame->nb_samples, avctx->sample_fmt,
32);
} else {
ret = av_samples_alloc(buf->extended_data, &buf->linesize[0],
avctx->channels, frame->nb_samples,
avctx->sample_fmt, 32);
} }
if (ret) if ((ret = avcodec_fill_audio_frame(frame, avctx->channels,
avctx->sample_fmt, buf->data[0],
buf->audio_data_size, 32)))
return ret; return ret;
/* if data was not used for extended_data, we need to copy as many of if (frame->extended_data == frame->data)
the extended_data channel pointers as will fit */ buf->extended_data = buf->data;
if (needs_extended_data) { else
for (i = 0; i < AV_NUM_DATA_POINTERS; i++) buf->extended_data = frame->extended_data;
buf->data[i] = buf->extended_data[i]; memcpy(buf->data, frame->data, sizeof(frame->data));
} buf->linesize[0] = frame->linesize[0];
buf->audio_data_size = buf_size;
buf->nb_channels = avctx->channels; buf->nb_channels = avctx->channels;
} } else {
/* copy InternalBuffer info to the AVFrame */ /* copy InternalBuffer info to the AVFrame */
frame->type = FF_BUFFER_TYPE_INTERNAL;
frame->extended_data = buf->extended_data; frame->extended_data = buf->extended_data;
frame->linesize[0] = buf->linesize[0]; frame->linesize[0] = buf->linesize[0];
memcpy(frame->data, buf->data, sizeof(frame->data)); memcpy(frame->data, buf->data, sizeof(frame->data));
}
frame->type = FF_BUFFER_TYPE_INTERNAL;
if (avctx->pkt) frame->pkt_pts = avctx->pkt->pts; if (avctx->pkt) frame->pkt_pts = avctx->pkt->pts;
else frame->pkt_pts = AV_NOPTS_VALUE; else frame->pkt_pts = AV_NOPTS_VALUE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment