使用 Webrtc h264 支持为 Android 构建 Chromium
Building Chromium for Android with Webrtc h264 support
我正在尝试在 webrtc 中构建支持 h264 的 Chromium Android。我的理解是下面的 args.gn 文件应该可以满足我的要求。
target_os = "android"
target_cpu = "arm64"
proprietary_codecs = true
ffmpeg_branding = "Chrome"
但是,当我在我的 Pixel 3 上安装 APK 时,使用 chrome://inspect 从我的桌面进行调试,运行 new RTCPeerConnection().createOffer({offerToReceiveVideo: true}).then(s => console.log(s.sdp))
我只看到 VP8 和 VP9 编解码器.
我还有什么遗漏的吗?
我最终不得不更改代码以获得我想要的行为。
设置这些构建标志会导致 GPU 进程回答 "Yes, I support H264 video decoding" 任何查询 https://cs.chromium.org/chromium/src/media/gpu/android/media_codec_video_decoder.cc?q=proprietary_codecs&sq=package:chromium&dr=C&l=154
然而,webrtc 对支持的编解码器的定义来自这个函数,它只是轮询编码器支持的格式。 https://webrtc.googlesource.com/src/+/refs/heads/master/media/engine/webrtc_video_engine.cc#142。所以看起来虽然我的 Pixel 3 支持 H264 解码,但它不支持编码,因此 webrtc 认为它是一种不受支持的格式。有趣的是,Chrome 运行 在完全相同的设备上确实支持 webrtc H264。
我只想接收 H264 视频,所以我编辑了此函数,为 Chrome 支持的每种 H264 格式添加了 webrtc::SdpVideoFormat。
+static void AddH264Formats(std::vector<webrtc::SdpVideoFormat>& formats) {
+ webrtc::SdpVideoFormat h264Format(kH264CodecName, {
+ {cricket::kH264FmtpLevelAsymmetryAllowed, "1"}});
+
+ h264Format.parameters[cricket::kH264FmtpProfileLevelId] = "42001f";
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "1";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "0";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+
+ h264Format.parameters[cricket::kH264FmtpProfileLevelId] = "42e01f";
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "1";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "0";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+
+ h264Format.parameters[cricket::kH264FmtpProfileLevelId] = "4d0032";
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "1";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "0";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+}
+
std::vector<VideoCodec> AssignPayloadTypesAndDefaultCodecs(
const webrtc::VideoEncoderFactory* encoder_factory) {
- return encoder_factory ? AssignPayloadTypesAndDefaultCodecs(
- encoder_factory->GetSupportedFormats())
- : std::vector<VideoCodec>();
+ auto formats = encoder_factory->GetSupportedFormats();
+ AddH264Formats(formats);
+
+ return AssignPayloadTypesAndDefaultCodecs(formats);
}
我想我可以编辑 GpuVideoAcceleratorFactoriesImpl::GetVideoEncodeAcceleratorSupportedProfiles
而不是编辑 webrtc 代码。以这种方式编辑 GpuVideoAcceleratorFactoriesImpl 可能不太正确,但它可以让我分叉 Chromium 而不必弄乱 third_party 存储库。
我正在尝试在 webrtc 中构建支持 h264 的 Chromium Android。我的理解是下面的 args.gn 文件应该可以满足我的要求。
target_os = "android"
target_cpu = "arm64"
proprietary_codecs = true
ffmpeg_branding = "Chrome"
但是,当我在我的 Pixel 3 上安装 APK 时,使用 chrome://inspect 从我的桌面进行调试,运行 new RTCPeerConnection().createOffer({offerToReceiveVideo: true}).then(s => console.log(s.sdp))
我只看到 VP8 和 VP9 编解码器.
我还有什么遗漏的吗?
我最终不得不更改代码以获得我想要的行为。
设置这些构建标志会导致 GPU 进程回答 "Yes, I support H264 video decoding" 任何查询 https://cs.chromium.org/chromium/src/media/gpu/android/media_codec_video_decoder.cc?q=proprietary_codecs&sq=package:chromium&dr=C&l=154
然而,webrtc 对支持的编解码器的定义来自这个函数,它只是轮询编码器支持的格式。 https://webrtc.googlesource.com/src/+/refs/heads/master/media/engine/webrtc_video_engine.cc#142。所以看起来虽然我的 Pixel 3 支持 H264 解码,但它不支持编码,因此 webrtc 认为它是一种不受支持的格式。有趣的是,Chrome 运行 在完全相同的设备上确实支持 webrtc H264。
我只想接收 H264 视频,所以我编辑了此函数,为 Chrome 支持的每种 H264 格式添加了 webrtc::SdpVideoFormat。
+static void AddH264Formats(std::vector<webrtc::SdpVideoFormat>& formats) {
+ webrtc::SdpVideoFormat h264Format(kH264CodecName, {
+ {cricket::kH264FmtpLevelAsymmetryAllowed, "1"}});
+
+ h264Format.parameters[cricket::kH264FmtpProfileLevelId] = "42001f";
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "1";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "0";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+
+ h264Format.parameters[cricket::kH264FmtpProfileLevelId] = "42e01f";
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "1";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "0";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+
+ h264Format.parameters[cricket::kH264FmtpProfileLevelId] = "4d0032";
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "1";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+ h264Format.parameters[cricket::kH264FmtpPacketizationMode] = "0";
+ if(std::find(formats.begin(), formats.end(), h264Format) == formats.end()) {
+ formats.push_back(h264Format);
+ }
+}
+
std::vector<VideoCodec> AssignPayloadTypesAndDefaultCodecs(
const webrtc::VideoEncoderFactory* encoder_factory) {
- return encoder_factory ? AssignPayloadTypesAndDefaultCodecs(
- encoder_factory->GetSupportedFormats())
- : std::vector<VideoCodec>();
+ auto formats = encoder_factory->GetSupportedFormats();
+ AddH264Formats(formats);
+
+ return AssignPayloadTypesAndDefaultCodecs(formats);
}
我想我可以编辑 GpuVideoAcceleratorFactoriesImpl::GetVideoEncodeAcceleratorSupportedProfiles
而不是编辑 webrtc 代码。以这种方式编辑 GpuVideoAcceleratorFactoriesImpl 可能不太正确,但它可以让我分叉 Chromium 而不必弄乱 third_party 存储库。