diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-05-19 18:44:34 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-05-19 19:23:37 +0200 |
commit | 72a242c99832b9ef312222ac9181634f14963107 (patch) | |
tree | 8adc3da12c6b1fc9b7db909efec365111cc99582 | |
parent | f88f705abcb925cede3ffa392156489956e8c0b9 (diff) | |
download | ffmpeg-72a242c99832b9ef312222ac9181634f14963107.tar.gz |
swr: add swr_next_pts()
parameter descriptions partly reuse text from af_asyncts
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libswresample/swresample.c | 43 | ||||
-rw-r--r-- | libswresample/swresample.h | 17 | ||||
-rw-r--r-- | libswresample/swresample_internal.h | 6 |
3 files changed, 64 insertions, 2 deletions
diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 83bec202eb..dcc9a286c8 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -24,6 +24,8 @@ #include "libavutil/avassert.h" #include "libavutil/audioconvert.h" +#include <float.h> + #define C30DB M_SQRT2 #define C15DB 1.189207115 #define C__0DB 1.0 @@ -78,6 +80,15 @@ static const AVOption options[]={ {"phase_shift" , "Resampling Phase Shift" , OFFSET(phase_shift) , AV_OPT_TYPE_INT , {.dbl=10 }, 0 , 30 , PARAM }, {"linear_interp" , "Use Linear Interpolation" , OFFSET(linear_interp) , AV_OPT_TYPE_INT , {.dbl=0 }, 0 , 1 , PARAM }, {"cutoff" , "Cutoff Frequency Ratio" , OFFSET(cutoff) , AV_OPT_TYPE_DOUBLE,{.dbl=0.8 }, 0 , 1 , PARAM }, +{"min_comp" , "Minimum difference between timestamps and audio data (in seconds) below which no timestamp compensation of either kind is applied" + , OFFSET(min_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=FLT_MAX }, 0 , FLT_MAX , PARAM }, +{"min_hard_comp" , "Minimum difference between timestamps and audio data (in seconds) to trigger padding/trimming the data." + , OFFSET(min_hard_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=0.1 }, 0 , INT_MAX , PARAM }, +{"comp_duration" , "Duration (in seconds) over which data is stretched/squeezeed to make it match the timestamps." + , OFFSET(soft_compensation_duration),AV_OPT_TYPE_FLOAT ,{.dbl=1 }, 0 , INT_MAX , PARAM }, +{"max_soft_comp" , "Maximum factor by which data is stretched/squeezeed to make it match the timestamps." + , OFFSET(max_soft_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=0 }, 0 , INT_MAX , PARAM }, + {0} }; @@ -644,7 +655,10 @@ int swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_coun fill_audiodata(out, out_arg); if(s->resample){ - return 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) + s->outpts += ret * (int64_t)s->in_sample_rate; + return ret; }else{ AudioData tmp= *in; int ret2=0; @@ -693,6 +707,8 @@ int swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_coun s->in_buffer_count += in_count; } } + if(ret2>0 && !s->drop_output) + s->outpts += ret2 * (int64_t)s->in_sample_rate; return ret2; } } @@ -731,3 +747,28 @@ int swr_inject_silence(struct SwrContext *s, int count){ av_freep(&silence.data); return ret; } + +int64_t swr_next_pts(struct SwrContext *s, int64_t pts){ + if(pts == INT64_MIN) + return s->outpts; + if(s->min_compensation >= FLT_MAX) { + return (s->outpts = pts - swr_get_delay(s, s->in_sample_rate * (int64_t)s->out_sample_rate)); + } else { + int64_t delta = pts - swr_get_delay(s, s->in_sample_rate * (int64_t)s->out_sample_rate) - s->outpts; + double fdelta = delta /(double)(s->in_sample_rate * (int64_t)s->out_sample_rate); + + if(fabs(fdelta) > s->min_compensation) { + if(!s->outpts || fabs(fdelta) > s->min_hard_compensation){ + if(delta > 0) swr_inject_silence(s, delta / s->out_sample_rate); + else swr_drop_output (s, -delta / s-> in_sample_rate); + } else { + int duration = s->out_sample_rate * s->soft_compensation_duration; + int comp = av_clipf(fdelta, -s->max_soft_compensation, s->max_soft_compensation) * duration ; + av_log(s, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n", fdelta, comp, duration); + swr_set_compensation(s, comp, duration); + } + } + + return s->outpts; + } +} diff --git a/libswresample/swresample.h b/libswresample/swresample.h index e027f5619c..85a337abbe 100644 --- a/libswresample/swresample.h +++ b/libswresample/swresample.h @@ -30,7 +30,7 @@ #include "libavutil/samplefmt.h" #define LIBSWRESAMPLE_VERSION_MAJOR 0 -#define LIBSWRESAMPLE_VERSION_MINOR 14 +#define LIBSWRESAMPLE_VERSION_MINOR 15 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ @@ -133,6 +133,21 @@ int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in , int in_count); /** + * Convert the next timestamp from input to output + * timestampe are in 1/(in_sample_rate * out_sample_rate) units. + * + * @note There are 2 slightly differently behaving modes. + * First is when automatic timestamp compensation is not used, (min_compensation >= FLT_MAX) + * in this case timestamps will be passed through with delays compensated + * Second is when automatic timestamp compensation is used, (min_compensation < FLT_MAX) + * in this case the output timestamps will match output sample numbers + * + * @param pts timstamp for the next input sample, INT64_MIN if unknown + * @returns the output timestamp for the next output sample + */ +int64_t swr_next_pts(struct SwrContext *s, int64_t pts); + +/** * Activate resampling compensation. */ int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance); diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h index 30ab6cd1a1..b0e7423773 100644 --- a/libswresample/swresample_internal.h +++ b/libswresample/swresample_internal.h @@ -62,6 +62,11 @@ struct SwrContext { int linear_interp; /**< if 1 then the resampling FIR filter will be linearly interpolated */ double cutoff; /**< resampling cutoff frequency. 1.0 corresponds to half the output sample rate */ + float min_compensation; ///< minimum below which no compensation will happen + float min_hard_compensation; ///< minimum below which no silence inject / sample drop will happen + float soft_compensation_duration; ///< duration over which soft compensation is applied + float max_soft_compensation; ///< maximum soft compensation in seconds over soft_compensation_duration + int resample_first; ///< 1 if resampling must come first, 0 if rematrixing int rematrix; ///< flag to indicate if rematrixing is needed (basically if input and output layouts mismatch) int rematrix_custom; ///< flag to indicate that a custom matrix has been defined @@ -77,6 +82,7 @@ struct SwrContext { int in_buffer_count; ///< cached buffer length int resample_in_constraint; ///< 1 if the input end was reach before the output end, 0 otherwise int flushed; ///< 1 if data is to be flushed and no further input is expected + int64_t outpts; ///< output PTS int drop_output; ///< number of output samples to drop struct AudioConvert *in_convert; ///< input conversion context |