consumer和producer
- 一、consumer 类型介绍
- 二、创建过程
- 三、创建Producer时传进来rtpParameter
- tips
一、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>
{
....
....//创建Consumerconst 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.typeconsumableRtpParameters};}
}
//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;elsereturn 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时,参数中包含rtpParametersasync 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