avresample: Introduce AVFrame-based API
This commit is contained in:
		@@ -13,6 +13,12 @@ libavutil:     2014-08-09
 | 
			
		||||
 | 
			
		||||
API changes, most recent first:
 | 
			
		||||
 | 
			
		||||
2014-04-xx - xxxxxxx - lavr 2.1.0 - avresample.h
 | 
			
		||||
  Add avresample_convert_frame() and avresample_config().
 | 
			
		||||
 | 
			
		||||
2014-04-xx - xxxxxxx - lavu 54.1.0 - error.h
 | 
			
		||||
  Add AVERROR_INPUT_CHANGED and AVERROR_OUTPUT_CHANGED.
 | 
			
		||||
 | 
			
		||||
2014-08-xx - xxxxxxx - lavc 55.57.4 - avcodec.h
 | 
			
		||||
  Deprecate FF_IDCT_XVIDMMX define and xvidmmx idct option.
 | 
			
		||||
  Replaced by FF_IDCT_XVID and xvid respectively.
 | 
			
		||||
 
 | 
			
		||||
@@ -95,6 +95,7 @@
 | 
			
		||||
#include "libavutil/avutil.h"
 | 
			
		||||
#include "libavutil/channel_layout.h"
 | 
			
		||||
#include "libavutil/dict.h"
 | 
			
		||||
#include "libavutil/frame.h"
 | 
			
		||||
#include "libavutil/log.h"
 | 
			
		||||
#include "libavutil/mathematics.h"
 | 
			
		||||
 | 
			
		||||
@@ -165,6 +166,10 @@ AVAudioResampleContext *avresample_alloc_context(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Initialize AVAudioResampleContext.
 | 
			
		||||
 * @note The context must be configured using the AVOption API.
 | 
			
		||||
 *
 | 
			
		||||
 * @see av_opt_set_int()
 | 
			
		||||
 * @see av_opt_set_dict()
 | 
			
		||||
 *
 | 
			
		||||
 * @param avr  audio resample context
 | 
			
		||||
 * @return     0 on success, negative AVERROR code on failure
 | 
			
		||||
@@ -422,6 +427,70 @@ int avresample_available(AVAudioResampleContext *avr);
 | 
			
		||||
 */
 | 
			
		||||
int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Convert the samples in the input AVFrame and write them to the output AVFrame.
 | 
			
		||||
 *
 | 
			
		||||
 * Input and output AVFrames must have channel_layout, sample_rate and format set.
 | 
			
		||||
 *
 | 
			
		||||
 * The upper bound on the number of output samples is obtained through
 | 
			
		||||
 * avresample_get_out_samples().
 | 
			
		||||
 *
 | 
			
		||||
 * If the output AVFrame does not have the data pointers allocated the nb_samples
 | 
			
		||||
 * field will be set using avresample_get_out_samples() and av_frame_get_buffer()
 | 
			
		||||
 * is called to allocate the frame.
 | 
			
		||||
 *
 | 
			
		||||
 * The output AVFrame can be NULL or have fewer allocated samples than required.
 | 
			
		||||
 * In this case, any remaining samples not written to the output will be added
 | 
			
		||||
 * to an internal FIFO buffer, to be returned at the next call to this function
 | 
			
		||||
 * or to avresample_convert() or to avresample_read().
 | 
			
		||||
 *
 | 
			
		||||
 * If converting sample rate, there may be data remaining in the internal
 | 
			
		||||
 * resampling delay buffer. avresample_get_delay() tells the number of
 | 
			
		||||
 * remaining samples. To get this data as output, call this function or
 | 
			
		||||
 * avresample_convert() with NULL input.
 | 
			
		||||
 *
 | 
			
		||||
 * At the end of the conversion process, there may be data remaining in the
 | 
			
		||||
 * internal FIFO buffer. avresample_available() tells the number of remaining
 | 
			
		||||
 * samples. To get this data as output, either call this function or
 | 
			
		||||
 * avresample_convert() with NULL input or call avresample_read().
 | 
			
		||||
 *
 | 
			
		||||
 * If the AVAudioResampleContext configuration does not match the output and
 | 
			
		||||
 * input AVFrame settings the conversion does not take place and depending on
 | 
			
		||||
 * which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED
 | 
			
		||||
 * or AVERROR_OUTPUT_CHANGED|AVERROR_INPUT_CHANGED is returned.
 | 
			
		||||
 *
 | 
			
		||||
 * @see avresample_get_out_samples()
 | 
			
		||||
 * @see avresample_available()
 | 
			
		||||
 * @see avresample_convert()
 | 
			
		||||
 * @see avresample_read()
 | 
			
		||||
 * @see avresample_get_delay()
 | 
			
		||||
 *
 | 
			
		||||
 * @param avr             audio resample context
 | 
			
		||||
 * @param output          output AVFrame
 | 
			
		||||
 * @param input           input AVFrame
 | 
			
		||||
 * @return                0 on success, AVERROR on failure or nonmatching
 | 
			
		||||
 *                        configuration.
 | 
			
		||||
 */
 | 
			
		||||
int avresample_convert_frame(AVAudioResampleContext *avr,
 | 
			
		||||
                             AVFrame *output, AVFrame *input);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Configure or reconfigure the AVAudioResampleContext using the information
 | 
			
		||||
 * provided by the AVFrames.
 | 
			
		||||
 *
 | 
			
		||||
 * The original resampling context is reset even on failure.
 | 
			
		||||
 * The function calls avresample_close() internally if the context is open.
 | 
			
		||||
 *
 | 
			
		||||
 * @see avresample_open();
 | 
			
		||||
 * @see avresample_close();
 | 
			
		||||
 *
 | 
			
		||||
 * @param avr             audio resample context
 | 
			
		||||
 * @param output          output AVFrame
 | 
			
		||||
 * @param input           input AVFrame
 | 
			
		||||
 * @return                0 on success, AVERROR on failure.
 | 
			
		||||
 */
 | 
			
		||||
int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @}
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@
 | 
			
		||||
#include "libavutil/common.h"
 | 
			
		||||
#include "libavutil/dict.h"
 | 
			
		||||
#include "libavutil/error.h"
 | 
			
		||||
#include "libavutil/frame.h"
 | 
			
		||||
#include "libavutil/log.h"
 | 
			
		||||
#include "libavutil/mem.h"
 | 
			
		||||
#include "libavutil/opt.h"
 | 
			
		||||
@@ -500,6 +501,135 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,
 | 
			
		||||
                                  current_buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in)
 | 
			
		||||
{
 | 
			
		||||
    if (avresample_is_open(avr)) {
 | 
			
		||||
        avresample_close(avr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (in) {
 | 
			
		||||
        avr->in_channel_layout  = in->channel_layout;
 | 
			
		||||
        avr->in_sample_rate     = in->sample_rate;
 | 
			
		||||
        avr->in_sample_fmt      = in->format;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (out) {
 | 
			
		||||
        avr->out_channel_layout = out->channel_layout;
 | 
			
		||||
        avr->out_sample_rate    = out->sample_rate;
 | 
			
		||||
        avr->out_sample_fmt     = out->format;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int config_changed(AVAudioResampleContext *avr,
 | 
			
		||||
                          AVFrame *out, AVFrame *in)
 | 
			
		||||
{
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
 | 
			
		||||
    if (in) {
 | 
			
		||||
        if (avr->in_channel_layout != in->channel_layout ||
 | 
			
		||||
            avr->in_sample_rate    != in->sample_rate ||
 | 
			
		||||
            avr->in_sample_fmt     != in->format) {
 | 
			
		||||
            ret |= AVERROR_INPUT_CHANGED;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (out) {
 | 
			
		||||
        if (avr->out_channel_layout != out->channel_layout ||
 | 
			
		||||
            avr->out_sample_rate    != out->sample_rate ||
 | 
			
		||||
            avr->out_sample_fmt     != out->format) {
 | 
			
		||||
            ret |= AVERROR_OUTPUT_CHANGED;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int convert_frame(AVAudioResampleContext *avr,
 | 
			
		||||
                                AVFrame *out, AVFrame *in)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    uint8_t **out_data = NULL, **in_data = NULL;
 | 
			
		||||
    int out_linesize = 0, in_linesize = 0;
 | 
			
		||||
    int out_nb_samples = 0, in_nb_samples = 0;
 | 
			
		||||
 | 
			
		||||
    if (out) {
 | 
			
		||||
        out_data       = out->extended_data;
 | 
			
		||||
        out_linesize   = out->linesize[0];
 | 
			
		||||
        out_nb_samples = out->nb_samples;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (in) {
 | 
			
		||||
        in_data       = in->extended_data;
 | 
			
		||||
        in_linesize   = in->linesize[0];
 | 
			
		||||
        in_nb_samples = in->nb_samples;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = avresample_convert(avr, out_data, out_linesize,
 | 
			
		||||
                             out_nb_samples,
 | 
			
		||||
                             in_data, in_linesize,
 | 
			
		||||
                             in_nb_samples);
 | 
			
		||||
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        if (out)
 | 
			
		||||
            out->nb_samples = 0;
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (out)
 | 
			
		||||
        out->nb_samples = ret;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int available_samples(AVFrame *out)
 | 
			
		||||
{
 | 
			
		||||
    int bytes_per_sample = av_get_bytes_per_sample(out->format);
 | 
			
		||||
    int samples = out->linesize[0] / bytes_per_sample;
 | 
			
		||||
 | 
			
		||||
    if (av_sample_fmt_is_planar(out->format)) {
 | 
			
		||||
        return samples;
 | 
			
		||||
    } else {
 | 
			
		||||
        int channels = av_get_channel_layout_nb_channels(out->channel_layout);
 | 
			
		||||
        return samples / channels;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int avresample_convert_frame(AVAudioResampleContext *avr,
 | 
			
		||||
                             AVFrame *out, AVFrame *in)
 | 
			
		||||
{
 | 
			
		||||
    int ret, setup = 0;
 | 
			
		||||
 | 
			
		||||
    if (!avresample_is_open(avr)) {
 | 
			
		||||
        if ((ret = avresample_config(avr, out, in)) < 0)
 | 
			
		||||
            return ret;
 | 
			
		||||
        if ((ret = avresample_open(avr)) < 0)
 | 
			
		||||
            return ret;
 | 
			
		||||
        setup = 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        // return as is or reconfigure for input changes?
 | 
			
		||||
        if ((ret = config_changed(avr, out, in)))
 | 
			
		||||
            return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (out) {
 | 
			
		||||
        if (!out->linesize[0]) {
 | 
			
		||||
            out->nb_samples = avresample_get_out_samples(avr, in->nb_samples);
 | 
			
		||||
            if ((ret = av_frame_get_buffer(out, 0)) < 0) {
 | 
			
		||||
                if (setup)
 | 
			
		||||
                    avresample_close(avr);
 | 
			
		||||
                return ret;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            if (!out->nb_samples)
 | 
			
		||||
                out->nb_samples = available_samples(out);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return convert_frame(avr, out, in);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
 | 
			
		||||
                          int stride)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@
 | 
			
		||||
#include "libavutil/version.h"
 | 
			
		||||
 | 
			
		||||
#define LIBAVRESAMPLE_VERSION_MAJOR  2
 | 
			
		||||
#define LIBAVRESAMPLE_VERSION_MINOR  0
 | 
			
		||||
#define LIBAVRESAMPLE_VERSION_MINOR  1
 | 
			
		||||
#define LIBAVRESAMPLE_VERSION_MICRO  0
 | 
			
		||||
 | 
			
		||||
#define LIBAVRESAMPLE_VERSION_INT  AV_VERSION_INT(LIBAVRESAMPLE_VERSION_MAJOR, \
 | 
			
		||||
 
 | 
			
		||||
@@ -60,6 +60,8 @@
 | 
			
		||||
#define AVERROR_BUG                (-0x5fb8aabe) ///< Bug detected, please report the issue
 | 
			
		||||
#define AVERROR_UNKNOWN            (-0x31b4b1ab) ///< Unknown error, typically from an external library
 | 
			
		||||
#define AVERROR_EXPERIMENTAL       (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it.
 | 
			
		||||
#define AVERROR_INPUT_CHANGED      (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED)
 | 
			
		||||
#define AVERROR_OUTPUT_CHANGED     (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Put a description of the AVERROR code errnum in errbuf.
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define LIBAVUTIL_VERSION_MAJOR 54
 | 
			
		||||
#define LIBAVUTIL_VERSION_MINOR  0
 | 
			
		||||
#define LIBAVUTIL_VERSION_MINOR  1
 | 
			
		||||
#define LIBAVUTIL_VERSION_MICRO  0
 | 
			
		||||
 | 
			
		||||
#define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user