MediaConduitErrorCode WebrtcVideoConduit::ConfigureRecvMediaCodecs( const std::vector<VideoCodecConfig* >& codecConfigList) { CSFLogDebug(logTag, "%s ", __FUNCTION__); MediaConduitErrorCode condError = kMediaConduitNoError; bool success = false; std::string payloadName; condError = StopReceiving(); if (condError != kMediaConduitNoError) { return condError; } if(codecConfigList.empty()) { CSFLogError(logTag, "%s Zero number of codecs to configure", __FUNCTION__); return kMediaConduitMalformedArgument; } webrtc::ViEKeyFrameRequestMethod kf_request = webrtc::kViEKeyFrameRequestNone; bool use_nack_basic = false; //Try Applying the codecs in the list // we treat as success if atleast one codec was applied and reception was // started successfully. for(std::vector<VideoCodecConfig*>::size_type i=0;i < codecConfigList.size();i++) { //if the codec param is invalid or diplicate, return error if((condError = ValidateCodecConfig(codecConfigList[i],false)) != kMediaConduitNoError) { return condError; } // Check for the keyframe request type: PLI is preferred // over FIR, and FIR is preferred over none. if (codecConfigList[i]->RtcpFbNackIsSet("pli")) { kf_request = webrtc::kViEKeyFrameRequestPliRtcp; } else if(kf_request == webrtc::kViEKeyFrameRequestNone && codecConfigList[i]->RtcpFbCcmIsSet("fir")) { kf_request = webrtc::kViEKeyFrameRequestFirRtcp; } // Check whether NACK is requested if(codecConfigList[i]->RtcpFbNackIsSet("")) { use_nack_basic = true; } webrtc::VideoCodec video_codec; memset(&video_codec, 0, sizeof(webrtc::VideoCodec)); if (mExternalRecvCodec && codecConfigList[i]->mType == mExternalRecvCodec->mType) { CSFLogError(logTag, "%s Configuring External H264 Receive Codec", __FUNCTION__); // XXX Do we need a separate setting for receive maxbitrate? Is it // different for hardware codecs? For now assume symmetry. CodecConfigToWebRTCCodec(codecConfigList[i], video_codec); // values SetReceiveCodec() cares about are name, type, maxbitrate if(mPtrViECodec->SetReceiveCodec(mChannel,video_codec) == -1) { CSFLogError(logTag, "%s Invalid Receive Codec %d ", __FUNCTION__, mPtrViEBase->LastError()); } else { CSFLogError(logTag, "%s Successfully Set the codec %s", __FUNCTION__, codecConfigList[i]->mName.c_str()); if(CopyCodecToDB(codecConfigList[i])) { success = true; } else { CSFLogError(logTag,"%s Unable to update Codec Database", __FUNCTION__); return kMediaConduitUnknownError; } } } else { //Retrieve pre-populated codec structure for our codec. for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++) { if(mPtrViECodec->GetCodec(idx, video_codec) == 0) { payloadName = video_codec.plName; if(codecConfigList[i]->mName.compare(payloadName) == 0) { CodecConfigToWebRTCCodec(codecConfigList[i], video_codec); if(mPtrViECodec->SetReceiveCodec(mChannel,video_codec) == -1) { CSFLogError(logTag, "%s Invalid Receive Codec %d ", __FUNCTION__, mPtrViEBase->LastError()); } else { CSFLogError(logTag, "%s Successfully Set the codec %s", __FUNCTION__, codecConfigList[i]->mName.c_str()); if(CopyCodecToDB(codecConfigList[i])) { success = true; } else { CSFLogError(logTag,"%s Unable to update Codec Database", __FUNCTION__); return kMediaConduitUnknownError; } } break; //we found a match } } }//end for codeclist } }//end for if(!success) { CSFLogError(logTag, "%s Setting Receive Codec Failed ", __FUNCTION__); return kMediaConduitInvalidReceiveCodec; } if (!mVideoCodecStat) { mVideoCodecStat = new VideoCodecStatistics(mChannel, mPtrViECodec); } mVideoCodecStat->Register(false); // XXX Currently, we gather up all of the feedback types that the remote // party indicated it supports for all video codecs and configure the entire // conduit based on those capabilities. This is technically out of spec, // as these values should be configured on a per-codec basis. However, // the video engine only provides this API on a per-conduit basis, so that's // how we have to do it. The approach of considering the remote capablities // for the entire conduit to be a union of all remote codec capabilities // (rather than the more conservative approach of using an intersection) // is made to provide as many feedback mechanisms as are likely to be // processed by the remote party (and should be relatively safe, since the // remote party is required to ignore feedback types that it does not // understand). // // Note that our configuration uses this union of remote capabilites as // input to the configuration. It is not isomorphic to the configuration. // For example, it only makes sense to have one frame request mechanism // active at a time; so, if the remote party indicates more than one // supported mechanism, we're only configuring the one we most prefer. // // See http://code.google.com/p/webrtc/issues/detail?id=2331 if (kf_request != webrtc::kViEKeyFrameRequestNone) { CSFLogDebug(logTag, "Enabling %s frame requests for video stream\n", (kf_request == webrtc::kViEKeyFrameRequestPliRtcp ? "PLI" : "FIR")); if(mPtrRTP->SetKeyFrameRequestMethod(mChannel, kf_request) != 0) { CSFLogError(logTag, "%s KeyFrameRequest Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitKeyFrameRequestError; } } switch (kf_request) { case webrtc::kViEKeyFrameRequestNone: mFrameRequestMethod = FrameRequestNone; break; case webrtc::kViEKeyFrameRequestPliRtcp: mFrameRequestMethod = FrameRequestPli; break; case webrtc::kViEKeyFrameRequestFirRtcp: mFrameRequestMethod = FrameRequestFir; break; default: MOZ_ASSERT(PR_FALSE); mFrameRequestMethod = FrameRequestUnknown; } if(use_nack_basic) { CSFLogDebug(logTag, "Enabling NACK (recv) for video stream\n"); if (mPtrRTP->SetNACKStatus(mChannel, true) != 0) { CSFLogError(logTag, "%s NACKStatus Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitNACKStatusError; } } mUsingNackBasic = use_nack_basic; condError = StartReceiving(); if (condError != kMediaConduitNoError) { return condError; } // by now we should be successfully started the reception mPtrRTP->SetRembStatus(mChannel, false, true); DumpCodecDB(); return kMediaConduitNoError; }
MediaConduitErrorCode WebrtcAudioConduit::ConfigureRecvMediaCodecs( const std::vector<AudioCodecConfig*>& codecConfigList) { CSFLogDebug(logTag, "%s ", __FUNCTION__); MediaConduitErrorCode condError = kMediaConduitNoError; int error = 0; //webrtc engine errors bool success = false; // Are we receiving already? If so, stop receiving and playout // since we can't apply new recv codec when the engine is playing. if(mEngineReceiving) { CSFLogDebug(logTag, "%s Engine Already Receiving. Attemping to Stop ", __FUNCTION__); // AudioEngine doesn't fail fatally on stopping reception. Ref:voe_errors.h. // hence we need not be strict in failing here on errors mPtrVoEBase->StopReceive(mChannel); CSFLogDebug(logTag, "%s Attemping to Stop playout ", __FUNCTION__); if(mPtrVoEBase->StopPlayout(mChannel) == -1) { if( mPtrVoEBase->LastError() == VE_CANNOT_STOP_PLAYOUT) { CSFLogDebug(logTag, "%s Stop-Playout Failed %d", __FUNCTION__, mPtrVoEBase->LastError()); return kMediaConduitPlayoutError; } } } mEngineReceiving = false; if(codecConfigList.empty()) { CSFLogError(logTag, "%s Zero number of codecs to configure", __FUNCTION__); return kMediaConduitMalformedArgument; } // Try Applying the codecs in the list. // We succeed if at least one codec was applied and reception was // started successfully. for(std::vector<AudioCodecConfig*>::size_type i=0 ;i<codecConfigList.size();i++) { //if the codec param is invalid or diplicate, return error if((condError = ValidateCodecConfig(codecConfigList[i],false)) != kMediaConduitNoError) { return condError; } webrtc::CodecInst cinst; if(!CodecConfigToWebRTCCodec(codecConfigList[i],cinst)) { CSFLogError(logTag,"%s CodecConfig to WebRTC Codec Failed ",__FUNCTION__); continue; } if(mPtrVoECodec->SetRecPayloadType(mChannel,cinst) == -1) { error = mPtrVoEBase->LastError(); CSFLogError(logTag, "%s SetRecvCodec Failed %d ",__FUNCTION__, error); continue; } else { CSFLogDebug(logTag, "%s Successfully Set RecvCodec %s", __FUNCTION__, codecConfigList[i]->mName.c_str()); //copy this to local database if(CopyCodecToDB(codecConfigList[i])) { success = true; } else { CSFLogError(logTag,"%s Unable to updated Codec Database", __FUNCTION__); return kMediaConduitUnknownError; } } } //end for if(!success) { CSFLogError(logTag, "%s Setting Receive Codec Failed ", __FUNCTION__); return kMediaConduitInvalidReceiveCodec; } //If we are here, atleast one codec should have been set if(mPtrVoEBase->StartReceive(mChannel) == -1) { error = mPtrVoEBase->LastError(); CSFLogError(logTag , "%s StartReceive Failed %d ",__FUNCTION__, error); if(error == VE_RECV_SOCKET_ERROR) { return kMediaConduitSocketError; } return kMediaConduitUnknownError; } if(mPtrVoEBase->StartPlayout(mChannel) == -1) { CSFLogError(logTag, "%s Starting playout Failed", __FUNCTION__); return kMediaConduitPlayoutError; } //we should be good here for setting this. mEngineReceiving = true; DumpCodecDB(); return kMediaConduitNoError; }
/** * Note: Setting the send-codec on the Video Engine will restart the encoder, * sets up new SSRC and reset RTP_RTCP module with the new codec setting. * * Note: this is called from MainThread, and the codec settings are read on * videoframe delivery threads (i.e in SendVideoFrame(). With * renegotiation/reconfiguration, this now needs a lock! Alternatively * changes could be queued until the next frame is delivered using an * Atomic pointer and swaps. */ MediaConduitErrorCode WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig) { CSFLogDebug(logTag, "%s for %s", __FUNCTION__, codecConfig ? codecConfig->mName.c_str() : "<null>"); bool codecFound = false; MediaConduitErrorCode condError = kMediaConduitNoError; int error = 0; //webrtc engine errors webrtc::VideoCodec video_codec; std::string payloadName; memset(&video_codec, 0, sizeof(video_codec)); { //validate basic params if((condError = ValidateCodecConfig(codecConfig,true)) != kMediaConduitNoError) { return condError; } } condError = StopTransmitting(); if (condError != kMediaConduitNoError) { return condError; } if (mExternalSendCodec && codecConfig->mType == mExternalSendCodec->mType) { CSFLogError(logTag, "%s Configuring External H264 Send Codec", __FUNCTION__); // width/height will be overridden on the first frame video_codec.width = 320; video_codec.height = 240; #ifdef MOZ_WEBRTC_OMX if (codecConfig->mType == webrtc::kVideoCodecH264) { video_codec.resolution_divisor = 16; } else { video_codec.resolution_divisor = 1; // We could try using it to handle odd resolutions } #else video_codec.resolution_divisor = 1; // We could try using it to handle odd resolutions #endif video_codec.qpMax = 56; video_codec.numberOfSimulcastStreams = 1; video_codec.mode = webrtc::kRealtimeVideo; codecFound = true; } else { // we should be good here to set the new codec. for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++) { if(0 == mPtrViECodec->GetCodec(idx, video_codec)) { payloadName = video_codec.plName; if(codecConfig->mName.compare(payloadName) == 0) { // Note: side-effect of this is that video_codec is filled in // by GetCodec() codecFound = true; break; } } }//for } if(codecFound == false) { CSFLogError(logTag, "%s Codec Mismatch ", __FUNCTION__); return kMediaConduitInvalidSendCodec; } // Note: only for overriding parameters from GetCodec()! CodecConfigToWebRTCCodec(codecConfig, video_codec); if(mPtrViECodec->SetSendCodec(mChannel, video_codec) == -1) { error = mPtrViEBase->LastError(); if(error == kViECodecInvalidCodec) { CSFLogError(logTag, "%s Invalid Send Codec", __FUNCTION__); return kMediaConduitInvalidSendCodec; } CSFLogError(logTag, "%s SetSendCodec Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } if (!mVideoCodecStat) { mVideoCodecStat = new VideoCodecStatistics(mChannel, mPtrViECodec); } mVideoCodecStat->Register(true); mSendingWidth = 0; mSendingHeight = 0; mSendingFramerate = video_codec.maxFramerate; if(codecConfig->RtcpFbNackIsSet("")) { CSFLogDebug(logTag, "Enabling NACK (send) for video stream\n"); if (mPtrRTP->SetNACKStatus(mChannel, true) != 0) { CSFLogError(logTag, "%s NACKStatus Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitNACKStatusError; } } condError = StartTransmitting(); if (condError != kMediaConduitNoError) { return condError; } { MutexAutoLock lock(mCodecMutex); //Copy the applied config for future reference. mCurSendCodecConfig = new VideoCodecConfig(*codecConfig); } mPtrRTP->SetRembStatus(mChannel, true, false); return kMediaConduitNoError; }
MediaConduitErrorCode WebrtcVideoConduit::ConfigureRecvMediaCodecs( const std::vector<VideoCodecConfig* >& codecConfigList) { CSFLogDebug(logTag, "%s ", __FUNCTION__); MediaConduitErrorCode condError = kMediaConduitNoError; int error = 0; //webrtc engine errors bool success = false; std::string payloadName; if(mEngineReceiving) { CSFLogDebug(logTag, "%s Engine Already Receiving . Attemping to Stop ", __FUNCTION__); if(mPtrViEBase->StopReceive(mChannel) == -1) { error = mPtrViEBase->LastError(); if(error == kViEBaseUnknownError) { CSFLogDebug(logTag, "%s StopReceive() Success ", __FUNCTION__); mEngineReceiving = false; } else { CSFLogError(logTag, "%s StopReceive() Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } } } if(codecConfigList.empty()) { CSFLogError(logTag, "%s Zero number of codecs to configure", __FUNCTION__); return kMediaConduitMalformedArgument; } //Try Applying the codecs in the list // we treat as success if atleast one codec was applied and reception was // started successfully. for(std::vector<VideoCodecConfig*>::size_type i=0;i < codecConfigList.size();i++) { //if the codec param is invalid or diplicate, return error if((condError = ValidateCodecConfig(codecConfigList[i],false)) != kMediaConduitNoError) { return condError; } webrtc::VideoCodec video_codec; mEngineReceiving = false; memset(&video_codec, 0, sizeof(webrtc::VideoCodec)); //Retrieve pre-populated codec structure for our codec. for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++) { if(mPtrViECodec->GetCodec(idx, video_codec) == 0) { payloadName = video_codec.plName; if(codecConfigList[i]->mName.compare(payloadName) == 0) { CodecConfigToWebRTCCodec(codecConfigList[i], video_codec); if(mPtrViECodec->SetReceiveCodec(mChannel,video_codec) == -1) { CSFLogError(logTag, "%s Invalid Receive Codec %d ", __FUNCTION__, mPtrViEBase->LastError()); } else { CSFLogError(logTag, "%s Successfully Set the codec %s", __FUNCTION__, codecConfigList[i]->mName.c_str()); if(CopyCodecToDB(codecConfigList[i])) { success = true; } else { CSFLogError(logTag,"%s Unable to updated Codec Database", __FUNCTION__); return kMediaConduitUnknownError; } } break; //we found a match } } }//end for codeclist }//end for if(!success) { CSFLogError(logTag, "%s Setting Receive Codec Failed ", __FUNCTION__); return kMediaConduitInvalidReceiveCodec; } //Start Receive on the video engine if(mPtrViEBase->StartReceive(mChannel) == -1) { error = mPtrViEBase->LastError(); CSFLogError(logTag, "%s Start Receive Error %d ", __FUNCTION__, error); return kMediaConduitUnknownError; } // by now we should be successfully started the reception mEngineReceiving = true; DumpCodecDB(); return kMediaConduitNoError; }
MediaConduitErrorCode WebrtcAudioConduit::ConfigureSendMediaCodec(const AudioCodecConfig* codecConfig) { CSFLogDebug(logTag, "%s ", __FUNCTION__); MediaConduitErrorCode condError = kMediaConduitNoError; int error = 0;//webrtc engine errors webrtc::CodecInst cinst; //validate codec param if((condError = ValidateCodecConfig(codecConfig, true)) != kMediaConduitNoError) { return condError; } //are we transmitting already, stop and apply the send codec if(mEngineTransmitting) { CSFLogDebug(logTag, "%s Engine Already Sending. Attemping to Stop ", __FUNCTION__); if(mPtrVoEBase->StopSend(mChannel) == -1) { CSFLogError(logTag, "%s StopSend() Failed %d ", __FUNCTION__, mPtrVoEBase->LastError()); return kMediaConduitUnknownError; } } mEngineTransmitting = false; if(!CodecConfigToWebRTCCodec(codecConfig,cinst)) { CSFLogError(logTag,"%s CodecConfig to WebRTC Codec Failed ",__FUNCTION__); return kMediaConduitMalformedArgument; } if(mPtrVoECodec->SetSendCodec(mChannel, cinst) == -1) { error = mPtrVoEBase->LastError(); CSFLogError(logTag, "%s SetSendCodec - Invalid Codec %d ",__FUNCTION__, error); if(error == VE_CANNOT_SET_SEND_CODEC || error == VE_CODEC_ERROR) { CSFLogError(logTag, "%s Invalid Send Codec", __FUNCTION__); return kMediaConduitInvalidSendCodec; } CSFLogError(logTag, "%s SetSendCodec Failed %d ", __FUNCTION__, mPtrVoEBase->LastError()); return kMediaConduitUnknownError; } #ifdef MOZILLA_INTERNAL_API // TEMPORARY - see bug 694814 comment 2 nsresult rv; nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs); if (branch) { int32_t aec = 0; // 0 == unchanged bool aec_on = false; branch->GetBoolPref("media.peerconnection.aec_enabled", &aec_on); branch->GetIntPref("media.peerconnection.aec", &aec); CSFLogDebug(logTag,"Audio config: aec: %d", aec_on ? aec : -1); mEchoOn = aec_on; if (static_cast<webrtc::EcModes>(aec) != webrtc::kEcUnchanged) mEchoCancel = static_cast<webrtc::EcModes>(aec); branch->GetIntPref("media.peerconnection.capture_delay", &mCaptureDelay); } } #endif if (0 != (error = mPtrVoEProcessing->SetEcStatus(mEchoOn, mEchoCancel))) { CSFLogError(logTag,"%s Error setting EVStatus: %d ",__FUNCTION__, error); return kMediaConduitUnknownError; } //Let's Send Transport State-machine on the Engine if(mPtrVoEBase->StartSend(mChannel) == -1) { error = mPtrVoEBase->LastError(); CSFLogError(logTag, "%s StartSend failed %d", __FUNCTION__, error); return kMediaConduitUnknownError; } //Copy the applied config for future reference. delete mCurSendCodecConfig; mCurSendCodecConfig = new AudioCodecConfig(codecConfig->mType, codecConfig->mName, codecConfig->mFreq, codecConfig->mPacSize, codecConfig->mChannels, codecConfig->mRate, codecConfig->mLoadManager); mEngineTransmitting = true; return kMediaConduitNoError; }
MediaConduitErrorCode WebrtcVideoConduit::ConfigureRecvMediaCodecs( const std::vector<VideoCodecConfig* >& codecConfigList) { CSFLogDebug(logTag, "%s ", __FUNCTION__); MediaConduitErrorCode condError = kMediaConduitNoError; int error = 0; //webrtc engine errors bool success = false; std::string payloadName; // are we receiving already? If so, stop receiving and playout // since we can't apply new recv codec when the engine is playing. if(mEngineReceiving) { CSFLogDebug(logTag, "%s Engine Already Receiving . Attemping to Stop ", __FUNCTION__); if(mPtrViEBase->StopReceive(mChannel) == -1) { error = mPtrViEBase->LastError(); if(error == kViEBaseUnknownError) { CSFLogDebug(logTag, "%s StopReceive() Success ", __FUNCTION__); mEngineReceiving = false; } else { CSFLogError(logTag, "%s StopReceive() Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } } } mEngineReceiving = false; if(codecConfigList.empty()) { CSFLogError(logTag, "%s Zero number of codecs to configure", __FUNCTION__); return kMediaConduitMalformedArgument; } webrtc::ViEKeyFrameRequestMethod kf_request = webrtc::kViEKeyFrameRequestNone; bool use_nack_basic = false; //Try Applying the codecs in the list // we treat as success if atleast one codec was applied and reception was // started successfully. for(std::vector<VideoCodecConfig*>::size_type i=0;i < codecConfigList.size();i++) { //if the codec param is invalid or diplicate, return error if((condError = ValidateCodecConfig(codecConfigList[i],false)) != kMediaConduitNoError) { return condError; } // Check for the keyframe request type: PLI is preferred // over FIR, and FIR is preferred over none. if (codecConfigList[i]->RtcpFbIsSet(SDP_RTCP_FB_NACK_PLI)) { kf_request = webrtc::kViEKeyFrameRequestPliRtcp; } else if(kf_request == webrtc::kViEKeyFrameRequestNone && codecConfigList[i]->RtcpFbIsSet(SDP_RTCP_FB_CCM_FIR)) { kf_request = webrtc::kViEKeyFrameRequestFirRtcp; } // Check whether NACK is requested if(codecConfigList[i]->RtcpFbIsSet(SDP_RTCP_FB_NACK_BASIC)) { use_nack_basic = true; } webrtc::VideoCodec video_codec; mEngineReceiving = false; memset(&video_codec, 0, sizeof(webrtc::VideoCodec)); //Retrieve pre-populated codec structure for our codec. for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++) { if(mPtrViECodec->GetCodec(idx, video_codec) == 0) { payloadName = video_codec.plName; if(codecConfigList[i]->mName.compare(payloadName) == 0) { CodecConfigToWebRTCCodec(codecConfigList[i], video_codec); if(mPtrViECodec->SetReceiveCodec(mChannel,video_codec) == -1) { CSFLogError(logTag, "%s Invalid Receive Codec %d ", __FUNCTION__, mPtrViEBase->LastError()); } else { CSFLogError(logTag, "%s Successfully Set the codec %s", __FUNCTION__, codecConfigList[i]->mName.c_str()); if(CopyCodecToDB(codecConfigList[i])) { success = true; } else { CSFLogError(logTag,"%s Unable to updated Codec Database", __FUNCTION__); return kMediaConduitUnknownError; } } break; //we found a match } } }//end for codeclist }//end for if(!success) { CSFLogError(logTag, "%s Setting Receive Codec Failed ", __FUNCTION__); return kMediaConduitInvalidReceiveCodec; } // XXX Currently, we gather up all of the feedback types that the remote // party indicated it supports for all video codecs and configure the entire // conduit based on those capabilities. This is technically out of spec, // as these values should be configured on a per-codec basis. However, // the video engine only provides this API on a per-conduit basis, so that's // how we have to do it. The approach of considering the remote capablities // for the entire conduit to be a union of all remote codec capabilities // (rather than the more conservative approach of using an intersection) // is made to provide as many feedback mechanisms as are likely to be // processed by the remote party (and should be relatively safe, since the // remote party is required to ignore feedback types that it does not // understand). // // Note that our configuration uses this union of remote capabilites as // input to the configuration. It is not isomorphic to the configuration. // For example, it only makes sense to have one frame request mechanism // active at a time; so, if the remote party indicates more than one // supported mechanism, we're only configuring the one we most prefer. // // See http://code.google.com/p/webrtc/issues/detail?id=2331 if (kf_request != webrtc::kViEKeyFrameRequestNone) { CSFLogDebug(logTag, "Enabling %s frame requests for video stream\n", (kf_request == webrtc::kViEKeyFrameRequestPliRtcp ? "PLI" : "FIR")); if(mPtrRTP->SetKeyFrameRequestMethod(mChannel, kf_request) != 0) { CSFLogError(logTag, "%s KeyFrameRequest Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitKeyFrameRequestError; } } switch (kf_request) { case webrtc::kViEKeyFrameRequestNone: mFrameRequestMethod = FrameRequestNone; break; case webrtc::kViEKeyFrameRequestPliRtcp: mFrameRequestMethod = FrameRequestPli; break; case webrtc::kViEKeyFrameRequestFirRtcp: mFrameRequestMethod = FrameRequestFir; break; default: MOZ_ASSERT(PR_FALSE); mFrameRequestMethod = FrameRequestUnknown; } if(use_nack_basic) { CSFLogDebug(logTag, "Enabling NACK (recv) for video stream\n"); if (mPtrRTP->SetNACKStatus(mChannel, true) != 0) { CSFLogError(logTag, "%s NACKStatus Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitNACKStatusError; } } mUsingNackBasic = use_nack_basic; //Start Receive on the video engine if(mPtrViEBase->StartReceive(mChannel) == -1) { error = mPtrViEBase->LastError(); CSFLogError(logTag, "%s Start Receive Error %d ", __FUNCTION__, error); return kMediaConduitUnknownError; } #ifdef MOZILLA_INTERNAL_API if (NS_IsMainThread()) { nsresult rv; nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs); if (branch) { branch->GetBoolPref("media.video.test_latency", &mVideoLatencyTestEnable); } } } #endif // by now we should be successfully started the reception mPtrRTP->SetRembStatus(mChannel, false, true); mEngineReceiving = true; DumpCodecDB(); return kMediaConduitNoError; }
/** * Note: Setting the send-codec on the Video Engine will restart the encoder, * sets up new SSRC and reset RTP_RTCP module with the new codec setting. */ MediaConduitErrorCode WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig) { CSFLogDebug(logTag, "%s ", __FUNCTION__); bool codecFound = false; MediaConduitErrorCode condError = kMediaConduitNoError; int error = 0; //webrtc engine errors webrtc::VideoCodec video_codec; std::string payloadName; //validate basic params if((condError = ValidateCodecConfig(codecConfig,true)) != kMediaConduitNoError) { return condError; } //Check if we have same codec already applied if(CheckCodecsForMatch(mCurSendCodecConfig, codecConfig)) { CSFLogDebug(logTag, "%s Codec has been applied already ", __FUNCTION__); return kMediaConduitCodecInUse; } //transmitting already ? if(mEngineTransmitting) { CSFLogDebug(logTag, "%s Engine Already Sending. Attemping to Stop ", __FUNCTION__); if(mPtrViEBase->StopSend(mChannel) == -1) { CSFLogError(logTag, "%s StopSend() Failed %d ",__FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } } //reset the flag mEngineTransmitting = false; // we should be good here to set the new codec. for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++) { if(0 == mPtrViECodec->GetCodec(idx, video_codec)) { payloadName = video_codec.plName; if(codecConfig->mName.compare(payloadName) == 0) { CodecConfigToWebRTCCodec(codecConfig, video_codec); codecFound = true; break; } } }//for if(codecFound == false) { CSFLogError(logTag, "%s Codec Mismatch ", __FUNCTION__); return kMediaConduitInvalidSendCodec; } if(mPtrViECodec->SetSendCodec(mChannel, video_codec) == -1) { error = mPtrViEBase->LastError(); if(error == kViECodecInvalidCodec) { CSFLogError(logTag, "%s Invalid Send Codec", __FUNCTION__); return kMediaConduitInvalidSendCodec; } CSFLogError(logTag, "%s SetSendCodec Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } if(mPtrViEBase->StartSend(mChannel) == -1) { CSFLogError(logTag, "%s Start Send Error %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } //Copy the applied codec for future reference delete mCurSendCodecConfig; mCurSendCodecConfig = new VideoCodecConfig(codecConfig->mType, codecConfig->mName, codecConfig->mWidth, codecConfig->mHeight); // by now we should be successfully started the transmission mEngineTransmitting = true; return kMediaConduitNoError; }
/** * Note: Setting the send-codec on the Video Engine will restart the encoder, * sets up new SSRC and reset RTP_RTCP module with the new codec setting. */ MediaConduitErrorCode WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig) { CSFLogDebug(logTag, "%s ", __FUNCTION__); bool codecFound = false; MediaConduitErrorCode condError = kMediaConduitNoError; int error = 0; //webrtc engine errors webrtc::VideoCodec video_codec; std::string payloadName; //validate basic params if((condError = ValidateCodecConfig(codecConfig,true)) != kMediaConduitNoError) { return condError; } //Check if we have same codec already applied if(CheckCodecsForMatch(mCurSendCodecConfig, codecConfig)) { CSFLogDebug(logTag, "%s Codec has been applied already ", __FUNCTION__); return kMediaConduitCodecInUse; } //transmitting already ? if(mEngineTransmitting) { CSFLogDebug(logTag, "%s Engine Already Sending. Attemping to Stop ", __FUNCTION__); if(mPtrViEBase->StopSend(mChannel) == -1) { CSFLogError(logTag, "%s StopSend() Failed %d ",__FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } } mEngineTransmitting = false; if (codecConfig->mLoadManager) { mPtrViEBase->RegisterCpuOveruseObserver(mChannel, codecConfig->mLoadManager); mPtrViEBase->SetLoadManager(codecConfig->mLoadManager); } // we should be good here to set the new codec. for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++) { if(0 == mPtrViECodec->GetCodec(idx, video_codec)) { payloadName = video_codec.plName; if(codecConfig->mName.compare(payloadName) == 0) { CodecConfigToWebRTCCodec(codecConfig, video_codec); codecFound = true; break; } } }//for if(codecFound == false) { CSFLogError(logTag, "%s Codec Mismatch ", __FUNCTION__); return kMediaConduitInvalidSendCodec; } if(mPtrViECodec->SetSendCodec(mChannel, video_codec) == -1) { error = mPtrViEBase->LastError(); if(error == kViECodecInvalidCodec) { CSFLogError(logTag, "%s Invalid Send Codec", __FUNCTION__); return kMediaConduitInvalidSendCodec; } CSFLogError(logTag, "%s SetSendCodec Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } mSendingWidth = 0; mSendingHeight = 0; if(codecConfig->RtcpFbIsSet(SDP_RTCP_FB_NACK_BASIC)) { CSFLogDebug(logTag, "Enabling NACK (send) for video stream\n"); if (mPtrRTP->SetNACKStatus(mChannel, true) != 0) { CSFLogError(logTag, "%s NACKStatus Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitNACKStatusError; } } if(mPtrViEBase->StartSend(mChannel) == -1) { CSFLogError(logTag, "%s Start Send Error %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } //Copy the applied config for future reference. delete mCurSendCodecConfig; mCurSendCodecConfig = new VideoCodecConfig(*codecConfig); mPtrRTP->SetRembStatus(mChannel, true, false); // by now we should be successfully started the transmission mEngineTransmitting = true; return kMediaConduitNoError; }
MediaConduitErrorCode WebrtcAudioConduit::ConfigureRecvMediaCodecs( const std::vector<AudioCodecConfig*>& codecConfigList) { CSFLogDebug(logTag, "%s ", __FUNCTION__); MediaConduitErrorCode condError = kMediaConduitNoError; int error = 0; //webrtc engine errors bool success = false; // Are we receiving already? If so, stop receiving and playout // since we can't apply new recv codec when the engine is playing. condError = StopReceiving(); if (condError != kMediaConduitNoError) { return condError; } if(codecConfigList.empty()) { CSFLogError(logTag, "%s Zero number of codecs to configure", __FUNCTION__); return kMediaConduitMalformedArgument; } // Try Applying the codecs in the list. // We succeed if at least one codec was applied and reception was // started successfully. for(std::vector<AudioCodecConfig*>::size_type i=0 ;i<codecConfigList.size();i++) { //if the codec param is invalid or diplicate, return error if((condError = ValidateCodecConfig(codecConfigList[i],false)) != kMediaConduitNoError) { return condError; } webrtc::CodecInst cinst; if(!CodecConfigToWebRTCCodec(codecConfigList[i],cinst)) { CSFLogError(logTag,"%s CodecConfig to WebRTC Codec Failed ",__FUNCTION__); continue; } if(mPtrVoECodec->SetRecPayloadType(mChannel,cinst) == -1) { error = mPtrVoEBase->LastError(); CSFLogError(logTag, "%s SetRecvCodec Failed %d ",__FUNCTION__, error); continue; } else { CSFLogDebug(logTag, "%s Successfully Set RecvCodec %s", __FUNCTION__, codecConfigList[i]->mName.c_str()); //copy this to local database if(CopyCodecToDB(codecConfigList[i])) { success = true; } else { CSFLogError(logTag,"%s Unable to updated Codec Database", __FUNCTION__); return kMediaConduitUnknownError; } } } //end for if(!success) { CSFLogError(logTag, "%s Setting Receive Codec Failed ", __FUNCTION__); return kMediaConduitInvalidReceiveCodec; } //If we are here, atleast one codec should have been set condError = StartReceiving(); if (condError != kMediaConduitNoError) { return condError; } DumpCodecDB(); return kMediaConduitNoError; }
MediaConduitErrorCode WebrtcAudioConduit::ConfigureSendMediaCodec(const AudioCodecConfig* codecConfig) { CSFLogDebug(logTag, "%s ", __FUNCTION__); MediaConduitErrorCode condError = kMediaConduitNoError; int error = 0;//webrtc engine errors webrtc::CodecInst cinst; //validate codec param if((condError = ValidateCodecConfig(codecConfig, true)) != kMediaConduitNoError) { return condError; } condError = StopTransmitting(); if (condError != kMediaConduitNoError) { return condError; } if(!CodecConfigToWebRTCCodec(codecConfig,cinst)) { CSFLogError(logTag,"%s CodecConfig to WebRTC Codec Failed ",__FUNCTION__); return kMediaConduitMalformedArgument; } if(mPtrVoECodec->SetSendCodec(mChannel, cinst) == -1) { error = mPtrVoEBase->LastError(); CSFLogError(logTag, "%s SetSendCodec - Invalid Codec %d ",__FUNCTION__, error); if(error == VE_CANNOT_SET_SEND_CODEC || error == VE_CODEC_ERROR) { CSFLogError(logTag, "%s Invalid Send Codec", __FUNCTION__); return kMediaConduitInvalidSendCodec; } CSFLogError(logTag, "%s SetSendCodec Failed %d ", __FUNCTION__, mPtrVoEBase->LastError()); return kMediaConduitUnknownError; } #if !defined(MOZILLA_EXTERNAL_LINKAGE) // TEMPORARY - see bug 694814 comment 2 nsresult rv; nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs); if (branch) { branch->GetIntPref("media.peerconnection.capture_delay", &mCaptureDelay); } } #endif condError = StartTransmitting(); if (condError != kMediaConduitNoError) { return condError; } //Copy the applied config for future reference. delete mCurSendCodecConfig; mCurSendCodecConfig = new AudioCodecConfig(codecConfig->mType, codecConfig->mName, codecConfig->mFreq, codecConfig->mPacSize, codecConfig->mChannels, codecConfig->mRate); return kMediaConduitNoError; }
/** * Note: Setting the send-codec on the Video Engine will restart the encoder, * sets up new SSRC and reset RTP_RTCP module with the new codec setting. */ MediaConduitErrorCode WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig) { CSFLogDebug(logTag, "%s for %s", __FUNCTION__, codecConfig ? codecConfig->mName.c_str() : "<null>"); bool codecFound = false; MediaConduitErrorCode condError = kMediaConduitNoError; int error = 0; //webrtc engine errors webrtc::VideoCodec video_codec; std::string payloadName; memset(&video_codec, 0, sizeof(video_codec)); //validate basic params if((condError = ValidateCodecConfig(codecConfig,true)) != kMediaConduitNoError) { return condError; } //Check if we have same codec already applied if(CheckCodecsForMatch(mCurSendCodecConfig, codecConfig)) { CSFLogDebug(logTag, "%s Codec has been applied already ", __FUNCTION__); return kMediaConduitCodecInUse; } //transmitting already ? if(mEngineTransmitting) { CSFLogDebug(logTag, "%s Engine Already Sending. Attemping to Stop ", __FUNCTION__); if(mPtrViEBase->StopSend(mChannel) == -1) { CSFLogError(logTag, "%s StopSend() Failed %d ",__FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } mEngineTransmitting = false; } if (mLoadManager) { mPtrViEBase->RegisterCpuOveruseObserver(mChannel, mLoadManager); mPtrViEBase->SetLoadManager(mLoadManager); } if (mExternalSendCodec && codecConfig->mType == mExternalSendCodec->mType) { CSFLogError(logTag, "%s Configuring External H264 Send Codec", __FUNCTION__); // width/height will be overridden on the first frame video_codec.width = 320; video_codec.height = 240; video_codec.qpMax = 56; video_codec.numberOfSimulcastStreams = 1; video_codec.mode = webrtc::kRealtimeVideo; codecFound = true; } else { // we should be good here to set the new codec. for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++) { if(0 == mPtrViECodec->GetCodec(idx, video_codec)) { payloadName = video_codec.plName; if(codecConfig->mName.compare(payloadName) == 0) { // Note: side-effect of this is that video_codec is filled in // by GetCodec() codecFound = true; break; } } }//for } if(codecFound == false) { CSFLogError(logTag, "%s Codec Mismatch ", __FUNCTION__); return kMediaConduitInvalidSendCodec; } // Note: only for overriding parameters from GetCodec()! CodecConfigToWebRTCCodec(codecConfig, video_codec); if(mPtrViECodec->SetSendCodec(mChannel, video_codec) == -1) { error = mPtrViEBase->LastError(); if(error == kViECodecInvalidCodec) { CSFLogError(logTag, "%s Invalid Send Codec", __FUNCTION__); return kMediaConduitInvalidSendCodec; } CSFLogError(logTag, "%s SetSendCodec Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } if (!mVideoCodecStat) { mVideoCodecStat = new VideoCodecStatistics(mChannel, mPtrViECodec, true); } mSendingWidth = 0; mSendingHeight = 0; if(codecConfig->RtcpFbIsSet(SDP_RTCP_FB_NACK_BASIC)) { CSFLogDebug(logTag, "Enabling NACK (send) for video stream\n"); if (mPtrRTP->SetNACKStatus(mChannel, true) != 0) { CSFLogError(logTag, "%s NACKStatus Failed %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitNACKStatusError; } } if(mPtrViEBase->StartSend(mChannel) == -1) { CSFLogError(logTag, "%s Start Send Error %d ", __FUNCTION__, mPtrViEBase->LastError()); return kMediaConduitUnknownError; } //Copy the applied config for future reference. delete mCurSendCodecConfig; mCurSendCodecConfig = new VideoCodecConfig(*codecConfig); mPtrRTP->SetRembStatus(mChannel, true, false); // by now we should be successfully started the transmission mEngineTransmitting = true; return kMediaConduitNoError; }
MediaConduitErrorCode WebrtcAudioConduit::ConfigureSendMediaCodec(const AudioCodecConfig* codecConfig) { CSFLogDebug(logTag, "%s ", __FUNCTION__); MediaConduitErrorCode condError = kMediaConduitNoError; int error = 0;//webrtc engine errors webrtc::CodecInst cinst; //validate codec param if((condError = ValidateCodecConfig(codecConfig, true)) != kMediaConduitNoError) { return condError; } //are we transmitting already, stop and apply the send codec if(mEngineTransmitting) { CSFLogDebug(logTag, "%s Engine Already Sending. Attemping to Stop ", __FUNCTION__); if(mPtrVoEBase->StopSend(mChannel) == -1) { CSFLogError(logTag, "%s StopSend() Failed %d ", __FUNCTION__, mPtrVoEBase->LastError()); return kMediaConduitUnknownError; } } mEngineTransmitting = false; if(!CodecConfigToWebRTCCodec(codecConfig,cinst)) { CSFLogError(logTag,"%s CodecConfig to WebRTC Codec Failed ",__FUNCTION__); return kMediaConduitMalformedArgument; } if(mPtrVoECodec->SetSendCodec(mChannel, cinst) == -1) { error = mPtrVoEBase->LastError(); CSFLogError(logTag, "%s SetSendCodec - Invalid Codec %d ",__FUNCTION__, error); if(error == VE_CANNOT_SET_SEND_CODEC || error == VE_CODEC_ERROR) { return kMediaConduitInvalidSendCodec; } return kMediaConduitUnknownError; } //Let's Send Transport State-machine on the Engine if(mPtrVoEBase->StartSend(mChannel) == -1) { error = mPtrVoEBase->LastError(); CSFLogError(logTag, "%s StartSend failed %d", __FUNCTION__, error); return kMediaConduitUnknownError; } //Copy the applied config for future reference. delete mCurSendCodecConfig; mCurSendCodecConfig = new AudioCodecConfig(codecConfig->mType, codecConfig->mName, codecConfig->mFreq, codecConfig->mPacSize, codecConfig->mChannels, codecConfig->mRate); mEngineTransmitting = true; return kMediaConduitNoError; }