int64_t swr_next_pts(struct SwrContext *s, int64_t pts){ if(pts == INT64_MIN) return s->outpts; if (s->firstpts == AV_NOPTS_VALUE) s->outpts = s->firstpts = pts; 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 + s->drop_output*(int64_t)s->in_sample_rate; double fdelta = delta /(double)(s->in_sample_rate * (int64_t)s->out_sample_rate); if(fabs(fdelta) > s->min_compensation) { if(s->outpts == s->firstpts || fabs(fdelta) > s->min_hard_compensation){ int ret; if(delta > 0) ret = swr_inject_silence(s, delta / s->out_sample_rate); else ret = swr_drop_output (s, -delta / s-> in_sample_rate); if(ret<0){ av_log(s, AV_LOG_ERROR, "Failed to compensate for timestamp delta of %f\n", fdelta); } } else if(s->soft_compensation_duration && s->max_soft_compensation) { int duration = s->out_sample_rate * s->soft_compensation_duration; double max_soft_compensation = s->max_soft_compensation / (s->max_soft_compensation < 0 ? -s->in_sample_rate : 1); int comp = av_clipf(fdelta, -max_soft_compensation, 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; } }
int AudioController::control(af_instance *af, int cmd, void *arg) { auto ac = priv(af); auto d = ac->d; switch(cmd){ case AF_CONTROL_REINIT: return ac->reinitialize(static_cast<mp_audio*>(arg)); case AF_CONTROL_SET_VOLUME: d->amp = *((float*)arg); d->dirty |= Amp; return AF_OK; case AF_CONTROL_GET_VOLUME: *((float*)arg) = d->amp; return AF_OK; case AF_CONTROL_SET_PLAYBACK_SPEED: d->scale = *(double*)arg; d->dirty |= Scale; return d->tempoScalerActivated; case AF_CONTROL_SET_FORMAT: d->fmt_conv = *(int*)arg; if (!isSupported(d->fmt_conv)) d->fmt_conv = AF_FORMAT_UNKNOWN; return !!d->fmt_conv; case AF_CONTROL_SET_RESAMPLE_RATE: d->outrate = *(int *)arg; d->dirty |= Resample; return AF_OK; case AF_CONTROL_SET_CHANNELS: d->layout = ChannelLayoutMap::toLayout(*(mp_chmap*)arg); return AF_OK; case AF_CONTROL_RESET: if (d->swr) while (swr_drop_output(d->swr, 1000) > 0) ; return AF_OK; default: return AF_UNKNOWN; } }
static void drop_all_output(struct af_resample *s) { while (swr_drop_output(s->avrctx, 1000) > 0) {} }