我们看播放器都有倍速功能,倍速又是怎么实现的呢?
public void setSpeed(float speed) {
_setPropertyFloat(FFP_PROP_FLOAT_PLAYBACK_RATE, speed);
}
public float getSpeed(float speed) {
return _getPropertyFloat(FFP_PROP_FLOAT_PLAYBACK_RATE, .0f);
}
{ "_setPropertyFloat", "(IF)V", (void *) ijkMediaPlayer_setPropertyFloat },
ffp_set_property_float(mp->ffplayer, id, value);
ffp_set_playback_rate(ffp, value);
void ffp_set_playback_rate(FFPlayer *ffp, float rate)
{
if (!ffp)
return;
av_log(ffp, AV_LOG_INFO, "Playback rate: %f\n", rate);
ffp->pf_playback_rate = rate;
ffp->pf_playback_rate_changed = 1;
}
我们先看pf_playback_rate_changed
我们知道音频数据都来自于
static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
{
if (ffp->pf_playback_rate_changed) {
ffp->pf_playback_rate_changed = 0;
#if defined(__ANDROID__)
if (!ffp->soundtouch_enable) {
SDL_AoutSetPlaybackRate(ffp->aout, ffp->pf_playback_rate);
}
#else
SDL_AoutSetPlaybackRate(ffp->aout, ffp->pf_playback_rate);
#endif
}
}
我们继续看SDL_AoutSetPlaybackRate
void SDL_AoutSetPlaybackRate(SDL_Aout *aout, float playbackRate)
{
if (aout) {
if (aout->func_set_playback_rate)
aout->func_set_playback_rate(aout, playbackRate);
}
}
SDL_Aout *SDL_AoutAndroid_CreateForAudioTrack(){
aout->func_set_playback_rate = func_set_playback_rate;
}
static void func_set_playback_rate(SDL_Aout *aout, float speed)
{
if (!aout)
return;
SDL_Aout_Opaque *opaque = aout->opaque;
SDL_LockMutex(opaque->wakeup_mutex);
SDLTRACE("%s %f", __func__, (double)speed);
opaque->speed = speed;
opaque->speed_changed = 1;
SDL_CondSignal(opaque->wakeup_cond);
SDL_UnlockMutex(opaque->wakeup_mutex);
}
我们知道音频的播放是调用AudioTrack的write方法
static int aout_thread_n(JNIEnv *env, SDL_Aout *aout){
if (opaque->speed_changed) {
opaque->speed_changed = 0;
SDL_Android_AudioTrack_setSpeed(env, atrack, opaque->speed);
}
}
通过搜寻代码 发现最后走到的是AudioTrack的setPlaybackRate
void J4AC_android_media_AudioTrack__setSpeed(JNIEnv *env, jobject thiz, jfloat speed)
{
if (J4A_GetSystemAndroidApiLevel(env) < 23) {
jint sample_rate = J4AC_android_media_AudioTrack__getSampleRate(env,thiz);
if (J4A_ExceptionCheck__throwAny(env)) {
return;
}
J4AC_android_media_AudioTrack__setPlaybackRate__catchAll(env, thiz,
(jint) (sample_rate * speed));
return;
}
jobject temp = NULL;
jobject params = J4AC_android_media_AudioTrack__getPlaybackParams(env, thiz);
if (J4A_ExceptionCheck__throwAny(env) || !params)
goto fail;
temp = J4AC_android_media_PlaybackParams__setSpeed(env, params, speed);
J4A_DeleteLocalRef__p(env, &temp);
if (J4A_ExceptionCheck__throwAny(env))
goto fail;
J4A_ALOGE("%s %f", __func__, (double)speed);
J4AC_android_media_AudioTrack__setPlaybackParams(env, thiz, params);
if (J4A_ExceptionCheck__throwAny(env))
goto fail;
fail:
J4A_DeleteLocalRef__p(env, ¶ms);
}
通过上面的代码可以看到倍速实际上就是重新设置了Audiotrack的采样率。
比如原始音频采样率是44100,speed设置为0.5。那么对Audiotrack就设置为了22050,这样就导致了原来一个时间端的数据,就会播放成两个时间段。
有一点要注意倍速最多能是多少
可以看到倍速可以变慢,但是变快最多也就是两倍。?
|