转载注明出处:http://www.cnblogs.com/renhui/p/6510872.html

之前使用IjkPlayer做播放器的使用的时候,在做倍速播放的时候,发现播放的声音音调明显变高了。问题的详情参见Bilibili/ijkplayer的#2930、#2785等。

在解决问题之前首先对倍速的代码做一次追踪

a. Android应用中Java层面调用的代码:

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);
}

倍速代码

b.找到C库里面对应的方法:_setPropertyFloat (ijkplayer_jni.c)

static void ijkMediaPlayer_setPropertyFloat(JNIEnv *env, jobject thiz, jint id, jfloat value)
{
IjkMediaPlayer *mp = jni_get_media_player(env, thiz);
JNI_CHECK_GOTO(mp, env, NULL, "mpjni: setPropertyFloat: null mp", LABEL_RETURN);
ijkmp_set_property_float(mp, id, value); LABEL_RETURN:
ijkmp_dec_ref_p(&mp);
return;
}

倍速代码

c.找到C库中的对应的方法:ijkmp_set_property_float(ijkplayer.c)

void ijkmp_set_property_float(IjkMediaPlayer *mp, int id, float value)
{
assert(mp);
pthread_mutex_lock(&mp->mutex);
ffp_set_property_float(mp->ffplayer, id, value);
pthread_mutex_unlock(&mp->mutex);
}

倍速代码

d.找到C库中对应的方法:ffp_set_property_float(ff_ffplay.c)

void ffp_set_property_float(FFPlayer *ffp, int id, float value)
{
switch (id) {
case FFP_PROP_FLOAT_PLAYBACK_RATE:
ffp_set_playback_rate(ffp, value);
break;
case FFP_PROP_FLOAT_PLAYBACK_VOLUME:
ffp_set_playback_volume(ffp, value);
break;
default:
return;
}
}

倍速代码

e.找到C库中对应的方法ffp_set_playback_rate:(ff_ffplay.c)

void ffp_set_playback_rate(FFPlayer *ffp, float rate)
{
if (!ffp)
return; ffp->pf_playback_rate = rate;
ffp->pf_playback_rate_changed = ;
}

倍速代码

追踪完毕,我们发现,基本上在Java层设置的倍速代码,会被一层一层的传递到FFPlayer上面去。在IjkPlayer 0.7.9版本之前,可以说,我们对变调的问题,没有头绪,因为IjkPlayer将音频的处理模块直接调用系统的音频处理模块进行输出,这样的话,我们就可以看到在Android 6.0以下的手机在用IjkPlayer跑倍速的时候,出现音调变高的情况。

近期,IjkPlayer的github上面发布了最新版本0.7.9版本。

下面引用一下IjkPlayer近几个版本的changelog(Android相关的):

tag k0.7.9
ffmpeg: add tcp timeout control // 增加TCP超时控制逻辑
android: support soundtouch // Android端 支持soundtouch机制 tag k0.7.8
ffplay: support accurate seek // ffplay 支持更加精确的seek
ijkio: fix some issue  // 修复一些问题

发现,0.7.9版本支持了soundtouch机制了。而且给出了开启soundtouch机制的方式。

{ "soundtouch", "SoundTouch: enable", OPTION_OFFSET(soundtouch_enable), OPTION_INT(, , ) }

如果不开启,在音频播放的时候,还是使用系统提供的api做播放处理(那么声调问题还是存在)。开启后,如果不对IjkPlayer C层面的逻辑做更改,也会有声调的问题(因为B站对倍速的要求就是变调)。

那么后续的工作就是先了解soundtouch然后对IjkPlayer的代码做相关的调整。

了解和学习souchtouch:在 http://www.surina.net/soundtouch/index.html (官网) 里面了解和学习。辅助学习的博客:http://www.cnblogs.com/wangguchangqing/p/6003087.html

同步下来0.7.9版本的代码后,可以看到,在extra目录下增加了soundtouch目录,这个目录下面就是soundtouch相关的逻辑。经过浏览代码发现只需要去调整soundtouch/source/SoundStretch/main.cpp里面的代码:

pSoundTouch->setSampleRate(sampleRate);
pSoundTouch->setChannels(channels); pSoundTouch->setTempoChange(params->tempoDelta);
pSoundTouch->setPitchSemiTones(); // 更改这里,其他不变
pSoundTouch->setRateChange(params->rateDelta);

调用重新打so,引入,Java层开启soundtouch

ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "soundtouch", 1);

使用倍速,此时变调的问题,应该解决了。

~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

目前Ijk版本为0.8.1版本,这个版本下,不去做上面的那些事情,只需要设置1,就为变速变调的状态。

ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "soundtouch", );

设置0,就是变速不变调的状态,

ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "soundtouch", );

当然,如果按照上面的更改修改了C代码了,也可以,只不过,不管设置多少,都为变速不变调的状态了。

开源播放器 ijkplayer (二) :ijkplayer倍速变调问题解决方案的更多相关文章

  1. 开源播放器 ijkplayer (一) :使用Ijkplayer播放直播视频

    1.ijkplayer 编码 IjkPlayer支持硬解码和软解码. 软解码时不会旋转视频角度这时需要你通过onInfo的what == IMediaPlayer.MEDIA_INFO_VIDEO_R ...

  2. 搭建rtmp直播流服务之4:videojs和ckPlayer开源播放器二次开发(播放rtmp、hls直播流及普通视频)

    前面几章讲解了使用 nginx-rtmp搭建直播流媒体服务器; ffmpeg推流到nginx-rtmp服务器; java通过命令行调用ffmpeg实现推流服务; 从数据源获取,到使用ffmpeg推流, ...

  3. 基于FFMPEG的跨平台播放器实现(二)

    基于FFMPEG的跨平台播放器实现(二) 上一节讲到了在Android平台下采用FFmpeg+surface组合打造播放器的方法,这一节讲一下Windows平台FFmpeg + D3D.Linux平台 ...

  4. 笔谈kxmovie开源播放器库的使用

    开源播放器项目 kxmovie(https://github.com/kolyvan/kxmovie),现在仍然是很多刚开始接触播放器开发的程序员的参照范本.以下是我操作kxmovie项目的过程: ( ...

  5. 开源播放器 ijkplayer (四) :Ijkplayer切换网络时停止播放的问题处理

    问题起因: 在进行ijkplayer播放器的测试时,发现ijkplayer播放器在切换网络时出现直播画面停止的问题. 问题分析: 抓取日志发现:tv.danmaku.ijk.media.player. ...

  6. 开源播放器ijkplayer源码结构

    ijkplayer核心源码主要在ijkmedia文件夹下ijkplayer.ijksdl及ijkutils. 注:tag k0.3.1 player: remove ijkutil android相关 ...

  7. Android 实现简单音乐播放器(二)

    在Android 实现简单音乐播放器(一)中,我介绍了MusicPlayer的页面设计. 现在,我简单总结一些功能实现过程中的要点和有趣的细节,结合MainActivity.java代码进行说明(写出 ...

  8. Linux 下编译Android-VLC开源播放器详解(附源码下载)

    这两天需要做音视频播放相关的东西,所以重新找了目前android下的解码库.Android自带的解码库支持不全,因此很多第三方播放器都是自带解码器,绝大部分都是使用FFMpeg作为解码库.我11年的时 ...

  9. QT5:C++实现基于multimedia的音乐播放器(二)

    今天接着上一篇来实现播放器的槽函数. 先来实现播放模式,槽函数如下: //播放模式 void Music::musicPlayPattern() { //z=++z%3; ) { //顺序播放 pla ...

随机推荐

  1. JEECG-Swagger UI的使用说明

    一.代码生成 (此步骤为代码生成器的使用,如不清楚请查阅相关文档视频) 1.进入菜单[在线开发]-->[Online表单开发],选中一张单表/主表,点击代码生成按钮. 2.弹出页面中填写代码生成 ...

  2. ---dd-wrt memo

    http://blog.csdn.net/fyh2003/article/details/44458657http://blog.csdn.net/u010189241/article/details ...

  3. Win32API标准模板

    #include<Windows.h> LRESULT CALLBACK WndProc //处理发送到窗口的消息的应用程序定义的函数.wndproc类型定义指向此回调函数的指针. //W ...

  4. js原型继承四步曲

    <sctript> //1.创建父类 function Parent(){ this.name = name; } Parent.prototype.age = 20; //2.创建子类 ...

  5. ide调试

    F8:  程序向下执行一行(如果当前行有方法调用,这个方法将被执行完毕返回,然后到下一行) F7: 程序向下执行一行.如果该行有自定义方法,则运行进入自定义方法(不会进入官方类库的方法) Alt + ...

  6. 深拷贝 浅拷贝 python

    1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象. 2. copy.deepcopy 深拷贝 拷贝对象及其子对象 一个很好的例子: # -*-coding:utf-8 -*- ...

  7. 【python-dict】dict的使用及实现原理

    以下内容是针对:python源码剖析中的第五章——python中Dict对象 的读书笔记(针对书中讲到的内容进行了自己的整理,并且针对部分内容根据自己的需求进行了扩展) 一.Dict的用法 Dict的 ...

  8. 【c++】内存检查工具Valgrind介绍,安装及使用以及内存泄漏的常见原因

    转自:https://www.cnblogs.com/LyndonYoung/articles/5320277.html Valgrind是运行在Linux上一套基于仿真技术的程序调试和分析工具,它包 ...

  9. Linux系统性能监控工具:tsar 安装、配置、以及使用

    介绍 tsar 是淘宝自己开发的一个监控工具,可用于收集和汇总系统信息,例如CPU,负载,IO和应用程序信息,例如nginx,HAProxy,Squid等.结果可以存储在本地磁盘或发送到Nagios. ...

  10. Spring注入静态变量的方法,以及CXF如何获取客户端IP

    1.如果使用@Resource注解来注入静态变量的,服务器启动就会报错的.可以新增一个set方法,同时在set方法上用@Resource注解来注入. 2.或者直接在Spring的配置文件中使用< ...