MediaConduitErrorCode WebrtcVideoConduit::ValidateCodecConfig(const VideoCodecConfig* codecInfo, bool send) const { bool codecAppliedAlready = false; if(!codecInfo) { CSFLogError(logTag, "%s Null CodecConfig ", __FUNCTION__); return kMediaConduitMalformedArgument; } if((codecInfo->mName.empty()) || (codecInfo->mName.length() >= CODEC_PLNAME_SIZE)) { CSFLogError(logTag, "%s Invalid Payload Name Length ", __FUNCTION__); return kMediaConduitMalformedArgument; } //check if we have the same codec already applied if(send) { codecAppliedAlready = CheckCodecsForMatch(mCurSendCodecConfig,codecInfo); } else { codecAppliedAlready = CheckCodecForMatch(codecInfo); } if(codecAppliedAlready) { CSFLogDebug(logTag, "%s Codec %s Already Applied ", __FUNCTION__, codecInfo->mName.c_str()); return kMediaConduitCodecInUse; } return kMediaConduitNoError; }
/** * Checks if the codec is already in Conduit's database */ bool WebrtcAudioConduit::CheckCodecForMatch(const AudioCodecConfig* codecInfo) const { //the db should have atleast one codec for(std::vector<AudioCodecConfig*>::size_type i=0;i < mRecvCodecList.size();i++) { if(CheckCodecsForMatch(mRecvCodecList[i],codecInfo)) { //match return true; } } //no match or empty local db return false; }
/** * Perform validation on the codecConfig to be applied. * Verifies if the codec is already applied. */ MediaConduitErrorCode WebrtcAudioConduit::ValidateCodecConfig(const AudioCodecConfig* codecInfo, bool send) { bool codecAppliedAlready = false; if(!codecInfo) { CSFLogError(logTag, "%s Null CodecConfig ", __FUNCTION__); return kMediaConduitMalformedArgument; } if((codecInfo->mName.empty()) || (codecInfo->mName.length() >= CODEC_PLNAME_SIZE)) { CSFLogError(logTag, "%s Invalid Payload Name Length ", __FUNCTION__); return kMediaConduitMalformedArgument; } //Only mono or stereo channels supported if( (codecInfo->mChannels != 1) && (codecInfo->mChannels != 2)) { CSFLogError(logTag, "%s Channel Unsupported ", __FUNCTION__); return kMediaConduitMalformedArgument; } //check if we have the same codec already applied if(send) { MutexAutoLock lock(mCodecMutex); codecAppliedAlready = CheckCodecsForMatch(mCurSendCodecConfig,codecInfo); } else { codecAppliedAlready = CheckCodecForMatch(codecInfo); } if(codecAppliedAlready) { CSFLogDebug(logTag, "%s Codec %s Already Applied ", __FUNCTION__, codecInfo->mName.c_str()); } 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 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__); } 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, 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; } //Copy the applied config for future reference. delete mCurSendCodecConfig; mCurSendCodecConfig = new VideoCodecConfig(*codecConfig); mPtrRTP->SetRembStatus(mChannel, true, false); 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; }
/** * 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; }