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::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); } PtrVector<VideoCodecConfig> configs; nsresult rv = NegotiatedDetailsToVideoCodecConfigs( *aTrack.GetNegotiatedDetails(), &configs); if (NS_FAILED(rv)) { MOZ_MTLOG(ML_ERROR, "Failed to convert JsepCodecDescriptions to " "VideoCodecConfigs."); return rv; } if (configs.values.empty()) { MOZ_MTLOG(ML_ERROR, "Can't set up a conduit with 0 codecs"); return NS_ERROR_FAILURE; } if (receiving) { // Prune out stuff we cannot actually do. We should work to eliminate the // need for this. bool configuredH264 = false; for (size_t i = 0; i < configs.values.size();) { // TODO(bug 1200768): We can only handle configuring one recv H264 codec if (configuredH264 && (configs.values[i]->mName == "H264")) { delete configs.values[i]; configs.values.erase(configs.values.begin() + i); continue; } // TODO(bug 1018791): This really should be checked sooner if (EnsureExternalCodec(*conduit, configs.values[i], false)) { delete configs.values[i]; configs.values.erase(configs.values.begin() + i); continue; } if (configs.values[i]->mName == "H264") { configuredH264 = true; } ++i; } 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()); rv = ConfigureVideoCodecMode(aTrack,*conduit); if (NS_FAILED(rv)) { return rv; } // TODO(bug 1018791): This really should be checked sooner if (EnsureExternalCodec(*conduit, configs.values[0], true)) { MOZ_MTLOG(ML_ERROR, "External codec not available"); return NS_ERROR_FAILURE; } auto error = conduit->ConfigureSendMediaCodec(configs.values[0]); if (error) { MOZ_MTLOG(ML_ERROR, "ConfigureSendMediaCodec failed: " << error); return NS_ERROR_FAILURE; } } *aConduitp = conduit; return NS_OK; }