Webrtc支持HEVC之Mediasoup SDP协商编码流程(三)

一、SDP校验

1、服务端的rtp能力配置

文件位置:cst-medias-server/core/config.js

具体内容:moduls.export-mediasoup-routerOpitions-mediaCodeces

注意事项:对于音视频codec,clinet只会使用第一个识别到的codec,因此需要把配置的编码器放到同类型的第一位

2、客户端解析服务端rtp能力

cpp 复制代码
// 通过信令像服务端请求Codec编码器信息
......
// 导入codec信息
MediaSoupClient->Load
// 加载codec信息,获取到端上支持的编码器类型
Device::Load
{
    // 解析并修改codec信息,缺失字段填入默认值
    ortc::validateRtpCapabilities(routerRtpCapabilities);
    // 获取rtp能力,包括配置的音视频codec能力(会显示所有能支持的codec能力),
    auto nativeRtpCapabilities = Handler::GetNativeRtpCapabilities(peerConnectionOptions);
    // 通过sdp协商,获取到支持的rtp能力
    // 匹配到远端和本机支持的rtp能力
    // 音频"mimeType": "audio/opus",
    // 视频"mimeType": "video/H264"、"mimeType": "video/VP8"、"mimeType": "video/VP9"
    this->extendedRtpCapabilities =
		  ortc::getExtendedRtpCapabilities(nativeRtpCapabilities, routerRtpCapabilities);
    // 是否支持音视频则用
    this->canProduceByKind["audio"] = ortc::canSend("audio", this->extendedRtpCapabilities);
	this->canProduceByKind["video"] = ortc::canSend("video", this->extendedRtpCapabilities);
    // 获取接受rtp能力,codec和extendedRtpCapabilities一致
    this->recvRtpCapabilities = ortc::getRecvRtpCapabilities(this->extendedRtpCapabilities);
}

(1)、mediasoup获取rtp能力

  • 创建一个PeerConnection,

  • 通过PeerConnection::AddTransceiver,添加音频和视频

  • 并通过PeerConnection::CreateOffer,获取SDP信息

  • 通过 Sdp::Utils::extractRtpCapabilities解析sdp获取到codce、fecMechanisms、headerExtensions能力

(2)、webrtc获取SDP-Codec信息

cpp 复制代码
// mediasoup
PeerConnection::CreateOffer
// 创建offer
SdpOfferAnswerHandler::CreateOffer
SdpOfferAnswerHandler::DoCreateOffer
// 获取headerExtensions
SdpOfferAnswerHandler::GetOptionsForOffer
// 主要是封装
WebRtcSessionDescriptionFactory::CreateOffer
MediaSessionDescriptionFactory::CreateOffer
{
....
// 获取codec的能力---这里面获取的codec有点多
MediaSessionDescriptionFactory::GetCodecsForOffer
...
// 遍历上面支持的MediaDescriptionOptions
// 添加音频编码器
AddAudioContentForOffer
{
// 通过不同类型的direction,获取到不同的编码器,并且和传入的编码器进行匹配
GetAudioCodecsForOffer
// 把编码器插入offer之中
CreateMediaContentOffer
// 插入编码器
offer->AddCodecs(codecs);
// 最终codec存放的位置为
SessionDescription-->ContentInfo->AudioContentDescription->MediaContentDescriptionImpl<AudioCodec>
}
    
// 添加视频编码器
AddVideoContentForOffer
{
// 逻辑和音频一样,最终codec存放的位置为
SessionDescription-->ContentInfo->VideoContentDescription->MediaContentDescriptionImpl<VideoCodec>
}
}

(3)、编码器获取

cpp 复制代码
// 创建PeerConnection时
PeerConnectionFactory::CreatePeerConnectionOrError
// 初始化PeerConnection
PeerConnection::Initialize
// 创建SdpOfferAnswerHandler
SdpOfferAnswerHandler::Create
// 初始化SdpOfferAnswerHandler
SdpOfferAnswerHandler::Initialize
// 创建WebRtcSessionDescriptionFactory
webrtc_session_desc_factory_ = std::make_unique<WebRtcSessionDescriptionFactory>
// 创建MediaSessionDescriptionFactory
MediaSessionDescriptionFactory()
{
	...
  	// 初始化音视频编码器
  	audio_send_codecs_ = media_engine->voice().send_codecs();
    audio_recv_codecs_ = media_engine->voice().recv_codecs();
    video_send_codecs_ = media_engine->video().send_codecs(rtx_enabled);
    video_recv_codecs_ = media_engine->video().recv_codecs(rtx_enabled);
    // 编码器分类
  	ComputeAudioCodecsIntersectionAndUnion();
  	ComputeVideoCodecsIntersectionAndUnion();
}

// 获取视频编码器
WebRtcVideoEngine::send_codecs
// 获取默认支持的codec
GetPayloadTypesAndDefaultCodecs
{
    // 获取支持的编码器
    BuiltinVideoEncoderFactory::GetSupportedFormats
    // 获取支持的编码器---配置在internal_encoder_factory.cc
    InternalEncoderFactory::GetSupportedFormats
}

二、客户端创建编码器

1、创建通道

cpp 复制代码
// 信令请求,获取transport相关信息
......
// 创建通道
TransportManager::CreateSendTransport
Device::CreateSendTransport
// 创建发生通道
SendTransport
{	 // 解析音频、视频rtp能力(官方代码只会获取一个extendedRtpCapabilities第一个编码器)
     ortc::getSendingRtpParameters("audio", *extendedRtpCapabilities)
     ortc::getSendingRtpParameters("video", *extendedRtpCapabilities)
}

2、创建Producer

cpp 复制代码
// 信令,请求producer信息
......
// 利用前面创建出来的通道,组建RtpEncodingParameters,创建producer
SendTransport::Produce
// 这里会进行sdp协商, offer来自peerconnction->CreateOffer
SendHandler::Send
{
    ......
    // 创建offer
    pc->CreateOffer(options);
    ......
    // 设置offer
    pc->SetLocalDescription(PeerConnection::SdpType::OFFER, offer);
    ......
    // local sdp
    auto localSdp       = this->pc->GetLocalDescription();
    // 解析成object
    auto localSdpObject = sdptransform::parse(localSdp);
    // 获取offer 需要的对应媒体信息
    json& offerMediaObject = localSdpObject["media"][mediaSectionIdx.idx];
    // 这里获取的只有ssrc、rtx、flexfex
    auto newEncodings = Sdp::Utils::getRtpEncodings(offerMediaObject);
    // 把前面设置的RtpEncodingParameters 编码器参数填入newEncodings编码器。
    fillJsonRtpEncodingParameters(newEncodings.front(), encodings->front());
    // 指定object
    sendingRtpParameters["encodings"] = newEncodings;
    // 获取第一个编码器类型
    auto mimeType = sendingRtpParameters["codecs"][0]["mimeType"].get<std::string>();
    // 配置设置远端sdp
    this->remoteSdp->send
    // 获取answer
    auto answer = this->remoteSdp->GetSdp();
    // 设置answer,注意此时的SDP信息中,只存在一个编码器信息
    this->pc->SetRemoteDescription(PeerConnection::SdpType::ANSWER, answer);
}

3、创建编码器

Webrtc支持HEVC之编解码器创建(二)-CSDN博客

相关推荐
憧憬成为原神糕手1 小时前
FFmpeg 音视频开发笔记(一):H.264 解码为 YUV
笔记·ffmpeg·音视频
ai产品老杨2 小时前
突破品牌壁垒:基于 GB28181 与 RTSP 的异构 AI 视频平台架构深度解析(支持 Docker 与源码交付)
人工智能·架构·音视频
AI服务老曹2 小时前
【架构深析】打破安防“黑盒”:GB28181/RTSP 视频管理平台如何通过源码交付与 API 驱动节省 95% 开发成本
架构·音视频
科研前沿2 小时前
多视角相机驱动的室内人员空间定位技术白皮书
大数据·人工智能·python·科技·数码相机·音视频
ai产品老杨3 小时前
深度解析:异构算力下的 AI 视频管理平台架构实现 (GB28181 / Docker / 源码交付)
人工智能·架构·音视频
ai产品老杨4 小时前
深度解析:基于 Docker 与 GB28181 的企业级 AI 视频管理平台——实现 X86/ARM 异构计算与全场景边缘计算架构
人工智能·docker·音视频
电子科技圈5 小时前
四大“门派”围攻边缘及端侧AI SoC市场“光明顶”
人工智能·嵌入式硬件·mcu·物联网·网络安全·音视频·语音识别
地球@+jdhb448 小时前
2026年,去豆包视频水印有哪些真正靠谱的方法?我亲自替你蹚了一遍坑
音视频
时空自由民.9 小时前
ESP ADF音频篇章
macos·音视频·xcode
ZC跨境爬虫1 天前
跟着 MDN 学 HTML day_17:媒体与 Web Audio API 自动播放指南——策略、检测与最佳实践
前端·笔记·ui·html·音视频·媒体