使用 GStreamer 的音乐文件(wav、mp3、...等)的多播流:可以接收但数据是间歇的

Multicast streaming of music file (wav, mp3, ...etc) with GStreamer: can receive but the data is Intermittent

我想在嵌入式linux (Yocto) 系统中实现多播流。

我以为Gstreamer很容易实现,但是当filesrc是mp3时,接收到的数据很不稳定,好像通过了低通滤波器。 当filesrc为wav时,接收到的数据就像是通过了断断续续的高通滤波器。

这是 gst 启动命令 (mp3)。

发送:

GST_DEBUG=3 gst-launch-1.0 filesrc location="background.mp3" ! decodebin ! \
 audioconvert ! rtpL16pay ! queue ! udpsink host=239.0.0.1 auto-multicast=true port=5004

接收:

GST_DEBUG=3 gst-launch-1.0 udpsrc multicast-group=239.0.0.1 auto-multicast=true port=5004 \
caps="application/x-rtp,  media=audio, clock-rate=44100, payload=0" ! rtpL16depay !\
 audioconvert ! alsasink

GST_DEBUG3结果如下:

发送:

Setting pipeline to PAUSED ...
0:00:00.115165875   936   0x7b8c40 WARN                 basesrc gstbasesrc.c:3486:gst_base_src_start_complete:<filesrc0> pad not activated yet
Pipeline is PREROLLING ...

====== BEEP: 4.1.4 build on Feb 14 2017 13:39:18. ======
        Core: MP3 decoder Wrapper  build on Mar 21 2014 15:04:50
 file: /usr/lib/imx-mm/audio-codec/wrap/lib_mp3d_wrap_arm12_elinux.so.3
CODEC: BLN_MAD-MMCODECS_MP3D_ARM_02.13.00_CORTEX-A8  build on Jul 12 2016 13:15:30.
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock

接收:

Setting pipeline to PAUSED ...

Pipeline is live and does not need PREROLL ...

Setting pipeline to PLAYING ...

New clock: GstSystemClock

0:00:00.269585916  1232   0x772320 WARN                    alsa conf.c:4974:snd_config_expand: alsalib error: Unknown parameters {AES0 0x02 AES1 0x82 AES2 0x00 AES3 0x02}

0:00:00.269914500  1232   0x772320 WARN                    alsa pcm.c:2495:snd_pcm_open_noupdate: alsalib error: Unknown PCM default:{AES0 0x02 AES1 0x82 AES2 0x00 AES3 0x02}

0:00:00.283770666  1232   0x772320 WARN                    alsa pcm_hw.c:1250:snd_pcm_hw_get_chmap: alsalib error: Cannot read Channel Map ctl

: No such file or directory

Redistribute latency...

0:00:06.335845459  1232   0x772320 WARN           audiobasesink gstaudiobasesink.c:1807:gst_audio_base_sink_get_alignment:<alsasink0> Unexpected discontinuity in audio timestamps of -0:00:00.120430839, resyncing

0:00:07.167036751  1232   0x772320 WARN           audiobasesink gstaudiobasesink.c:1512:gst_audio_base_sink_skew_slaving:<alsasink0> correct clock skew -0:00:00.020498109 < -+0:00:00.020000000

0:00:07.178596167  1232   0x772320 WARN           audiobasesink gstaudiobasesink.c:1484:gst_audio_base_sink_skew_slaving:<alsasink0> correct clock skew +0:00:00.020102330 > +0:00:00.020000000

0:00:08.215633667  1232   0x772320 WARN           audiobasesink gstaudiobasesink.c:1807:gst_audio_base_sink_get_alignment:<alsasink0> Unexpected discontinuity in audio timestamps of -0:00:00.128480725, resyncing

0:00:08.962452751  1232   0x772320 WARN           audiobasesink gstaudiobasesink.c:1512:gst_audio_base_sink_skew_slaving:<alsasink0> correct clock skew -0:00:00.020283552 < -+0:00:00.020000000

0:00:09.095737543  1232   0x772320 WARN           audiobasesink gstaudiobasesink.c:1484:gst_audio_base_sink_skew_slaving:<alsasink0> correct clock skew +0:00:00.020221135 > +0:00:00.020000000

0:00:10.135542001  1232   0x772320 WARN           audiobasesink gstaudiobasesink.c:1807:gst_audio_base_sink_get_alignment:<alsasink0> Unexpected discontinuity in audio timestamps of -0:00:00.125238095, resyncing

这是 gst 命令 (wav)

发送:

GST_DEBUG=3 gst-launch-1.0 filesrc location="background.wav" ! decodebin ! \
 audioconvert ! rtpL16pay ! queue ! udpsink host=239.0.0.1 auto-multicast=true port=5004

接收:

GST_DEBUG=3 gst-launch-1.0 udpsrc multicast-group=239.0.0.1 auto-multicast=true port=5004 \
caps="application/x-rtp,  media=audio, clock-rate=44100, payload=0" ! rtpL16depay !\
 audioconvert ! alsasink

GST_DEBUG3结果如下:

发送:

Setting pipeline to PAUSED ...
0:00:00.116759125   958  0x1c0cc40 WARN                 basesrc gstbasesrc.c:3486:gst_base_src_start_complete:<filesrc0> pad not activated yet
Pipeline is PREROLLING ...
0:00:00.136465125   958  0x1c1f460 FIXME                default gstutils.c:3764:gst_pad_create_stream_id_internal:<wavparse0:src> Creating random stream-id, consider implementing a deterministic way of creating a stream-id
0:00:00.137230750   958  0x1c1f460 WARN                    riff riff-read.c:794:gst_riff_parse_info:<wavparse0> Unknown INFO (metadata) tag entry IPRT
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
0:00:00.152916625   958  0x1c0cc40 WARN                     bin gstbin.c:2597:gst_bin_do_latency_func:<pipeline0> did not really configure latency of 0:00:00.000000000
New clock: GstSystemClock
^Chandling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 0:00:03.435631250
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

接收:

Setting pipeline to PAUSED ...

Pipeline is live and does not need PREROLL ...

Setting pipeline to PLAYING ...

New clock: GstSystemClock

0:00:00.270927792  1238  0x120d320 WARN                    alsa conf.c:4974:snd_config_expand: alsalib error: Unknown parameters {AES0 0x02 AES1 0x82 AES2 0x00 AES3 0x02}

0:00:00.271261625  1238  0x120d320 WARN                    alsa pcm.c:2495:snd_pcm_open_noupdate: alsalib error: Unknown PCM default:{AES0 0x02 AES1 0x82 AES2 0x00 AES3 0x02}

0:00:00.284991583  1238  0x120d320 WARN                    alsa pcm_hw.c:1250:snd_pcm_hw_get_chmap: alsalib error: Cannot read Channel Map ctl

: No such file or directory

Redistribute latency...

0:00:04.227007167  1238  0x120d320 WARN           audiobasesink gstaudiobasesink.c:1807:gst_audio_base_sink_get_alignment:<alsasink0> Unexpected discontinuity in audio timestamps of +0:00:00.053514739, resyncing

0:00:04.314387751  1238  0x120d320 WARN           audiobasesink gstaudiobasesink.c:1807:gst_audio_base_sink_get_alignment:<alsasink0> Unexpected discontinuity in audio timestamps of +0:00:00.055510204, resyncing

0:00:04.396900334  1238  0x120d320 WARN           audiobasesink gstaudiobasesink.c:1807:gst_audio_base_sink_get_alignment:<alsasink0> Unexpected discontinuity in audio timestamps of +0:00:00.052607709, resyncing

0:00:04.483605876  1238  0x120d320 WARN           audiobasesink gstaudiobasesink.c:1807:gst_audio_base_sink_get_alignment:<alsasink0> Unexpected discontinuity in audio timestamps of +0:00:00.055215419, resyncing

0:00:04.570297626  1238  0x120d320 WARN           audiobasesink gstaudiobasesink.c:1807:gst_audio_base_sink_get_alignment:<alsasink0> Unexpected discontinuity in audio timestamps of +0:00:00.055215419, resyncing

如果我使用 pulsesink 而不是 alsasink,则会出现以下内容。

Setting pipeline to PAUSED ...

Pipeline is live and does not need PREROLL ...

Setting pipeline to PLAYING ...

New clock: GstSystemClock

Redistribute latency...

0:00:00.410499500  1255 0x70813120 WARN                   pulse pulsesink.c:702:gst_pulsering_stream_underflow_cb:<pulsesink0> Got underflow

0:00:00.423478917  1255   0x7e7920 WARN           audiobasesink gstaudiobasesink.c:1807:gst_audio_base_sink_get_alignment:<pulsesink0> Unexpected discontinuity in audio timestamps of +0:00:00.038095238, resyncing

0:00:00.450453459  1255 0x70813120 WARN                   pulse pulsesink.c:702:gst_pulsering_stream_underflow_cb:<pulsesink0> Got underflow

有什么问题吗?有人可以解决这个问题吗? 希望得到您的回复。

感谢您的阅读。

我认为问题是application/x-rtp参数在发射器和接收器之间不匹配。

这可以很容易地解决,将 verbose 放入发送器中,然后在接收器中使用相同的参数:

让我们看一个例子:

TX:

gst-launch-1.0 -v filesrc location="test.mp3" ! decodebin ! audioconvert ! rtpL16pay ! queue ! udpsink host=239.0.0.1 auto-multicast=true port=5004

接下来是最后几行(感谢 -v):

/GstPipeline:pipeline0/GstQueue:queue0.GstPad:sink: caps = "application/x-rtp\,\ media\=(string)audio\,\ clock-rate\=(int)44100\,\ encoding-name\=(string)L16\,\ encoding-params\=(string)2\,\ channels\=(int)2\,\ payload\=(int)96\,\ ssrc\=(uint)1806894235\,\ timestamp-offset\=(uint)468998694\,\ seqnum-offset\=(uint)20785" /GstPipeline:pipeline0/GstRtpL16Pay:rtpl16pay0.GstPad:sink: caps = "audio/x-raw\,\ layout\=(string)interleaved\,\ rate\=(int)44100\,\ format\=(string)S16BE\,\ channels\=(int)2\,\ channel-mask\=(bitmask)0x0000000000000003" /GstPipeline:pipeline0/GstAudioConvert:audioconvert0.GstPad:sink: caps = "audio/x-raw\,\ format\=(string)S32LE\,\ layout\=(string)interleaved\,\ rate\=(int)44100\,\ channels\=(int)2\,\ channel-mask\=(bitmask)0x0000000000000003" /GstPipeline:pipeline0/GstDecodeBin:decodebin0.GstDecodePad:src_0.GstProxyPad:proxypad1: caps = "audio/x-raw\,\ format\=(string)S32LE\,\ layout\=(string)interleaved\,\ rate\=(int)44100\,\ channels\=(int)2\,\ channel-mask\=(bitmask)0x0000000000000003" /GstPipeline:pipeline0/GstRtpL16Pay:rtpl16pay0: timestamp = 468998694 /GstPipeline:pipeline0/GstRtpL16Pay:rtpl16pay0: seqnum = 20785 Pipeline is PREROLLED ... Setting pipeline to PLAYING ... New clock: GstSystemClock

在播放器或接收器中使用相同的参数: 接收:

gst-launch-1.0 udpsrc caps='application/x-rtp, media=(string)audio, clock-rate=(int)44100, encoding-name=(string)L16, encoding-params=(string)2, channels=(int)2, payload=(int)96' ! rtpL16depay ! pulsesink

这玩起来很完美。

在我的例子中转到 .wav 文件 transmitter 是:

gst-launch-1.0 -v filesrc location="test.wav" ! decodebin ! audioconvert ! rtpL16pay ! queue ! udpsink host=239.0.0.1 auto-multicast=true port=5004

最后一行输出:

/GstPipeline:pipeline0/GstQueue:queue0.GstPad:sink: caps = "application/x-rtp\,\ media\=(string)audio\,\ clock-rate\=(int)44100\,\ encoding-name\=(string)L16\,\ encoding-params\=(string)1\,\ channels\=(int)1\,\ payload\=(int)96\,\ ssrc\=(uint)620824608\,\ timestamp-offset\=(uint)433377669\,\ seqnum-offset\=(uint)7103" /GstPipeline:pipeline0/GstRtpL16Pay:rtpl16pay0.GstPad:sink: caps = "audio/x-raw\,\ layout\=(string)interleaved\,\ rate\=(int)44100\,\ format\=(string)S16BE\,\ channels\=(int)1" /GstPipeline:pipeline0/GstAudioConvert:audioconvert0.GstPad:sink: caps = "audio/x-raw\,\ format\=(string)S16LE\,\ layout\=(string)interleaved\,\ channels\=(int)1\,\ rate\=(int)44100" /GstPipeline:pipeline0/GstDecodeBin:decodebin0.GstDecodePad:src_0.GstProxyPad:proxypad1: caps = "audio/x-raw\,\ format\=(string)S16LE\,\ layout\=(string)interleaved\,\ channels\=(int)1\,\ rate\=(int)44100" /GstPipeline:pipeline0/GstRtpL16Pay:rtpl16pay0: timestamp = 433377669 /GstPipeline:pipeline0/GstRtpL16Pay:rtpl16pay0: seqnum = 7103 Pipeline is PREROLLED ... Setting pipeline to PLAYING ... New clock: GstSystemClock

接收器中使用此信息:

gst-launch-1.0 udpsrc caps='application/x-rtp, media=(string)audio, clock-rate=(int)44100, encoding-name=(string)L16, encoding-params=(string)1, channels=(int)1, payload=(int)96' ! rtpL16depay ! pulsesink

音频播放也很流畅。

希望对您有所帮助。