解决方法:
1. 增大 audioflingersink 中对 audiotrack 中 ringbuffer 大小的配置;
diff --git a/gst/audioflingersink/gstaudioflingersink.cpp b/gst/audioflingersink/gstaudioflingersink.cpp
index 840c3f3..7ec653f 100644
--- a/gst/audioflingersink/gstaudioflingersink.cpp
+++ b/gst/audioflingersink/gstaudioflingersink.cpp
@@ -38,7 +38,7 @@
using namespace android;
#undef LOG_TAG
#define LOG_TAG "GstAudioFlingerSink"
-#define DEFAULT_BUFFER_TIME (100 * GST_MSECOND)
+#define DEFAULT_BUFFER_TIME (400 * GST_MSECOND)
#define MIN_CORRECTION (50*GST_MSECOND)
#define DEFAULT_VOLUME 1.0
#define DEFAULT_MUTE FALSE
2. 修改 playsink 的 pipeline,在 audioflingersink 之前添加 queue ,或者将 audioconvert 之前的 queue 转移到 audioflinger 之前。
diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c
diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c
index 839cde1..cdde376 100644
--- a/gst/playback/gstplaysink.c
+++ b/gst/playback/gstplaysink.c
@@ -2726,7 +2726,7 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw)
prev = chain->filter;
}
}
-
+#if 0
/* we have to add a queue when we need to decouple for the video sink in
* visualisations and for streamsynchronizer */
GST_DEBUG_OBJECT (playsink, "adding audio queue");
@@ -2748,6 +2748,7 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw)
}
prev = chain->queue;
}
+#endif
/* find ts-offset element */
gst_object_replace ((GstObject **) & chain->ts_offset, (GstObject *)
@@ -2847,6 +2848,28 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw)
}
}
+ /* we have to add a queue when we need to playback APE music
+ * at the level higher than "high" */
+ GST_DEBUG_OBJECT (playsink, "adding audio queue");
+ chain->queue = gst_element_factory_make ("queue", "asinkqueue");
+ if (chain->queue == NULL) {
+ post_missing_element_message (playsink, "queue");
+ GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+ (_("Missing element '%s' - check your GStreamer installation."),
+ "queue"), ("audio playback and visualizations might not work"));
+ } else {
+ g_object_set (chain->queue, "silent", TRUE, NULL);
+ gst_bin_add (bin, chain->queue);
+ if (prev) {
+ if (!gst_element_link_pads_full (prev, "src", chain->queue, "sink",
+ GST_PAD_LINK_CHECK_TEMPLATE_CAPS))
+ goto link_failed;
+ } else {
+ head = chain->queue;
+ }
+ prev = chain->queue;
+ }
+
if (prev) {
/* we only have to link to the previous element if we have something in
* front of the sink */
详细说明:
首先我们先来观察一下流畅播放和有卡顿播放时的log对比
1. 流畅播放情况下的log(添加queue后)
0:00:09.083588870 4410 0x1379180 DEBUG audioflingersink gstaudioflingersink.cpp:542:gst_android_audioringbuffer_write: size to write = 1179648
0:00:15.226308832 4410 0x1379180 LOG audioflingersink gstaudioflingersink.cpp:675:gst_android_audioringbuffer_commit:<audioflingersink0> wrote 294912 samples
0:00:15.227225871 4410 0x1379180 LOG audioflingersink gstaudioflingersink.cpp:649:gst_android_audioringbuffer_commit:<audioflingersink0> entering commit
0:00:15.227344318 4410 0x1379180 DEBUG audioflingersink gstaudioflingersink.cpp:522:gst_android_audioringbuffer_write: pos == 589824, data = 0xb4e37058, samples = 294912, next_sample = 589824
0:00:15.227488044 4410 0x1379180 DEBUG audioflingersink gstaudioflingersink.cpp:542:gst_android_audioringbuffer_write: size to write = 1179648
0:00:21.370138633 4410 0x1379180 LOG audioflingersink gstaudioflingersink.cpp:675:gst_android_audioringbuffer_commit:<audioflingersink0> wrote 294912 samples
0:00:21.371076892 4410 0x1379180 LOG audioflingersink gstaudioflingersink.cpp:649:gst_android_audioringbuffer_commit:<audioflingersink0> entering commit
0:00:21.371197152 4410 0x1379180 DEBUG audioflingersink gstaudioflingersink.cpp:522:gst_android_audioringbuffer_write: pos == 884736, data = 0xb53f6058, samples = 294912, next_sample = 884736
2. 有卡顿情况下的log
0:00:03.948740474 29704 0x105dc00 DEBUG audioflingersink gstaudioflingersink.cpp:542:gst_android_audioringbuffer_write: size to write = 1179648
0:00:09.994151475 29704 0x105dc00 LOG audioflingersink gstaudioflingersink.cpp:675:gst_android_audioringbuffer_commit:<audioflingersink0> wrote 294912 samples
0:00:10.668653145 29704 0x105dc00 LOG audioflingersink gstaudioflingersink.cpp:649:gst_android_audioringbuffer_commit:<audioflingersink0> entering commit
0:00:10.669338938 29704 0x105dc00 DEBUG audioflingersink gstaudioflingersink.cpp:522:gst_android_audioringbuffer_write: pos == 589824, data = 0xb5387058, samples = 294912, next_sample = 589824
0:00:10.669590031 29704 0x105dc00 DEBUG audioflingersink gstaudioflingersink.cpp:542:gst_android_audioringbuffer_write: size to write = 1179648
0:00:16.714031100 29704 0x105dc00 LOG audioflingersink gstaudioflingersink.cpp:675:gst_android_audioringbuffer_commit:<audioflingersink0> wrote 294912 samples
0:00:17.390009935 29704 0x105dc00 LOG audioflingersink gstaudioflingersink.cpp:649:gst_android_audioringbuffer_commit:<audioflingersink0> entering commit
0:00:17.390678775 29704 0x105dc00 DEBUG audioflingersink gstaudioflingersink.cpp:522:gst_android_audioringbuffer_write: pos == 884736, data = 0xb5387058, samples = 294912, next_sample = 884736
通过对比我们可以发现,在wrote ××× samples 和 entering commit 这两行log的时间上, 流畅情况下是没有大的时间差的,而在有卡顿的情况下我们可以发现存在0.67秒的时间差,这个在实时听感上也是一致的。也就是说造成播放中停顿的问题原因应该出在这个地方。
查看gstaudioflingersink.cpp中对应的代码可以确定,wrote ××× samples这一行代表了上一个buffer写到音频设备里完毕的时间,entering commit这一行代表了下一个buffer开始往设备里写的时间,其间存在着0.67秒的时间差。
现在我们来看看audioringbuffer中对于commit这个虚函数功能的定义,commit():write samples into the ringbuffer。 而在audioflingersink中定义的commit函数却直接调用了android MediaPlayerInterface::AudioSink 类中write()函数直接将buffer数据写到了音频设备中。因此在这里audiolingersink只是借用了audioringbuffer的接口,但是并没有真正用到ringbuffer。由于android的audio框架中已经有了ringbuffer机制,所以audioflingersink 插件的编写者应该是考虑到这一点,不想在这里再多此一举,而且可以减少由于buffering带来的延迟。
由此我们可以确定问题的原因是由于在往音频设备中写下一个buffer数据时,commit()函数没有能够及时的拿到上游传递过来的buffer数据而造成的卡顿延迟。
另外我们还要关注一下每次写的buffer的大小,log中wrote 294912 samples在采样率为48khz的时候相当于6.144秒的音频数据,如此之大的buffer数据应该是造成android audio框架中ringbuffer工作异常的元凶。在ringbuffer中数据消耗到一定水平时需要再次向其写入数据,而其中剩余的数据只够播放几十毫秒的时间,在audioflingersink之前存在audioconvert转换,转换6.144s的数据却需要几百毫秒,因此当ringbuffer中数据播放完而又得不到及时补充就会产生听感上的卡顿。
因此解决这个问题的方法有两种:第一,在audioflingersink之前添加一个queue,使得其随时都有准备好了的buffer数据可供使用;第二,增大ringbuffer的大小,给audioconvert留有足够的处理时间,从而不会造成播放过程的间断。
Gstreamer/audioflingersink/APE: 使用palybin播放extrahigh,insane等级的ape音乐出现卡顿现象相关推荐
- 播放器实战22 解决花屏与卡顿问题
1.内存对齐 1.1什么是内存对齐 在C语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如int.long.float等)的变量,也可以是一些复合数据类型(如数组.结构.联合等)的数据 ...
- H265网页视频播放器播放H265编码录像视频文件如何减缓卡顿情况?
视频播放延时卡顿的问题从视频服务诞生以来就一直存在,即便是在技术发达的今天,延时卡顿问题仍然是不能完全解决的(不同视频流延时说明). TSINGSEE青犀视频研发团队开发的H265播放器播放录像文件时 ...
- 杰里之 非 TWS 方案解决播放 wtg 提示音后蓝 牙音乐卡顿问题【篇】
需对 bt_decode.c 进行修改如下(一共三处)
- [iOS]调和 pop 手势导致 AVPlayer 播放卡顿
作者 NewPan 关注 2017.07.15 14:24* 字数 3110 阅读 749评论 8喜欢 17 声明:我为这个框架写了四篇文章: 第一篇:[iOS]UINavigationControl ...
- 《直播疑难杂症排查》之二:播放卡顿
##播放卡顿的表现 播放卡顿的表现总结下来包括但不限于以下这些: 频繁出现缓冲 播放不够流畅,画面一卡一卡的 ##常见播放卡顿问题排查 从代码层面来看,什么是卡顿?其实是指播放器渲染的帧率太低,比如: ...
- 蓝牙音乐和导航语音播放混音卡顿问题
最近发现公司自研的智能车载设备上存在一个问题:手机通过蓝牙连接车机,在手机上播放音乐车机上发声然后跟车机上的导航语音播报一起混音播出的时候会出现卡顿的现象:但是在车机上播放音乐和导航混音就正常.另外需 ...
- iOS微信聊天界面朋友圈多个小视频同时播放不卡顿
我的简书地址http://www.jianshu.com/p/10206ed63e0d 之前有个需求是实现如微信朋友圈动态列表小视频播放的效果,最近有空整理下给同样有需要的同学. 我们都知道微信朋友圈 ...
- 直播疑难杂症排查(2) — 播放卡顿
本文是 <直播疑难杂症排查>系列的第二篇文章,我们主要分析下如何排查播放卡顿问题. 1. 播放卡顿的表现 播放卡顿的表现总结下来包括但不限于以下这些: 频繁出现缓冲 播放不够流畅,画面一卡 ...
- 《直播疑难杂症排查》:播放卡顿
原文来自七牛云,感谢原作者. 1.播放卡顿的表现 播放卡顿的表现总结下来包括但不限于以下这些: 频繁出现缓冲 播放不够流畅,画面一卡一卡的 2.常见播放卡顿问题排查 从代码层面来看,什么是卡顿?其实是 ...
- Android常用播放器对比,Android平台四大音乐播放器对比评测
现如今,谷歌android手机系统越来越流行,在此平台上的应用软件也逐渐增多.今天,我们就天天动听.Winamp.酷我听听.QQ音乐等四款较常用的播放软件作一番评比,看看它们在android平台上的表 ...
最新文章
- python基础===Number
- 【 Vivado 】XDC文件的约束顺序
- Python 【大风号】短视频的自动上传与发布实例演示,同时支持抖音、快手、哔哩哔哩、小红书、微视、西瓜视频、微信视频号等平台的视频自动化同步发布
- Android 2018最新验证手机号正则表达式
- OkHttp3 HTTP请求执行流程分析
- vim 插件cscope 使用
- C语言基础教程之函数
- SQL Server AUTO_FIX_Login_Users
- HTML/CSS面试题(收集)
- 大话一些大二层网络技术新兴术语,并总结它与OpenStack的关系 (by quqi99)
- cpu超线程优缺点_超线程对游戏性能会影响?
- 龙卷风路径_龙卷风一般在中国的什么地方有?
- 小tips:页面滚动到关闭时的位置与不滚动
- 根据两点的经纬度求方位角和距离,等
- 使用Persimmon UI Builder 开发的一些技巧和注意事项 -- (RT-thread 柿饼UI)
- 【架构】大数据风控数据系统架构
- 电路原理 | 电路基本定理
- AWS(EC2)助我实现项目管理应用上云
- 【每周CV论文推荐】StyleGAN人脸属性编辑有哪些经典论文需要阅读
- Reinforced History Backtracking for Conversational Question Answering论文翻译
热门文章
- C语言:51单片机看这一篇就够了
- 一文告诉你16条微信小程序推广渠道大全
- u-boot 之配置分析 (2)
- Fruit (hdu 2152)
- RGB转灰度的几种算法
- Apple Pay编程指南
- CPU输入/输出的控制方式有哪些?
- 坐标系的旋转与欧拉角
- 程序性能常用衡量指标
- 当古典音乐遇上NFT