static nsresult NegotiatedDetailsToVideoCodecConfigs(const JsepTrackNegotiatedDetails& aDetails, PtrVector<VideoCodecConfig>* aConfigs) { std::vector<JsepCodecDescription*> codecs(GetCodecs(aDetails)); for (const JsepCodecDescription* codec : codecs) { VideoCodecConfig* config; if (NS_FAILED(JsepCodecDescToCodecConfig(*codec, &config))) { return NS_ERROR_INVALID_ARG; } for (size_t i = 0; i < aDetails.GetEncodingCount(); ++i) { const JsepTrackEncoding& jsepEncoding(aDetails.GetEncoding(i)); if (jsepEncoding.HasFormat(codec->mDefaultPt)) { VideoCodecConfig::SimulcastEncoding encoding; encoding.rid = jsepEncoding.mRid; encoding.constraints = jsepEncoding.mConstraints; config->mSimulcastEncodings.push_back(encoding); } } aConfigs->values.push_back(config); } return NS_OK; }
static nsresult NegotiatedDetailsToAudioCodecConfigs(const JsepTrackNegotiatedDetails& aDetails, PtrVector<AudioCodecConfig>* aConfigs) { std::vector<JsepCodecDescription*> codecs(GetCodecs(aDetails)); for (const JsepCodecDescription* codec : codecs) { AudioCodecConfig* config; if (NS_FAILED(JsepCodecDescToCodecConfig(*codec, &config))) { return NS_ERROR_INVALID_ARG; } aConfigs->values.push_back(config); } return NS_OK; }
nsresult MediaPipelineFactory::GetOrCreateVideoConduit( const JsepTrackPair& aTrackPair, const JsepTrack& aTrack, RefPtr<MediaSessionConduit>* aConduitp) { if (!aTrack.GetNegotiatedDetails()) { MOZ_ASSERT(false, "Track is missing negotiated details"); return NS_ERROR_INVALID_ARG; } bool receiving = aTrack.GetDirection() == sdp::kRecv; RefPtr<VideoSessionConduit> conduit = mPCMedia->GetVideoConduit(aTrackPair.mLevel); if (!conduit) { conduit = VideoSessionConduit::Create(); if (!conduit) { MOZ_MTLOG(ML_ERROR, "Could not create video conduit"); return NS_ERROR_FAILURE; } mPCMedia->AddVideoConduit(aTrackPair.mLevel, conduit); } if (!GetBestCodec(*aTrack.GetNegotiatedDetails())) { MOZ_MTLOG(ML_ERROR, "Can't set up a conduit with 0 codecs"); return NS_ERROR_FAILURE; } size_t numCodecs = aTrack.GetNegotiatedDetails()->GetCodecCount(); bool configuredH264 = false; if (receiving) { PtrVector<VideoCodecConfig> configs; for (size_t i = 0; i < numCodecs; i++) { const JsepCodecDescription* cdesc = aTrack.GetNegotiatedDetails()->GetCodec(i); // We can only handle configuring one recv H264 codec if (configuredH264 && (cdesc->mName == "H264")) { continue; } VideoCodecConfig* configRaw; nsresult rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw); if (NS_FAILED(rv)) return rv; UniquePtr<VideoCodecConfig> config(configRaw); if (EnsureExternalCodec(*conduit, config.get(), false)) { continue; } if (cdesc->mName == "H264") { configuredH264 = true; } configs.values.push_back(config.release()); } auto error = conduit->ConfigureRecvMediaCodecs(configs.values); if (error) { MOZ_MTLOG(ML_ERROR, "ConfigureRecvMediaCodecs failed: " << error); return NS_ERROR_FAILURE; } if (!aTrackPair.mSending) { // No send track, but we still need to configure an SSRC for receiver // reports. if (!conduit->SetLocalSSRC(aTrackPair.mRecvonlySsrc)) { MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed"); return NS_ERROR_FAILURE; } } } else { // For now we only expect to have one ssrc per local track. auto ssrcs = aTrack.GetSsrcs(); if (!ssrcs.empty()) { if (!conduit->SetLocalSSRC(ssrcs.front())) { MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed"); return NS_ERROR_FAILURE; } } conduit->SetLocalCNAME(aTrack.GetCNAME().c_str()); const JsepCodecDescription* cdesc = GetBestCodec(*aTrack.GetNegotiatedDetails()); VideoCodecConfig* configRaw; nsresult rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw); if (NS_FAILED(rv)) return rv; rv = ConfigureVideoCodecMode(aTrack,*conduit); if (NS_FAILED(rv)) { return rv; } // Take possession of this pointer ScopedDeletePtr<VideoCodecConfig> config(configRaw); if (EnsureExternalCodec(*conduit, config, true)) { MOZ_MTLOG(ML_ERROR, "External codec not available"); return NS_ERROR_FAILURE; } auto error = conduit->ConfigureSendMediaCodec(config); if (error) { MOZ_MTLOG(ML_ERROR, "ConfigureSendMediaCodec failed: " << error); return NS_ERROR_FAILURE; } } *aConduitp = conduit; return NS_OK; }
nsresult MediaPipelineFactory::GetOrCreateAudioConduit( const JsepTrackPair& aTrackPair, const JsepTrack& aTrack, RefPtr<MediaSessionConduit>* aConduitp) { if (!aTrack.GetNegotiatedDetails()) { MOZ_ASSERT(false, "Track is missing negotiated details"); return NS_ERROR_INVALID_ARG; } bool receiving = aTrack.GetDirection() == sdp::kRecv; RefPtr<AudioSessionConduit> conduit = mPCMedia->GetAudioConduit(aTrackPair.mLevel); if (!conduit) { conduit = AudioSessionConduit::Create(); if (!conduit) { MOZ_MTLOG(ML_ERROR, "Could not create audio conduit"); return NS_ERROR_FAILURE; } mPCMedia->AddAudioConduit(aTrackPair.mLevel, conduit); } if (!GetBestCodec(*aTrack.GetNegotiatedDetails())) { MOZ_MTLOG(ML_ERROR, "Can't set up a conduit with 0 codecs"); return NS_ERROR_FAILURE; } size_t numCodecs = aTrack.GetNegotiatedDetails()->GetCodecCount(); if (receiving) { PtrVector<AudioCodecConfig> configs; for (size_t i = 0; i < numCodecs; i++) { const JsepCodecDescription* cdesc = aTrack.GetNegotiatedDetails()->GetCodec(i); AudioCodecConfig* configRaw; nsresult rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw); if (NS_FAILED(rv)) return rv; configs.values.push_back(configRaw); } auto error = conduit->ConfigureRecvMediaCodecs(configs.values); if (error) { MOZ_MTLOG(ML_ERROR, "ConfigureRecvMediaCodecs failed: " << error); return NS_ERROR_FAILURE; } if (!aTrackPair.mSending) { // No send track, but we still need to configure an SSRC for receiver // reports. if (!conduit->SetLocalSSRC(aTrackPair.mRecvonlySsrc)) { MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed"); return NS_ERROR_FAILURE; } } } else { // For now we only expect to have one ssrc per local track. auto ssrcs = aTrack.GetSsrcs(); if (!ssrcs.empty()) { if (!conduit->SetLocalSSRC(ssrcs.front())) { MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed"); return NS_ERROR_FAILURE; } } conduit->SetLocalCNAME(aTrack.GetCNAME().c_str()); const JsepCodecDescription* cdesc = GetBestCodec(*aTrack.GetNegotiatedDetails()); AudioCodecConfig* configRaw; nsresult rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw); if (NS_FAILED(rv)) return rv; ScopedDeletePtr<AudioCodecConfig> config(configRaw); auto error = conduit->ConfigureSendMediaCodec(config.get()); if (error) { MOZ_MTLOG(ML_ERROR, "ConfigureSendMediaCodec failed: " << error); return NS_ERROR_FAILURE; } const SdpExtmapAttributeList::Extmap* audioLevelExt = aTrack.GetNegotiatedDetails()->GetExt( "urn:ietf:params:rtp-hdrext:ssrc-audio-level"); if (audioLevelExt) { MOZ_MTLOG(ML_DEBUG, "Calling EnableAudioLevelExtension"); error = conduit->EnableAudioLevelExtension(true, audioLevelExt->entry); if (error) { MOZ_MTLOG(ML_ERROR, "EnableAudioLevelExtension failed: " << error); return NS_ERROR_FAILURE; } } } *aConduitp = conduit; return NS_OK; }