mediasoup 源码分析(六)consumer和producer

一、consumer 类型介绍

mediasoup总共有四种消费者类型,SimpleConsumer、PipeConsumer、SvcConsumer、SimucastConsumer。
consumer的类型是基于producer的类型来创建的。
SimpleConsumer: 普通RTP数据的消费者,对应PlainTransport。
PipeConsumer:不同Worker之间Router之间的数据流转,则其为接收或者消费从另外一个Worker中的Router传过来的数据。
SvcConsumer:传输时一般分为3层(核心层、拓展层、边缘层)进行传输,则其处理消费多层数据。
SimulcastConsumer :Simulcast 多播模式,即当共享者使用的是多路流时,则使用其来接收。

二、创建过程

见Transport.ts 的consume函数

async consume(
{
   producerId,
   rtpCapabilities,
   paused = false,
   preferredLayers,
   appData = {}
}: ConsumerOptions
): Promise<Consumer>
{
....
....
  //创建Consumer
  const reqData =
 {
	 kind : producer.kind,
	 rtpParameters,
	 //创建consumer时,type类型来自producer的类型  
	 //对应 Producer中的_data.type ,在Producer构造函数中创建
	 type  : producer.type,  
	 consumableRtpEncodings : producer.consumableRtpParameters.encodings,
	 paused,
	 preferredLayers
  };
 const status =await this._channel.request('transport.consume', internal, reqData);
}

producer.type来自于创建producer时c++层的返回结果,代码如下:
创建producer时指定了rtpParameters,c++层会基于该参数中的编码器信息确定producer的类型。
代码见Transport.cpp

//c++层创建producer,并把类型返回给node.js层的Transport.ts
Transport::HandleRequest(Channel::Request* request)
{
   case Channel::Request::MethodId::TRANSPORT_PRODUCE:
   {
     auto* producer = new RTC::Producer(producerId, this, request->data); 

    // Create status response.
	 json data = json::object();
     data["type"] = RTC::RtpParameters::GetTypeString(producer->GetType());
	 request->Accept(data);
     //返回producer的类型,这个返回值在Channel.ts的this._consumerSocket读取到
     //然后传给_processMessage中的sent.resolve(msg.data),这个最终返回到request()的resolve
     //最后返回给Transport.ts中创建producer的地方
   	 const status = await this._channel.request('transport.produce', internal, reqData);
     //此处的status就是上面的c++层的data。
     //又新定义一个data结构把参数传给了Producer的构造函数内部。
	 const data =
	 {
		kind,
		rtpParameters,
		type : status.type,//这个类型就是创建consumer是的producer.type
		consumableRtpParameters
	 };

   }
}
//c++层Producer的构造函数
Producer::Producer(const std::string& id, RTC::Producer::Listener* listener, json& data)
	  : id(id), listener(listener)
	{ 
		auto jsonRtpParametersIt = data.find("rtpParameters");

		if (jsonRtpParametersIt == data.end() || !jsonRtpParametersIt->is_object())
			MS_THROW_TYPE_ERROR("missing rtpParameters");

		// This may throw.
		this->rtpParameters = RTC::RtpParameters(*jsonRtpParametersIt);
          
		// Evaluate type. 基于rtpParameters获得Producer的类型
		this->type = RTC::RtpParameters::GetType(this->rtpParameters);
}
//基于rtpParameters获取producer类型的逻辑

	RtpParameters::Type RtpParameters::GetType(const RtpParameters& rtpParameters)
	{
		MS_TRACE();

		if (rtpParameters.encodings.size() == 1)
		{
			auto& encoding = rtpParameters.encodings[0];

			if (encoding.spatialLayers > 1 || encoding.temporalLayers > 1)
				return RtpParameters::Type::SVC;
			else
				return RtpParameters::Type::SIMPLE;
		}
		else if (rtpParameters.encodings.size() > 1)
		{
			return RtpParameters::Type::SIMULCAST;
		}

		return RtpParameters::Type::NONE;
	}

三、创建Producer时传进来rtpParameter

见:mediasoup-demo/server/lib/Room.js

//server.js接收到创建producer时,参数中包含rtpParameters

async createBroadcasterProducer(
	  {
		broadcasterId,
		transportId,
		kind,
		rtpParameters
		}
	)
	{
		const broadcaster = this._broadcasters.get(broadcasterId);

		if (!broadcaster)
			throw new Error(`broadcaster with id "${broadcasterId}" does not exist`);

		const transport = broadcaster.data.transports.get(transportId);

		if (!transport)
			throw new Error(`transport with id "${transportId}" does not exist`);

		const producer =
			await transport.produce({ kind, rtpParameters });
   }  
//如ffmpeg.sh,是创建的PlainTranport,其创建rtpParameter参数如下:
rtpParameters:="{ \"codecs\": [{ \"mimeType\":\"audio/opus\", \"payloadType\":${AUDIO_PT}, \"clockRate\":48000, \"channels\":2, \"parameters\":{ \"sprop-stereo\":1 } }], \"encodings\": [{ \"ssrc\":${AUDIO_SSRC} }] }" \
对照上面c++的判断producer类型的地方,此处encoding.size=1,但是没有配置spatialLayers,
所以是simple类型,和PlainTranport对应。

tips

更多关于mediasoup的文章可以进入我的专栏查看
http://t.csdnimg.cn/3UQeL

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

littleboy_IT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值