[FFmpeg-cvslog] swr: add swr_next_pts()

Michael Niedermayer git at videolan.org
Sat May 19 19:28:56 CEST 2012


ffmpeg | branch: master | Michael Niedermayer <michaelni at gmx.at> | Sat May 19 18:44:34 2012 +0200| [72a242c99832b9ef312222ac9181634f14963107] | committer: Michael Niedermayer

swr: add swr_next_pts()

parameter descriptions partly reuse text from af_asyncts

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=72a242c99832b9ef312222ac9181634f14963107
---

 libswresample/swresample.c          |   43 ++++++++++++++++++++++++++++++++++-
 libswresample/swresample.h          |   17 +++++++++++++-
 libswresample/swresample_internal.h |    6 +++++
 3 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/libswresample/swresample.c b/libswresample/swresample.c
index 83bec20..dcc9a28 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 e027f56..85a337a 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 30ab6cd..b0e7423 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



More information about the ffmpeg-cvslog mailing list