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>tags/n2.7
| @@ -15,6 +15,9 @@ libavutil: 2014-08-09 | |||
| 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 | |||
| 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); | |||
| } | |||
| 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) { | |||
| AudioData *a= &s->in_buffer; | |||
| int i, j, ret; | |||
| @@ -414,4 +433,5 @@ struct Resampler const swri_resampler={ | |||
| set_compensation, | |||
| get_delay, | |||
| 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){ | |||
| AudioData * in= &s->in; | |||
| AudioData *out= &s->out; | |||
| int av_unused max_output; | |||
| if (!swr_is_initialized(s)) { | |||
| av_log(s, AV_LOG_ERROR, "Context has not been initialized\n"); | |||
| return AVERROR(EINVAL); | |||
| } | |||
| #if ASSERT_LEVEL >1 | |||
| max_output = swr_get_out_samples(s, in_count); | |||
| #endif | |||
| while(s->drop_output > 0){ | |||
| 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); | |||
| if(ret>0 && !s->drop_output) | |||
| s->outpts += ret * (int64_t)s->in_sample_rate; | |||
| av_assert2(max_output < 0 || ret < 0 || ret <= max_output); | |||
| return ret; | |||
| }else{ | |||
| 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) | |||
| s->outpts += ret2 * (int64_t)s->in_sample_rate; | |||
| av_assert2(max_output < 0 || ret2 < 0 || ret2 <= max_output); | |||
| 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 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 | |||
| * end. | |||
| * | |||
| * 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. | |||
| * Conversion will run directly without copying whenever possible. | |||
| * If more input is provided than output space, then the input will be buffered. | |||
| * You can avoid this buffering by using swr_get_out_samples() to retrieve an | |||
| * 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 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); | |||
| /** | |||
| * 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 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 int64_t (* get_out_samples_func)(struct SwrContext *s, int in_samples); | |||
| struct Resampler { | |||
| resample_init_func init; | |||
| @@ -85,6 +86,7 @@ struct Resampler { | |||
| set_compensation_func set_compensation; | |||
| get_delay_func get_delay; | |||
| invert_initial_buffer_func invert_initial_buffer; | |||
| get_out_samples_func get_out_samples; | |||
| }; | |||
| extern struct Resampler const swri_resampler; | |||
| @@ -29,7 +29,7 @@ | |||
| #include "libavutil/avutil.h" | |||
| #define LIBSWRESAMPLE_VERSION_MAJOR 1 | |||
| #define LIBSWRESAMPLE_VERSION_MINOR 1 | |||
| #define LIBSWRESAMPLE_VERSION_MINOR 2 | |||
| #define LIBSWRESAMPLE_VERSION_MICRO 100 | |||
| #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ | |||