Gstreamer/audioflingersink/APE: 使用palybin播放extrahigh,insane等级的ape音乐出现卡顿现象
来源:互联网 发布:vb中len什么意思 编辑:程序博客网 时间:2024/04/30 00:59
解决方法:
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留有足够的处理时间,从而不会造成播放过程的间断。
0 0
- Gstreamer/audioflingersink/APE: 使用palybin播放extrahigh,insane等级的ape音乐出现卡顿现象
- java播放mp3/ogg/ape/flac音乐
- foobar播放ape的问题
- APE
- APE格式音乐处理
- Linux 下使用 Audacious 播放 APE 音频
- winamp播放ape文件
- 【Vegas原创】用foobar 播放ape,分割ape,合并ape,制作cue,刻录ape ,制作MP3
- 【Vegas原创】用foobar 播放ape,分割ape,合并ape,制作cue,刻录ape ,制作MP3
- Winamp播放.APE和.CUE
- java播放MP3/APE音乐文件
- ape的基本知识
- ape的基本知识
- ape 及cue在xmms下的播放
- 基于android多媒体框架实现播放APE音频的实现
- ubuntu14.04 clementine音乐播放器无法播放ape格式解决方法
- ubuntu14.04 clementine音乐播放器无法播放ape格式解决方法
- 台式APE播放机 硬盘APE播放器 APE Player Ver0.1完成
- SCI 投稿Cover letter模板大全
- android editText 软键盘enter键图标的设置
- VLAN原理详解
- 总结swift语言常见的20个问题和回答
- Java Socket发送与接收HTTP消息简单实现
- Gstreamer/audioflingersink/APE: 使用palybin播放extrahigh,insane等级的ape音乐出现卡顿现象
- Java毫秒和真实时间的转换
- Android zxing二维码扫描 扫描框适应各种分辨率
- 浅谈java字符串
- 图结构练习——最小生成树
- android 逆向 初级(一)
- Git工具比较:sourcetree tortoisegit
- Android中自动跳转到系统设置界面
- nc 自定义dialog