diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2011-12-15 17:56:06 -0500 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2012-01-15 21:24:17 -0500 |
commit | 5ee5fa021f32e0506bed6ebd183c807d5162bc72 (patch) | |
tree | f6371f3fb6596b801196abc24fe571f31944a74f /libavcodec | |
parent | d78062386e425deafe9a08d109cff70b7a2de22c (diff) | |
download | ffmpeg-5ee5fa021f32e0506bed6ebd183c807d5162bc72.tar.gz |
avcodec: add a public function, avcodec_fill_audio_frame().
This is a convenience function for the user to fill audio AVFrame information.
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/avcodec.h | 20 | ||||
-rw-r--r-- | libavcodec/utils.c | 94 |
2 files changed, 75 insertions, 39 deletions
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 49d2a0f918..a5071aa438 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -4239,6 +4239,26 @@ int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, 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. * The input picture should be * stored using a specific format, namely avctx.pix_fmt. diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 8473aacb4f..c3faa76169 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -239,11 +239,47 @@ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){ *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) { AVCodecInternal *avci = avctx->internal; InternalBuffer *buf; - int buf_size, ret, i, needs_extended_data; + int buf_size, ret; buf_size = av_samples_get_buffer_size(NULL, avctx->channels, frame->nb_samples, avctx->sample_fmt, @@ -251,9 +287,6 @@ static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) if (buf_size < 0) return AVERROR(EINVAL); - needs_extended_data = av_sample_fmt_is_planar(avctx->sample_fmt) && - avctx->channels > AV_NUM_DATA_POINTERS; - /* allocate InternalBuffer if needed */ if (!avci->buffer) { avci->buffer = av_mallocz(sizeof(InternalBuffer)); @@ -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 as-is, allocate a new buffer and/or rearrange the channel pointers */ if (!buf->extended_data) { - /* if the channel pointers will fit, just set extended_data to data, - otherwise allocate the extended_data channel pointers */ - if (needs_extended_data) { - buf->extended_data = av_mallocz(avctx->channels * - sizeof(*buf->extended_data)); - if (!buf->extended_data) + if (!buf->data[0]) { + if (!(buf->data[0] = av_mallocz(buf_size))) return AVERROR(ENOMEM); - } else { - buf->extended_data = buf->data; + buf->audio_data_size = buf_size; } - - /* 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; - /* if data was not used for extended_data, we need to copy as many of - the extended_data channel pointers as will fit */ - if (needs_extended_data) { - for (i = 0; i < AV_NUM_DATA_POINTERS; i++) - buf->data[i] = buf->extended_data[i]; - } - buf->audio_data_size = buf_size; - buf->nb_channels = avctx->channels; + if (frame->extended_data == frame->data) + buf->extended_data = buf->data; + else + buf->extended_data = frame->extended_data; + memcpy(buf->data, frame->data, sizeof(frame->data)); + buf->linesize[0] = frame->linesize[0]; + buf->nb_channels = avctx->channels; + } else { + /* copy InternalBuffer info to the AVFrame */ + frame->extended_data = buf->extended_data; + frame->linesize[0] = buf->linesize[0]; + memcpy(frame->data, buf->data, sizeof(frame->data)); } - /* copy InternalBuffer info to the AVFrame */ frame->type = FF_BUFFER_TYPE_INTERNAL; - frame->extended_data = buf->extended_data; - frame->linesize[0] = buf->linesize[0]; - memcpy(frame->data, buf->data, sizeof(frame->data)); if (avctx->pkt) frame->pkt_pts = avctx->pkt->pts; else frame->pkt_pts = AV_NOPTS_VALUE; |