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