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

4
我正在使用OPAL voip SIP堆栈开发一款voip应用程序。我重写了一个名为OpalLocalEndpoint的类,并将编码数据读取/写入到我的gstreamer流水线中。对于读取,我从appsink获取rtp payloaded数据,对于写入,我将payloaded数据推送到appsrc。
我从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交互,它可以正常工作。我猜想我可能在某个地方搞砸了 caps。有人能提供关于我应该寻找什么的任何想法吗?
我遇到了与我的其他编码器相同的问题,例如 theora,h263 等,尽管每种方式都不同。

听起来很令人兴奋,我甚至不确定我是否理解了所有细节 :-) 不过我有两个想法,你可以尝试作为实验:在你的SIP应用程序中,尝试发送一些测试模式,比如所有10101010字节,并观察另一端。 - Szocske
其次,尝试使用一些简单的网络传输工具(如netcat)测试您的媒体生成器和接收器是否正常工作。 - Szocske
@Szocske,我可以通过wireshark验证数据成功传输到另一端。我认为问题可能在于rtp数据包的分段?此外,我很好奇问题是否出现在libavcodec和ffmpeg的ffdec_h264之间的不兼容性上。此外,我实际上没有访问sip应用程序的网络传输层,因为这是由opal管理的。如果我有访问权限,我会关闭它并使用gstrtpbin与udpsink / udpsrc,并完成它。 - Jonathan Henson
Wireshark只能显示数据的一半,实验1中你想证明从RTP提取出来后,传递给媒体应用程序之前数据是完整的。 - Szocske
@Szocske OPAL的传输层处理通过套接字抓取rtp数据包,然后将未经修改的数据包传递给我,我使用Gstreamer进行解码。我不知道如何执行此测试,因为在任何情况下,我只能访问一端。我可以发送一个测试模式。我将尝试在明天使用gstreamer的videotestsrc来实现。H.264有点棘手,我不能只发送任意模式,因为有效载荷器需要从编码器获取某些数据。 - Jonathan Henson
@Szocske 我确认问题确实是OPAL的传输层。我绕过了发送RTP数据包的OPAL部分,自己通过udpsink发送它们并在udpsrc上接收它们,结果可行。因此,问题与实际流媒体无关。 - Jonathan Henson
1个回答

1
原来VOIP堆栈是一个非常优秀的堆栈,但它似乎有一个bug或者我没有理解它打包和传输RTP数据包的方式。我绕过了它,通过gstreamer udpsink和udpsrc发送数据,现在一切正常。现在我的唯一问题就是要向堆栈的开发团队提问。感谢你的帮助。

你能帮我一下吗?我有两个使用IP和UDP端口传输语音的gstreamer管道,我想以电话方式自动化传输,即一个Linux呼叫另一个Linux,在确认后,双方的管道开始语音交换。顺便说一下,我在这里问是因为我认为这与本主题相关。 - fer y
我已经为这个问题创建了一个新的提问,请查看:http://stackoverflow.com/questions/20329685/signaling-a-wi-fi-head-set - fer y

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接