[英]Unable to set remote SDP offer for H264 encoded video on Huawei devices
I'm developing a WebRTC video call app (one-way video and two-way audio) for Android with prebuilt package org.webrtc:google-webrtc:1.0.32006
. I'm developing a WebRTC video call app (one-way video and two-way audio) for Android with prebuilt package
org.webrtc:google-webrtc:1.0.32006
. I'm stuck with an error from this lib that states:我遇到了这个库中的一个错误,该错误指出:
LS_ERROR
tag: webrtc_video_engine.cc
message: (line 745): No video codecs supported.
after trying to set a remote SDP offer:尝试设置远程 SDP 报价后:
v=0
o=- 955391267744368972 0 IN IP4 0.0.0.0
s=-
t=0 0
a=ice-options:trickle
a=group:BUNDLE video0 audio1 application2
m=video 9 UDP/TLS/RTP/SAVPF 96
c=IN IP4 0.0.0.0
a=setup:actpass
a=ice-ufrag:NwMv07hmtKD9s8EFikQCvqv7JvMpVhv4
a=ice-pwd:[xxx]
a=rtcp-mux
a=rtcp-rsize
a=sendrecv
a=rtpmap:96 H264/90000
a=rtcp-fb:96 nack pli
a=framerate:30
a=fmtp:96 packetization-mode=1;profile-level-id=42c01f;sprop-parameter-sets=J0LAH5WgKA9oQAAAAwBAAAAPOSAACYlgABqz+97gHiRNQA==,KM4fIA==
a=ssrc:2596331602 msid:user823769301@host-4c0ea8a4 webrtctransceiver0
a=ssrc:2596331602 cname:user823769301@host-4c0ea8a4
a=mid:video0
a=fingerprint:sha-256 [xxx]
m=audio 0 UDP/TLS/RTP/SAVPF 97
c=IN IP4 0.0.0.0
a=setup:actpass
a=ice-ufrag:NwMv07hmtKD9s8EFikQCvqv7JvMpVhv4
a=ice-pwd:[xxx]
a=bundle-only
a=rtcp-mux
a=rtcp-rsize
a=sendrecv
a=rtpmap:97 OPUS/48000/2
a=rtcp-fb:97 nack pli
a=fmtp:97 sprop-maxcapturerate=48000;sprop-stereo=0
a=ssrc:235675792 msid:user823769301@host-4c0ea8a4 webrtctransceiver1
a=ssrc:235675792 cname:user823769301@host-4c0ea8a4
a=mid:audio1
a=fingerprint:sha-256 [xxx]
m=application 0 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=setup:actpass
a=ice-ufrag:NwMv07hmtKD9s8EFikQCvqv7JvMpVhv4
a=ice-pwd:[xxx]
a=bundle-only
a=mid:application2
a=sctp-port:5000
a=fingerprint:sha-256 [xxx]
It gets me confused as android.media.MediaCodecList
contains OMX.google.h264
and HardwareVideoDecoderFactory::supportedCodecs
contains name: H264; params: {level-asymmetry-allowed=1, profile-level-id=42e01f, packetization-mode=1}
它让我感到困惑,因为
android.media.MediaCodecList
包含OMX.google.h264
和HardwareVideoDecoderFactory::supportedCodecs
包含name: H264; params: {level-asymmetry-allowed=1, profile-level-id=42e01f, packetization-mode=1}
name: H264; params: {level-asymmetry-allowed=1, profile-level-id=42e01f, packetization-mode=1}
I'm using Honor 7X and Huawei P10 and I'm aware that their chipsets lack the hardware H264 encoding which is fine as I do not stream any video from the Android device.我使用的是荣耀 7X 和华为 P10,我知道他们的芯片组缺少硬件 H264 编码,这很好,因为我没有 stream 来自 Android 设备的任何视频。
As a video streaming device I use RaspberryPi build with GStreamer as media processing pipeline.作为视频流设备,我使用带有 GStreamer 的 RaspberryPi 构建作为媒体处理管道。 The output of
v4l2-ctl --list-formats
: v4l2-ctl --list-formats
的 output :
Type: Video Capture
[0]: 'YU12' (Planar YUV 4:2:0)
[1]: 'YUYV' (YUYV 4:2:2)
[2]: 'RGB3' (24-bit RGB 8-8-8)
[3]: 'JPEG' (JFIF JPEG, compressed)
[4]: 'H264' (H.264, compressed)
[5]: 'MJPG' (Motion-JPEG, compressed)
[6]: 'YVYU' (YVYU 4:2:2)
[7]: 'VYUY' (VYUY 4:2:2)
[8]: 'UYVY' (UYVY 4:2:2)
[9]: 'NV12' (Y/CbCr 4:2:0)
[10]: 'BGR3' (24-bit BGR 8-8-8)
[11]: 'YV12' (Planar YVU 4:2:0)
[12]: 'NV21' (Y/CrCb 4:2:0)
[13]: 'RX24' (32-bit XBGR 8-8-8-8)
And this is my pipeline definition:这是我的管道定义:
#define RTP_CAPS_OPUS "application/x-rtp,media=audio,encoding-name=OPUS,payload="
#define RTP_CAPS_H264 "application/x-rtp,media=video,encoding-name=H264,payload="
"v4l2src ! video/x-raw,width=640,height=480,framerate=30/1 ! v4l2h264enc ! video/x-h264,level=(string)3.1,stream-format=(string)byte-stream ! h264parse ! rtph264pay ! "
"" RTP_CAPS_H264 "96 ! sendrecv. "
"alsasrc ! queue ! webrtcdsp noise-suppression-level=3 ! webrtcechoprobe ! audioamplify amplification=1 ! audioconvert ! audioresample ! queue ! opusenc ! rtpopuspay ! "
"queue ! " RTP_CAPS_OPUS "97 ! sendrecv. "
My guess is that the H264 profiles are different (RPi: 42c01f
; Huawei: 42e01f
).我的猜测是 H264 配置文件不同(RPi:
42c01f
;华为: 42e01f
)。 Also difference in the format's payload might be in a way ( 96
vs. 100
respectively), however I don't have any clue about the significance of these differences.格式有效负载的差异也可能在某种程度上(分别为
96
和100
),但是我对这些差异的重要性没有任何线索。
My second guess is that I should not set a=sendrecv
in both clients video media description, but I can't figure out how to accomplish that via WebRTC Android API.我的第二个猜测是我不应该在两个客户端的视频媒体描述中设置
a=sendrecv
,但我不知道如何通过 WebRTC Android API 来实现。 Should I put sendonly
for RPi then?那我应该为
sendonly
设置 sendonly 吗?
And finally, why should I set the VideoEncoderFactory
event though I don't encode any video?最后,虽然我没有对任何视频进行编码,但为什么要设置
VideoEncoderFactory
事件? Without explicitly passing a DefaultVideoEncoderFactory
to PeerConnection
I cannot establish any connection at all.如果没有明确地将
DefaultVideoEncoderFactory
传递给PeerConnection
,我根本无法建立任何连接。
Would you be able to point me in the right direction?你能指出我正确的方向吗? Any clues, experiences and documentation pieces are highly appreciated!
任何线索、经验和文档都非常感谢!
After some struggle we managed to fix the problem.经过一番努力,我们设法解决了这个问题。 The solution is to force the
sendonly
flag on the video media SDP part.解决方案是在视频媒体 SDP 部分强制使用
sendonly
标志。 This can be done in two ways (in my case both of these were needed to successfully bypass the lacking H264 encoder on Huawei):这可以通过两种方式完成(在我的情况下,这两种方式都需要成功绕过华为缺少的 H264 编码器):
When creating a SDP offer you can put an attribute to MediaConstraints
that will enforce proper SDP generation创建 SDP 报价时,您可以为
MediaConstraints
设置一个属性,该属性将强制生成正确的 SDP
val mediaConstraints = MediaConstraints()
mediaConstraints.mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"))
peerConnection.createOffer(observer, mediaConstraints)
This way the device will generate a list of all video formats that it could decode and put it in SDP video request with recvonly
.这样,设备将生成它可以解码的所有视频格式的列表,并将其放入带有
recvonly
的 SDP 视频请求中。
To enforce sendonly
on gstreamer side we came up with kinda hacky solution为了在 gstreamer 端强制执行
sendonly
,我们想出了一个 hacky 解决方案
GstSDPMedia *video_media = (GstSDPMedia *)offer->sdp->medias[0].data;
const GstSDPAttribute *direction_attribute = gst_sdp_media_get_attribute(video_media, 5);
gst_sdp_attribute_set(direction_attribute, "sendonly", NULL);
This results in correct attribute being set on SDP offer/answer from gstreamer and does not force the device to look for video encoders.这会导致在来自 gstreamer 的 SDP 提议/答案上设置正确的属性,并且不会强制设备查找视频编码器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.