使用 gstreamer 和 ffmpeg 进行 H.264 解码

Posted

技术标签:

【中文标题】使用 gstreamer 和 ffmpeg 进行 H.264 解码【英文标题】:H.264 decoding using gstreamer and ffmpeg 【发布时间】:2011-12-11 07:51:10 【问题描述】:

我正在使用 OPAL voip SIP 堆栈开发一个 voip 应用程序。

我正在重写一个名为 OpalLocalEndpoint 的类,并在我的 gstreamer 管道中读取/写入编码数据。读取时,我从一个应用程序接收器中获取 rtp 负载数据,写入时我将负载数据推送到应用程序rc。

我从 wireshark 捕获了 SDP 文件。

这是应用程序的客户端。

v=0
o=- 1319058426 1 IN IP4 192.168.0.71
s=Opal SIP Session
c=IN IP4 192.168.0.71
t=0 0
m=audio 5086 RTP/AVP 125 0 8 124 101
a=sendrecv
a=rtpmap:125 Speex/16000/1
a=fmtp:125 sr=16000,mode=any
a=rtpmap:0 PCMU/8000/1
a=rtpmap:8 PCMA/8000/1
a=rtpmap:124 Speex/8000/1
a=fmtp:124 sr=8000,mode=any
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16,32,36
m=video 5088 RTP/AVP 109 108 34 114
b=AS:4096
b=TIAS:4096000
a=sendrecv
a=rtpmap:109 h264/90000
a=fmtp:109 packetization-mode=1;profile-level-id=42C01E
a=rtpmap:108 h263-1998/90000
a=fmtp:108 D=1;F=1;I=1;J=1;CIF=1;CIF4=1;QCIF=1;CUSTOM=320,240,1;CUSTOM=640,480,1
a=rtpmap:34 h263/90000
a=fmtp:34 F=1;CIF=1;CIF4=1;QCIF=1
a=rtpmap:114 MP4V-ES/90000
a=fmtp:114 profile-level-id=5

这是服务器回复客户端

v=0
o=- 1319058099 1 IN IP4 192.168.0.215
s=HHP Video Codec/1.0
c=IN IP4 192.168.0.215
t=0 0
m=audio 5006 RTP/AVP 125 0 8 124
a=inactive
a=rtpmap:125 Speex/16000/1
a=rtpmap:0 PCMU/8000/1
a=rtpmap:8 PCMA/8000/1
a=rtpmap:124 Speex/8000/1
a=maxptime:20
m=video 5004 RTP/AVP 109
b=AS:2048
b=TIAS:2048000
a=sendrecv
a=rtpmap:109 h264/90000
a=fmtp:109 packetization-mode=1;profile-level-id=42c01e

我使用以下代码对数据进行编码:

 v4l2src name=videoSrc ! video/x-raw-yuv, format=(fourcc)I420, width=352, height=288, framerate=(fraction)30/1 ! videobalance name=VideoBalance ! textoverlay name=chanNameFilter ! textoverlay name=osdMessageFilter ! textoverlay name=sessionTimerOverlay ! x264enc byte-stream=true bframes=0 b-adapt=0 tune=0x4 speed-preset=3 bitrate=256 sliced-threads=false profile=0 ! rtph264pay mtu=1412 ! appsink name=videoAppSink sync=false

并尝试用

解码传入的数据
appsrc is-live=true do-timestamp=false typefind=true name=videoAppSrc ! application/x-rtp, media=video, payload=109, clock-rate=90000, encoding-type=H264, byte-stream=true, access-unit=true ! rtph264depay ! ffdec_h264 !  xvimagesink name=videoOutputSink

但是,虽然编码数据显示在客户端上(一开始并没有,我必须添加所有这些属性,直到它最终正确显示),但我无法让解码端工作.

它显示了一个主要是灰色的屏幕,带有粉红色、黄色和绿色的光点。有时我会得到更多正确的颜色,而大多数时候只是灰色。

如果我使用相同的管道与 VLC 进行交互,它可以正常工作。我的猜测是我在某处搞砸了帽子。任何人都可以就我应该寻找什么提供任何想法吗?

我在使用其他每个编码器时也遇到了同样的问题,即 theora、h263 等……尽管每个编码器的方式不同。

【问题讨论】:

听起来令人兴奋,我什至不确定我是否了解所有细节 :-) 虽然您可以尝试作为实验,但我有两个想法: 在您的 sip 应用程序中,尝试发送一些测试模式,例如全部 10101010 字节,并在另一端观察。 其次,使用一些简单的网络传输器(如 netcat)尝试您的媒体生成器和接收器,看看它们是否有效。 @Szocske,我可以通过wireshark验证数据是否可以正常传输到另一端。我想也许问题出在 rtp 数据包碎片上?另外,我很好奇问题是否在于 libavcodec 和 ffmpeg 的 ffdec_h264 之间的某些不兼容。另外,我真的无法访问 sip 应用程序的网络传输层,因为它是由 opal 管理的。如果我可以访问,我会关闭它并使用 gstrtpbin 和 udpsink /udpsrc 并完成它。 wireshark 只向您显示数据获得了一半,在实验 1 中,您想证明数据在从 RTP 提取后以及传递到媒体应用程序之前是完整的。 @Szocske OPAL 的传输层处理通过套接字抓取 rtp 数据包,然后将我认为是未触及的数据包传递给我,我使用 Gstreamer 进行卸载。我不知道如何执行此测试,因为在任何一种情况下,我都只能访问一个端点。我可以发送一个测试模式。我将在早上使用 gstreamer 的 videotestsrc 进行尝试。 H.264 有点棘手,我不能只发送任意模式,因为载荷器需要来自编码器的某些数据。 【参考方案1】:

事实证明,VOIP 堆栈本来是一个出色的堆栈,但要么有错误,要么我不明白它打包和传输 RTP 数据包的方式。我绕过它并通过 gstreamer udpsink 和 udpsrc 发送数据,它工作正常。现在我剩下的唯一问题将直接提交给堆栈的开发团队。感谢您的帮助。

【讨论】:

你能帮帮我吗?我有两个使用 IP 和 UDP 端口传输语音的 gstreamer 管道,我想以电话方式自动传输,即一个 Linux 呼叫另一个,在确认双方的管道后开始语音交换? P.s 我在这里问这个是因为我虽然它与这个线程相关 我为这个问题创建了一个新问题。请查看:***.com/questions/20329685/signaling-a-wi-fi-head-set

以上是关于使用 gstreamer 和 ffmpeg 进行 H.264 解码的主要内容,如果未能解决你的问题,请参考以下文章

gstreamer入门和概述

gstreamer入门和概述

gstreamer入门和概述

gstreamer入门和概述

[ubuntu][原创]ubuntu16.04 安装gstreamer0.10-ffmpeg正确方法

OneVPL与FFmpeg/GStreamer硬件编解码器