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
原创粉丝点击