swresample: Add swr_get_out_samples()
Previous version reviewed-by: Pavel Koshevoy <pkoshevoy@gmail.com> Previous version reviewed-by: wm4 <nfxjfg@googlemail.com> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
@ -15,6 +15,9 @@ libavutil: 2014-08-09
|
|||||||
|
|
||||||
API changes, most recent first:
|
API changes, most recent first:
|
||||||
|
|
||||||
|
2015-06-04 - xxxxxxx - lswr 1.2.100
|
||||||
|
Add swr_get_out_samples()
|
||||||
|
|
||||||
2015-05-27 - xxxxxxx - lavu 54.26.100 - cpu.h
|
2015-05-27 - xxxxxxx - lavu 54.26.100 - cpu.h
|
||||||
Add AV_CPU_FLAG_AVXSLOW.
|
Add AV_CPU_FLAG_AVXSLOW.
|
||||||
|
|
||||||
|
@ -345,6 +345,25 @@ static int64_t get_delay(struct SwrContext *s, int64_t base){
|
|||||||
return av_rescale(num, base, s->in_sample_rate*(int64_t)c->src_incr << c->phase_shift);
|
return av_rescale(num, base, s->in_sample_rate*(int64_t)c->src_incr << c->phase_shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t get_out_samples(struct SwrContext *s, int in_samples) {
|
||||||
|
ResampleContext *c = s->resample;
|
||||||
|
// The + 2 are added to allow implementations to be slightly inaccuarte, they should not be needed currently
|
||||||
|
// They also make it easier to proof that changes and optimizations do not
|
||||||
|
// break the upper bound
|
||||||
|
int64_t num = s->in_buffer_count + 2LL + in_samples;
|
||||||
|
num *= 1 << c->phase_shift;
|
||||||
|
num -= c->index;
|
||||||
|
num = av_rescale_rnd(num, s->out_sample_rate, ((int64_t)s->in_sample_rate) << c->phase_shift, AV_ROUND_UP) + 2;
|
||||||
|
|
||||||
|
if (c->compensation_distance) {
|
||||||
|
if (num > INT_MAX)
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
|
num = FFMAX(num, (num * c->ideal_dst_incr - 1) / c->dst_incr + 1);
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
static int resample_flush(struct SwrContext *s) {
|
static int resample_flush(struct SwrContext *s) {
|
||||||
AudioData *a= &s->in_buffer;
|
AudioData *a= &s->in_buffer;
|
||||||
int i, j, ret;
|
int i, j, ret;
|
||||||
@ -414,4 +433,5 @@ struct Resampler const swri_resampler={
|
|||||||
set_compensation,
|
set_compensation,
|
||||||
get_delay,
|
get_delay,
|
||||||
invert_initial_buffer,
|
invert_initial_buffer,
|
||||||
|
get_out_samples,
|
||||||
};
|
};
|
||||||
|
@ -673,11 +673,15 @@ int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_C
|
|||||||
const uint8_t *in_arg [SWR_CH_MAX], int in_count){
|
const uint8_t *in_arg [SWR_CH_MAX], int in_count){
|
||||||
AudioData * in= &s->in;
|
AudioData * in= &s->in;
|
||||||
AudioData *out= &s->out;
|
AudioData *out= &s->out;
|
||||||
|
int av_unused max_output;
|
||||||
|
|
||||||
if (!swr_is_initialized(s)) {
|
if (!swr_is_initialized(s)) {
|
||||||
av_log(s, AV_LOG_ERROR, "Context has not been initialized\n");
|
av_log(s, AV_LOG_ERROR, "Context has not been initialized\n");
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
#if ASSERT_LEVEL >1
|
||||||
|
max_output = swr_get_out_samples(s, in_count);
|
||||||
|
#endif
|
||||||
|
|
||||||
while(s->drop_output > 0){
|
while(s->drop_output > 0){
|
||||||
int ret;
|
int ret;
|
||||||
@ -720,6 +724,9 @@ int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_C
|
|||||||
int ret = swr_convert_internal(s, out, out_count, in, in_count);
|
int ret = swr_convert_internal(s, out, out_count, in, in_count);
|
||||||
if(ret>0 && !s->drop_output)
|
if(ret>0 && !s->drop_output)
|
||||||
s->outpts += ret * (int64_t)s->in_sample_rate;
|
s->outpts += ret * (int64_t)s->in_sample_rate;
|
||||||
|
|
||||||
|
av_assert2(max_output < 0 || ret < 0 || ret <= max_output);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}else{
|
}else{
|
||||||
AudioData tmp= *in;
|
AudioData tmp= *in;
|
||||||
@ -771,6 +778,7 @@ int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_C
|
|||||||
}
|
}
|
||||||
if(ret2>0 && !s->drop_output)
|
if(ret2>0 && !s->drop_output)
|
||||||
s->outpts += ret2 * (int64_t)s->in_sample_rate;
|
s->outpts += ret2 * (int64_t)s->in_sample_rate;
|
||||||
|
av_assert2(max_output < 0 || ret2 < 0 || ret2 <= max_output);
|
||||||
return ret2;
|
return ret2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -822,6 +830,28 @@ int64_t swr_get_delay(struct SwrContext *s, int64_t base){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int swr_get_out_samples(struct SwrContext *s, int in_samples)
|
||||||
|
{
|
||||||
|
int64_t out_samples;
|
||||||
|
|
||||||
|
if (in_samples < 0)
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
|
if (s->resampler && s->resample) {
|
||||||
|
if (!s->resampler->get_out_samples)
|
||||||
|
return AVERROR(ENOSYS);
|
||||||
|
out_samples = s->resampler->get_out_samples(s, in_samples);
|
||||||
|
} else {
|
||||||
|
out_samples = s->in_buffer_count + in_samples;
|
||||||
|
av_assert0(s->out_sample_rate == s->in_sample_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_samples > INT_MAX)
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
|
return out_samples;
|
||||||
|
}
|
||||||
|
|
||||||
int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance){
|
int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance){
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -294,9 +294,10 @@ void swr_close(struct SwrContext *s);
|
|||||||
* in and in_count can be set to 0 to flush the last few samples out at the
|
* in and in_count can be set to 0 to flush the last few samples out at the
|
||||||
* end.
|
* end.
|
||||||
*
|
*
|
||||||
* If more input is provided than output space then the input will be buffered.
|
* If more input is provided than output space, then the input will be buffered.
|
||||||
* You can avoid this buffering by providing more output space than input.
|
* You can avoid this buffering by using swr_get_out_samples() to retrieve an
|
||||||
* Conversion will run directly without copying whenever possible.
|
* upper bound on the required number of output samples for the given number of
|
||||||
|
* input samples. Conversion will run directly without copying whenever possible.
|
||||||
*
|
*
|
||||||
* @param s allocated Swr context, with parameters set
|
* @param s allocated Swr context, with parameters set
|
||||||
* @param out output buffers, only the first one need be set in case of packed audio
|
* @param out output buffers, only the first one need be set in case of packed audio
|
||||||
@ -435,6 +436,24 @@ int swr_inject_silence(struct SwrContext *s, int count);
|
|||||||
*/
|
*/
|
||||||
int64_t swr_get_delay(struct SwrContext *s, int64_t base);
|
int64_t swr_get_delay(struct SwrContext *s, int64_t base);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an upper bound on the number of samples that the next swr_convert
|
||||||
|
* call will output, if called with in_samples of input samples. This
|
||||||
|
* depends on the internal state, and anything changing the internal state
|
||||||
|
* (like further swr_convert() calls) will may change the number of samples
|
||||||
|
* swr_get_out_samples() returns for the same number of input samples.
|
||||||
|
*
|
||||||
|
* @param in_samples number of input samples.
|
||||||
|
* @note any call to swr_inject_silence(), swr_convert(), swr_next_pts()
|
||||||
|
* or swr_set_compensation() invalidates this limit
|
||||||
|
* @note it is recommended to pass the correct available buffer size
|
||||||
|
* to all functions like swr_convert() even if swr_get_out_samples()
|
||||||
|
* indicates that less would be used.
|
||||||
|
* @returns an upper bound on the number of samples that the next swr_convert
|
||||||
|
* will output or a negative value to indicate an error
|
||||||
|
*/
|
||||||
|
int swr_get_out_samples(struct SwrContext *s, int in_samples);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*
|
*
|
||||||
|
@ -76,6 +76,7 @@ typedef int (* resample_flush_func)(struct SwrContext *c);
|
|||||||
typedef int (* set_compensation_func)(struct ResampleContext *c, int sample_delta, int compensation_distance);
|
typedef int (* set_compensation_func)(struct ResampleContext *c, int sample_delta, int compensation_distance);
|
||||||
typedef int64_t (* get_delay_func)(struct SwrContext *s, int64_t base);
|
typedef int64_t (* get_delay_func)(struct SwrContext *s, int64_t base);
|
||||||
typedef int (* invert_initial_buffer_func)(struct ResampleContext *c, AudioData *dst, const AudioData *src, int src_size, int *dst_idx, int *dst_count);
|
typedef int (* invert_initial_buffer_func)(struct ResampleContext *c, AudioData *dst, const AudioData *src, int src_size, int *dst_idx, int *dst_count);
|
||||||
|
typedef int64_t (* get_out_samples_func)(struct SwrContext *s, int in_samples);
|
||||||
|
|
||||||
struct Resampler {
|
struct Resampler {
|
||||||
resample_init_func init;
|
resample_init_func init;
|
||||||
@ -85,6 +86,7 @@ struct Resampler {
|
|||||||
set_compensation_func set_compensation;
|
set_compensation_func set_compensation;
|
||||||
get_delay_func get_delay;
|
get_delay_func get_delay;
|
||||||
invert_initial_buffer_func invert_initial_buffer;
|
invert_initial_buffer_func invert_initial_buffer;
|
||||||
|
get_out_samples_func get_out_samples;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct Resampler const swri_resampler;
|
extern struct Resampler const swri_resampler;
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include "libavutil/avutil.h"
|
#include "libavutil/avutil.h"
|
||||||
|
|
||||||
#define LIBSWRESAMPLE_VERSION_MAJOR 1
|
#define LIBSWRESAMPLE_VERSION_MAJOR 1
|
||||||
#define LIBSWRESAMPLE_VERSION_MINOR 1
|
#define LIBSWRESAMPLE_VERSION_MINOR 2
|
||||||
#define LIBSWRESAMPLE_VERSION_MICRO 100
|
#define LIBSWRESAMPLE_VERSION_MICRO 100
|
||||||
|
|
||||||
#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \
|
#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \
|
||||||
|
Reference in New Issue
Block a user