mirror of https://git.ffmpeg.org/ffmpeg.git
avresample: Introduce AVFrame-based API
This commit is contained in:
parent
8c6f430291
commit
fb1ddcdc8f
|
@ -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, \
|
||||
|
|
Loading…
Reference in New Issue