diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp index bac42cc9c..fdef9062b 100755 --- a/talk/libjingle.gyp +++ b/talk/libjingle.gyp @@ -488,8 +488,6 @@ 'media/webrtc/webrtcvideocapturer.h', 'media/webrtc/webrtcvideodecoderfactory.h', 'media/webrtc/webrtcvideoencoderfactory.h', - 'media/webrtc/webrtcvideoengine.cc', - 'media/webrtc/webrtcvideoengine.h', 'media/webrtc/webrtcvideoengine2.cc', 'media/webrtc/webrtcvideoengine2.h', 'media/webrtc/webrtcvideoframe.cc', diff --git a/talk/libjingle_tests.gyp b/talk/libjingle_tests.gyp index 246fa3b13..3ca2f1ff3 100755 --- a/talk/libjingle_tests.gyp +++ b/talk/libjingle_tests.gyp @@ -107,7 +107,6 @@ # Disabled because some tests fail. # TODO(ronghuawu): Reenable these tests. # 'media/devices/devicemanager_unittest.cc', - 'media/webrtc/webrtcvideoengine_unittest.cc', 'media/webrtc/webrtcvideoengine2_unittest.cc', 'media/webrtc/webrtcvoiceengine_unittest.cc', ], diff --git a/talk/media/base/mediaengine.cc b/talk/media/base/mediaengine.cc index 23c99290e..9be590c2f 100644 --- a/talk/media/base/mediaengine.cc +++ b/talk/media/base/mediaengine.cc @@ -49,20 +49,6 @@ MediaEngineFactory::MediaEngineCreateFunction return old_function; } -// TODO(pthatcher): Remove this method and require all the users of -// media engines to choose one explictly, or at least remove the -// default behavior and require calling SetCreateFunction explictly. -MediaEngineInterface* MediaEngineFactory::Create() { - if (create_function_) { - return create_function_(); - } -#if defined(HAVE_WEBRTC_VOICE) && defined(HAVE_WEBRTC_VIDEO) - return WebRtcMediaEngineFactory::Create(); -#else - return new NullMediaEngine(); -#endif // HAVE_WEBRTC_VIDEO && HAVE_WEBRTC_VOICE -} - }; // namespace cricket #endif // DISABLE_MEDIA_ENGINE_FACTORY diff --git a/talk/media/webrtc/constants.h b/talk/media/webrtc/constants.h index b1a0cd81d..ff73faa6c 100755 --- a/talk/media/webrtc/constants.h +++ b/talk/media/webrtc/constants.h @@ -33,19 +33,12 @@ namespace cricket { extern const int kVideoMtu; extern const int kVideoRtpBufferSize; -extern const char kVp8CodecName[]; -extern const char kVp9CodecName[]; extern const char kH264CodecName[]; -extern const int kDefaultVideoMaxWidth; -extern const int kDefaultVideoMaxHeight; -extern const int kDefaultVideoMaxFramerate; extern const int kMinVideoBitrate; extern const int kStartVideoBitrate; extern const int kMaxVideoBitrate; -extern const int kCpuMonitorPeriodMs; - } // namespace cricket #endif // TALK_MEDIA_WEBRTC_CONSTANTS_H_ diff --git a/talk/media/webrtc/dummyinstantiation.cc b/talk/media/webrtc/dummyinstantiation.cc index 7d2796709..74428312d 100644 --- a/talk/media/webrtc/dummyinstantiation.cc +++ b/talk/media/webrtc/dummyinstantiation.cc @@ -25,13 +25,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "talk/media/webrtc/fakewebrtcvideoengine.h" #include "talk/media/webrtc/fakewebrtcvoiceengine.h" static void EnsureAPIMatch() { new cricket::FakeWebRtcVoiceEngine(NULL, 0); - new cricket::FakeWebRtcVideoDecoder(); - new cricket::FakeWebRtcVideoEncoder(); - new cricket::FakeWebRtcVideoEngine(NULL, 0); - new cricket::FakeWebRtcVideoEngine::Capturer(); } diff --git a/talk/media/webrtc/fakewebrtcvideoengine.h b/talk/media/webrtc/fakewebrtcvideoengine.h index e3a230400..bfe22c433 100644 --- a/talk/media/webrtc/fakewebrtcvideoengine.h +++ b/talk/media/webrtc/fakewebrtcvideoengine.h @@ -263,1103 +263,6 @@ class FakeWebRtcVideoEncoderFactory : public WebRtcVideoEncoderFactory { bool encoders_have_internal_sources_; }; -// Information associated with an external encoder. -struct ExternalEncoderInfo { - bool internal_source; -}; - -class FakeWebRtcVideoEngine - : public webrtc::ViEBase, - public webrtc::ViECodec, - public webrtc::ViECapture, - public webrtc::ViENetwork, - public webrtc::ViERender, - public webrtc::ViERTP_RTCP, - public webrtc::ViEImageProcess, - public webrtc::ViEExternalCodec { - public: - struct Channel { - Channel() - : capture_id_(-1), - original_channel_id_(-1), - has_renderer_(false), - render_started_(false), - send(false), - receive_(false), - can_transmit_(true), - remote_rtx_ssrc_(-1), - rtcp_status_(webrtc::kRtcpNone), - key_frame_request_method_(webrtc::kViEKeyFrameRequestNone), - tmmbr_(false), - remb_contribute_(false), - remb_bw_partition_(false), - rtp_offset_send_id_(-1), - rtp_offset_receive_id_(-1), - rtp_absolute_send_time_send_id_(-1), - rtp_absolute_send_time_receive_id_(-1), - rtp_video_rotation_send_id_(-1), - rtp_video_rotation_receive_id_(-1), - sender_target_delay_(0), - receiver_target_delay_(0), - transmission_smoothing_(false), - nack_(false), - hybrid_nack_fec_(false), - send_video_bitrate_(0), - send_fec_bitrate_(0), - send_nack_bitrate_(0), - send_bandwidth_(0), - receive_bandwidth_(0), - reserved_transmit_bitrate_bps_(0), - suspend_below_min_bitrate_(false), - overuse_observer_(NULL), - last_recvd_payload_type_(-1) { - ssrcs_[0] = 0; // default ssrc. - memset(&send_codec, 0, sizeof(send_codec)); - memset(&overuse_options_, 0, sizeof(overuse_options_)); - } - int capture_id_; - int original_channel_id_; - bool has_renderer_; - bool render_started_; - bool send; - bool receive_; - bool can_transmit_; - std::map ssrcs_; - std::map rtx_ssrcs_; - int remote_rtx_ssrc_; - // Mapping rtx_send_payload_types_[rtx] = associated. - std::map rtx_send_payload_types_; - // Mapping rtx_recv_payload_types_[rtx] = associated. - std::map rtx_recv_payload_types_; - std::string cname_; - webrtc::ViERTCPMode rtcp_status_; - webrtc::ViEKeyFrameRequestMethod key_frame_request_method_; - bool tmmbr_; - bool remb_contribute_; // This channel contributes to the remb report. - bool remb_bw_partition_; // This channel is allocated part of total bw. - int rtp_offset_send_id_; - int rtp_offset_receive_id_; - int rtp_absolute_send_time_send_id_; - int rtp_absolute_send_time_receive_id_; - int rtp_video_rotation_send_id_; - int rtp_video_rotation_receive_id_; - int sender_target_delay_; - int receiver_target_delay_; - bool transmission_smoothing_; - bool nack_; - bool hybrid_nack_fec_; - std::vector recv_codecs; - std::set ext_decoder_pl_types_; - std::map ext_encoders_; - webrtc::VideoCodec send_codec; - unsigned int send_video_bitrate_; - unsigned int send_fec_bitrate_; - unsigned int send_nack_bitrate_; - unsigned int send_bandwidth_; - unsigned int receive_bandwidth_; - // Bandwidth to deduct from estimated uplink capacity. - unsigned int reserved_transmit_bitrate_bps_; - bool suspend_below_min_bitrate_; - webrtc::CpuOveruseObserver* overuse_observer_; - webrtc::CpuOveruseOptions overuse_options_; - int last_recvd_payload_type_; - }; - class Capturer : public webrtc::ViEExternalCapture { - public: - Capturer() : channel_id_(-1), denoising_(false), - last_capture_time_(0), incoming_frame_num_(0) { } - int channel_id() const { return channel_id_; } - void set_channel_id(int channel_id) { channel_id_ = channel_id; } - bool denoising() const { return denoising_; } - void set_denoising(bool denoising) { denoising_ = denoising; } - int64 last_capture_time() const { return last_capture_time_; } - int incoming_frame_num() const { return incoming_frame_num_; } - - // From ViEExternalCapture - void IncomingFrame(const webrtc::I420VideoFrame& frame) override { - last_capture_time_ = frame.render_time_ms(); - ++incoming_frame_num_; - } - - private: - int channel_id_; - bool denoising_; - int64 last_capture_time_; - int incoming_frame_num_; - }; - - FakeWebRtcVideoEngine(const cricket::VideoCodec* const* codecs, - int num_codecs) - : inited_(false), - last_channel_(kViEChannelIdBase - 1), - fail_create_channel_(false), - last_capturer_(kViECaptureIdBase - 1), - fail_alloc_capturer_(false), - codecs_(codecs), - num_codecs_(num_codecs), - num_set_send_codecs_(0) { - } - - ~FakeWebRtcVideoEngine() { - ASSERT(0 == channels_.size()); - ASSERT(0 == capturers_.size()); - } - bool IsInited() const { return inited_; } - - int GetLastChannel() const { return last_channel_; } - int GetChannelFromLocalSsrc(int local_ssrc) const { - // ssrcs_[0] is the default local ssrc. - for (std::map::const_iterator iter = channels_.begin(); - iter != channels_.end(); ++iter) { - if (local_ssrc == iter->second->ssrcs_[0]) { - return iter->first; - } - } - return -1; - } - - int GetNumChannels() const { return static_cast(channels_.size()); } - bool IsChannel(int channel) const { - return (channels_.find(channel) != channels_.end()); - } - void set_fail_create_channel(bool fail_create_channel) { - fail_create_channel_ = fail_create_channel; - } - - int GetLastCapturer() const { return last_capturer_; } - int GetNumCapturers() const { return static_cast(capturers_.size()); } - int GetIncomingFrameNum(int channel_id) const { - for (std::map::const_iterator iter = capturers_.begin(); - iter != capturers_.end(); ++iter) { - Capturer* capturer = iter->second; - if (capturer->channel_id() == channel_id) { - return capturer->incoming_frame_num(); - } - } - return -1; - } - void set_fail_alloc_capturer(bool fail_alloc_capturer) { - fail_alloc_capturer_ = fail_alloc_capturer; - } - int GetNumSetSendCodecs() const { return num_set_send_codecs_; } - - int GetCaptureId(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->capture_id_; - } - int GetOriginalChannelId(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->original_channel_id_; - } - bool GetHasRenderer(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->has_renderer_; - } - bool GetRenderStarted(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->render_started_; - } - bool GetSend(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->send; - } - bool GetReceive(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->receive_; - } - int GetCaptureChannelId(int capture_id) const { - WEBRTC_ASSERT_CAPTURER(capture_id); - return capturers_.find(capture_id)->second->channel_id(); - } - bool GetCaptureDenoising(int capture_id) const { - WEBRTC_ASSERT_CAPTURER(capture_id); - return capturers_.find(capture_id)->second->denoising(); - } - int64 GetCaptureLastTimestamp(int capture_id) const { - WEBRTC_ASSERT_CAPTURER(capture_id); - return capturers_.find(capture_id)->second->last_capture_time(); - } - webrtc::ViERTCPMode GetRtcpStatus(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->rtcp_status_; - } - webrtc::ViEKeyFrameRequestMethod GetKeyFrameRequestMethod(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->key_frame_request_method_; - } - bool GetTmmbrStatus(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->tmmbr_; - } - bool GetRembStatusBwPartition(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->remb_bw_partition_; - } - bool GetRembStatusContribute(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->remb_contribute_; - } - int GetSendRtpExtensionId(int channel, const std::string& extension) { - WEBRTC_ASSERT_CHANNEL(channel); - if (extension == kRtpTimestampOffsetHeaderExtension) { - return channels_.find(channel)->second->rtp_offset_send_id_; - } else if (extension == kRtpAbsoluteSenderTimeHeaderExtension) { - return channels_.find(channel)->second->rtp_absolute_send_time_send_id_; - } else if (extension == kRtpVideoRotationHeaderExtension) { - return channels_.find(channel)->second->rtp_video_rotation_send_id_; - } - return -1; - } - int GetReceiveRtpExtensionId(int channel, const std::string& extension) { - WEBRTC_ASSERT_CHANNEL(channel); - if (extension == kRtpTimestampOffsetHeaderExtension) { - return channels_.find(channel)->second->rtp_offset_receive_id_; - } else if (extension == kRtpAbsoluteSenderTimeHeaderExtension) { - return - channels_.find(channel)->second->rtp_absolute_send_time_receive_id_; - } else if (extension == kRtpVideoRotationHeaderExtension) { - return channels_.find(channel)->second->rtp_video_rotation_receive_id_; - } - return -1; - } - bool GetTransmissionSmoothingStatus(int channel) { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->transmission_smoothing_; - } - int GetSenderTargetDelay(int channel) { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->sender_target_delay_; - } - int GetReceiverTargetDelay(int channel) { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->receiver_target_delay_; - } - bool GetNackStatus(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->nack_; - } - bool GetHybridNackFecStatus(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->hybrid_nack_fec_; - } - int GetNumSsrcs(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return static_cast( - channels_.find(channel)->second->ssrcs_.size()); - } - int GetNumRtxSsrcs(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return static_cast( - channels_.find(channel)->second->rtx_ssrcs_.size()); - } - bool GetIsTransmitting(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->can_transmit_; - } - webrtc::CpuOveruseObserver* GetCpuOveruseObserver(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->overuse_observer_; - } - webrtc::CpuOveruseOptions GetCpuOveruseOptions(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->overuse_options_; - } - int GetSsrc(int channel, int idx) const { - WEBRTC_ASSERT_CHANNEL(channel); - if (channels_.find(channel)->second->ssrcs_.find(idx) == - channels_.find(channel)->second->ssrcs_.end()) { - return -1; - } - return channels_.find(channel)->second->ssrcs_[idx]; - } - int GetRtxSsrc(int channel, int idx) const { - WEBRTC_ASSERT_CHANNEL(channel); - if (channels_.find(channel)->second->rtx_ssrcs_.find(idx) == - channels_.find(channel)->second->rtx_ssrcs_.end()) { - return -1; - } - return channels_.find(channel)->second->rtx_ssrcs_[idx]; - } - bool ReceiveCodecRegistered(int channel, - const webrtc::VideoCodec& codec) const { - WEBRTC_ASSERT_CHANNEL(channel); - const std::vector& codecs = - channels_.find(channel)->second->recv_codecs; - return std::find(codecs.begin(), codecs.end(), codec) != codecs.end(); - }; - bool ExternalDecoderRegistered(int channel, - unsigned int pl_type) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second-> - ext_decoder_pl_types_.count(pl_type) != 0; - }; - int GetNumExternalDecoderRegistered(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return static_cast( - channels_.find(channel)->second->ext_decoder_pl_types_.size()); - }; - bool ExternalEncoderRegistered(int channel, - unsigned int pl_type) const { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->ext_encoders_.count(pl_type) != 0; - }; - int GetNumExternalEncoderRegistered(int channel) const { - WEBRTC_ASSERT_CHANNEL(channel); - return static_cast( - channels_.find(channel)->second->ext_encoders_.size()); - }; - bool ExternalEncoderHasInternalSource(int channel, - unsigned int pl_type) const { - WEBRTC_ASSERT_CHANNEL(channel); - ASSERT(channels_.find(channel)->second->ext_encoders_.count(pl_type) != 0); - return channels_.find(channel) - ->second->ext_encoders_[pl_type] - .internal_source; - }; - int GetTotalNumExternalEncoderRegistered() const { - std::map::const_iterator it; - int total_num_registered = 0; - for (it = channels_.begin(); it != channels_.end(); ++it) - total_num_registered += - static_cast(it->second->ext_encoders_.size()); - return total_num_registered; - } - void SetSendBitrates(int channel, unsigned int video_bitrate, - unsigned int fec_bitrate, unsigned int nack_bitrate) { - WEBRTC_ASSERT_CHANNEL(channel); - channels_[channel]->send_video_bitrate_ = video_bitrate; - channels_[channel]->send_fec_bitrate_ = fec_bitrate; - channels_[channel]->send_nack_bitrate_ = nack_bitrate; - } - void SetSendBandwidthEstimate(int channel, unsigned int send_bandwidth) { - WEBRTC_ASSERT_CHANNEL(channel); - channels_[GetOriginalChannelId(channel)]->send_bandwidth_ = send_bandwidth; - } - void SetReceiveBandwidthEstimate(int channel, - unsigned int receive_bandwidth) { - WEBRTC_ASSERT_CHANNEL(channel); - channels_[GetOriginalChannelId(channel)]->receive_bandwidth_ = - receive_bandwidth; - } - std::vector GetRtxSendPayloadTypes(int channel) { - std::vector rtx_payload_types; - if (channels_.find(channel) == channels_.end()) - return rtx_payload_types; - - for (const auto& payload_type : - channels_[channel]->rtx_send_payload_types_) { - rtx_payload_types.push_back(payload_type.first); - } - return rtx_payload_types; - } - std::vector GetRtxRecvPayloadTypes(int channel) { - std::vector rtx_payload_types; - if (channels_.find(channel) == channels_.end()) - return rtx_payload_types; - - for (const auto& payload_type : - channels_[channel]->rtx_recv_payload_types_) { - rtx_payload_types.push_back(payload_type.first); - } - return rtx_payload_types; - } - int GetRemoteRtxSsrc(int channel) { - WEBRTC_CHECK_CHANNEL(channel); - return channels_.find(channel)->second->remote_rtx_ssrc_; - } - bool GetSuspendBelowMinBitrateStatus(int channel) { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->suspend_below_min_bitrate_; - } - int GetLastRecvdPayloadType(int channel) const { - WEBRTC_CHECK_CHANNEL(channel); - return channels_.find(channel)->second->last_recvd_payload_type_; - } - unsigned int GetReservedTransmitBitrate(int channel) { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->reserved_transmit_bitrate_bps_; - } - - WEBRTC_STUB(Release, ()); - - // webrtc::ViEBase - WEBRTC_FUNC(Init, ()) { - inited_ = true; - return 0; - }; - WEBRTC_STUB(SetVoiceEngine, (webrtc::VoiceEngine*)); - WEBRTC_FUNC(CreateChannel, (int& channel)) { // NOLINT - if (fail_create_channel_) { - return -1; - } - if (kViEChannelIdMax == last_channel_) { - return -1; - } - Channel* ch = new Channel(); - ++last_channel_; - // The original channel of the first channel in a group refers to itself - // for code simplicity. - ch->original_channel_id_ = last_channel_; - channels_[last_channel_] = ch; - channel = last_channel_; - return 0; - }; - WEBRTC_FUNC(CreateChannel, (int& channel, int original_channel)) { - WEBRTC_CHECK_CHANNEL(original_channel); - if (CreateChannel(channel) != 0) { - return -1; - } - channels_[channel]->original_channel_id_ = original_channel; - return 0; - } - WEBRTC_STUB(CreateChannelWithoutDefaultEncoder, (int&, int original_channel)); - webrtc::ChannelGroup* GetChannelGroup(int channel_id) override { - return nullptr; - } - webrtc::ViEChannel* GetChannel(int channel_id) override { return nullptr; } - webrtc::ViEEncoder* GetEncoder(int channel_id) override { return nullptr; } - webrtc::ViESharedData* shared_data() override { return nullptr; } - - WEBRTC_FUNC(CreateReceiveChannel, (int& channel, int original_channel)) { - return CreateChannel(channel, original_channel); - } - WEBRTC_FUNC(DeleteChannel, (const int channel)) { - WEBRTC_CHECK_CHANNEL(channel); - // Make sure we deregister all the decoders before deleting a channel. - EXPECT_EQ(0, GetNumExternalDecoderRegistered(channel)); - delete channels_[channel]; - channels_.erase(channel); - return 0; - } - WEBRTC_FUNC(RegisterCpuOveruseObserver, - (int channel, webrtc::CpuOveruseObserver* observer)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->overuse_observer_ = observer; - return 0; - } - WEBRTC_STUB(GetCpuOveruseMetrics, (int, webrtc::CpuOveruseMetrics*)); - WEBRTC_VOID_STUB(RegisterCpuOveruseMetricsObserver, - (int, webrtc::CpuOveruseMetricsObserver*)); - WEBRTC_FUNC(SetCpuOveruseOptions, - (int channel, const webrtc::CpuOveruseOptions& options)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->overuse_options_ = options; - return 0; - } - WEBRTC_STUB(ConnectAudioChannel, (const int, const int)); - WEBRTC_STUB(DisconnectAudioChannel, (const int)); - WEBRTC_FUNC(StartSend, (const int channel)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->send = true; - return 0; - } - WEBRTC_FUNC(StopSend, (const int channel)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->send = false; - return 0; - } - WEBRTC_FUNC(StartReceive, (const int channel)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->receive_ = true; - return 0; - } - WEBRTC_FUNC(StopReceive, (const int channel)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->receive_ = false; - return 0; - } - WEBRTC_STUB(GetVersion, (char version[1024])); - WEBRTC_STUB(LastError, ()); - WEBRTC_VOID_STUB(RegisterSendStatisticsProxy, - (int, webrtc::SendStatisticsProxy*)); - - WEBRTC_VOID_STUB(RegisterReceiveStatisticsProxy, - (int, webrtc::ReceiveStatisticsProxy*)); - - // webrtc::ViECodec - WEBRTC_FUNC_CONST(NumberOfCodecs, ()) { - return num_codecs_; - }; - WEBRTC_FUNC_CONST(GetCodec, (const unsigned char list_number, - webrtc::VideoCodec& out_codec)) { - if (list_number >= NumberOfCodecs()) { - return -1; - } - memset(&out_codec, 0, sizeof(out_codec)); - const cricket::VideoCodec& c(*codecs_[list_number]); - if ("I420" == c.name) { - out_codec.codecType = webrtc::kVideoCodecI420; - } else if ("VP8" == c.name) { - out_codec.codecType = webrtc::kVideoCodecVP8; - } else if ("red" == c.name) { - out_codec.codecType = webrtc::kVideoCodecRED; - } else if ("ulpfec" == c.name) { - out_codec.codecType = webrtc::kVideoCodecULPFEC; - } else { - out_codec.codecType = webrtc::kVideoCodecUnknown; - } - rtc::strcpyn(out_codec.plName, sizeof(out_codec.plName), - c.name.c_str()); - out_codec.plType = c.id; - out_codec.width = c.width; - out_codec.height = c.height; - out_codec.startBitrate = kStartVideoBitrate; - out_codec.maxBitrate = kMaxVideoBitrate; - out_codec.minBitrate = kMinVideoBitrate; - out_codec.maxFramerate = c.framerate; - return 0; - }; - WEBRTC_FUNC(SetSendCodec, (const int channel, - const webrtc::VideoCodec& codec)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->send_codec = codec; - ++num_set_send_codecs_; - return 0; - }; - WEBRTC_FUNC_CONST(GetSendCodec, (const int channel, - webrtc::VideoCodec& codec)) { // NOLINT - WEBRTC_CHECK_CHANNEL(channel); - codec = channels_.find(channel)->second->send_codec; - return 0; - }; - WEBRTC_FUNC(SetReceiveCodec, (const int channel, - const webrtc::VideoCodec& codec)) { // NOLINT - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->recv_codecs.push_back(codec); - return 0; - }; - WEBRTC_STUB_CONST(GetReceiveCodec, (const int, webrtc::VideoCodec&)); - WEBRTC_STUB_CONST(GetCodecConfigParameters, (const int, - unsigned char*, unsigned char&)); - WEBRTC_STUB(SetImageScaleStatus, (const int, const bool)); - WEBRTC_STUB_CONST(GetSendCodecStastistics, (const int, - unsigned int&, unsigned int&)); - WEBRTC_STUB_CONST(GetReceiveCodecStastistics, (const int, - unsigned int&, unsigned int&)); - WEBRTC_STUB_CONST(GetReceiveSideDelay, (const int video_channel, - int* delay_ms)); - virtual uint32_t GetLastObservedBitrateBps(int channel) const override { - return 0; - } - WEBRTC_FUNC_CONST(GetCodecTargetBitrate, (const int channel, - unsigned int* codec_target_bitrate)) { - WEBRTC_CHECK_CHANNEL(channel); - - std::map::const_iterator it = channels_.find(channel); - if (it->second->send) { - // Assume the encoder produces the expected rate. - *codec_target_bitrate = it->second->send_video_bitrate_; - } else { - *codec_target_bitrate = 0; - } - return 0; - } - virtual unsigned int GetDiscardedPackets(const int channel) const { - return 0; - } - - WEBRTC_STUB(SetKeyFrameRequestCallbackStatus, (const int, const bool)); - WEBRTC_STUB(SetSignalKeyPacketLossStatus, (const int, const bool, - const bool)); - WEBRTC_STUB(RegisterEncoderObserver, (const int, - webrtc::ViEEncoderObserver&)); - WEBRTC_STUB(DeregisterEncoderObserver, (const int)); - WEBRTC_STUB(RegisterDecoderObserver, (const int, - webrtc::ViEDecoderObserver&)); - WEBRTC_STUB(DeregisterDecoderObserver, (const int)); - WEBRTC_STUB(SendKeyFrame, (const int)); - WEBRTC_STUB(WaitForFirstKeyFrame, (const int, const bool)); - WEBRTC_STUB(StartDebugRecording, (int, const char*)); - WEBRTC_STUB(StopDebugRecording, (int)); - WEBRTC_VOID_FUNC(SuspendBelowMinBitrate, (int channel)) { - WEBRTC_ASSERT_CHANNEL(channel); - channels_[channel]->suspend_below_min_bitrate_ = true; - } - - // webrtc::ViECapture - WEBRTC_STUB(NumberOfCaptureDevices, ()); - WEBRTC_STUB(GetCaptureDevice, (unsigned int, char*, - const unsigned int, char*, const unsigned int)); - WEBRTC_STUB(AllocateCaptureDevice, (const char*, const unsigned int, int&)); - WEBRTC_FUNC(AllocateExternalCaptureDevice, - (int& capture_id, webrtc::ViEExternalCapture*& capture)) { - if (fail_alloc_capturer_) { - return -1; - } - if (kViECaptureIdMax == last_capturer_) { - return -1; - } - Capturer* cap = new Capturer(); - capturers_[++last_capturer_] = cap; - capture_id = last_capturer_; - capture = cap; - return 0; - } - WEBRTC_STUB(AllocateCaptureDevice, (webrtc::VideoCaptureModule&, int&)); - WEBRTC_FUNC(ReleaseCaptureDevice, (const int capture_id)) { - WEBRTC_CHECK_CAPTURER(capture_id); - delete capturers_[capture_id]; - capturers_.erase(capture_id); - return 0; - } - WEBRTC_FUNC(ConnectCaptureDevice, (const int capture_id, - const int channel)) { - WEBRTC_CHECK_CHANNEL(channel); - WEBRTC_CHECK_CAPTURER(capture_id); - channels_[channel]->capture_id_ = capture_id; - capturers_[capture_id]->set_channel_id(channel); - return 0; - } - WEBRTC_FUNC(DisconnectCaptureDevice, (const int channel)) { - WEBRTC_CHECK_CHANNEL(channel); - int capture_id = channels_[channel]->capture_id_; - WEBRTC_CHECK_CAPTURER(capture_id); - channels_[channel]->capture_id_ = -1; - capturers_[capture_id]->set_channel_id(-1); - return 0; - } - WEBRTC_STUB(StartCapture, (const int, const webrtc::CaptureCapability&)); - WEBRTC_STUB(StopCapture, (const int)); - WEBRTC_STUB(SetVideoRotation, (const int, const webrtc::VideoRotation)); - WEBRTC_STUB(SetCaptureDelay, (const int, const unsigned int)); - WEBRTC_STUB(NumberOfCapabilities, (const char*, const unsigned int)); - WEBRTC_STUB(GetCaptureCapability, (const char*, const unsigned int, - const unsigned int, webrtc::CaptureCapability&)); - WEBRTC_STUB(ShowCaptureSettingsDialogBox, (const char*, const unsigned int, - const char*, void*, const unsigned int, const unsigned int)); - WEBRTC_STUB(GetOrientation, (const char*, webrtc::VideoRotation&)); - WEBRTC_STUB(EnableBrightnessAlarm, (const int, const bool)); - WEBRTC_STUB(RegisterObserver, (const int, webrtc::ViECaptureObserver&)); - WEBRTC_STUB(DeregisterObserver, (const int)); - - // webrtc::ViENetwork - WEBRTC_VOID_STUB(SetBitrateConfig, (int, int, int, int)); - WEBRTC_VOID_FUNC(SetNetworkTransmissionState, (const int channel, - const bool is_transmitting)) { - WEBRTC_ASSERT_CHANNEL(channel); - channels_[channel]->can_transmit_ = is_transmitting; - } - WEBRTC_STUB(RegisterSendTransport, (const int, webrtc::Transport&)); - WEBRTC_STUB(DeregisterSendTransport, (const int)); - - WEBRTC_FUNC(ReceivedRTPPacket, (const int channel, - const void* packet, - const size_t length, - const webrtc::PacketTime& packet_time)) { - WEBRTC_ASSERT_CHANNEL(channel); - ASSERT(length > 1); - uint8_t payload_type = static_cast(packet)[1] & 0x7F; - channels_[channel]->last_recvd_payload_type_ = payload_type; - return 0; - } - - WEBRTC_STUB(ReceivedRTCPPacket, (const int, const void*, const size_t)); - // Not using WEBRTC_STUB due to bool return value - virtual bool IsIPv6Enabled(int channel) { return true; } - WEBRTC_STUB(SetMTU, (int, unsigned int)); - WEBRTC_STUB(ReceivedBWEPacket, (const int, int64_t, size_t, - const webrtc::RTPHeader&)); - - // webrtc::ViERender - WEBRTC_STUB(RegisterVideoRenderModule, (webrtc::VideoRender&)); - WEBRTC_STUB(DeRegisterVideoRenderModule, (webrtc::VideoRender&)); - WEBRTC_STUB(AddRenderer, (const int, void*, const unsigned int, const float, - const float, const float, const float)); - WEBRTC_FUNC(RemoveRenderer, (const int render_id)) { - if (IsCapturerId(render_id)) { - WEBRTC_CHECK_CAPTURER(render_id); - return 0; - } else if (IsChannelId(render_id)) { - WEBRTC_CHECK_CHANNEL(render_id); - channels_[render_id]->has_renderer_ = false; - return 0; - } - return -1; - } - WEBRTC_FUNC(StartRender, (const int render_id)) { - if (IsCapturerId(render_id)) { - WEBRTC_CHECK_CAPTURER(render_id); - return 0; - } else if (IsChannelId(render_id)) { - WEBRTC_CHECK_CHANNEL(render_id); - channels_[render_id]->render_started_ = true; - return 0; - } - return -1; - } - WEBRTC_FUNC(StopRender, (const int render_id)) { - if (IsCapturerId(render_id)) { - WEBRTC_CHECK_CAPTURER(render_id); - return 0; - } else if (IsChannelId(render_id)) { - WEBRTC_CHECK_CHANNEL(render_id); - channels_[render_id]->render_started_ = false; - return 0; - } - return -1; - } - WEBRTC_STUB(SetExpectedRenderDelay, (int render_id, int render_delay)); - WEBRTC_STUB(ConfigureRender, (int, const unsigned int, const float, - const float, const float, const float)); - WEBRTC_FUNC(AddRenderer, (const int render_id, - webrtc::RawVideoType video_type, - webrtc::ExternalRenderer* renderer)) { - if (IsCapturerId(render_id)) { - WEBRTC_CHECK_CAPTURER(render_id); - return 0; - } else if (IsChannelId(render_id)) { - WEBRTC_CHECK_CHANNEL(render_id); - channels_[render_id]->has_renderer_ = true; - return 0; - } - return -1; - } - - // webrtc::ViERTP_RTCP - WEBRTC_FUNC(SetLocalSSRC, (const int channel, - const unsigned int ssrc, - const webrtc::StreamType usage, - const unsigned char idx)) { - WEBRTC_CHECK_CHANNEL(channel); - switch (usage) { - case webrtc::kViEStreamTypeNormal: - channels_[channel]->ssrcs_[idx] = ssrc; - break; - case webrtc::kViEStreamTypeRtx: - channels_[channel]->rtx_ssrcs_[idx] = ssrc; - break; - default: - return -1; - } - return 0; - } - - WEBRTC_FUNC_CONST(SetRemoteSSRCType, (const int channel, - const webrtc::StreamType usage, const unsigned int ssrc)) { - WEBRTC_CHECK_CHANNEL(channel); - if (usage == webrtc::kViEStreamTypeRtx) { - channels_.find(channel)->second->remote_rtx_ssrc_ = ssrc; - return 0; - } - return -1; - } - - WEBRTC_FUNC_CONST(GetLocalSSRC, (const int channel, - unsigned int& ssrc)) { - // ssrcs_[0] is the default local ssrc. - WEBRTC_CHECK_CHANNEL(channel); - ssrc = channels_.find(channel)->second->ssrcs_[0]; - return 0; - } - WEBRTC_STUB_CONST(GetRemoteSSRC, (const int, unsigned int&)); - WEBRTC_STUB_CONST(GetRemoteCSRCs, (const int, unsigned int*)); - - WEBRTC_FUNC(SetRtxSendPayloadType, - (const int channel, - const uint8 payload_type, - const uint8 associated_payload_type)) { - WEBRTC_CHECK_CHANNEL(channel); - assert(payload_type >= 0); - assert(associated_payload_type >= 0); - channels_[channel]->rtx_send_payload_types_[payload_type] = - associated_payload_type; - return 0; - } - - WEBRTC_FUNC(SetRtxReceivePayloadType, - (const int channel, - const uint8 payload_type, - const uint8 associated_payload_type)) { - WEBRTC_CHECK_CHANNEL(channel); - assert(payload_type >= 0); - assert(associated_payload_type >= 0); - channels_[channel]->rtx_recv_payload_types_[payload_type] = - associated_payload_type; - return 0; - } - - WEBRTC_STUB(SetStartSequenceNumber, (const int, unsigned short)); - WEBRTC_FUNC(SetRTCPStatus, - (const int channel, const webrtc::ViERTCPMode mode)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->rtcp_status_ = mode; - return 0; - } - WEBRTC_STUB_CONST(GetRTCPStatus, (const int, webrtc::ViERTCPMode&)); - WEBRTC_FUNC(SetRTCPCName, (const int channel, - const char rtcp_cname[KMaxRTCPCNameLength])) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->cname_.assign(rtcp_cname); - return 0; - } - WEBRTC_FUNC_CONST(GetRTCPCName, (const int channel, - char rtcp_cname[KMaxRTCPCNameLength])) { - WEBRTC_CHECK_CHANNEL(channel); - rtc::strcpyn(rtcp_cname, KMaxRTCPCNameLength, - channels_.find(channel)->second->cname_.c_str()); - return 0; - } - WEBRTC_STUB_CONST(GetRemoteRTCPCName, (const int, char*)); - WEBRTC_STUB(SendApplicationDefinedRTCPPacket, (const int, const unsigned char, - unsigned int, const char*, unsigned short)); - WEBRTC_FUNC(SetNACKStatus, (const int channel, const bool enable)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->nack_ = enable; - channels_[channel]->hybrid_nack_fec_ = false; - return 0; - } - WEBRTC_STUB(SetFECStatus, (const int, const bool, const unsigned char, - const unsigned char)); - WEBRTC_FUNC(SetHybridNACKFECStatus, (const int channel, const bool enable, - const unsigned char red_type, const unsigned char fec_type)) { - WEBRTC_CHECK_CHANNEL(channel); - if (red_type == fec_type || - red_type == channels_[channel]->send_codec.plType || - fec_type == channels_[channel]->send_codec.plType) { - return -1; - } - channels_[channel]->nack_ = false; - channels_[channel]->hybrid_nack_fec_ = enable; - return 0; - } - WEBRTC_FUNC(SetKeyFrameRequestMethod, - (const int channel, - const webrtc::ViEKeyFrameRequestMethod method)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->key_frame_request_method_ = method; - return 0; - } - WEBRTC_FUNC(SetSenderBufferingMode, (int channel, int target_delay)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->sender_target_delay_ = target_delay; - return 0; - } - WEBRTC_FUNC(SetReceiverBufferingMode, (int channel, int target_delay)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->receiver_target_delay_ = target_delay; - return 0; - } - // |Send| and |receive| are stored locally in variables that more clearly - // explain what they mean. - WEBRTC_FUNC(SetRembStatus, (int channel, bool send, bool receive)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->remb_contribute_ = receive; - channels_[channel]->remb_bw_partition_ = send; - return 0; - } - WEBRTC_FUNC(SetTMMBRStatus, (const int channel, const bool enable)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->tmmbr_ = enable; - return 0; - } - WEBRTC_FUNC(SetSendTimestampOffsetStatus, (int channel, bool enable, - int id)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->rtp_offset_send_id_ = enable? id : -1; - return 0; - } - WEBRTC_FUNC(SetReceiveTimestampOffsetStatus, (int channel, bool enable, - int id)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->rtp_offset_receive_id_ = enable? id : -1; - return 0; - } - WEBRTC_FUNC(SetSendAbsoluteSendTimeStatus, (int channel, bool enable, - int id)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->rtp_absolute_send_time_send_id_ = enable? id : -1; - return 0; - } - WEBRTC_FUNC(SetReceiveAbsoluteSendTimeStatus, (int channel, bool enable, - int id)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->rtp_absolute_send_time_receive_id_ = enable? id : -1; - return 0; - } - WEBRTC_FUNC(SetSendVideoRotationStatus, (int channel, bool enable, int id)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->rtp_video_rotation_send_id_ = enable? id : -1; - return 0; - } - WEBRTC_FUNC(SetReceiveVideoRotationStatus, - (int channel, bool enable, int id)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->rtp_video_rotation_receive_id_ = enable? id : -1; - return 0; - } - WEBRTC_STUB(SetRtcpXrRrtrStatus, (int, bool)); - WEBRTC_FUNC(SetTransmissionSmoothingStatus, (int channel, bool enable)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->transmission_smoothing_ = enable; - return 0; - } - WEBRTC_FUNC(SetReservedTransmitBitrate, (int channel, - unsigned int reserved_transmit_bitrate_bps)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->reserved_transmit_bitrate_bps_ = - reserved_transmit_bitrate_bps; - return 0; - } - WEBRTC_STUB_CONST(GetSendRtcpPacketTypeCounter, (int, - webrtc::RtcpPacketTypeCounter*)); - WEBRTC_STUB_CONST(GetReceiveRtcpPacketTypeCounter, (int, - webrtc::RtcpPacketTypeCounter*)); - WEBRTC_STUB_CONST(GetReceivedRTCPStatistics, (const int, unsigned short&, - unsigned int&, unsigned int&, unsigned int&, int64_t&)); - WEBRTC_STUB_CONST(GetSentRTCPStatistics, (const int, unsigned short&, - unsigned int&, unsigned int&, unsigned int&, int64_t&)); - WEBRTC_STUB_CONST(GetRTPStatistics, (const int, size_t&, unsigned int&, - size_t&, unsigned int&)); - WEBRTC_STUB_CONST(GetReceiveChannelRtcpStatistics, (const int, - webrtc::RtcpStatistics&, int64_t&)); - WEBRTC_STUB_CONST(GetSendChannelRtcpStatistics, (const int, - webrtc::RtcpStatistics&, int64_t&)); - WEBRTC_STUB_CONST(GetRtpStatistics, (const int, webrtc::StreamDataCounters&, - webrtc::StreamDataCounters&)); - WEBRTC_FUNC_CONST(GetBandwidthUsage, (const int channel, - unsigned int& total_bitrate, unsigned int& video_bitrate, - unsigned int& fec_bitrate, unsigned int& nack_bitrate)) { - WEBRTC_CHECK_CHANNEL(channel); - std::map::const_iterator it = channels_.find(channel); - if (it->second->send) { - video_bitrate = it->second->send_video_bitrate_; - fec_bitrate = it->second->send_fec_bitrate_; - nack_bitrate = it->second->send_nack_bitrate_; - total_bitrate = video_bitrate + fec_bitrate + nack_bitrate; - } else { - total_bitrate = 0; - video_bitrate = 0; - fec_bitrate = 0; - nack_bitrate = 0; - } - return 0; - } - WEBRTC_FUNC_CONST(GetEstimatedSendBandwidth, (const int channel, - unsigned int* send_bandwidth_estimate)) { - WEBRTC_CHECK_CHANNEL(channel); - std::map::const_iterator it = channels_.find(channel); - // Assume the current video, fec and nack bitrate sums up to our estimate. - if (it->second->send) { - it = channels_.find(GetOriginalChannelId(channel)); - *send_bandwidth_estimate = it->second->send_bandwidth_; - } else { - *send_bandwidth_estimate = 0; - } - return 0; - } - WEBRTC_FUNC_CONST(GetEstimatedReceiveBandwidth, (const int channel, - unsigned int* receive_bandwidth_estimate)) { - WEBRTC_CHECK_CHANNEL(channel); - std::map::const_iterator it = channels_.find(channel); - if (it->second->receive_) { - it = channels_.find(GetOriginalChannelId(channel)); - *receive_bandwidth_estimate = it->second->receive_bandwidth_; - } else { - *receive_bandwidth_estimate = 0; - } - return 0; - } - WEBRTC_STUB(RegisterSendChannelRtcpStatisticsCallback, - (int, webrtc::RtcpStatisticsCallback*)); - WEBRTC_STUB(DeregisterSendChannelRtcpStatisticsCallback, - (int, webrtc::RtcpStatisticsCallback*)); - WEBRTC_STUB(RegisterReceiveChannelRtcpStatisticsCallback, - (int, webrtc::RtcpStatisticsCallback*)); - WEBRTC_STUB(DeregisterReceiveChannelRtcpStatisticsCallback, - (int, webrtc::RtcpStatisticsCallback*)); - WEBRTC_STUB(RegisterSendChannelRtpStatisticsCallback, - (int, webrtc::StreamDataCountersCallback*)); - WEBRTC_STUB(DeregisterSendChannelRtpStatisticsCallback, - (int, webrtc::StreamDataCountersCallback*)); - WEBRTC_STUB(RegisterReceiveChannelRtpStatisticsCallback, - (int, webrtc::StreamDataCountersCallback*)); - WEBRTC_STUB(DeregisterReceiveChannelRtpStatisticsCallback, - (int, webrtc::StreamDataCountersCallback*)); - WEBRTC_STUB(RegisterSendBitrateObserver, - (int, webrtc::BitrateStatisticsObserver*)); - WEBRTC_STUB(DeregisterSendBitrateObserver, - (int, webrtc::BitrateStatisticsObserver*)); - WEBRTC_STUB(RegisterSendFrameCountObserver, - (int, webrtc::FrameCountObserver*)); - WEBRTC_STUB(DeregisterSendFrameCountObserver, - (int, webrtc::FrameCountObserver*)); - WEBRTC_STUB(RegisterRtcpPacketTypeCounterObserver, - (int, webrtc::RtcpPacketTypeCounterObserver*)); - - WEBRTC_STUB(StartRTPDump, (const int, const char*, webrtc::RTPDirections)); - WEBRTC_STUB(StopRTPDump, (const int, webrtc::RTPDirections)); - WEBRTC_STUB(RegisterRTPObserver, (const int, webrtc::ViERTPObserver&)); - WEBRTC_STUB(DeregisterRTPObserver, (const int)); - - // webrtc::ViEImageProcess - WEBRTC_STUB(RegisterCaptureEffectFilter, (const int, - webrtc::ViEEffectFilter&)); - WEBRTC_STUB(DeregisterCaptureEffectFilter, (const int)); - WEBRTC_STUB(RegisterSendEffectFilter, (const int, - webrtc::ViEEffectFilter&)); - WEBRTC_STUB(DeregisterSendEffectFilter, (const int)); - WEBRTC_STUB(RegisterRenderEffectFilter, (const int, - webrtc::ViEEffectFilter&)); - WEBRTC_STUB(DeregisterRenderEffectFilter, (const int)); - WEBRTC_STUB(EnableDeflickering, (const int, const bool)); - WEBRTC_FUNC(EnableDenoising, (const int capture_id, const bool denoising)) { - WEBRTC_CHECK_CAPTURER(capture_id); - capturers_[capture_id]->set_denoising(denoising); - return 0; - } - WEBRTC_STUB(EnableColorEnhancement, (const int, const bool)); - // webrtc::ViEExternalCodec - WEBRTC_FUNC(RegisterExternalSendCodec, - (const int channel, - const unsigned char pl_type, - webrtc::VideoEncoder*, - bool internal_source)) { - WEBRTC_CHECK_CHANNEL(channel); - ExternalEncoderInfo info; - info.internal_source = internal_source; - channels_[channel]->ext_encoders_[pl_type] = info; - return 0; - } - WEBRTC_FUNC(DeRegisterExternalSendCodec, - (const int channel, const unsigned char pl_type)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->ext_encoders_.erase(pl_type); - return 0; - } - WEBRTC_FUNC(RegisterExternalReceiveCodec, - (const int channel, const unsigned char pl_type, webrtc::VideoDecoder*, - bool, int)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->ext_decoder_pl_types_.insert(pl_type); - return 0; - } - WEBRTC_FUNC(DeRegisterExternalReceiveCodec, - (const int channel, const unsigned char pl_type)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->ext_decoder_pl_types_.erase(pl_type); - return 0; - } - - private: - bool IsChannelId(int id) const { - return (id >= kViEChannelIdBase && id <= kViEChannelIdMax); - } - bool IsCapturerId(int id) const { - return (id >= kViECaptureIdBase && id <= kViECaptureIdMax); - } - - bool inited_; - int last_channel_; - std::map channels_; - bool fail_create_channel_; - int last_capturer_; - std::map capturers_; - bool fail_alloc_capturer_; - const cricket::VideoCodec* const* codecs_; - int num_codecs_; - int num_set_send_codecs_; // how many times we call SetSendCodec(). -}; - } // namespace cricket #endif // TALK_MEDIA_WEBRTC_FAKEWEBRTCVIDEOENGINE_H_ diff --git a/talk/media/webrtc/webrtcmediaengine.cc b/talk/media/webrtc/webrtcmediaengine.cc index 37705e24a..ca36f7331 100644 --- a/talk/media/webrtc/webrtcmediaengine.cc +++ b/talk/media/webrtc/webrtcmediaengine.cc @@ -28,27 +28,11 @@ #if defined(LIBPEERCONNECTION_LIB) || defined(LIBPEERCONNECTION_IMPLEMENTATION) #include "talk/media/webrtc/webrtcmediaengine.h" -#include "talk/media/webrtc/webrtcvideoengine.h" #include "talk/media/webrtc/webrtcvideoengine2.h" #include "talk/media/webrtc/webrtcvoiceengine.h" -#include "webrtc/system_wrappers/interface/field_trial.h" namespace cricket { -class WebRtcMediaEngine - : public CompositeMediaEngine { - public: - WebRtcMediaEngine() {} - WebRtcMediaEngine(webrtc::AudioDeviceModule* adm, - webrtc::AudioDeviceModule* adm_sc, - WebRtcVideoEncoderFactory* encoder_factory, - WebRtcVideoDecoderFactory* decoder_factory) { - voice_.SetAudioDeviceModule(adm, adm_sc); - video_.SetExternalEncoderFactory(encoder_factory); - video_.SetExternalDecoderFactory(decoder_factory); - } -}; - class WebRtcMediaEngine2 : public CompositeMediaEngine { public: @@ -70,10 +54,6 @@ cricket::MediaEngineInterface* CreateWebRtcMediaEngine( webrtc::AudioDeviceModule* adm_sc, cricket::WebRtcVideoEncoderFactory* encoder_factory, cricket::WebRtcVideoDecoderFactory* decoder_factory) { - if (webrtc::field_trial::FindFullName("WebRTC-NewVideoAPI") == "Disabled") { - return new cricket::WebRtcMediaEngine(adm, adm_sc, encoder_factory, - decoder_factory); - } return new cricket::WebRtcMediaEngine2(adm, adm_sc, encoder_factory, decoder_factory); } @@ -85,12 +65,6 @@ void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine) { namespace cricket { -// Used by ChannelManager when no media engine is passed in to it -// explicitly (acts as a default). -MediaEngineInterface* WebRtcMediaEngineFactory::Create() { - return new cricket::WebRtcMediaEngine(); -} - // Used by PeerConnectionFactory to create a media engine passed into // ChannelManager. MediaEngineInterface* WebRtcMediaEngineFactory::Create( diff --git a/talk/media/webrtc/webrtcvideoengine.cc b/talk/media/webrtc/webrtcvideoengine.cc index 5c41c438b..6ff09a3c8 100644 --- a/talk/media/webrtc/webrtcvideoengine.cc +++ b/talk/media/webrtc/webrtcvideoengine.cc @@ -1,4246 +1 @@ -/* - * libjingle - * Copyright 2004 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef HAVE_WEBRTC_VIDEO -#include "talk/media/webrtc/webrtcvideoengine.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "talk/media/base/constants.h" -#include "talk/media/base/rtputils.h" -#include "talk/media/base/streamparams.h" -#include "talk/media/base/videoadapter.h" -#include "talk/media/base/videocapturer.h" -#include "talk/media/base/videorenderer.h" -#include "talk/media/devices/filevideocapturer.h" -#include "talk/media/webrtc/constants.h" -#include "talk/media/webrtc/simulcast.h" -#include "talk/media/webrtc/webrtcpassthroughrender.h" -#include "talk/media/webrtc/webrtcvideocapturer.h" -#include "talk/media/webrtc/webrtcvideodecoderfactory.h" -#include "talk/media/webrtc/webrtcvideoencoderfactory.h" -#include "talk/media/webrtc/webrtcvideoframe.h" -#include "talk/media/webrtc/webrtcvie.h" -#include "talk/media/webrtc/webrtcvoe.h" -#include "talk/media/webrtc/webrtcvoiceengine.h" -#include "webrtc/base/basictypes.h" -#include "webrtc/base/buffer.h" -#include "webrtc/base/byteorder.h" -#include "webrtc/base/checks.h" -#include "webrtc/base/common.h" -#include "webrtc/base/cpumonitor.h" -#include "webrtc/base/logging.h" -#include "webrtc/base/stringutils.h" -#include "webrtc/base/thread.h" -#include "webrtc/base/timeutils.h" -#include "webrtc/experiments.h" -#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" -#include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h" -#include "webrtc/modules/video_coding/codecs/vp8/vp8_factory.h" -#include "webrtc/system_wrappers/interface/field_trial.h" - -namespace { - -cricket::VideoFormat CreateVideoFormat(int width, int height, int framerate) { - return cricket::VideoFormat( - width, - height, - cricket::VideoFormat::FpsToInterval(framerate), - cricket::FOURCC_ANY); -} - -cricket::VideoFormat VideoFormatFromCodec(const cricket::VideoCodec& codec) { - return CreateVideoFormat(codec.width, codec.height, codec.framerate); -} - -cricket::VideoFormat VideoFormatFromVieCodec(const webrtc::VideoCodec& codec) { - return CreateVideoFormat(codec.width, codec.height, codec.maxFramerate); -} - -template -void Clamp(cricket::Settable* box, T min, T max) { - T val; - if (!box->Get(&val)) { - return; - } - if (val < min) { - box->Set(min); - return; - } - if (val > max) { - box->Set(max); - return; - } -} - -template -bool Changed(cricket::Settable proposed, - cricket::Settable original) { - return proposed.IsSet() && proposed != original; -} - -template -bool Changed(cricket::Settable proposed, - cricket::Settable original, - T* value) { - return proposed.Get(value) && proposed != original; -} - -// Wrap cricket::WebRtcVideoEncoderFactory as a webrtc::VideoEncoderFactory. -class EncoderFactoryAdapter : public webrtc::VideoEncoderFactory { - public: - // EncoderFactoryAdapter doesn't take ownership of |factory|, which is owned - // by e.g. PeerConnectionFactory. - explicit EncoderFactoryAdapter(cricket::WebRtcVideoEncoderFactory* factory) - : factory_(factory) {} - virtual ~EncoderFactoryAdapter() {} - - // Implement webrtc::VideoEncoderFactory. - webrtc::VideoEncoder* Create() override { - return factory_->CreateVideoEncoder(webrtc::kVideoCodecVP8); - } - - void Destroy(webrtc::VideoEncoder* encoder) override { - return factory_->DestroyVideoEncoder(encoder); - } - - private: - cricket::WebRtcVideoEncoderFactory* factory_; -}; - -} // namespace - -namespace cricket { - -// Constants defined in talk/media/webrtc/constants.h -// TODO(pbos): Move these to a separate constants.cc file. -const int kVideoMtu = 1200; -const int kVideoRtpBufferSize = 65536; - -// TODO(ronghuawu): Change to 640x360. -const int kMinVideoBitrate = 30; -const int kStartVideoBitrate = 300; -const int kMaxVideoBitrate = 2000; - -const int kCpuMonitorPeriodMs = 2000; // 2 seconds. - -// TODO(pthatcher): Figure out what the proper value here is, or if we -// can just remove this altogether. -static const int kDefaultRenderDelayMs = 100; - -static const int kDefaultLogSeverity = rtc::LS_WARNING; - -static const int kDefaultNumberOfTemporalLayers = 1; // 1:1 - -static const int kChannelIdUnset = -1; -static const uint32 kDefaultChannelSsrcKey = 0; -static const uint32 kSsrcUnset = 0; - -static bool BitrateIsSet(int value) { - return value > kAutoBandwidth; -} - -static int GetBitrate(int value, int deflt) { - return BitrateIsSet(value) ? value : deflt; -} - -// Static allocation of payload type values for external video codec. -static int GetExternalVideoPayloadType(size_t index) { - static const int kExternalVideoPayloadTypeBase = 120; - index += kExternalVideoPayloadTypeBase; - ASSERT(index < 128); - return static_cast(index); -} - -static void LogMultiline(rtc::LoggingSeverity sev, char* text) { - const char* delim = "\r\n"; - // TODO(fbarchard): Fix strtok lint warning. - for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) { - LOG_V(sev) << tok; - } -} - -// Severity is an integer because it comes is assumed to be from command line. -static int SeverityToFilter(int severity) { - int filter = webrtc::kTraceNone; - switch (severity) { - case rtc::LS_VERBOSE: - filter |= webrtc::kTraceAll; - FALLTHROUGH(); - case rtc::LS_INFO: - filter |= (webrtc::kTraceStateInfo | webrtc::kTraceInfo); - FALLTHROUGH(); - case rtc::LS_WARNING: - filter |= (webrtc::kTraceTerseInfo | webrtc::kTraceWarning); - FALLTHROUGH(); - case rtc::LS_ERROR: - filter |= (webrtc::kTraceError | webrtc::kTraceCritical); - } - return filter; -} - -static const bool kNotSending = false; - -// Default video dscp value. -// See http://tools.ietf.org/html/rfc2474 for details -// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00 -static const rtc::DiffServCodePoint kVideoDscpValue = - rtc::DSCP_AF41; - -void AddDefaultFeedbackParams(VideoCodec* codec) { - codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamCcm, kRtcpFbCcmParamFir)); - codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kParamValueEmpty)); - codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kRtcpFbNackParamPli)); - codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamRemb, kParamValueEmpty)); -} - -static VideoCodec MakeVideoCodecWithDefaultFeedbackParams(int payload_type, - const char* name) { - VideoCodec codec(payload_type, name, kDefaultVideoMaxWidth, - kDefaultVideoMaxHeight, kDefaultVideoMaxFramerate, 0); - AddDefaultFeedbackParams(&codec); - return codec; -} - -bool CodecIsInternallySupported(const std::string& codec_name) { - if (CodecNamesEq(codec_name, kVp8CodecName)) { - return true; - } - if (CodecNamesEq(codec_name, kVp9CodecName)) { - const std::string group_name = - webrtc::field_trial::FindFullName("WebRTC-SupportVP9"); - return group_name == "Enabled" || group_name == "EnabledByFlag"; - } - return false; -} - -std::vector DefaultVideoCodecList() { - std::vector codecs; - if (CodecIsInternallySupported(kVp9CodecName)) { - codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp9PlType, - kVp9CodecName)); - // TODO(andresp): Add rtx codec for vp9 and verify it works. - } - codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp8PlType, - kVp8CodecName)); - codecs.push_back( - VideoCodec::CreateRtxCodec(kDefaultRtxVp8PlType, kDefaultVp8PlType)); - codecs.push_back(VideoCodec(kDefaultRedPlType, kRedCodecName)); - codecs.push_back(VideoCodec(kDefaultUlpfecType, kUlpfecCodecName)); - return codecs; -} - -WebRtcSimulcastEncoderFactory::WebRtcSimulcastEncoderFactory( - cricket::WebRtcVideoEncoderFactory* factory) - : factory_(factory) { -} - -WebRtcSimulcastEncoderFactory::~WebRtcSimulcastEncoderFactory() { -} - -bool WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory( - const std::vector& codecs) { - // If any codec is VP8, use the simulcast factory. If asked to create a - // non-VP8 codec, we'll just return a contained factory encoder directly. - for (const auto& codec: codecs) { - if (codec.type == webrtc::kVideoCodecVP8) { - return true; - } - } - return false; -} - -webrtc::VideoEncoder* WebRtcSimulcastEncoderFactory::CreateVideoEncoder( - webrtc::VideoCodecType type) { - ASSERT(factory_ != NULL); - // If it's a codec type we can simulcast, create a wrapped encoder. - if (type == webrtc::kVideoCodecVP8) { - return new webrtc::SimulcastEncoderAdapter( - new EncoderFactoryAdapter(factory_)); - } - webrtc::VideoEncoder* encoder = factory_->CreateVideoEncoder(type); - if (encoder) { - non_simulcast_encoders_.push_back(encoder); - } - return encoder; -} - -const std::vector& -WebRtcSimulcastEncoderFactory::codecs() const { - return factory_->codecs(); -} - -bool WebRtcSimulcastEncoderFactory::EncoderTypeHasInternalSource( - webrtc::VideoCodecType type) const { - return factory_->EncoderTypeHasInternalSource(type); -} - -void WebRtcSimulcastEncoderFactory::DestroyVideoEncoder( - webrtc::VideoEncoder* encoder) { - // Check first to see if the encoder wasn't wrapped in a - // SimulcastEncoderAdapter. In that case, ask the factory to destroy it. - if (std::remove(non_simulcast_encoders_.begin(), - non_simulcast_encoders_.end(), encoder) != - non_simulcast_encoders_.end()) { - factory_->DestroyVideoEncoder(encoder); - return; - } - - // Otherwise, SimulcastEncoderAdapter can be deleted directly, and will call - // DestroyVideoEncoder on the factory for individual encoder instances. - delete encoder; -} - -struct FlushBlackFrameData : public rtc::MessageData { - FlushBlackFrameData(uint32 s, int64 t, int i) - : ssrc(s), timestamp(t), interval(i) { - } - uint32 ssrc; - int64 timestamp; - int interval; -}; - -class WebRtcRenderAdapter : public webrtc::ExternalRenderer { - public: - WebRtcRenderAdapter(VideoRenderer* renderer, int channel_id) - : renderer_(renderer), - channel_id_(channel_id), - width_(0), - height_(0), - capture_start_rtp_time_stamp_(-1), - capture_start_ntp_time_ms_(0) { - } - - virtual ~WebRtcRenderAdapter() { - } - - void SetRenderer(VideoRenderer* renderer) { - rtc::CritScope cs(&crit_); - renderer_ = renderer; - // FrameSizeChange may have already been called when renderer was not set. - // If so we should call SetSize here. - // TODO(ronghuawu): Add unit test for this case. Didn't do it now - // because the WebRtcRenderAdapter is currently hiding in cc file. No - // good way to get access to it from the unit test. - if (width_ > 0 && height_ > 0 && renderer_) { - if (!renderer_->SetSize(width_, height_, 0)) { - LOG(LS_ERROR) - << "WebRtcRenderAdapter (channel " << channel_id_ - << ") SetRenderer failed to SetSize to: " - << width_ << "x" << height_; - } - } - } - - // Implementation of webrtc::ExternalRenderer. - virtual int FrameSizeChange(unsigned int width, unsigned int height, - unsigned int /*number_of_streams*/) { - rtc::CritScope cs(&crit_); - width_ = width; - height_ = height; - LOG(LS_INFO) << "WebRtcRenderAdapter (channel " << channel_id_ - << ") frame size changed to: " - << width << "x" << height; - if (!renderer_) { - LOG(LS_VERBOSE) << "WebRtcRenderAdapter (channel " << channel_id_ - << ") the renderer has not been set. " - << "SetSize will be called later in SetRenderer."; - return 0; - } - return renderer_->SetSize(width_, height_, 0) ? 0 : -1; - } - - virtual int DeliverFrame(unsigned char* buffer, - size_t buffer_size, - uint32_t rtp_time_stamp, - int64_t ntp_time_ms, - int64_t render_time, - void* handle) { - CHECK(false) << "All frames should be delivered as I420 frames through " - "DeliverI420Frame."; - return 0; - } - - virtual int DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame) { - rtc::CritScope cs(&crit_); - const int64_t elapsed_time_ms = ElapsedTimeMs(webrtc_frame.timestamp()); - UpdateFrameStats(elapsed_time_ms, webrtc_frame.ntp_time_ms()); - if (!renderer_) { - return 0; - } - - WebRtcVideoFrame cricket_frame( - webrtc_frame.video_frame_buffer(), - elapsed_time_ms * rtc::kNumNanosecsPerMillisec, - webrtc_frame.render_time_ms() * rtc::kNumNanosecsPerMillisec, - webrtc_frame.rotation()); - return renderer_->RenderFrame(&cricket_frame) ? 0 : -1; - } - - virtual bool IsTextureSupported() { return true; } - - unsigned int width() { - rtc::CritScope cs(&crit_); - return width_; - } - - unsigned int height() { - rtc::CritScope cs(&crit_); - return height_; - } - - int framerate() { - rtc::CritScope cs(&crit_); - return static_cast(frame_rate_tracker_.units_second()); - } - - VideoRenderer* renderer() { - rtc::CritScope cs(&crit_); - return renderer_; - } - - int64 capture_start_ntp_time_ms() { - rtc::CritScope cs(&crit_); - return capture_start_ntp_time_ms_; - } - - private: - int64_t ElapsedTimeMs(uint32_t rtp_time_stamp) { - if (capture_start_rtp_time_stamp_ < 0) { - capture_start_rtp_time_stamp_ = rtp_time_stamp; - } - const int kVideoCodecClockratekHz = cricket::kVideoCodecClockrate / 1000; - return (rtp_ts_wraparound_handler_.Unwrap(rtp_time_stamp) - - capture_start_rtp_time_stamp_) / kVideoCodecClockratekHz; - } - - void UpdateFrameStats(int64_t elapsed_time_ms, int64_t ntp_time_ms) { - if (ntp_time_ms > 0) { - capture_start_ntp_time_ms_ = ntp_time_ms - elapsed_time_ms; - } - frame_rate_tracker_.Update(1); - } - - rtc::CriticalSection crit_; - VideoRenderer* renderer_; - int channel_id_; - unsigned int width_; - unsigned int height_; - rtc::RateTracker frame_rate_tracker_; - rtc::TimestampWrapAroundHandler rtp_ts_wraparound_handler_; - int64 capture_start_rtp_time_stamp_; - int64 capture_start_ntp_time_ms_; -}; - -class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver { - public: - explicit WebRtcDecoderObserver() - : framerate_(0), - bitrate_(0), - decode_ms_(0), - max_decode_ms_(0), - current_delay_ms_(0), - target_delay_ms_(0), - jitter_buffer_ms_(0), - min_playout_delay_ms_(0), - render_delay_ms_(0) {} - - // virtual functions from VieDecoderObserver. - virtual void IncomingCodecChanged(const int video_channel_id, - const webrtc::VideoCodec& videoCodec) {} - virtual void IncomingRate(const int video_channel_id, - const unsigned int framerate, - const unsigned int bitrate) { - rtc::CritScope cs(&crit_); - framerate_ = framerate; - bitrate_ = bitrate; - } - - virtual void DecoderTiming(int decode_ms, - int max_decode_ms, - int current_delay_ms, - int target_delay_ms, - int jitter_buffer_ms, - int min_playout_delay_ms, - int render_delay_ms) { - rtc::CritScope cs(&crit_); - decode_ms_ = decode_ms; - max_decode_ms_ = max_decode_ms; - current_delay_ms_ = current_delay_ms; - target_delay_ms_ = target_delay_ms; - jitter_buffer_ms_ = jitter_buffer_ms; - min_playout_delay_ms_ = min_playout_delay_ms; - render_delay_ms_ = render_delay_ms; - } - - virtual void RequestNewKeyFrame(const int video_channel_id) {} - - // Populate |rinfo| based on previously-set data in |*this|. - void ExportTo(VideoReceiverInfo* rinfo) { - rtc::CritScope cs(&crit_); - rinfo->framerate_rcvd = framerate_; - rinfo->decode_ms = decode_ms_; - rinfo->max_decode_ms = max_decode_ms_; - rinfo->current_delay_ms = current_delay_ms_; - rinfo->target_delay_ms = target_delay_ms_; - rinfo->jitter_buffer_ms = jitter_buffer_ms_; - rinfo->min_playout_delay_ms = min_playout_delay_ms_; - rinfo->render_delay_ms = render_delay_ms_; - } - - private: - mutable rtc::CriticalSection crit_; - int framerate_; - int bitrate_; - int decode_ms_; - int max_decode_ms_; - int current_delay_ms_; - int target_delay_ms_; - int jitter_buffer_ms_; - int min_playout_delay_ms_; - int render_delay_ms_; -}; - -class WebRtcEncoderObserver : public webrtc::ViEEncoderObserver { - public: - explicit WebRtcEncoderObserver() - : framerate_(0), bitrate_(0), suspended_(false) {} - - // virtual functions from VieEncoderObserver. - virtual void OutgoingRate(const int video_channel_id, - const unsigned int framerate, - const unsigned int bitrate) { - rtc::CritScope cs(&crit_); - framerate_ = framerate; - bitrate_ = bitrate; - } - - virtual void SuspendChange(int video_channel_id, bool is_suspended) { - rtc::CritScope cs(&crit_); - suspended_ = is_suspended; - } - - int framerate() const { - rtc::CritScope cs(&crit_); - return framerate_; - } - int bitrate() const { - rtc::CritScope cs(&crit_); - return bitrate_; - } - bool suspended() const { - rtc::CritScope cs(&crit_); - return suspended_; - } - - private: - mutable rtc::CriticalSection crit_; - int framerate_; - int bitrate_; - bool suspended_; -}; - -struct CapturedFrameInfo { - CapturedFrameInfo() - : width(0), - height(0), - screencast(false), - elapsed_time(-1), - timestamp(-1) {} - CapturedFrameInfo(size_t width, - size_t height, - bool screencast, - int64_t elapsed_time, - int64_t timestamp) - : width(width), - height(height), - screencast(screencast), - elapsed_time(elapsed_time), - timestamp(timestamp) {} - - size_t width; - size_t height; - bool screencast; - - int64_t elapsed_time; - int64_t timestamp; -}; - -class WebRtcLocalStreamInfo { - public: - WebRtcLocalStreamInfo() : time_stamp_(-1) {} - int64 time_stamp() const { - rtc::CritScope cs(&crit_); - return time_stamp_; - } - int framerate() { - rtc::CritScope cs(&crit_); - return static_cast(rate_tracker_.units_second()); - } - - void UpdateFrame(const VideoFrame* frame) { - rtc::CritScope cs(&crit_); - time_stamp_ = frame->GetTimeStamp(); - rate_tracker_.Update(1); - } - - private: - mutable rtc::CriticalSection crit_; - int64 time_stamp_; - rtc::RateTracker rate_tracker_; - - DISALLOW_COPY_AND_ASSIGN(WebRtcLocalStreamInfo); -}; - -// WebRtcVideoChannelRecvInfo is a container class with members such as renderer -// and a decoder observer that is used by receive channels. -// It must exist as long as the receive channel is connected to renderer or a -// decoder observer in this class and methods in the class should only be called -// from the worker thread. -class WebRtcVideoChannelRecvInfo { - public: - typedef std::map DecoderMap; // Key: payload type - explicit WebRtcVideoChannelRecvInfo(int channel_id) - : channel_id_(channel_id), render_adapter_(NULL, channel_id) {} - int channel_id() { return channel_id_; } - void SetRenderer(VideoRenderer* renderer) { - render_adapter_.SetRenderer(renderer); - } - WebRtcRenderAdapter* render_adapter() { return &render_adapter_; } - WebRtcDecoderObserver* decoder_observer() { return &decoder_observer_; } - void RegisterDecoder(int pl_type, webrtc::VideoDecoder* decoder) { - ASSERT(!IsDecoderRegistered(pl_type)); - registered_decoders_[pl_type] = decoder; - } - bool IsDecoderRegistered(int pl_type) { - return registered_decoders_.count(pl_type) != 0; - } - const DecoderMap& registered_decoders() { - return registered_decoders_; - } - void ClearRegisteredDecoders() { - registered_decoders_.clear(); - } - - private: - int channel_id_; // Webrtc video channel number. - // Renderer for this channel. - WebRtcRenderAdapter render_adapter_; - WebRtcDecoderObserver decoder_observer_; - DecoderMap registered_decoders_; -}; - -class WebRtcOveruseObserver : public webrtc::CpuOveruseObserver { - public: - explicit WebRtcOveruseObserver(CoordinatedVideoAdapter* video_adapter) - : video_adapter_(video_adapter), - enabled_(false) { - } - - // TODO(mflodman): Consider sending resolution as part of event, to let - // adapter know what resolution the request is based on. Helps eliminate stale - // data, race conditions. - void OveruseDetected() override { - rtc::CritScope cs(&crit_); - if (!enabled_) { - return; - } - - video_adapter_->OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE); - } - - void NormalUsage() override { - rtc::CritScope cs(&crit_); - if (!enabled_) { - return; - } - - video_adapter_->OnCpuResolutionRequest(CoordinatedVideoAdapter::UPGRADE); - } - - void Enable(bool enable) { - LOG(LS_INFO) << "WebRtcOveruseObserver enable: " << enable; - rtc::CritScope cs(&crit_); - enabled_ = enable; - } - - bool enabled() const { return enabled_; } - - private: - CoordinatedVideoAdapter* video_adapter_; - bool enabled_; - rtc::CriticalSection crit_; -}; - - -class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> { - public: - typedef std::map EncoderMap; // Key: payload type - - enum AdaptFormatType { - // This is how we make SetSendStreamFormat take precedence over - // SetSendCodecs. - kAdaptFormatTypeNone = 0, // Unset - kAdaptFormatTypeCodec = 1, // From SetSendCodec - kAdaptFormatTypeStream = 2, // From SetStreamFormat - }; - - WebRtcVideoChannelSendInfo(int channel_id, int capture_id, - webrtc::ViEExternalCapture* external_capture, - rtc::CpuMonitor* cpu_monitor) - : channel_id_(channel_id), - capture_id_(capture_id), - sending_(false), - muted_(false), - video_capturer_(NULL), - external_capture_(external_capture), - cpu_monitor_(cpu_monitor), - old_adaptation_changes_(0), - adapt_format_type_(kAdaptFormatTypeNone) { - } - - int channel_id() const { return channel_id_; } - int capture_id() const { return capture_id_; } - void set_sending(bool sending) { sending_ = sending; } - bool sending() const { return sending_; } - void set_send_params(const VideoSendParams& send_params) { - send_params_ = send_params; - } - const VideoSendParams& send_params() const { - return send_params_; - } - const Settable& last_captured_frame_info() const { - return last_captured_frame_info_; - } - void set_muted(bool on) { - // TODO(asapersson): add support. - muted_ = on; - } - bool muted() {return muted_; } - - WebRtcEncoderObserver* encoder_observer() { return &encoder_observer_; } - webrtc::ViEExternalCapture* external_capture() { return external_capture_; } - const VideoFormat& adapt_format() const { return adapt_format_; } - AdaptFormatType adapt_format_type() const { return adapt_format_type_; } - bool adapt_format_set() const { - return adapt_format_type() != kAdaptFormatTypeNone; - } - - // Returns true if the last captured frame info changed. - void SetLastCapturedFrameInfo( - const VideoFrame* frame, bool screencast, bool* changed) { - CapturedFrameInfo last; - *changed = - !(last_captured_frame_info_.Get(&last) && - frame->GetWidth() == last.width && - frame->GetHeight() == last.height && screencast == last.screencast); - - last_captured_frame_info_.Set( - CapturedFrameInfo(frame->GetWidth(), frame->GetHeight(), screencast, - frame->GetElapsedTime(), frame->GetTimeStamp())); - } - - // Tells the video adapter to adapt down to a given format. The - // type indicates where the format came from, where different types - // have slightly different behavior and priority. - void SetAdaptFormat(const VideoFormat& format, AdaptFormatType type) { - if (type < adapt_format_type_) { - // Formats from SetSendStream format are higher priority than - // ones from SetSendCodecs wich is higher priority than not - // being set. If something lower-prioirty comes in, just ignore - // it. - return; - } - - // TODO(pthatcher): Use the adapter for all max size enforcement, - // both codec-based and SetSendStreamFormat-based. For now, we - // can't do that without fixing a lot of unit tests. - if (video_adapter() && type == kAdaptFormatTypeStream) { - video_adapter()->OnOutputFormatRequest(format); - } - - adapt_format_ = format; - adapt_format_type_ = type; - } - - int CurrentAdaptReason() const { - if (!video_adapter()) { - return CoordinatedVideoAdapter::ADAPTREASON_NONE; - } - return video_adapter()->adapt_reason(); - } - int AdaptChanges() const { - if (!video_adapter()) { - return old_adaptation_changes_; - } - return old_adaptation_changes_ + video_adapter()->adaptation_changes(); - } - - void set_stream_params(const StreamParams& sp) { - send_params_.stream = sp; - } - const StreamParams& stream_params() const { return send_params_.stream; } - // A default send channel can be non-active if a stream hasn't been - // added yet, or if all streams have been removed (at which point, - // Deactive is called). - bool IsActive() { - return stream_params().first_ssrc() != 0; - } - void Deactivate() { - send_params_.stream = StreamParams(); - } - - WebRtcLocalStreamInfo* local_stream_info() { - return &local_stream_info_; - } - VideoCapturer* video_capturer() { - return video_capturer_; - } - void set_video_capturer(VideoCapturer* video_capturer, - ViEWrapper* vie_wrapper) { - if (video_capturer == video_capturer_) { - return; - } - - CoordinatedVideoAdapter* old_video_adapter = video_adapter(); - if (old_video_adapter) { - // Get adaptation changes from old video adapter. - old_adaptation_changes_ += old_video_adapter->adaptation_changes(); - // Disconnect signals from old video adapter. - SignalCpuAdaptationUnable.disconnect(old_video_adapter); - if (cpu_monitor_) { - cpu_monitor_->SignalUpdate.disconnect(old_video_adapter); - } - } - - video_capturer_ = video_capturer; - - vie_wrapper->base()->RegisterCpuOveruseObserver(channel_id_, NULL); - if (!video_capturer) { - overuse_observer_.reset(); - return; - } - - CoordinatedVideoAdapter* adapter = video_adapter(); - ASSERT(adapter && "Video adapter should not be null here."); - - // TODO(pthatcher): Use the adapter for all max size enforcement, - // both codec-based and SetSendStreamFormat-based. For now, we - // can't do that without fixing a lot of unit tests. - if (adapt_format_type_ == kAdaptFormatTypeStream) { - adapter->OnOutputFormatRequest(adapt_format_); - } - - UpdateAdapterCpuOptions(); - - overuse_observer_.reset(new WebRtcOveruseObserver(adapter)); - vie_wrapper->base()->RegisterCpuOveruseObserver(channel_id_, - overuse_observer_.get()); - // (Dis)connect the video adapter from the cpu monitor as appropriate. - SetCpuOveruseDetection( - video_options_.cpu_overuse_detection.GetWithDefaultIfUnset(false)); - - SignalCpuAdaptationUnable.repeat(adapter->SignalCpuAdaptationUnable); - } - - CoordinatedVideoAdapter* video_adapter() { - if (!video_capturer_) { - return NULL; - } - return video_capturer_->video_adapter(); - } - const CoordinatedVideoAdapter* video_adapter() const { - if (!video_capturer_) { - return NULL; - } - return video_capturer_->video_adapter(); - } - - void ApplyCpuOptions(const VideoOptions& video_options) { - bool cpu_overuse_detection_changed = - video_options.cpu_overuse_detection.IsSet() && - (video_options.cpu_overuse_detection.GetWithDefaultIfUnset(false) != - video_options_.cpu_overuse_detection.GetWithDefaultIfUnset(false)); - // Use video_options_.SetAll() instead of assignment so that unset value in - // video_options will not overwrite the previous option value. - video_options_.SetAll(video_options); - UpdateAdapterCpuOptions(); - if (cpu_overuse_detection_changed) { - SetCpuOveruseDetection( - video_options_.cpu_overuse_detection.GetWithDefaultIfUnset(false)); - } - } - - void UpdateAdapterCpuOptions() { - if (!video_capturer_) { - return; - } - - bool cpu_smoothing, adapt_third; - float low, med, high; - bool cpu_adapt = - video_options_.adapt_input_to_cpu_usage.GetWithDefaultIfUnset(false); - bool cpu_overuse_detection = - video_options_.cpu_overuse_detection.GetWithDefaultIfUnset(false); - - // TODO(thorcarpenter): Have VideoAdapter be responsible for setting - // all these video options. - CoordinatedVideoAdapter* video_adapter = video_capturer_->video_adapter(); - if (video_options_.adapt_input_to_cpu_usage.IsSet() || - video_options_.cpu_overuse_detection.IsSet()) { - video_adapter->set_cpu_adaptation(cpu_adapt || cpu_overuse_detection); - } - if (video_options_.adapt_cpu_with_smoothing.Get(&cpu_smoothing)) { - video_adapter->set_cpu_smoothing(cpu_smoothing); - } - if (video_options_.process_adaptation_threshhold.Get(&med)) { - video_adapter->set_process_threshold(med); - } - if (video_options_.system_low_adaptation_threshhold.Get(&low)) { - video_adapter->set_low_system_threshold(low); - } - if (video_options_.system_high_adaptation_threshhold.Get(&high)) { - video_adapter->set_high_system_threshold(high); - } - if (video_options_.video_adapt_third.Get(&adapt_third)) { - video_adapter->set_scale_third(adapt_third); - } - } - - void SetCpuOveruseDetection(bool enable) { - if (overuse_observer_) { - overuse_observer_->Enable(enable); - } - - // The video adapter is signaled by overuse detection if enabled; otherwise - // it will be signaled by cpu monitor. - CoordinatedVideoAdapter* adapter = video_adapter(); - if (adapter) { - if (cpu_monitor_) { - if (enable) { - cpu_monitor_->SignalUpdate.disconnect(adapter); - } else { - cpu_monitor_->SignalUpdate.connect( - adapter, &CoordinatedVideoAdapter::OnCpuLoadUpdated); - } - } - } - } - - void ProcessFrame(const VideoFrame& original_frame, bool mute, - VideoFrame** processed_frame) { - if (!mute) { - *processed_frame = original_frame.Copy(); // Shallow copy. - } else { - // Cache a black frame of the same dimensions as original_frame. - if (black_frame_.GetWidth() != original_frame.GetWidth() || - black_frame_.GetHeight() != original_frame.GetHeight()) { - black_frame_.InitToBlack(static_cast(original_frame.GetWidth()), - static_cast(original_frame.GetHeight()), - 1, 1, - original_frame.GetElapsedTime(), - original_frame.GetTimeStamp()); - } - *processed_frame = black_frame_.Copy(); // Shallow copy. - (*processed_frame)->SetElapsedTime(original_frame.GetElapsedTime()); - (*processed_frame)->SetTimeStamp(original_frame.GetTimeStamp()); - } - local_stream_info_.UpdateFrame(*processed_frame); - } - void RegisterEncoder(int pl_type, webrtc::VideoEncoder* encoder) { - ASSERT(!IsEncoderRegistered(pl_type)); - registered_encoders_[pl_type] = encoder; - } - bool IsEncoderRegistered(int pl_type) { - return registered_encoders_.count(pl_type) != 0; - } - const EncoderMap& registered_encoders() { - return registered_encoders_; - } - void ClearRegisteredEncoders() { - registered_encoders_.clear(); - } - - sigslot::repeater0<> SignalCpuAdaptationUnable; - - private: - int channel_id_; - int capture_id_; - VideoSendParams send_params_; - // TODO(pthatcher): Merge CapturedFrameInfo and LocalStreamInfo. - Settable last_captured_frame_info_; - bool sending_; - bool muted_; - VideoCapturer* video_capturer_; - WebRtcEncoderObserver encoder_observer_; - webrtc::ViEExternalCapture* external_capture_; - EncoderMap registered_encoders_; - - WebRtcLocalStreamInfo local_stream_info_; - - rtc::CpuMonitor* cpu_monitor_; - rtc::scoped_ptr overuse_observer_; - - int old_adaptation_changes_; - - VideoOptions video_options_; - - VideoFormat adapt_format_; - AdaptFormatType adapt_format_type_; - WebRtcVideoFrame black_frame_; // Cached frame for mute. -}; - -static bool GetCpuOveruseOptions(const VideoOptions& options, - webrtc::CpuOveruseOptions* overuse_options) { - int underuse_threshold = 0; - int overuse_threshold = 0; - if (!options.cpu_underuse_threshold.Get(&underuse_threshold) || - !options.cpu_overuse_threshold.Get(&overuse_threshold)) { - return false; - } - if (underuse_threshold <= 0 || overuse_threshold <= 0) { - return false; - } - // Valid thresholds. - bool encode_usage = - options.cpu_overuse_encode_usage.GetWithDefaultIfUnset(false); - overuse_options->enable_capture_jitter_method = !encode_usage; - overuse_options->enable_encode_usage_method = encode_usage; - if (encode_usage) { - // Use method based on encode usage. - overuse_options->low_encode_usage_threshold_percent = underuse_threshold; - overuse_options->high_encode_usage_threshold_percent = overuse_threshold; - - // Set optional thresholds, if configured. - int underuse_rsd_threshold = 0; - if (options.cpu_underuse_encode_rsd_threshold.Get( - &underuse_rsd_threshold)) { - overuse_options->low_encode_time_rsd_threshold = underuse_rsd_threshold; - } - int overuse_rsd_threshold = 0; - if (options.cpu_overuse_encode_rsd_threshold.Get(&overuse_rsd_threshold)) { - overuse_options->high_encode_time_rsd_threshold = overuse_rsd_threshold; - } - } else { - // Use default method based on capture jitter. - overuse_options->low_capture_jitter_threshold_ms = - static_cast(underuse_threshold); - overuse_options->high_capture_jitter_threshold_ms = - static_cast(overuse_threshold); - } - return true; -} - -WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine) - : voice_engine_(voice_engine), trace_callback_(voice_engine) { - Construct(new ViEWrapper(), new ViETraceWrapper(), voice_engine, - new rtc::CpuMonitor(NULL)); -} - -WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine, - ViEWrapper* vie_wrapper, - rtc::CpuMonitor* cpu_monitor) - : voice_engine_(voice_engine), trace_callback_(voice_engine) { - Construct(vie_wrapper, new ViETraceWrapper(), voice_engine, cpu_monitor); -} - -WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine, - ViEWrapper* vie_wrapper, - ViETraceWrapper* tracing, - rtc::CpuMonitor* cpu_monitor) - : voice_engine_(voice_engine), trace_callback_(voice_engine) { - Construct(vie_wrapper, tracing, voice_engine, cpu_monitor); -} - -void WebRtcVideoEngine::Construct(ViEWrapper* vie_wrapper, - ViETraceWrapper* tracing, - WebRtcVoiceEngine* voice_engine, - rtc::CpuMonitor* cpu_monitor) { - LOG(LS_INFO) << "WebRtcVideoEngine::WebRtcVideoEngine"; - worker_thread_ = NULL; - vie_wrapper_.reset(vie_wrapper); - vie_wrapper_base_initialized_ = false; - tracing_.reset(tracing); - initialized_ = false; - SetTraceFilter(SeverityToFilter(kDefaultLogSeverity)); - render_module_.reset(new WebRtcPassthroughRender()); - capture_started_ = false; - decoder_factory_ = NULL; - encoder_factory_ = NULL; - cpu_monitor_.reset(cpu_monitor); - - SetTraceOptions(""); - if (tracing_->SetTraceCallback(&trace_callback_) != 0) { - LOG_RTCERR1(SetTraceCallback, &trace_callback_); - } - - default_video_codec_list_ = DefaultVideoCodecList(); - - // Set default quality levels for our supported codecs. We override them here - // if we know your cpu performance is low, and they can be updated explicitly - // by calling SetDefaultCodec. For example by a flute preference setting, or - // by the server with a jec in response to our reported system info. - CHECK(SetDefaultCodec(default_video_codec_list_.front())) - << "Failed to initialize list of supported codec types."; - - // Consider jitter, packet loss, etc when rendering. This will - // theoretically make rendering more smooth. - EnableTimedRender(); - - // Load our RTP Header extensions. - rtp_header_extensions_.push_back( - RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, - kRtpTimestampOffsetHeaderExtensionDefaultId)); - rtp_header_extensions_.push_back( - RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, - kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); - rtp_header_extensions_.push_back( - RtpHeaderExtension(kRtpVideoRotationHeaderExtension, - kRtpVideoRotationHeaderExtensionDefaultId)); -} - -WebRtcVideoEngine::~WebRtcVideoEngine() { - LOG(LS_INFO) << "WebRtcVideoEngine::~WebRtcVideoEngine"; - if (initialized_) { - Terminate(); - } - - tracing_->SetTraceCallback(NULL); - // Test to see if the media processor was deregistered properly. - ASSERT(SignalMediaFrame.is_empty()); -} - -bool WebRtcVideoEngine::Init(rtc::Thread* worker_thread) { - LOG(LS_INFO) << "WebRtcVideoEngine::Init"; - worker_thread_ = worker_thread; - ASSERT(worker_thread_ != NULL); - - cpu_monitor_->set_thread(worker_thread_); - if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) { - LOG(LS_ERROR) << "Failed to start CPU monitor."; - cpu_monitor_.reset(); - } - - bool result = InitVideoEngine(); - if (result) { - LOG(LS_INFO) << "VideoEngine Init done"; - } else { - LOG(LS_ERROR) << "VideoEngine Init failed, releasing"; - Terminate(); - } - return result; -} - -bool WebRtcVideoEngine::InitVideoEngine() { - LOG(LS_INFO) << "WebRtcVideoEngine::InitVideoEngine"; - - // Init WebRTC VideoEngine. - if (!vie_wrapper_base_initialized_) { - if (vie_wrapper_->base()->Init() != 0) { - LOG_RTCERR0(Init); - return false; - } - vie_wrapper_base_initialized_ = true; - } - - // Log the VoiceEngine version info. - char buffer[1024] = ""; - if (vie_wrapper_->base()->GetVersion(buffer) != 0) { - LOG_RTCERR0(GetVersion); - return false; - } - - LOG(LS_INFO) << "WebRtc VideoEngine Version:"; - LogMultiline(rtc::LS_INFO, buffer); - - // Hook up to VoiceEngine for sync purposes, if supplied. - if (!voice_engine_) { - LOG(LS_WARNING) << "NULL voice engine"; - } else if ((vie_wrapper_->base()->SetVoiceEngine( - voice_engine_->voe()->engine())) != 0) { - LOG_RTCERR0(SetVoiceEngine); - return false; - } - - // Register our custom render module. - if (vie_wrapper_->render()->RegisterVideoRenderModule( - *render_module_.get()) != 0) { - LOG_RTCERR0(RegisterVideoRenderModule); - return false; - } - - initialized_ = true; - return true; -} - -void WebRtcVideoEngine::Terminate() { - LOG(LS_INFO) << "WebRtcVideoEngine::Terminate"; - initialized_ = false; - - if (vie_wrapper_->render()->DeRegisterVideoRenderModule( - *render_module_.get()) != 0) { - LOG_RTCERR0(DeRegisterVideoRenderModule); - } - - if (vie_wrapper_->base()->SetVoiceEngine(NULL) != 0) { - LOG_RTCERR0(SetVoiceEngine); - } - - if (cpu_monitor_.get()) { - cpu_monitor_->Stop(); - } -} - -int WebRtcVideoEngine::GetCapabilities() { - return VIDEO_RECV | VIDEO_SEND; -} - -bool WebRtcVideoEngine::SetDefaultEncoderConfig( - const VideoEncoderConfig& config) { - return SetDefaultCodec(config.max_codec); -} - -// SetDefaultCodec may be called while the capturer is running. For example, a -// test call is started in a page with QVGA default codec, and then a real call -// is started in another page with VGA default codec. This is the corner case -// and happens only when a session is started. We ignore this case currently. -bool WebRtcVideoEngine::SetDefaultCodec(const VideoCodec& codec) { - if (!RebuildCodecList(codec)) { - LOG(LS_WARNING) << "Failed to RebuildCodecList"; - return false; - } - - ASSERT(!video_codecs_.empty()); - default_codec_format_ = VideoFormatFromCodec(video_codecs_[0]); - - return true; -} - -WebRtcVideoMediaChannel* WebRtcVideoEngine::CreateChannel( - VoiceMediaChannel* voice_channel) { - return CreateChannel(VideoOptions(), voice_channel); -} - -WebRtcVideoMediaChannel* WebRtcVideoEngine::CreateChannel( - const VideoOptions& options, - VoiceMediaChannel* voice_channel) { - WebRtcVideoMediaChannel* channel = - new WebRtcVideoMediaChannel(this, voice_channel); - if (!channel->Init()) { - delete channel; - return NULL; - } - - if (!channel->SetOptions(options)) { - LOG(LS_WARNING) << "Failed to set options while creating channel."; - } - return channel; -} - -const std::vector& WebRtcVideoEngine::codecs() const { - return video_codecs_; -} - -const std::vector& -WebRtcVideoEngine::rtp_header_extensions() const { - return rtp_header_extensions_; -} - -void WebRtcVideoEngine::SetLogging(int min_sev, const char* filter) { - // if min_sev == -1, we keep the current log level. - if (min_sev >= 0) { - SetTraceFilter(SeverityToFilter(min_sev)); - } - SetTraceOptions(filter); -} - -int WebRtcVideoEngine::GetLastEngineError() { - return vie_wrapper_->error(); -} - -// Checks to see whether we comprehend and could receive a particular codec -bool WebRtcVideoEngine::FindCodec(const VideoCodec& in) { - if (encoder_factory_) { - const std::vector& codecs = - encoder_factory_->codecs(); - for (size_t j = 0; j < codecs.size(); ++j) { - VideoCodec codec(GetExternalVideoPayloadType(j), codecs[j].name, 0, 0, 0, - 0); - if (codec.Matches(in)) - return true; - } - } - for (size_t j = 0; j != default_video_codec_list_.size(); ++j) { - if (default_video_codec_list_[j].Matches(in)) { - return true; - } - } - - return false; -} - -// Given the requested codec, returns true if we can send that codec type and -// updates out with the best quality we could send for that codec. -// TODO(ronghuawu): Remove |current| from the interface. -bool WebRtcVideoEngine::CanSendCodec(const VideoCodec& requested, - const VideoCodec& /* current */, - VideoCodec* out) { - if (!out) { - return false; - } - - std::vector::const_iterator local_max; - for (local_max = video_codecs_.begin(); - local_max < video_codecs_.end(); - ++local_max) { - // First match codecs by payload type - if (!requested.Matches(*local_max)) { - continue; - } - - out->id = requested.id; - out->name = requested.name; - out->preference = requested.preference; - out->params = requested.params; - out->framerate = std::min(requested.framerate, local_max->framerate); - out->width = 0; - out->height = 0; - out->params = requested.params; - out->feedback_params = requested.feedback_params; - - if (0 == requested.width && 0 == requested.height) { - // Special case with resolution 0. The channel should not send frames. - return true; - } else if (0 == requested.width || 0 == requested.height) { - // 0xn and nx0 are invalid resolutions. - return false; - } - - // Reduce the requested size by /= 2 until it's width under - // |local_max->width|. - out->width = requested.width; - out->height = requested.height; - while (out->width > local_max->width) { - out->width /= 2; - out->height /= 2; - } - - if (out->width > 0 && out->height > 0) { - return true; - } - } - return false; -} - -static void ConvertToCricketVideoCodec( - const webrtc::VideoCodec& in_codec, VideoCodec* out_codec) { - out_codec->id = in_codec.plType; - out_codec->name = in_codec.plName; - out_codec->width = in_codec.width; - out_codec->height = in_codec.height; - out_codec->framerate = in_codec.maxFramerate; - if (BitrateIsSet(in_codec.minBitrate)) { - out_codec->SetParam(kCodecParamMinBitrate, in_codec.minBitrate); - } - if (BitrateIsSet(in_codec.maxBitrate)) { - out_codec->SetParam(kCodecParamMaxBitrate, in_codec.maxBitrate); - } - if (BitrateIsSet(in_codec.startBitrate)) { - out_codec->SetParam(kCodecParamStartBitrate, in_codec.startBitrate); - } - if (in_codec.qpMax) { - out_codec->SetParam(kCodecParamMaxQuantization, in_codec.qpMax); - } -} - -bool WebRtcVideoEngine::ConvertFromCricketVideoCodec( - const VideoCodec& in_codec, webrtc::VideoCodec* out_codec) { - bool found = false; - int ncodecs = vie_wrapper_->codec()->NumberOfCodecs(); - for (int i = 0; i < ncodecs; ++i) { - if (vie_wrapper_->codec()->GetCodec(i, *out_codec) == 0 && - _stricmp(in_codec.name.c_str(), out_codec->plName) == 0) { - found = true; - break; - } - } - - // If not found, check if this is supported by external encoder factory. - if (!found && encoder_factory_) { - const std::vector& codecs = - encoder_factory_->codecs(); - for (size_t i = 0; i < codecs.size(); ++i) { - if (_stricmp(in_codec.name.c_str(), codecs[i].name.c_str()) == 0) { - out_codec->codecType = codecs[i].type; - out_codec->plType = GetExternalVideoPayloadType(i); - rtc::strcpyn(out_codec->plName, sizeof(out_codec->plName), - codecs[i].name.c_str(), codecs[i].name.length()); - found = true; - break; - } - } - } - - // Is this an RTX codec? Handled separately here since webrtc doesn't handle - // them as webrtc::VideoCodec internally. - if (!found && _stricmp(in_codec.name.c_str(), kRtxCodecName) == 0) { - rtc::strcpyn(out_codec->plName, sizeof(out_codec->plName), - in_codec.name.c_str(), in_codec.name.length()); - out_codec->plType = in_codec.id; - found = true; - } - - if (!found) { - LOG(LS_ERROR) << "invalid codec type"; - return false; - } - - if (in_codec.id != 0) - out_codec->plType = in_codec.id; - - if (in_codec.width != 0) - out_codec->width = in_codec.width; - - if (in_codec.height != 0) - out_codec->height = in_codec.height; - - if (in_codec.framerate != 0) - out_codec->maxFramerate = in_codec.framerate; - - // Convert bitrate parameters. - int max_bitrate = -1; - int min_bitrate = -1; - int start_bitrate = -1; - - in_codec.GetParam(kCodecParamMinBitrate, &min_bitrate); - in_codec.GetParam(kCodecParamMaxBitrate, &max_bitrate); - in_codec.GetParam(kCodecParamStartBitrate, &start_bitrate); - - - out_codec->minBitrate = min_bitrate; - out_codec->startBitrate = start_bitrate; - out_codec->maxBitrate = max_bitrate; - - // Convert general codec parameters. - int max_quantization = 0; - if (in_codec.GetParam(kCodecParamMaxQuantization, &max_quantization)) { - if (max_quantization < 0) { - return false; - } - out_codec->qpMax = max_quantization; - } - return true; -} - -void WebRtcVideoEngine::RegisterChannel(WebRtcVideoMediaChannel *channel) { - rtc::CritScope cs(&channels_crit_); - channels_.push_back(channel); -} - -void WebRtcVideoEngine::UnregisterChannel(WebRtcVideoMediaChannel *channel) { - rtc::CritScope cs(&channels_crit_); - channels_.erase(std::remove(channels_.begin(), channels_.end(), channel), - channels_.end()); -} - -bool WebRtcVideoEngine::EnableTimedRender() { - if (initialized_) { - LOG(LS_WARNING) << "EnableTimedRender can not be called after Init"; - return false; - } - render_module_.reset(webrtc::VideoRender::CreateVideoRender(0, NULL, - false, webrtc::kRenderExternal)); - return true; -} - -void WebRtcVideoEngine::SetTraceFilter(int filter) { - tracing_->SetTraceFilter(filter); -} - -// See https://sites.google.com/a/google.com/wavelet/ -// Home/Magic-Flute--RTC-Engine-/Magic-Flute-Command-Line-Parameters -// for all supported command line setttings. -void WebRtcVideoEngine::SetTraceOptions(const std::string& options) { - // Set WebRTC trace file. - std::vector opts; - rtc::tokenize(options, ' ', '"', '"', &opts); - std::vector::iterator tracefile = - std::find(opts.begin(), opts.end(), "tracefile"); - if (tracefile != opts.end() && ++tracefile != opts.end()) { - // Write WebRTC debug output (at same loglevel) to file - if (tracing_->SetTraceFile(tracefile->c_str()) == -1) { - LOG_RTCERR1(SetTraceFile, *tracefile); - } - } -} - -// Rebuilds the codec list to be only those that are less intensive -// than the specified codec. Prefers internal codec over external with -// higher preference field. -bool WebRtcVideoEngine::RebuildCodecList(const VideoCodec& in_codec) { - if (!FindCodec(in_codec)) - return false; - - video_codecs_.clear(); - - std::set internal_codec_names; - for (size_t i = 0; i != default_video_codec_list_.size(); ++i) { - VideoCodec codec = default_video_codec_list_[i]; - codec.width = in_codec.width; - codec.height = in_codec.height; - codec.framerate = in_codec.framerate; - video_codecs_.push_back(codec); - - internal_codec_names.insert(codec.name); - } - - if (encoder_factory_) { - const std::vector& codecs = - encoder_factory_->codecs(); - for (size_t i = 0; i < codecs.size(); ++i) { - bool is_internal_codec = internal_codec_names.find(codecs[i].name) != - internal_codec_names.end(); - if (!is_internal_codec) { - VideoCodec codec( - GetExternalVideoPayloadType(i), - codecs[i].name, - codecs[i].max_width, - codecs[i].max_height, - codecs[i].max_fps, - // Use negative preference on external codec to ensure the internal - // codec is preferred. - static_cast(0 - i)); - AddDefaultFeedbackParams(&codec); - video_codecs_.push_back(codec); - } - } - } - return true; -} - -int WebRtcVideoEngine::GetNumOfChannels() { - rtc::CritScope cs(&channels_crit_); - return static_cast(channels_.size()); -} - -void WebRtcVideoEngine::TraceCallbackImpl::Print( - webrtc::TraceLevel level, const char* trace, int length) { - rtc::LoggingSeverity sev = rtc::LS_VERBOSE; - if (level == webrtc::kTraceError || level == webrtc::kTraceCritical) - sev = rtc::LS_ERROR; - else if (level == webrtc::kTraceWarning) - sev = rtc::LS_WARNING; - else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo) - sev = rtc::LS_INFO; - else if (level == webrtc::kTraceTerseInfo) - sev = rtc::LS_INFO; - - // Skip past boilerplate prefix text - if (length < 72) { - std::string msg(trace, length); - LOG(LS_ERROR) << "Malformed webrtc log message: "; - LOG_V(sev) << msg; - } else { - std::string msg(trace + 71, length - 72); - if (!voice_engine_ || !voice_engine_->ShouldIgnoreTrace(msg)) { - LOG_V(sev) << "webrtc: " << msg; - } - } -} - -webrtc::VideoDecoder* WebRtcVideoEngine::CreateExternalDecoder( - webrtc::VideoCodecType type) { - if (!decoder_factory_) { - return NULL; - } - return decoder_factory_->CreateVideoDecoder(type); -} - -void WebRtcVideoEngine::DestroyExternalDecoder(webrtc::VideoDecoder* decoder) { - ASSERT(decoder_factory_ != NULL); - if (!decoder_factory_) - return; - decoder_factory_->DestroyVideoDecoder(decoder); -} - -webrtc::VideoEncoder* WebRtcVideoEngine::CreateExternalEncoder( - webrtc::VideoCodecType type, - bool* internal_source) { - ASSERT(internal_source != NULL); - if (!encoder_factory_) { - return NULL; - } - *internal_source = encoder_factory_->EncoderTypeHasInternalSource(type); - return encoder_factory_->CreateVideoEncoder(type); -} - -void WebRtcVideoEngine::DestroyExternalEncoder(webrtc::VideoEncoder* encoder) { - ASSERT(encoder_factory_ != NULL); - if (!encoder_factory_) - return; - encoder_factory_->DestroyVideoEncoder(encoder); -} - -bool WebRtcVideoEngine::IsExternalEncoderCodecType( - webrtc::VideoCodecType type) const { - if (!encoder_factory_) - return false; - const std::vector& codecs = - encoder_factory_->codecs(); - std::vector::const_iterator it; - for (it = codecs.begin(); it != codecs.end(); ++it) { - if (it->type == type) - return true; - } - return false; -} - -void WebRtcVideoEngine::SetExternalDecoderFactory( - WebRtcVideoDecoderFactory* decoder_factory) { - decoder_factory_ = decoder_factory; -} - -void WebRtcVideoEngine::SetExternalEncoderFactory( - WebRtcVideoEncoderFactory* encoder_factory) { - if (encoder_factory_ == encoder_factory) - return; - - // No matter what happens we shouldn't hold on to a stale - // WebRtcSimulcastEncoderFactory. - simulcast_encoder_factory_.reset(); - - if (encoder_factory) { - const std::vector& codecs = - encoder_factory->codecs(); - if (WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory(codecs)) { - simulcast_encoder_factory_.reset( - new WebRtcSimulcastEncoderFactory(encoder_factory)); - encoder_factory = simulcast_encoder_factory_.get(); - } - } - - encoder_factory_ = encoder_factory; - - // Rebuild codec list while reapplying the current default codec format. - VideoCodec max_codec = default_video_codec_list_[0]; - max_codec.width = video_codecs_[0].width; - max_codec.height = video_codecs_[0].height; - max_codec.framerate = video_codecs_[0].framerate; - if (!RebuildCodecList(max_codec)) { - LOG(LS_ERROR) << "Failed to initialize list of supported codec types"; - } -} - -// WebRtcVideoMediaChannel - -WebRtcVideoMediaChannel::WebRtcVideoMediaChannel( - WebRtcVideoEngine* engine, - VoiceMediaChannel* channel) - : engine_(engine), - voice_channel_(channel), - default_channel_id_(kChannelIdUnset), - nack_enabled_(true), - remb_enabled_(false), - render_started_(false), - first_receive_ssrc_(kSsrcUnset), - receiver_report_ssrc_(kSsrcUnset), - num_unsignalled_recv_channels_(0), - send_red_type_(-1), - send_fec_type_(-1), - sending_(false), - ratio_w_(0), - ratio_h_(0) { - engine->RegisterChannel(this); -} - -bool WebRtcVideoMediaChannel::Init() { - const uint32 ssrc_key = 0; - bool result = CreateChannel(ssrc_key, MD_SENDRECV, &default_channel_id_); - if (!result) { - return false; - } - if (voice_channel_) { - WebRtcVoiceMediaChannel* voice_channel = - static_cast(voice_channel_); - if (!voice_channel->SetupSharedBandwidthEstimation( - engine()->vie()->engine(), default_channel_id_)) { - return false; - } - } - return true; -} - -WebRtcVideoMediaChannel::~WebRtcVideoMediaChannel() { - Terminate(); -} - -void WebRtcVideoMediaChannel::Terminate() { - SetSend(false); - SetRender(false); - - while (!send_channels_.empty()) { - if (!DeleteSendChannel(send_channels_.begin()->first)) { - LOG(LS_ERROR) << "Unable to delete channel with ssrc key " - << send_channels_.begin()->first; - ASSERT(false); - break; - } - } - - // Remove all receive streams and the default channel. - while (!recv_channels_.empty()) { - RemoveRecvStreamInternal(recv_channels_.begin()->first); - } - - // Unregister the channel from the engine. - engine()->UnregisterChannel(this); - if (worker_thread()) { - worker_thread()->Clear(this); - } -} - -bool WebRtcVideoMediaChannel::SetRecvCodecs( - const std::vector& codecs) { - receive_codecs_.clear(); - associated_payload_types_.clear(); - for (std::vector::const_iterator iter = codecs.begin(); - iter != codecs.end(); ++iter) { - if (engine()->FindCodec(*iter)) { - webrtc::VideoCodec wcodec; - if (engine()->ConvertFromCricketVideoCodec(*iter, &wcodec)) { - receive_codecs_.push_back(wcodec); - int apt; - if (iter->GetParam(cricket::kCodecParamAssociatedPayloadType, &apt)) { - if (!IsValidRtpPayloadType(apt)) - return false; - associated_payload_types_[wcodec.plType] = apt; - } - } - } else { - LOG(LS_INFO) << "Unknown codec " << iter->name; - return false; - } - } - - for (RecvChannelMap::iterator it = recv_channels_.begin(); - it != recv_channels_.end(); ++it) { - if (!SetReceiveCodecs(it->second)) - return false; - } - return true; -} - -bool WebRtcVideoMediaChannel::SetSendCodecs( - const std::vector& codecs) { - // Match with local video codec list. - std::vector send_codecs; - VideoCodec checked_codec; - VideoCodec dummy_current; // Will be ignored by CanSendCodec. - std::map primary_rtx_pt_mapping; - bool nack_enabled = nack_enabled_; - bool remb_enabled = remb_enabled_; - for (std::vector::const_iterator iter = codecs.begin(); - iter != codecs.end(); ++iter) { - if (_stricmp(iter->name.c_str(), kRedCodecName) == 0) { - send_red_type_ = iter->id; - } else if (_stricmp(iter->name.c_str(), kUlpfecCodecName) == 0) { - send_fec_type_ = iter->id; - } else if (_stricmp(iter->name.c_str(), kRtxCodecName) == 0) { - int rtx_type = iter->id; - int rtx_primary_type = -1; - if (iter->GetParam(kCodecParamAssociatedPayloadType, &rtx_primary_type)) { - if (!IsValidRtpPayloadType(rtx_primary_type)) - return false; - primary_rtx_pt_mapping[rtx_primary_type] = rtx_type; - } - } else if (engine()->CanSendCodec(*iter, dummy_current, &checked_codec)) { - webrtc::VideoCodec wcodec; - if (engine()->ConvertFromCricketVideoCodec(checked_codec, &wcodec)) { - if (send_codecs.empty()) { - nack_enabled = HasNack(checked_codec); - remb_enabled = HasRemb(checked_codec); - } - send_codecs.push_back(wcodec); - } - } else { - LOG(LS_WARNING) << "Unknown codec " << iter->name; - } - } - - // Fail if we don't have a match. - if (send_codecs.empty()) { - LOG(LS_WARNING) << "No matching codecs available"; - return false; - } - - // Recv protection. - // Do not update if the status is same as previously configured. - if (nack_enabled_ != nack_enabled) { - for (RecvChannelMap::iterator it = recv_channels_.begin(); - it != recv_channels_.end(); ++it) { - int channel_id = it->second->channel_id(); - if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, - nack_enabled)) { - return false; - } - if (engine_->vie()->rtp()->SetRembStatus(channel_id, - kNotSending, - remb_enabled_) != 0) { - LOG_RTCERR3(SetRembStatus, channel_id, kNotSending, remb_enabled_); - return false; - } - } - nack_enabled_ = nack_enabled; - } - - // Send settings. - // Do not update if the status is same as previously configured. - if (remb_enabled_ != remb_enabled) { - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - int channel_id = iter->second->channel_id(); - if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, - nack_enabled_)) { - return false; - } - if (engine_->vie()->rtp()->SetRembStatus(channel_id, - remb_enabled, - remb_enabled) != 0) { - LOG_RTCERR3(SetRembStatus, channel_id, remb_enabled, remb_enabled); - return false; - } - } - remb_enabled_ = remb_enabled; - } - - // Select the first matched codec. - webrtc::VideoCodec& codec(send_codecs[0]); - - // TODO(changbin): Add support for more than on RTX payload type. Currently - // using only one to interop with previous versions of Chrome. - std::map::const_iterator rtx_it = - primary_rtx_pt_mapping.find(codec.plType); - if (rtx_it != primary_rtx_pt_mapping.end()) { - send_rtx_associated_types_[rtx_it->second] = rtx_it->first; - } - - if (BitrateIsSet(codec.minBitrate) && BitrateIsSet(codec.maxBitrate) && - codec.minBitrate > codec.maxBitrate) { - // TODO(pthatcher): This behavior contradicts other behavior in - // this file which will cause min > max to push the min down to - // the max. There are unit tests for both behaviors. We should - // pick one and do that. - LOG(LS_INFO) << "Rejecting codec with min bitrate (" - << codec.minBitrate << ") larger than max (" - << codec.maxBitrate << "). "; - return false; - } - - if (!SetSendCodec(codec)) { - return false; - } - - LogSendCodecChange("SetSendCodecs()"); - - return true; -} - -bool WebRtcVideoMediaChannel::MaybeRegisterExternalEncoder( - WebRtcVideoChannelSendInfo* send_channel, - const webrtc::VideoCodec& codec) { - // Codec type not supported or encoder already registered, so - // nothing to do. - if (!engine()->IsExternalEncoderCodecType(codec.codecType) || - send_channel->IsEncoderRegistered(codec.plType)) { - return true; - } - - bool internal_source; - webrtc::VideoEncoder* encoder = - engine()->CreateExternalEncoder(codec.codecType, &internal_source); - if (!encoder) { - // No external encoder created, so nothing to do. - return true; - } - - const int channel_id = send_channel->channel_id(); - if (engine()->vie()->ext_codec()->RegisterExternalSendCodec( - channel_id, codec.plType, encoder, internal_source) != 0) { - LOG_RTCERR2(RegisterExternalSendCodec, channel_id, codec.plName); - engine()->DestroyExternalEncoder(encoder); - return false; - } - - send_channel->RegisterEncoder(codec.plType, encoder); - return true; -} - -bool WebRtcVideoMediaChannel::GetSendCodec(VideoCodec* send_codec) { - if (!send_codec_) { - return false; - } - ConvertToCricketVideoCodec(*send_codec_, send_codec); - return true; -} - -bool WebRtcVideoMediaChannel::SetSendStreamFormat(uint32 ssrc, - const VideoFormat& format) { - WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); - if (!send_channel) { - LOG(LS_ERROR) << "The specified ssrc " << ssrc << " is not in use."; - return false; - } - - send_channel->SetAdaptFormat( - format, WebRtcVideoChannelSendInfo::kAdaptFormatTypeStream); - return true; -} - -bool WebRtcVideoMediaChannel::SetRender(bool render) { - if (render == render_started_) { - return true; // no action required - } - - bool ret = true; - for (RecvChannelMap::iterator it = recv_channels_.begin(); - it != recv_channels_.end(); ++it) { - if (render) { - if (engine()->vie()->render()->StartRender( - it->second->channel_id()) != 0) { - LOG_RTCERR1(StartRender, it->second->channel_id()); - ret = false; - } - } else { - if (engine()->vie()->render()->StopRender( - it->second->channel_id()) != 0) { - LOG_RTCERR1(StopRender, it->second->channel_id()); - ret = false; - } - } - } - if (ret) { - render_started_ = render; - } - - return ret; -} - -bool WebRtcVideoMediaChannel::SetSend(bool send) { - if (!HasReadySendChannels() && send) { - LOG(LS_ERROR) << "No stream added"; - return false; - } - if (send == sending()) { - return true; // No action required. - } - - if (send) { - // We've been asked to start sending. - // SetSendCodecs must have been called already. - if (!send_codec_) { - return false; - } - // Start send now. - if (!StartSend()) { - return false; - } - } else { - // We've been asked to stop sending. - if (!StopSend()) { - return false; - } - } - sending_ = send; - - return true; -} - -bool WebRtcVideoMediaChannel::AddSendStream(const StreamParams& sp) { - if (sp.first_ssrc() == 0) { - LOG(LS_ERROR) << "AddSendStream with 0 ssrc is not supported."; - return false; - } - - LOG(LS_INFO) << "AddSendStream " << sp.ToString(); - - if (!IsOneSsrcStream(sp) && !IsSimulcastStream(sp)) { - LOG(LS_ERROR) << "AddSendStream: bad local stream parameters"; - return false; - } - - uint32 ssrc_key; - if (!CreateSendChannelSsrcKey(sp.first_ssrc(), &ssrc_key)) { - LOG(LS_ERROR) << "Trying to register duplicate ssrc: " << sp.first_ssrc(); - return false; - } - // If the default channel is already used for sending create a new channel - // otherwise use the default channel for sending. - int channel_id = kChannelIdUnset; - if (!DefaultSendChannelIsActive()) { - channel_id = default_channel_id_; - } else { - if (!CreateChannel(ssrc_key, MD_SEND, &channel_id)) { - LOG(LS_ERROR) << "AddSendStream: unable to create channel"; - return false; - } - } - - WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrcKey(ssrc_key); - // If there are multiple send SSRCs, we can only set the first one here, and - // the rest of the SSRC(s) need to be set after SetSendCodec has been called - if (!SetLimitedNumberOfSendSsrcs(channel_id, sp, 1)) { - return false; - } - - // Set RTCP CName. - if (engine()->vie()->rtp()->SetRTCPCName(channel_id, - sp.cname.c_str()) != 0) { - LOG_RTCERR2(SetRTCPCName, channel_id, sp.cname.c_str()); - return false; - } - - // Use the SSRC of the default channel in the RTCP receiver reports. - if (IsDefaultChannelId(channel_id)) { - SetReceiverReportSsrc(sp.first_ssrc()); - } - - if (send_codec_) { - send_channel->SetAdaptFormat( - VideoFormatFromVieCodec(*send_codec_), - WebRtcVideoChannelSendInfo::kAdaptFormatTypeCodec); - - VideoSendParams send_params; - send_params.codec = *send_codec_; - send_params.stream = sp; - if (!SetSendParams(send_channel, send_params)) { - return false; - } - LogSendCodecChange("AddStream()"); - } else { - // Save the stream params for later, when we have a codec. - send_channel->set_stream_params(sp); - } - - if (sending_) { - return StartSend(send_channel); - } - return true; -} - -bool WebRtcVideoMediaChannel::RemoveSendStream(uint32 ssrc) { - if (ssrc == 0) { - LOG(LS_ERROR) << "RemoveSendStream with 0 ssrc is not supported."; - return false; - } - - uint32 ssrc_key; - if (!GetSendChannelSsrcKey(ssrc, &ssrc_key)) { - LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc - << " which doesn't exist."; - return false; - } - WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrcKey(ssrc_key); - int channel_id = send_channel->channel_id(); - if (IsDefaultChannelId(channel_id) && !send_channel->IsActive()) { - // Default channel will still exist. However, there is no stream - // to remove. - return false; - } - if (sending_) { - StopSend(send_channel); - } - - const WebRtcVideoChannelSendInfo::EncoderMap& encoder_map = - send_channel->registered_encoders(); - for (WebRtcVideoChannelSendInfo::EncoderMap::const_iterator it = - encoder_map.begin(); it != encoder_map.end(); ++it) { - if (engine()->vie()->ext_codec()->DeRegisterExternalSendCodec( - channel_id, it->first) != 0) { - LOG_RTCERR1(DeregisterEncoderObserver, channel_id); - } - engine()->DestroyExternalEncoder(it->second); - } - send_channel->ClearRegisteredEncoders(); - - // The receive channels depend on the default channel, recycle it instead. - if (IsDefaultChannelId(channel_id)) { - SetCapturer(GetDefaultSendChannelSsrc(), NULL); - send_channel->Deactivate(); - } else { - return DeleteSendChannel(ssrc_key); - } - return true; -} - -bool WebRtcVideoMediaChannel::AddRecvStream(const StreamParams& sp) { - if (sp.first_ssrc() == 0) { - LOG(LS_ERROR) << "AddRecvStream with 0 ssrc is not supported."; - return false; - } - - // TODO(zhurunz) Remove this once BWE works properly across different send - // and receive channels. - // Reuse default channel for recv stream in 1:1 call. - if (!ConferenceModeIsEnabled() && first_receive_ssrc_ == kSsrcUnset) { - LOG(LS_INFO) << "Recv stream " << sp.first_ssrc() - << " reuse default channel #" - << default_channel_id_; - first_receive_ssrc_ = sp.first_ssrc(); - if (!MaybeSetRtxSsrc(sp, default_channel_id_)) { - return false; - } - if (render_started_) { - if (engine()->vie()->render()->StartRender(default_channel_id_) !=0) { - LOG_RTCERR1(StartRender, default_channel_id_); - } - } - return true; - } - - int channel_id = kChannelIdUnset; - uint32 ssrc = sp.first_ssrc(); - WebRtcVideoChannelRecvInfo* recv_channel = GetRecvChannelBySsrc(ssrc); - if (!recv_channel && first_receive_ssrc_ != ssrc) { - // TODO(perkj): Implement recv media from multiple media SSRCs per stream. - // NOTE: We have two SSRCs per stream when RTX is enabled. - if (!IsOneSsrcStream(sp)) { - LOG(LS_ERROR) << "WebRtcVideoMediaChannel supports one primary SSRC per" - << " stream and one FID SSRC per primary SSRC."; - return false; - } - - // Create a new channel for receiving video data. - // In order to get the bandwidth estimation work fine for - // receive only channels, we connect all receiving channels - // to our master send channel. - if (!CreateChannel(sp.first_ssrc(), MD_RECV, &channel_id)) { - return false; - } - } else { - // Already exists. - if (first_receive_ssrc_ == ssrc) { - return false; - } - // Early receive added channel. - channel_id = recv_channel->channel_id(); - } - - if (!MaybeSetRtxSsrc(sp, channel_id)) { - return false; - } - - LOG(LS_INFO) << "New video stream " << sp.first_ssrc() - << " registered to VideoEngine channel #" - << channel_id << " and connected to channel #" - << default_channel_id_; - return true; -} - -bool WebRtcVideoMediaChannel::MaybeSetRtxSsrc(const StreamParams& sp, - int channel_id) { - uint32 rtx_ssrc; - bool has_rtx = sp.GetFidSsrc(sp.first_ssrc(), &rtx_ssrc); - if (has_rtx) { - LOG(LS_INFO) << "Setting rtx ssrc " << rtx_ssrc << " for stream " - << sp.first_ssrc(); - if (engine()->vie()->rtp()->SetRemoteSSRCType( - channel_id, webrtc::kViEStreamTypeRtx, rtx_ssrc) != 0) { - LOG_RTCERR3(SetRemoteSSRCType, channel_id, webrtc::kViEStreamTypeRtx, - rtx_ssrc); - return false; - } - rtx_to_primary_ssrc_[rtx_ssrc] = sp.first_ssrc(); - } - return true; -} - -bool WebRtcVideoMediaChannel::RemoveRecvStream(uint32 ssrc) { - if (ssrc == 0) { - LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported."; - return false; - } - return RemoveRecvStreamInternal(ssrc); -} - -bool WebRtcVideoMediaChannel::RemoveRecvStreamInternal(uint32 ssrc) { - // First remove the RTX SSRC mapping, to include this step even if exiting in - // the default receive channel logic below. - SsrcMap::iterator rtx_it = rtx_to_primary_ssrc_.begin(); - while (rtx_it != rtx_to_primary_ssrc_.end()) { - if (rtx_it->second == ssrc) { - rtx_to_primary_ssrc_.erase(rtx_it++); - } else { - ++rtx_it; - } - } - - WebRtcVideoChannelRecvInfo* recv_channel = GetRecvChannelBySsrc(ssrc); - if (!recv_channel) { - // TODO(perkj): Remove this once BWE works properly across different send - // and receive channels. - // The default channel is reused for recv stream in 1:1 call. - if (first_receive_ssrc_ == ssrc) { - first_receive_ssrc_ = kSsrcUnset; - // Need to stop the renderer and remove it since the render window can be - // deleted after this. - if (render_started_) { - if (engine()->vie()->render()->StopRender(default_channel_id_) !=0) { - LOG_RTCERR1(StopRender, recv_channel->channel_id()); - } - } - GetDefaultRecvChannel()->SetRenderer(NULL); - return true; - } - return false; - } - - int channel_id = recv_channel->channel_id(); - if (engine()->vie()->render()->RemoveRenderer(channel_id) != 0) { - LOG_RTCERR1(RemoveRenderer, channel_id); - } - - if (engine()->vie()->network()->DeregisterSendTransport(channel_id) !=0) { - LOG_RTCERR1(DeRegisterSendTransport, channel_id); - } - - if (engine()->vie()->codec()->DeregisterDecoderObserver( - channel_id) != 0) { - LOG_RTCERR1(DeregisterDecoderObserver, channel_id); - } - - const WebRtcVideoChannelRecvInfo::DecoderMap& decoder_map = - recv_channel->registered_decoders(); - for (WebRtcVideoChannelRecvInfo::DecoderMap::const_iterator it = - decoder_map.begin(); it != decoder_map.end(); ++it) { - if (engine()->vie()->ext_codec()->DeRegisterExternalReceiveCodec( - channel_id, it->first) != 0) { - LOG_RTCERR1(DeregisterDecoderObserver, channel_id); - } - engine()->DestroyExternalDecoder(it->second); - } - recv_channel->ClearRegisteredDecoders(); - - LOG(LS_INFO) << "Removing video stream " << ssrc - << " with VideoEngine channel #" - << channel_id; - bool ret = true; - if (engine()->vie()->base()->DeleteChannel(channel_id) == -1) { - LOG_RTCERR1(DeleteChannel, channel_id); - ret = false; - } - // Delete the WebRtcVideoChannelRecvInfo pointed to by it->second. - delete recv_channel; - recv_channels_.erase(ssrc); - return ret; -} - -bool WebRtcVideoMediaChannel::StartSend() { - bool success = true; - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - if (!StartSend(send_channel)) { - success = false; - } - } - return success; -} - -bool WebRtcVideoMediaChannel::StartSend( - WebRtcVideoChannelSendInfo* send_channel) { - const int channel_id = send_channel->channel_id(); - if (engine()->vie()->base()->StartSend(channel_id) != 0) { - LOG_RTCERR1(StartSend, channel_id); - return false; - } - - send_channel->set_sending(true); - return true; -} - -bool WebRtcVideoMediaChannel::StopSend() { - bool success = true; - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - if (!StopSend(send_channel)) { - success = false; - } - } - return success; -} - -bool WebRtcVideoMediaChannel::StopSend( - WebRtcVideoChannelSendInfo* send_channel) { - const int channel_id = send_channel->channel_id(); - if (engine()->vie()->base()->StopSend(channel_id) != 0) { - LOG_RTCERR1(StopSend, channel_id); - return false; - } - send_channel->set_sending(false); - return true; -} - -bool WebRtcVideoMediaChannel::SendIntraFrame() { - bool success = true; - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); - ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - const int channel_id = send_channel->channel_id(); - if (engine()->vie()->codec()->SendKeyFrame(channel_id) != 0) { - LOG_RTCERR1(SendKeyFrame, channel_id); - success = false; - } - } - return success; -} - -bool WebRtcVideoMediaChannel::HasReadySendChannels() { - return !send_channels_.empty() && - ((send_channels_.size() > 1) || DefaultSendChannelIsActive()); -} - -bool WebRtcVideoMediaChannel::DefaultSendChannelIsActive() { - return GetDefaultSendChannel() && GetDefaultSendChannel()->IsActive(); -} - -bool WebRtcVideoMediaChannel::GetSendChannelSsrcKey(uint32 local_ssrc, - uint32* ssrc_key) { - *ssrc_key = kDefaultChannelSsrcKey; - // If a send channel is not ready to send it will not have local_ssrc - // registered to it. - if (!HasReadySendChannels()) { - return false; - } - // The default channel is stored with ssrc key - // kDefaultChannelSsrcKey. The ssrc key therefore does not match the - // SSRC associated with the default channel. Check if the SSRC - // provided corresponds to the default channel's SSRC. - if (local_ssrc == GetDefaultSendChannelSsrc()) { - return true; - } - if (!GetSendChannelBySsrcKey(local_ssrc)) { - // If a stream has multiple ssrcs, the local_ssrc could be any of - // them, but we use the first one (StreamParams::first_ssrc()) as - // the key. - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - if (send_channel->stream_params().has_ssrc(local_ssrc)) { - *ssrc_key = iter->first; - return true; - } - } - return false; - } - // The ssrc key was found in the above std::map::find call. This - // means that the ssrc is the ssrc key. - *ssrc_key = local_ssrc; - return true; -} - -WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetDefaultSendChannel() { - return GetSendChannelBySsrcKey(kDefaultChannelSsrcKey); -} - -WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannelBySsrcKey( - uint32 ssrc_key) { - std::map::iterator iter = - send_channels_.find(ssrc_key); - if (iter == send_channels_.end()) { - return NULL; - } - return iter->second; -} - -WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannelBySsrc( - uint32 local_ssrc) { - uint32 ssrc_key; - if (!GetSendChannelSsrcKey(local_ssrc, &ssrc_key)) { - return NULL; - } - return send_channels_[ssrc_key]; -} - -bool WebRtcVideoMediaChannel::CreateSendChannelSsrcKey(uint32 local_ssrc, - uint32* ssrc_key) { - if (GetSendChannelSsrcKey(local_ssrc, ssrc_key)) { - // If there is an ssrc key corresponding to |local_ssrc|, the SSRC - // is already in use. SSRCs need to be unique in a session and at - // this point a duplicate SSRC has been detected. - return false; - } - if (!DefaultSendChannelIsActive()) { - // |ssrc_key| should be kDefaultChannelSsrcKey here as the default - // channel should be re-used whenever it is not used. - *ssrc_key = kDefaultChannelSsrcKey; - return true; - } - // SSRC is currently not in use and the default channel is already - // in use. Use the SSRC as ssrc_key since it is supposed to be - // unique in a session. - *ssrc_key = local_ssrc; - return true; -} - -int WebRtcVideoMediaChannel::GetSendChannelNum(VideoCapturer* capturer) { - int num = 0; - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - if (send_channel->video_capturer() == capturer) { - ++num; - } - } - return num; -} - -uint32 WebRtcVideoMediaChannel::GetDefaultSendChannelSsrc() { - return GetDefaultSendChannel()->stream_params().first_ssrc(); -} - -bool WebRtcVideoMediaChannel::DeleteSendChannel(uint32 ssrc_key) { - WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrcKey(ssrc_key); - if (!send_channel) { - return false; - } - MaybeDisconnectCapturer(send_channel->video_capturer()); - send_channel->set_video_capturer(NULL, engine()->vie()); - - int channel_id = send_channel->channel_id(); - int capture_id = send_channel->capture_id(); - if (engine()->vie()->codec()->DeregisterEncoderObserver( - channel_id) != 0) { - LOG_RTCERR1(DeregisterEncoderObserver, channel_id); - } - - // Destroy the external capture interface. - if (engine()->vie()->capture()->DisconnectCaptureDevice( - channel_id) != 0) { - LOG_RTCERR1(DisconnectCaptureDevice, channel_id); - } - if (engine()->vie()->capture()->ReleaseCaptureDevice( - capture_id) != 0) { - LOG_RTCERR1(ReleaseCaptureDevice, capture_id); - } - - // The default channel is stored in both |send_channels_| and - // |recv_channels_|. To make sure it is only deleted once from vie let the - // delete call happen when tearing down |recv_channels_| and not here. - if (!IsDefaultChannelId(channel_id)) { - engine_->vie()->base()->DeleteChannel(channel_id); - } - delete send_channel; - send_channels_.erase(ssrc_key); - return true; -} - -WebRtcVideoChannelRecvInfo* WebRtcVideoMediaChannel::GetDefaultRecvChannel() { - return GetRecvChannelBySsrc(kDefaultChannelSsrcKey); -} - -WebRtcVideoChannelRecvInfo* WebRtcVideoMediaChannel::GetRecvChannelBySsrc( - uint32 ssrc) { - if (recv_channels_.find(ssrc) == recv_channels_.end()) { - return NULL; - } - return recv_channels_[ssrc]; -} - -bool WebRtcVideoMediaChannel::RemoveCapturer(uint32 ssrc) { - WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); - if (!send_channel) { - return false; - } - VideoCapturer* capturer = send_channel->video_capturer(); - if (!capturer) { - return false; - } - MaybeDisconnectCapturer(capturer); - send_channel->set_video_capturer(NULL, engine()->vie()); - const int64 timestamp = send_channel->local_stream_info()->time_stamp(); - if (send_codec_) { - QueueBlackFrame(ssrc, timestamp, - VideoFormat::FpsToInterval(send_codec_->maxFramerate)); - } - return true; -} - -bool WebRtcVideoMediaChannel::SetRenderer(uint32 ssrc, - VideoRenderer* renderer) { - WebRtcVideoChannelRecvInfo* recv_channel = GetRecvChannelBySsrc(ssrc); - if (!recv_channel) { - // TODO(perkj): Remove this once BWE works properly across different send - // and receive channels. - // The default channel is reused for recv stream in 1:1 call. - if (first_receive_ssrc_ == ssrc && GetDefaultRecvChannel()) { - LOG(LS_INFO) << "SetRenderer " << ssrc - << " reuse default channel #" - << default_channel_id_; - GetDefaultRecvChannel()->SetRenderer(renderer); - return true; - } - return false; - } - - recv_channel->SetRenderer(renderer); - return true; -} - -bool WebRtcVideoMediaChannel::GetStats(VideoMediaInfo* info) { - // Get sender statistics and build VideoSenderInfo. - unsigned int total_bitrate_sent = 0; - unsigned int video_bitrate_sent = 0; - unsigned int fec_bitrate_sent = 0; - unsigned int nack_bitrate_sent = 0; - unsigned int estimated_send_bandwidth = 0; - unsigned int target_enc_bitrate = 0; - if (send_codec_) { - for (SendChannelMap::const_iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - const int channel_id = send_channel->channel_id(); - VideoSenderInfo sinfo; - if (!send_channel->IsActive()) { - // This should only happen if the default vie channel is not in use. - // This can happen if no streams have ever been added or the stream - // corresponding to the default channel has been removed. Note that - // there may be non-default vie channels in use when this happen so - // asserting send_channels_.size() == 1 is not correct and neither is - // breaking out of the loop. - ASSERT(channel_id == default_channel_id_); - continue; - } - size_t bytes_sent, bytes_recv; - unsigned int packets_sent, packets_recv; - if (engine_->vie()->rtp()->GetRTPStatistics(channel_id, bytes_sent, - packets_sent, bytes_recv, - packets_recv) != 0) { - LOG_RTCERR1(GetRTPStatistics, default_channel_id_); - continue; - } - WebRtcLocalStreamInfo* channel_stream_info = - send_channel->local_stream_info(); - - const StreamParams& sp = send_channel->stream_params(); - for (size_t i = 0; i < sp.ssrcs.size(); ++i) { - sinfo.add_ssrc(sp.ssrcs[i]); - } - sinfo.codec_name = send_codec_->plName; - sinfo.bytes_sent = bytes_sent; - sinfo.packets_sent = packets_sent; - sinfo.packets_cached = -1; - sinfo.packets_lost = -1; - sinfo.fraction_lost = -1; - sinfo.rtt_ms = -1; - - VideoCapturer* video_capturer = send_channel->video_capturer(); - if (video_capturer) { - VideoFormat last_captured_frame_format; - video_capturer->GetStats(&sinfo.adapt_frame_drops, - &sinfo.effects_frame_drops, - &sinfo.capturer_frame_time, - &last_captured_frame_format); - sinfo.input_frame_width = last_captured_frame_format.width; - sinfo.input_frame_height = last_captured_frame_format.height; - } else { - sinfo.input_frame_width = 0; - sinfo.input_frame_height = 0; - } - - webrtc::VideoCodec vie_codec; - if (!video_capturer || video_capturer->IsMuted()) { - sinfo.send_frame_width = 0; - sinfo.send_frame_height = 0; - } else if (engine()->vie()->codec()->GetSendCodec(channel_id, - vie_codec) == 0) { - sinfo.send_frame_width = vie_codec.width; - sinfo.send_frame_height = vie_codec.height; - } else { - sinfo.send_frame_width = -1; - sinfo.send_frame_height = -1; - LOG_RTCERR1(GetSendCodec, channel_id); - } - sinfo.framerate_input = channel_stream_info->framerate(); - sinfo.framerate_sent = send_channel->encoder_observer()->framerate(); - sinfo.nominal_bitrate = send_channel->encoder_observer()->bitrate(); - if (send_codec_) { - sinfo.preferred_bitrate = GetBitrate( - send_codec_->maxBitrate, kMaxVideoBitrate); - } - sinfo.adapt_reason = send_channel->CurrentAdaptReason(); - sinfo.adapt_changes = send_channel->AdaptChanges(); - - webrtc::CpuOveruseMetrics metrics; - engine()->vie()->base()->GetCpuOveruseMetrics(channel_id, &metrics); - sinfo.avg_encode_ms = metrics.avg_encode_time_ms; - sinfo.encode_usage_percent = metrics.encode_usage_percent; - - webrtc::RtcpPacketTypeCounter rtcp_counter; - if (engine()->vie()->rtp()->GetSendRtcpPacketTypeCounter( - channel_id, &rtcp_counter) == 0) { - sinfo.firs_rcvd = rtcp_counter.fir_packets; - sinfo.plis_rcvd = rtcp_counter.pli_packets; - sinfo.nacks_rcvd = rtcp_counter.nack_packets; - } else { - sinfo.firs_rcvd = -1; - sinfo.plis_rcvd = -1; - sinfo.nacks_rcvd = -1; - LOG_RTCERR1(GetRtcpPacketTypeCounters, channel_id); - } - - // Get received RTCP statistics for the sender (reported by the remote - // client in a RTCP packet), if available. - // It's not a fatal error if we can't, since RTCP may not have arrived - // yet. - webrtc::RtcpStatistics outgoing_stream_rtcp_stats; - int64_t outgoing_stream_rtt_ms; - - if (engine_->vie()->rtp()->GetSendChannelRtcpStatistics( - channel_id, - outgoing_stream_rtcp_stats, - outgoing_stream_rtt_ms) == 0) { - // Convert Q8 to float. - sinfo.packets_lost = outgoing_stream_rtcp_stats.cumulative_lost; - sinfo.fraction_lost = static_cast( - outgoing_stream_rtcp_stats.fraction_lost) / (1 << 8); - sinfo.rtt_ms = outgoing_stream_rtt_ms; - } - info->senders.push_back(sinfo); - - unsigned int channel_total_bitrate_sent = 0; - unsigned int channel_video_bitrate_sent = 0; - unsigned int channel_fec_bitrate_sent = 0; - unsigned int channel_nack_bitrate_sent = 0; - if (engine_->vie()->rtp()->GetBandwidthUsage( - channel_id, channel_total_bitrate_sent, channel_video_bitrate_sent, - channel_fec_bitrate_sent, channel_nack_bitrate_sent) == 0) { - total_bitrate_sent += channel_total_bitrate_sent; - video_bitrate_sent += channel_video_bitrate_sent; - fec_bitrate_sent += channel_fec_bitrate_sent; - nack_bitrate_sent += channel_nack_bitrate_sent; - } else { - LOG_RTCERR1(GetBandwidthUsage, channel_id); - } - - unsigned int target_enc_stream_bitrate = 0; - if (engine_->vie()->codec()->GetCodecTargetBitrate( - channel_id, &target_enc_stream_bitrate) == 0) { - target_enc_bitrate += target_enc_stream_bitrate; - } else { - LOG_RTCERR1(GetCodecTargetBitrate, channel_id); - } - } - if (!send_channels_.empty()) { - // GetEstimatedSendBandwidth returns the estimated bandwidth for all video - // engine channels in a channel group. Any valid channel id will do as it - // is only used to access the right group of channels. - const int channel_id = send_channels_.begin()->second->channel_id(); - // Get the send bandwidth available for this MediaChannel. - if (engine_->vie()->rtp()->GetEstimatedSendBandwidth( - channel_id, &estimated_send_bandwidth) != 0) { - LOG_RTCERR1(GetEstimatedSendBandwidth, channel_id); - } - } - } else { - LOG(LS_WARNING) << "GetStats: sender information not ready."; - } - - // Get the SSRC and stats for each receiver, based on our own calculations. - for (RecvChannelMap::const_iterator it = recv_channels_.begin(); - it != recv_channels_.end(); ++it) { - WebRtcVideoChannelRecvInfo* channel = it->second; - - unsigned int ssrc = 0; - // Get receiver statistics and build VideoReceiverInfo, if we have data. - // Skip the default channel (ssrc == 0). - if (engine_->vie()->rtp()->GetRemoteSSRC( - channel->channel_id(), ssrc) != 0 || - ssrc == 0) - continue; - - webrtc::StreamDataCounters sent; - webrtc::StreamDataCounters received; - if (engine_->vie()->rtp()->GetRtpStatistics(channel->channel_id(), - sent, received) != 0) { - LOG_RTCERR1(GetRTPStatistics, channel->channel_id()); - return false; - } - VideoReceiverInfo rinfo; - rinfo.add_ssrc(ssrc); - rinfo.bytes_rcvd = received.transmitted.payload_bytes; - rinfo.packets_rcvd = received.transmitted.packets; - rinfo.packets_lost = -1; - rinfo.packets_concealed = -1; - rinfo.fraction_lost = -1; // from SentRTCP - rinfo.frame_width = channel->render_adapter()->width(); - rinfo.frame_height = channel->render_adapter()->height(); - int fps = channel->render_adapter()->framerate(); - rinfo.framerate_decoded = fps; - rinfo.framerate_output = fps; - rinfo.capture_start_ntp_time_ms = - channel->render_adapter()->capture_start_ntp_time_ms(); - channel->decoder_observer()->ExportTo(&rinfo); - - webrtc::RtcpPacketTypeCounter rtcp_counter; - if (engine()->vie()->rtp()->GetReceiveRtcpPacketTypeCounter( - channel->channel_id(), &rtcp_counter) == 0) { - rinfo.firs_sent = rtcp_counter.fir_packets; - rinfo.plis_sent = rtcp_counter.pli_packets; - rinfo.nacks_sent = rtcp_counter.nack_packets; - } else { - rinfo.firs_sent = -1; - rinfo.plis_sent = -1; - rinfo.nacks_sent = -1; - LOG_RTCERR1(GetRtcpPacketTypeCounters, channel->channel_id()); - } - - // Get our locally created statistics of the received RTP stream. - webrtc::RtcpStatistics incoming_stream_rtcp_stats; - int64_t incoming_stream_rtt_ms; - if (engine_->vie()->rtp()->GetReceiveChannelRtcpStatistics( - channel->channel_id(), - incoming_stream_rtcp_stats, - incoming_stream_rtt_ms) == 0) { - // Convert Q8 to float. - rinfo.packets_lost = incoming_stream_rtcp_stats.cumulative_lost; - rinfo.fraction_lost = static_cast( - incoming_stream_rtcp_stats.fraction_lost) / (1 << 8); - } - info->receivers.push_back(rinfo); - } - unsigned int estimated_recv_bandwidth = 0; - if (!recv_channels_.empty()) { - // GetEstimatedReceiveBandwidth returns the estimated bandwidth for all - // video engine channels in a channel group. Any valid channel id will do as - // it is only used to access the right group of channels. - const int channel_id = recv_channels_.begin()->second->channel_id(); - // Gets the estimated receive bandwidth for the MediaChannel. - if (engine_->vie()->rtp()->GetEstimatedReceiveBandwidth( - channel_id, &estimated_recv_bandwidth) != 0) { - LOG_RTCERR1(GetEstimatedReceiveBandwidth, channel_id); - } - } - - // Build BandwidthEstimationInfo. - // TODO(zhurunz): Add real unittest for this. - BandwidthEstimationInfo bwe; - engine_->vie()->rtp()->GetPacerQueuingDelayMs( - GetDefaultRecvChannel()->channel_id(), &bwe.bucket_delay); - - // Calculations done above per send/receive stream. - bwe.actual_enc_bitrate = video_bitrate_sent; - bwe.transmit_bitrate = total_bitrate_sent; - bwe.retransmit_bitrate = nack_bitrate_sent; - bwe.available_send_bandwidth = estimated_send_bandwidth; - bwe.available_recv_bandwidth = estimated_recv_bandwidth; - bwe.target_enc_bitrate = target_enc_bitrate; - - info->bw_estimations.push_back(bwe); - - return true; -} - -bool WebRtcVideoMediaChannel::SetCapturer(uint32 ssrc, - VideoCapturer* capturer) { - ASSERT(ssrc != 0); - if (!capturer) { - return RemoveCapturer(ssrc); - } - WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); - if (!send_channel) { - return false; - } - VideoCapturer* old_capturer = send_channel->video_capturer(); - MaybeDisconnectCapturer(old_capturer); - - send_channel->set_video_capturer(capturer, engine()->vie()); - MaybeConnectCapturer(capturer); - if (!capturer->IsScreencast() && ratio_w_ != 0 && ratio_h_ != 0) { - capturer->UpdateAspectRatio(ratio_w_, ratio_h_); - } - const int64 timestamp = send_channel->local_stream_info()->time_stamp(); - if (send_codec_) { - QueueBlackFrame(ssrc, timestamp, - VideoFormat::FpsToInterval(send_codec_->maxFramerate)); - } - - capturer->SetApplyRotation( - !FindHeaderExtension(send_extensions_, kRtpVideoRotationHeaderExtension)); - - return true; -} - -bool WebRtcVideoMediaChannel::RequestIntraFrame() { - // There is no API exposed to application to request a key frame - // ViE does this internally when there are errors from decoder - return false; -} - -void WebRtcVideoMediaChannel::OnPacketReceived( - rtc::Buffer* packet, const rtc::PacketTime& packet_time) { - // Pick which channel to send this packet to. If this packet doesn't match - // any multiplexed streams, just send it to the default channel. Otherwise, - // send it to the specific decoder instance for that stream. - uint32 ssrc = 0; - if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) - return; - int processing_channel_id = GetRecvChannelId(ssrc); - if (processing_channel_id == kChannelIdUnset) { - // Allocate an unsignalled recv channel for processing in conference mode. - if (!ConferenceModeIsEnabled()) { - // If we can't find or allocate one, use the default. - processing_channel_id = default_channel_id_; - } else if (!CreateUnsignalledRecvChannel(ssrc, &processing_channel_id)) { - // If we can't create an unsignalled recv channel, drop the packet in - // conference mode. - return; - } - } - - engine()->vie()->network()->ReceivedRTPPacket( - processing_channel_id, packet->data(), packet->size(), - webrtc::PacketTime(packet_time.timestamp, packet_time.not_before)); -} - -void WebRtcVideoMediaChannel::OnRtcpReceived( - rtc::Buffer* packet, const rtc::PacketTime& packet_time) { -// Sending channels need all RTCP packets with feedback information. -// Even sender reports can contain attached report blocks. -// Receiving channels need sender reports in order to create -// correct receiver reports. - - uint32 ssrc = 0; - if (!GetRtcpSsrc(packet->data(), packet->size(), &ssrc)) { - LOG(LS_WARNING) << "Failed to parse SSRC from received RTCP packet"; - return; - } - int type = 0; - if (!GetRtcpType(packet->data(), packet->size(), &type)) { - LOG(LS_WARNING) << "Failed to parse type from received RTCP packet"; - return; - } - - // If it is a sender report, find the channel that is listening. - if (type == kRtcpTypeSR) { - int recv_channel_id = GetRecvChannelId(ssrc); - if (recv_channel_id != kChannelIdUnset && !IsDefaultChannelId(recv_channel_id)) { - engine_->vie()->network()->ReceivedRTCPPacket( - recv_channel_id, packet->data(), packet->size()); - } - } - // SR may continue RR and any RR entry may correspond to any one of the send - // channels. So all RTCP packets must be forwarded all send channels. ViE - // will filter out RR internally. - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - int channel_id = send_channel->channel_id(); - engine_->vie()->network()->ReceivedRTCPPacket(channel_id, packet->data(), - packet->size()); - } -} - -void WebRtcVideoMediaChannel::OnReadyToSend(bool ready) { - SetNetworkTransmissionState(ready); -} - -bool WebRtcVideoMediaChannel::MuteStream(uint32 ssrc, bool muted) { - WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); - if (!send_channel) { - LOG(LS_ERROR) << "The specified ssrc " << ssrc << " is not in use."; - return false; - } - send_channel->set_muted(muted); - return true; -} - -bool WebRtcVideoMediaChannel::SetRecvRtpHeaderExtensions( - const std::vector& extensions) { - if (receive_extensions_ == extensions) { - return true; - } - - const RtpHeaderExtension* offset_extension = - FindHeaderExtension(extensions, kRtpTimestampOffsetHeaderExtension); - const RtpHeaderExtension* send_time_extension = - FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension); - const RtpHeaderExtension* cvo_extension = - FindHeaderExtension(extensions, kRtpVideoRotationHeaderExtension); - - // Loop through all receive channels and enable/disable the extensions. - for (RecvChannelMap::iterator channel_it = recv_channels_.begin(); - channel_it != recv_channels_.end(); ++channel_it) { - int channel_id = channel_it->second->channel_id(); - if (!SetHeaderExtension( - &webrtc::ViERTP_RTCP::SetReceiveTimestampOffsetStatus, channel_id, - offset_extension)) { - return false; - } - if (!SetHeaderExtension( - &webrtc::ViERTP_RTCP::SetReceiveAbsoluteSendTimeStatus, channel_id, - send_time_extension)) { - return false; - } - if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetReceiveVideoRotationStatus, - channel_id, cvo_extension)) { - return false; - } - } - - receive_extensions_ = extensions; - return true; -} - -bool WebRtcVideoMediaChannel::SetSendRtpHeaderExtensions( - const std::vector& extensions) { - if (send_extensions_ == extensions) { - return true; - } - - const RtpHeaderExtension* offset_extension = - FindHeaderExtension(extensions, kRtpTimestampOffsetHeaderExtension); - const RtpHeaderExtension* send_time_extension = - FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension); - const RtpHeaderExtension* cvo_extension = - FindHeaderExtension(extensions, kRtpVideoRotationHeaderExtension); - - // Loop through all send channels and enable/disable the extensions. - for (SendChannelMap::iterator channel_it = send_channels_.begin(); - channel_it != send_channels_.end(); ++channel_it) { - int channel_id = channel_it->second->channel_id(); - if (!SetHeaderExtension( - &webrtc::ViERTP_RTCP::SetSendTimestampOffsetStatus, channel_id, - offset_extension)) { - return false; - } - if (!SetHeaderExtension( - &webrtc::ViERTP_RTCP::SetSendAbsoluteSendTimeStatus, channel_id, - send_time_extension)) { - return false; - } - if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetSendVideoRotationStatus, - channel_id, cvo_extension)) { - return false; - } - } - - if (send_time_extension) { - // For video RTP packets, we would like to update AbsoluteSendTimeHeader - // Extension closer to the network, @ socket level before sending. - // Pushing the extension id to socket layer. - MediaChannel::SetOption(NetworkInterface::ST_RTP, - rtc::Socket::OPT_RTP_SENDTIME_EXTN_ID, - send_time_extension->id); - } - - // For now assume that all streams want the same CVO setting. - // TODO(guoweis): Remove the need for this assumption. - for (const auto& kv : send_channels_) { - if (kv.second->video_capturer()) { - kv.second->video_capturer()->SetApplyRotation(!cvo_extension); - } - } - - send_extensions_ = extensions; - return true; -} - -int WebRtcVideoMediaChannel::GetRtpSendTimeExtnId() const { - const RtpHeaderExtension* send_time_extension = FindHeaderExtension( - send_extensions_, kRtpAbsoluteSenderTimeHeaderExtension); - if (send_time_extension) { - return send_time_extension->id; - } - return -1; -} - -bool WebRtcVideoMediaChannel::SetMaxSendBandwidth(int bps) { - LOG(LS_INFO) << "WebRtcVideoMediaChannel::SetMaxSendBandwidth"; - - if (!send_codec_) { - LOG(LS_INFO) << "The send codec has not been set up yet"; - return true; - } - - webrtc::VideoCodec new_codec = *send_codec_; - if (BitrateIsSet(bps)) { - new_codec.maxBitrate = bps / 1000; - } - if (!SetSendCodec(new_codec)) { - return false; - } - LogSendCodecChange("SetMaxSendBandwidth()"); - - return true; -} - -bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) { - // Always accept options that are unchanged. - if (options_ == options) { - return true; - } - - // Save the options, to be interpreted where appropriate. - // Use options_.SetAll() instead of assignment so that unset value in options - // will not overwrite the previous option value. - VideoOptions original = options_; - options_.SetAll(options); - - Clamp(&options_.system_low_adaptation_threshhold, 0.0f, 1.0f); - Clamp(&options_.system_high_adaptation_threshhold, 0.0f, 1.0f); - - bool use_simulcast_adapter; - if (options.use_simulcast_adapter.Get(&use_simulcast_adapter) && - options.use_simulcast_adapter != original.use_simulcast_adapter) { - webrtc::VP8EncoderFactoryConfig::set_use_simulcast_adapter( - use_simulcast_adapter); - } - - // Set CPU options and codec options for all send channels. - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - send_channel->ApplyCpuOptions(options_); - - if (send_codec_) { - VideoSendParams send_params = send_channel->send_params(); - - bool conference_mode_turned_off = ( - original.conference_mode.IsSet() && - options.conference_mode.IsSet() && - original.conference_mode.GetWithDefaultIfUnset(false) && - !options.conference_mode.GetWithDefaultIfUnset(false)); - if (conference_mode_turned_off) { - // This is a special case for turning conference mode off. - // Max bitrate should go back to the default maximum value instead - // of the current maximum. - send_params.codec.maxBitrate = kAutoBandwidth; - } - - // TODO(pthatcher): Remove this. We don't need 4 ways to set bitrates. - int new_start_bitrate; - if (options.video_start_bitrate.Get(&new_start_bitrate)) { - send_params.codec.startBitrate = new_start_bitrate; - } - - if (!SetSendParams(send_channel, send_params)) { - return false; - } - LogSendCodecChange("SetOptions()"); - } - } - - - int buffer_latency; - if (Changed(options.buffered_mode_latency, - original.buffered_mode_latency, - &buffer_latency)) { - LOG(LS_INFO) << "Buffer latency is " << buffer_latency; - for (SendChannelMap::iterator it = send_channels_.begin(); - it != send_channels_.end(); ++it) { - if (engine()->vie()->rtp()->SetSenderBufferingMode( - it->second->channel_id(), buffer_latency) != 0) { - LOG_RTCERR2(SetSenderBufferingMode, it->second->channel_id(), - buffer_latency); - } - } - for (RecvChannelMap::iterator it = recv_channels_.begin(); - it != recv_channels_.end(); ++it) { - if (engine()->vie()->rtp()->SetReceiverBufferingMode( - it->second->channel_id(), buffer_latency) != 0) { - LOG_RTCERR2(SetReceiverBufferingMode, it->second->channel_id(), - buffer_latency); - } - } - } - - bool dscp_enabled; - if (Changed(options.dscp, original.dscp, &dscp_enabled)) { - rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; - if (dscp_enabled) { - dscp = kVideoDscpValue; - } - LOG(LS_INFO) << "DSCP is " << dscp; - if (MediaChannel::SetDscp(dscp) != 0) { - LOG(LS_WARNING) << "Failed to set DSCP settings for video channel"; - } - } - - bool suspend_below_min_bitrate; - if (Changed(options.suspend_below_min_bitrate, - original.suspend_below_min_bitrate, - &suspend_below_min_bitrate)) { - if (suspend_below_min_bitrate) { - LOG(LS_INFO) << "Suspend below min bitrate enabled."; - for (SendChannelMap::iterator it = send_channels_.begin(); - it != send_channels_.end(); ++it) { - engine()->vie()->codec()->SuspendBelowMinBitrate( - it->second->channel_id()); - } - } else { - LOG(LS_WARNING) << "Cannot disable video suspension once it is enabled"; - } - } - - webrtc::CpuOveruseOptions overuse_options; - if (GetCpuOveruseOptions(options_, &overuse_options)) { - for (SendChannelMap::iterator it = send_channels_.begin(); - it != send_channels_.end(); ++it) { - if (engine()->vie()->base()->SetCpuOveruseOptions( - it->second->channel_id(), overuse_options) != 0) { - LOG_RTCERR1(SetCpuOveruseOptions, it->second->channel_id()); - } - } - } - return true; -} - -void WebRtcVideoMediaChannel::SetInterface(NetworkInterface* iface) { - MediaChannel::SetInterface(iface); - // Set the RTP recv/send buffer to a bigger size - MediaChannel::SetOption(NetworkInterface::ST_RTP, - rtc::Socket::OPT_RCVBUF, - kVideoRtpBufferSize); - - // Speculative change to increase the outbound socket buffer size. - // In b/15152257, we are seeing a significant number of packets discarded - // due to lack of socket buffer space, although it's not yet clear what the - // ideal value should be. - MediaChannel::SetOption(NetworkInterface::ST_RTP, - rtc::Socket::OPT_SNDBUF, - kVideoRtpBufferSize); -} - -void WebRtcVideoMediaChannel::UpdateAspectRatio(int ratio_w, int ratio_h) { - ASSERT(ratio_w != 0); - ASSERT(ratio_h != 0); - ratio_w_ = ratio_w; - ratio_h_ = ratio_h; - // For now assume that all streams want the same aspect ratio. - // TODO(hellner): remove the need for this assumption. - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - VideoCapturer* capturer = send_channel->video_capturer(); - if (capturer) { - capturer->UpdateAspectRatio(ratio_w, ratio_h); - } - } -} - -bool WebRtcVideoMediaChannel::GetRenderer(uint32 ssrc, - VideoRenderer** renderer) { - WebRtcVideoChannelRecvInfo* recv_channel = GetRecvChannelBySsrc(ssrc); - if (!recv_channel) { - if (first_receive_ssrc_ == ssrc && GetDefaultRecvChannel()) { - LOG(LS_INFO) << " GetRenderer " << ssrc - << " reuse default renderer #" - << default_channel_id_; - *renderer = GetDefaultRecvChannel()->render_adapter()->renderer(); - return true; - } - return false; - } - - *renderer = recv_channel->render_adapter()->renderer(); - return true; -} - -bool WebRtcVideoMediaChannel::GetVideoAdapter( - uint32 ssrc, CoordinatedVideoAdapter** video_adapter) { - WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); - if (!send_channel) { - return false; - } - *video_adapter = send_channel->video_adapter(); - return true; -} - -void WebRtcVideoMediaChannel::SendFrame(VideoCapturer* capturer, - const VideoFrame* frame) { - // If the |capturer| is registered to any send channel, then send the frame - // to those send channels. - bool capturer_is_channel_owned = false; - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - if (send_channel->video_capturer() == capturer) { - SendFrame(send_channel, frame, capturer->IsScreencast()); - capturer_is_channel_owned = true; - } - } - if (capturer_is_channel_owned) { - return; - } - - // TODO(hellner): Remove below for loop once the captured frame no longer - // come from the engine, i.e. the engine no longer owns a capturer. - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - if (!send_channel->video_capturer()) { - SendFrame(send_channel, frame, capturer->IsScreencast()); - } - } -} - -bool WebRtcVideoMediaChannel::SendFrame( - WebRtcVideoChannelSendInfo* send_channel, - const VideoFrame* frame, - bool is_screencast) { - if (!send_channel) { - return false; - } - - bool changed; - send_channel->SetLastCapturedFrameInfo(frame, is_screencast, &changed); - - if (!send_codec_) { - // Send codec has not been set. No reason to process the frame any further. - return false; - } - - // TODO(pthatcher): Move drop logic to adapter. - // If the frame should be dropped. - if (send_channel->adapt_format_set() && - send_channel->adapt_format().width == 0 && - send_channel->adapt_format().height == 0) { - return true; - } - - if (changed) { - // If the last captured frame info changed, then calling - // SetSendParams will update to the latest resolution. - VideoSendParams send_params = send_channel->send_params(); - // Note: We must copy the send_params because otherwise the memory - // checker will complain. - if (!SetSendParams(send_channel, send_params)) { - LOG(LS_ERROR) << "SetSendParams from SendFrame failed with " - << frame->GetWidth() << "x" << frame->GetHeight() - << " screencast? " << is_screencast; - return false; - } - LogSendCodecChange("Captured frame size changed"); - } - - const VideoFrame* frame_out = frame; - rtc::scoped_ptr processed_frame; - // TODO(hellner): Remove the need for disabling mute when screencasting. - const bool mute = (send_channel->muted() && !is_screencast); - send_channel->ProcessFrame(*frame_out, mute, processed_frame.use()); - if (processed_frame) { - frame_out = processed_frame.get(); - } - - webrtc::I420VideoFrame webrtc_frame(frame_out->GetVideoFrameBuffer(), 0, 0, - frame_out->GetVideoRotation()); - int64 timestamp_ntp_ms = 0; - // TODO(justinlin): Reenable after Windows issues with clock drift are fixed. - // Currently reverted to old behavior of discarding capture timestamp. -#if 0 - static const int kTimestampDeltaInSecondsForWarning = 2; - - // If the frame timestamp is 0, we will use the deliver time. - const int64 frame_timestamp = frame->GetTimeStamp(); - if (frame_timestamp != 0) { - if (abs(time(NULL) - frame_timestamp / rtc::kNumNanosecsPerSec) > - kTimestampDeltaInSecondsForWarning) { - LOG(LS_WARNING) << "Frame timestamp differs by more than " - << kTimestampDeltaInSecondsForWarning << " seconds from " - << "current Unix timestamp."; - } - - timestamp_ntp_ms = - rtc::UnixTimestampNanosecsToNtpMillisecs(frame_timestamp); - } -#endif - webrtc_frame.set_ntp_time_ms(timestamp_ntp_ms); - send_channel->external_capture()->IncomingFrame(webrtc_frame); - return true; -} - -bool WebRtcVideoMediaChannel::CreateChannel(uint32 ssrc_key, - MediaDirection direction, - int* channel_id) { - // There are 3 types of channels. Sending only, receiving only and - // sending and receiving. The sending and receiving channel is the - // default channel and there is only one. All other channels that - // are created are associated with the default channel which must - // exist. The default channel id is stored in - // |default_channel_id_|. All channels need to know about the - // default channel to properly handle remb which is why there are - // different ViE create channel calls. For this channel the local - // and remote ssrc_key is kDefaultChannelSsrcKey. However, it may - // have a non-zero local and/or remote ssrc depending on if it is - // currently sending and/or receiving. - if ((default_channel_id_ == kChannelIdUnset || direction == MD_SENDRECV) && - (!send_channels_.empty() || !recv_channels_.empty())) { - ASSERT(false); - return false; - } - - *channel_id = kChannelIdUnset; - if (direction == MD_RECV) { - // All rec channels are associated with default_channel_id_. - if (engine_->vie()->base()->CreateReceiveChannel(*channel_id, - default_channel_id_) != 0) { - LOG_RTCERR2(CreateReceiveChannel, *channel_id, default_channel_id_); - return false; - } - } else if (direction == MD_SEND) { - if (engine_->vie()->base()->CreateChannel(*channel_id, - default_channel_id_) != 0) { - LOG_RTCERR2(CreateChannel, *channel_id, default_channel_id_); - return false; - } - } else { - ASSERT(direction == MD_SENDRECV); - if (engine_->vie()->base()->CreateChannel(*channel_id) != 0) { - LOG_RTCERR1(CreateChannel, *channel_id); - return false; - } - } - if (!ConfigureChannel(*channel_id, direction, ssrc_key)) { - engine_->vie()->base()->DeleteChannel(*channel_id); - *channel_id = kChannelIdUnset; - return false; - } - - return true; -} - -bool WebRtcVideoMediaChannel::CreateUnsignalledRecvChannel( - uint32 ssrc_key, int* out_channel_id) { - int unsignalled_recv_channel_limit = - options_.unsignalled_recv_stream_limit.GetWithDefaultIfUnset( - kNumDefaultUnsignalledVideoRecvStreams); - if (num_unsignalled_recv_channels_ >= unsignalled_recv_channel_limit) { - return false; - } - if (!CreateChannel(ssrc_key, MD_RECV, out_channel_id)) { - return false; - } - // TODO(tvsriram): Support dynamic sizing of unsignalled recv channels. - num_unsignalled_recv_channels_++; - return true; -} - -bool WebRtcVideoMediaChannel::ConfigureChannel(int channel_id, - MediaDirection direction, - uint32 ssrc_key) { - const bool receiving = (direction == MD_RECV) || (direction == MD_SENDRECV); - const bool sending = (direction == MD_SEND) || (direction == MD_SENDRECV); - // Register external transport. - if (engine_->vie()->network()->RegisterSendTransport( - channel_id, *this) != 0) { - LOG_RTCERR1(RegisterSendTransport, channel_id); - return false; - } - - // Set MTU. - if (engine_->vie()->network()->SetMTU(channel_id, kVideoMtu) != 0) { - LOG_RTCERR2(SetMTU, channel_id, kVideoMtu); - return false; - } - // Turn on RTCP and loss feedback reporting. - if (engine()->vie()->rtp()->SetRTCPStatus( - channel_id, webrtc::kRtcpCompound_RFC4585) != 0) { - LOG_RTCERR2(SetRTCPStatus, channel_id, webrtc::kRtcpCompound_RFC4585); - return false; - } - // Enable pli as key frame request method. - if (engine_->vie()->rtp()->SetKeyFrameRequestMethod( - channel_id, webrtc::kViEKeyFrameRequestPliRtcp) != 0) { - LOG_RTCERR2(SetKeyFrameRequestMethod, - channel_id, webrtc::kViEKeyFrameRequestPliRtcp); - return false; - } - if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, nack_enabled_)) { - // Logged in SetNackFec. Don't spam the logs. - return false; - } - // Note that receiving must always be configured before sending to ensure - // that send and receive channel is configured correctly (ConfigureReceiving - // assumes no sending). - if (receiving) { - if (!ConfigureReceiving(channel_id, ssrc_key)) { - return false; - } - } - if (sending) { - if (!ConfigureSending(channel_id, ssrc_key)) { - return false; - } - } - - // Start receiving for both receive and send channels so that we get incoming - // RTP (if receiving) as well as RTCP feedback (if sending). - if (engine()->vie()->base()->StartReceive(channel_id) != 0) { - LOG_RTCERR1(StartReceive, channel_id); - return false; - } - - return true; -} - -bool WebRtcVideoMediaChannel::ConfigureReceiving(int channel_id, - uint32 remote_ssrc) { - // Make sure that an SSRC isn't registered more than once. - if (GetRecvChannelBySsrc(remote_ssrc)) { - return false; - } - // Connect the voice channel, if there is one. - // TODO(perkj): The A/V is synched by the receiving channel. So we need to - // know the SSRC of the remote audio channel in order to fetch the correct - // webrtc VoiceEngine channel. For now- only sync the default channel used - // in 1-1 calls. - if (remote_ssrc == kDefaultChannelSsrcKey && voice_channel_) { - WebRtcVoiceMediaChannel* voice_channel = - static_cast(voice_channel_); - if (engine_->vie()->base()->ConnectAudioChannel( - default_channel_id_, voice_channel->voe_channel()) != 0) { - LOG_RTCERR2(ConnectAudioChannel, channel_id, - voice_channel->voe_channel()); - LOG(LS_WARNING) << "A/V not synchronized"; - // Not a fatal error. - } - } - - rtc::scoped_ptr channel_info( - new WebRtcVideoChannelRecvInfo(channel_id)); - - // Install a render adapter. - if (engine_->vie()->render()->AddRenderer(channel_id, - webrtc::kVideoI420, channel_info->render_adapter()) != 0) { - LOG_RTCERR3(AddRenderer, channel_id, webrtc::kVideoI420, - channel_info->render_adapter()); - return false; - } - - if (engine()->vie()->render()->SetExpectedRenderDelay( - channel_id, kDefaultRenderDelayMs)) { - LOG_RTCERR2(SetExpectedRenderDelay, - channel_id, kDefaultRenderDelayMs); - } - - if (engine_->vie()->rtp()->SetRembStatus(channel_id, - kNotSending, - remb_enabled_) != 0) { - LOG_RTCERR3(SetRembStatus, channel_id, kNotSending, remb_enabled_); - return false; - } - - if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetReceiveTimestampOffsetStatus, - channel_id, receive_extensions_, kRtpTimestampOffsetHeaderExtension)) { - return false; - } - if (!SetHeaderExtension( - &webrtc::ViERTP_RTCP::SetReceiveAbsoluteSendTimeStatus, channel_id, - receive_extensions_, kRtpAbsoluteSenderTimeHeaderExtension)) { - return false; - } - if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetReceiveVideoRotationStatus, - channel_id, receive_extensions_, - kRtpVideoRotationHeaderExtension)) { - return false; - } - - if (receiver_report_ssrc_ != kSsrcUnset) { - if (engine()->vie()->rtp()->SetLocalSSRC( - channel_id, receiver_report_ssrc_) == -1) { - LOG_RTCERR2(SetLocalSSRC, channel_id, receiver_report_ssrc_); - return false; - } - } - - // Disable color enhancement since it is a bit too aggressive. - if (engine()->vie()->image()->EnableColorEnhancement(channel_id, - false) != 0) { - LOG_RTCERR1(EnableColorEnhancement, channel_id); - return false; - } - - if (!SetReceiveCodecs(channel_info.get())) { - return false; - } - - int buffer_latency = - options_.buffered_mode_latency.GetWithDefaultIfUnset( - cricket::kBufferedModeDisabled); - if (buffer_latency != cricket::kBufferedModeDisabled) { - if (engine()->vie()->rtp()->SetReceiverBufferingMode( - channel_id, buffer_latency) != 0) { - LOG_RTCERR2(SetReceiverBufferingMode, channel_id, buffer_latency); - } - } - - if (render_started_) { - if (engine_->vie()->render()->StartRender(channel_id) != 0) { - LOG_RTCERR1(StartRender, channel_id); - return false; - } - } - - // Register decoder observer for incoming framerate and bitrate. - if (engine()->vie()->codec()->RegisterDecoderObserver( - channel_id, *channel_info->decoder_observer()) != 0) { - LOG_RTCERR1(RegisterDecoderObserver, channel_info->decoder_observer()); - return false; - } - - recv_channels_[remote_ssrc] = channel_info.release(); - return true; -} - -bool WebRtcVideoMediaChannel::ConfigureSending(int channel_id, - uint32 local_ssrc_key) { - // The ssrc key can be zero or correspond to an SSRC. - // Make sure the default channel isn't configured more than once. - if (local_ssrc_key == kDefaultChannelSsrcKey && GetDefaultSendChannel()) { - return false; - } - // Make sure that the SSRC is not already in use. - uint32 dummy_key; - if (GetSendChannelSsrcKey(local_ssrc_key, &dummy_key)) { - return false; - } - int vie_capture = 0; - webrtc::ViEExternalCapture* external_capture = NULL; - // Register external capture. - if (engine()->vie()->capture()->AllocateExternalCaptureDevice( - vie_capture, external_capture) != 0) { - LOG_RTCERR0(AllocateExternalCaptureDevice); - return false; - } - - // Connect external capture. - if (engine()->vie()->capture()->ConnectCaptureDevice( - vie_capture, channel_id) != 0) { - LOG_RTCERR2(ConnectCaptureDevice, vie_capture, channel_id); - return false; - } - - // Set up a new send channel. - rtc::scoped_ptr send_channel( - new WebRtcVideoChannelSendInfo(channel_id, vie_capture, - external_capture, - engine()->cpu_monitor())); - send_channel->ApplyCpuOptions(options_); - send_channel->SignalCpuAdaptationUnable.connect(this, - &WebRtcVideoMediaChannel::OnCpuAdaptationUnable); - - webrtc::CpuOveruseOptions overuse_options; - if (GetCpuOveruseOptions(options_, &overuse_options)) { - if (engine()->vie()->base()->SetCpuOveruseOptions(channel_id, - overuse_options) != 0) { - LOG_RTCERR1(SetCpuOveruseOptions, channel_id); - } - } - - // Register encoder observer for outgoing framerate and bitrate. - if (engine()->vie()->codec()->RegisterEncoderObserver( - channel_id, *send_channel->encoder_observer()) != 0) { - LOG_RTCERR1(RegisterEncoderObserver, send_channel->encoder_observer()); - return false; - } - - if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetSendTimestampOffsetStatus, - channel_id, send_extensions_, kRtpTimestampOffsetHeaderExtension)) { - return false; - } - - if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetSendAbsoluteSendTimeStatus, - channel_id, send_extensions_, kRtpAbsoluteSenderTimeHeaderExtension)) { - return false; - } - - if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetSendVideoRotationStatus, - channel_id, send_extensions_, - kRtpVideoRotationHeaderExtension)) { - return false; - } - - if (engine()->vie()->rtp()->SetTransmissionSmoothingStatus(channel_id, - true) != 0) { - LOG_RTCERR2(SetTransmissionSmoothingStatus, channel_id, true); - return false; - } - - int buffer_latency = - options_.buffered_mode_latency.GetWithDefaultIfUnset( - cricket::kBufferedModeDisabled); - if (buffer_latency != cricket::kBufferedModeDisabled) { - if (engine()->vie()->rtp()->SetSenderBufferingMode( - channel_id, buffer_latency) != 0) { - LOG_RTCERR2(SetSenderBufferingMode, channel_id, buffer_latency); - } - } - - if (options_.suspend_below_min_bitrate.GetWithDefaultIfUnset(false)) { - engine()->vie()->codec()->SuspendBelowMinBitrate(channel_id); - } - - // The remb status direction correspond to the RTP stream (and not the RTCP - // stream). I.e. if send remb is enabled it means it is receiving remote - // rembs and should use them to estimate bandwidth. Receive remb mean that - // remb packets will be generated and that the channel should be included in - // it. If remb is enabled all channels are allowed to contribute to the remb - // but only receive channels will ever end up actually contributing. This - // keeps the logic simple. - if (engine_->vie()->rtp()->SetRembStatus(channel_id, - remb_enabled_, - remb_enabled_) != 0) { - LOG_RTCERR3(SetRembStatus, channel_id, remb_enabled_, remb_enabled_); - return false; - } - if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, nack_enabled_)) { - // Logged in SetNackFec. Don't spam the logs. - return false; - } - - send_channels_[local_ssrc_key] = send_channel.release(); - - return true; -} - -bool WebRtcVideoMediaChannel::SetNackFec(int channel_id, - int red_payload_type, - int fec_payload_type, - bool nack_enabled) { - bool enable = (red_payload_type != -1 && fec_payload_type != -1 && - !ConferenceModeIsEnabled()); - if (enable) { - if (engine_->vie()->rtp()->SetHybridNACKFECStatus( - channel_id, nack_enabled, red_payload_type, fec_payload_type) != 0) { - LOG_RTCERR4(SetHybridNACKFECStatus, channel_id, nack_enabled, - red_payload_type, fec_payload_type); - return false; - } - LOG(LS_INFO) << "Hybrid NACK/FEC enabled for channel " << channel_id; - } else { - if (engine_->vie()->rtp()->SetNACKStatus(channel_id, nack_enabled) != 0) { - LOG_RTCERR1(SetNACKStatus, channel_id); - return false; - } - std::string enabled = nack_enabled ? "enabled" : "disabled"; - LOG(LS_INFO) << "NACK " << enabled << " for channel " << channel_id; - } - return true; -} - -bool WebRtcVideoMediaChannel::SetSendCodec(const webrtc::VideoCodec& codec) { - bool ret_val = true; - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - ret_val = SetSendCodec(send_channel, codec) && ret_val; - } - if (ret_val) { - // All SetSendCodec calls were successful. Update the global state - // accordingly. - send_codec_.reset(new webrtc::VideoCodec(codec)); - } else { - // At least one SetSendCodec call failed, rollback. - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - if (send_codec_) { - SetSendCodec(send_channel, *send_codec_); - } - } - } - return ret_val; -} - -bool WebRtcVideoMediaChannel::SetSendCodec( - WebRtcVideoChannelSendInfo* send_channel, - const webrtc::VideoCodec& codec) { - if (!send_channel) { - return false; - } - - send_channel->SetAdaptFormat( - VideoFormatFromVieCodec(codec), - WebRtcVideoChannelSendInfo::kAdaptFormatTypeCodec); - - VideoSendParams send_params = send_channel->send_params(); - send_params.codec = codec; - return SetSendParams(send_channel, send_params); -} - -static std::string ToString(webrtc::VideoCodecComplexity complexity) { - switch (complexity) { - case webrtc::kComplexityNormal: - return "normal"; - case webrtc::kComplexityHigh: - return "high"; - case webrtc::kComplexityHigher: - return "higher"; - case webrtc::kComplexityMax: - return "max"; - default: - return "unknown"; - } -} - -static std::string ToString(webrtc::VP8ResilienceMode resilience) { - switch (resilience) { - case webrtc::kResilienceOff: - return "off"; - case webrtc::kResilientStream: - return "stream"; - case webrtc::kResilientFrames: - return "frames"; - default: - return "unknown"; - } -} - -void WebRtcVideoMediaChannel::LogSendCodecChange(const std::string& reason) { - webrtc::VideoCodec vie_codec; - if (engine()->vie()->codec()->GetSendCodec(default_channel_id_, vie_codec) != 0) { - LOG_RTCERR1(GetSendCodec, default_channel_id_); - return; - } - - LOG(LS_INFO) << reason << " : selected video codec " - << vie_codec.plName << "/" - << vie_codec.width << "x" << vie_codec.height << "x" - << static_cast(vie_codec.maxFramerate) << "fps" - << "@" << vie_codec.maxBitrate << "kbps" - << " (min=" << vie_codec.minBitrate << "kbps," - << " start=" << vie_codec.startBitrate << "kbps)"; - LOG(LS_INFO) << "Video max quantization: " << vie_codec.qpMax; - if (webrtc::kVideoCodecVP8 == vie_codec.codecType) { - LOG(LS_INFO) << "VP8 number of temporal layers: " - << static_cast( - vie_codec.codecSpecific.VP8.numberOfTemporalLayers); - LOG(LS_INFO) << "VP8 options : " - << "picture loss indication = " - << vie_codec.codecSpecific.VP8.pictureLossIndicationOn - << ", feedback mode = " - << vie_codec.codecSpecific.VP8.feedbackModeOn - << ", complexity = " - << ToString(vie_codec.codecSpecific.VP8.complexity) - << ", resilience = " - << ToString(vie_codec.codecSpecific.VP8.resilience) - << ", denoising = " - << vie_codec.codecSpecific.VP8.denoisingOn - << ", error concealment = " - << vie_codec.codecSpecific.VP8.errorConcealmentOn - << ", automatic resize = " - << vie_codec.codecSpecific.VP8.automaticResizeOn - << ", frame dropping = " - << vie_codec.codecSpecific.VP8.frameDroppingOn - << ", key frame interval = " - << vie_codec.codecSpecific.VP8.keyFrameInterval; - } - - for (const auto& kv : send_rtx_associated_types_) { - LOG(LS_INFO) << "RTX payload type: " << kv.first - << ", associated payload type:" << kv.second; - } - - LogSimulcastSubstreams(vie_codec); -} - -bool WebRtcVideoMediaChannel::SetReceiveCodecs( - WebRtcVideoChannelRecvInfo* info) { - int red_type = -1; - int fec_type = -1; - int channel_id = info->channel_id(); - // Build a map from payload types to video codecs so that we easily can find - // out if associated payload types are referring to valid codecs. - std::map pt_to_codec; - for (std::vector::iterator it = receive_codecs_.begin(); - it != receive_codecs_.end(); ++it) { - pt_to_codec[it->plType] = &(*it); - } - for (std::vector::iterator it = receive_codecs_.begin(); - it != receive_codecs_.end(); ++it) { - if (it->codecType == webrtc::kVideoCodecRED) { - red_type = it->plType; - } else if (it->codecType == webrtc::kVideoCodecULPFEC) { - fec_type = it->plType; - } - // If this is an RTX codec we have to verify that it is associated with - // a valid video codec which we have RTX support for. - if (_stricmp(it->plName, kRtxCodecName) == 0) { - std::map::iterator apt_it = - associated_payload_types_.find(it->plType); - bool valid_apt = false; - if (apt_it != associated_payload_types_.end()) { - std::map::iterator codec_it = - pt_to_codec.find(apt_it->second); - valid_apt = codec_it != pt_to_codec.end(); - } - if (!valid_apt) { - LOG(LS_ERROR) << "The RTX codec isn't associated with a known and " - "supported payload type"; - return false; - } - if (engine()->vie()->rtp()->SetRtxReceivePayloadType( - channel_id, it->plType, apt_it->second) != 0) { - LOG_RTCERR2(SetRtxReceivePayloadType, channel_id, - static_cast(it->plType)); - return false; - } - continue; - } - if (engine()->vie()->codec()->SetReceiveCodec(channel_id, *it) != 0) { - LOG_RTCERR2(SetReceiveCodec, channel_id, it->plName); - return false; - } - if (!info->IsDecoderRegistered(it->plType) && - it->codecType != webrtc::kVideoCodecRED && - it->codecType != webrtc::kVideoCodecULPFEC) { - webrtc::VideoDecoder* decoder = - engine()->CreateExternalDecoder(it->codecType); - if (decoder) { - if (engine()->vie()->ext_codec()->RegisterExternalReceiveCodec( - channel_id, it->plType, decoder) == 0) { - info->RegisterDecoder(it->plType, decoder); - } else { - LOG_RTCERR2(RegisterExternalReceiveCodec, channel_id, it->plName); - engine()->DestroyExternalDecoder(decoder); - } - } - } - } - return true; -} - -int WebRtcVideoMediaChannel::GetRecvChannelId(uint32 ssrc) { - if (ssrc == first_receive_ssrc_) { - return default_channel_id_; - } - int recv_channel_id = kChannelIdUnset; - WebRtcVideoChannelRecvInfo* recv_channel = GetRecvChannelBySsrc(ssrc); - if (!recv_channel) { - // Check if we have an RTX stream registered on this SSRC. - SsrcMap::iterator rtx_it = rtx_to_primary_ssrc_.find(ssrc); - if (rtx_it != rtx_to_primary_ssrc_.end()) { - if (rtx_it->second == first_receive_ssrc_) { - recv_channel_id = default_channel_id_; - } else { - recv_channel = GetRecvChannelBySsrc(rtx_it->second); - ASSERT(recv_channel != NULL); - recv_channel_id = recv_channel->channel_id(); - } - } - } else { - recv_channel_id = recv_channel->channel_id(); - } - return recv_channel_id; -} - -bool WebRtcVideoMediaChannel::SetSendParams( - WebRtcVideoChannelSendInfo* send_channel, - const VideoSendParams& send_params) { - ASSERT(engine()->worker_thread()->IsCurrent()); - const int channel_id = send_channel->channel_id(); - - MaybeRegisterExternalEncoder(send_channel, send_params.codec); - - CapturedFrameInfo frame; - if (!send_channel->last_captured_frame_info().Get(&frame)) { - // When we don't have a frame yet, configure the encoder with a - // QCIF (176x144) frame (to ensure HW encoder can be initialized). - // This gives us low memory usage but also makes it so configuration - // errors are discovered at the time we apply the settings rather than - // when we get the first frame (waiting for the first frame to know - // that you gave a bad codec parameter could make debugging hard). - frame.width = 176; - frame.height = 144; - - // TODO(pthatcher): Evaluate the risk of not setting up an encoder - // at all until we have a frame. Once we feel it's worth the - // risk, we can do something like this: - // send_channel->set_send_params(send_params); - // return true; - } - - // TODO(pthatcher): This checking of the max height and width is - // only needed because some unit tests bypass the VideoAdapter, and - // others expect behavior from the adapter different than what it - // actually does. We should fix the tests and remove this block. - VideoFormat max = send_channel->adapt_format(); - size_t max_width = static_cast(max.width); - size_t max_height = static_cast(max.height); - if ((!frame.screencast && - (frame.width > max_width || frame.height > max_height))) { - frame.width = max_width; - frame.height = max_height; - } - - webrtc::VideoCodec codec; - ConfigureVieCodecFromSendParams(channel_id, send_params, frame, &codec); - // TODO(pthatcher): Figure out a clean way to configure the max - // framerate and sanitize the bitrates inside of - // ConfigureVieCodecFromSendParams. - codec.maxFramerate = max.framerate(); - SanitizeBitrates(channel_id, &codec); - - // Get current vie codec. - webrtc::VideoCodec current; - if (engine()->vie()->codec()->GetSendCodec(channel_id, current) != 0) { - LOG_RTCERR1(GetSendCodec, channel_id); - return false; - } - - if (current != codec) { - if (engine()->vie()->codec()->SetSendCodec(channel_id, codec) != 0) { - LOG_RTCERR1(SetSendCodec, channel_id); - return false; - } - } - - if (frame.screencast) { - int screencast_min_bitrate = - options_.screencast_min_bitrate.GetWithDefaultIfUnset(0); - engine()->vie()->rtp()->SetMinTransmitBitrate(channel_id, - screencast_min_bitrate); - } else { - // In case of switching from screencast to regular capture, set - // min bitrate padding and pacer back to defaults. - engine()->vie()->rtp()->SetMinTransmitBitrate(channel_id, 0); - } - engine()->vie()->rtp()->SetTransmissionSmoothingStatus(channel_id, true); - - // If the set of SSRCs isn't populated, then don't apply them. If we - // do, we'll cause a bug where adding a stream, then removing a - // stream, then re-adding a stream with the same primary SSRC will - // cause the sequence numbers to change and confuse the receiver due - // to jumping SRTP sequence numbers. - if (send_params.stream.first_ssrc() != 0) { - if (!SetSendSsrcs(channel_id, send_params.stream, codec)) { - return false; - } - } - - // NOTE: SetRtxSendPayloadType must be called after all SSRCs are - // configured. Otherwise ssrc's configured after this point will use - // the primary PT for RTX. - for (const auto& kv : send_rtx_associated_types_) { - if (engine()->vie()->rtp()->SetRtxSendPayloadType(channel_id, kv.first, - kv.second) != 0) { - LOG_RTCERR3(SetRtxSendPayloadType, channel_id, kv.first, kv.second); - return false; - } - } - - send_channel->set_send_params(send_params); - return true; -} - -bool WebRtcVideoMediaChannel::ConfigureVieCodecFromSendParams( - int channel_id, - const VideoSendParams& send_params, - const CapturedFrameInfo& last_captured_frame_info, - webrtc::VideoCodec* codec_out) { - webrtc::VideoCodec codec = send_params.codec; - - codec.width = static_cast(last_captured_frame_info.width); - codec.height = static_cast(last_captured_frame_info.height); - codec.targetBitrate = 0; - if (codec.codecType == webrtc::kVideoCodecVP8) { - codec.codecSpecific.VP8.numberOfTemporalLayers = - kDefaultNumberOfTemporalLayers; - codec.codecSpecific.VP8.resilience = webrtc::kResilienceOff; - } - - if (last_captured_frame_info.screencast) { - codec.mode = webrtc::kScreensharing; - if (codec.codecType == webrtc::kVideoCodecVP8) { - codec.codecSpecific.VP8.denoisingOn = false; - codec.codecSpecific.VP8.automaticResizeOn = false; - codec.codecSpecific.VP8.frameDroppingOn = false; - } - } else { - codec.mode = webrtc::kRealtimeVideo; - if (codec.codecType == webrtc::kVideoCodecVP8) { - // TODO(pthatcher): Pass in options in VideoSendParams. - codec.codecSpecific.VP8.denoisingOn = - options_.video_noise_reduction.GetWithDefaultIfUnset(true); - codec.codecSpecific.VP8.automaticResizeOn = true; - codec.codecSpecific.VP8.frameDroppingOn = true; - } - } - - if (webrtc::kVideoCodecVP8 == codec.codecType) { - ConfigureSimulcastTemporalLayers( - kDefaultNumberOfTemporalLayers, &codec); - if (IsSimulcastStream(send_params.stream)) { - codec.codecSpecific.VP8.automaticResizeOn = false; - // TODO(pthatcher): Pass in options in VideoSendParams. - VideoOptions options; - GetOptions(&options); - if (ConferenceModeIsEnabled()) { - ConfigureSimulcastCodec(send_params.stream, options, &codec); - } - } - - if (last_captured_frame_info.screencast) { - // Use existing bitrate if not in conference mode. - if (ConferenceModeIsEnabled()) { - ConfigureConferenceModeScreencastCodec(&codec); - } - - DisableSimulcastCodec(&codec); - } - } - - *codec_out = codec; - return true; -} - -void WebRtcVideoMediaChannel::SanitizeBitrates( - int channel_id, webrtc::VideoCodec* codec) { - codec->minBitrate = GetBitrate(codec->minBitrate, kMinVideoBitrate); - codec->startBitrate = GetBitrate(codec->startBitrate, kStartVideoBitrate); - codec->maxBitrate = GetBitrate(codec->maxBitrate, kMaxVideoBitrate); - - if (codec->minBitrate > codec->maxBitrate) { - LOG(LS_INFO) << "Decreasing codec min bitrate to the max (" - << codec->maxBitrate << ") because the min (" - << codec->minBitrate << ") exceeds the max."; - codec->minBitrate = codec->maxBitrate; - } - if (codec->startBitrate < codec->minBitrate) { - LOG(LS_INFO) << "Increasing codec start bitrate to the min (" - << codec->minBitrate << ") because the start (" - << codec->startBitrate << ") is less than the min."; - codec->startBitrate = codec->minBitrate; - } else if (codec->startBitrate > codec->maxBitrate) { - LOG(LS_INFO) << "Decreasing codec start bitrate to the max (" - << codec->maxBitrate << ") because the start (" - << codec->startBitrate << ") exceeds the max."; - codec->startBitrate = codec->maxBitrate; - } - - // Use a previous target bitrate, if there is one. - unsigned int current_target_bitrate = 0; - if (engine()->vie()->codec()->GetCodecTargetBitrate( - channel_id, ¤t_target_bitrate) == 0) { - // Convert to kbps. - current_target_bitrate /= 1000; - if (current_target_bitrate > codec->maxBitrate) { - current_target_bitrate = codec->maxBitrate; - } - if (current_target_bitrate > codec->startBitrate) { - codec->startBitrate = current_target_bitrate; - } - } - - // Make sure the start bitrate is larger than lowest layer's min bitrate. - if (codec->numberOfSimulcastStreams > 1 && - codec->startBitrate < codec->simulcastStream[0].minBitrate) { - codec->startBitrate = codec->simulcastStream[0].minBitrate; - } -} - -void WebRtcVideoMediaChannel::OnMessage(rtc::Message* msg) { - FlushBlackFrameData* data = static_cast(msg->pdata); - FlushBlackFrame(data->ssrc, data->timestamp, data->interval); - delete data; -} - -int WebRtcVideoMediaChannel::SendPacket(int channel, const void* data, - size_t len) { - rtc::Buffer packet(reinterpret_cast(data), len, - kMaxRtpPacketLen); - return MediaChannel::SendPacket(&packet) ? static_cast(len) : -1; -} - -int WebRtcVideoMediaChannel::SendRTCPPacket(int channel, - const void* data, - size_t len) { - rtc::Buffer packet(reinterpret_cast(data), len, - kMaxRtpPacketLen); - return MediaChannel::SendRtcp(&packet) ? static_cast(len) : -1; -} - -void WebRtcVideoMediaChannel::QueueBlackFrame(uint32 ssrc, int64 timestamp, - int interval) { - if (timestamp) { - FlushBlackFrameData* black_frame_data = new FlushBlackFrameData( - ssrc, timestamp, interval); - const int delay_ms = static_cast( - 2 * interval * rtc::kNumMillisecsPerSec / rtc::kNumNanosecsPerSec); - worker_thread()->PostDelayed(delay_ms, this, 0, black_frame_data); - } -} - -void WebRtcVideoMediaChannel::FlushBlackFrame( - uint32 ssrc, int64 timestamp, int timestamp_delta) { - WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); - if (!send_channel) { - return; - } - - CapturedFrameInfo last_frame_info; - if (!send_channel->last_captured_frame_info().Get(&last_frame_info)) - return; - - if (last_frame_info.timestamp == timestamp) { - WebRtcVideoFrame black_frame; - if (!black_frame.InitToBlack(static_cast(last_frame_info.width), - static_cast(last_frame_info.height), 1, 1, - last_frame_info.elapsed_time + timestamp_delta, - last_frame_info.timestamp + timestamp_delta) || - !SendFrame(send_channel, &black_frame, last_frame_info.screencast)) { - LOG(LS_ERROR) << "Failed to send black frame."; - } - } -} - -void WebRtcVideoMediaChannel::OnCpuAdaptationUnable() { - // ssrc is hardcoded to 0. This message is based on a system wide issue, - // so finding which ssrc caused it doesn't matter. - SignalMediaError(0, VideoMediaChannel::ERROR_REC_CPU_MAX_CANT_DOWNGRADE); -} - -void WebRtcVideoMediaChannel::SetNetworkTransmissionState( - bool is_transmitting) { - LOG(LS_INFO) << "SetNetworkTransmissionState: " << is_transmitting; - for (SendChannelMap::iterator iter = send_channels_.begin(); - iter != send_channels_.end(); ++iter) { - WebRtcVideoChannelSendInfo* send_channel = iter->second; - int channel_id = send_channel->channel_id(); - engine_->vie()->network()->SetNetworkTransmissionState(channel_id, - is_transmitting); - } -} - -bool WebRtcVideoMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter, - int channel_id, const RtpHeaderExtension* extension) { - bool enable = false; - int id = 0; - if (extension) { - enable = true; - id = extension->id; - } - if ((engine_->vie()->rtp()->*setter)(channel_id, enable, id) != 0) { - LOG_RTCERR4(*setter, extension->uri, channel_id, enable, id); - return false; - } - return true; -} - -bool WebRtcVideoMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter, - int channel_id, const std::vector& extensions, - const char header_extension_uri[]) { - const RtpHeaderExtension* extension = FindHeaderExtension(extensions, - header_extension_uri); - return SetHeaderExtension(setter, channel_id, extension); -} - -bool WebRtcVideoMediaChannel::SetPrimaryAndRtxSsrcs( - int channel_id, int idx, uint32 primary_ssrc, - const StreamParams& sp) { - LOG(LS_INFO) << "Set primary ssrc " << primary_ssrc - << " on channel " << channel_id << " idx " << idx; - if (engine()->vie()->rtp()->SetLocalSSRC( - channel_id, primary_ssrc, webrtc::kViEStreamTypeNormal, idx) != 0) { - LOG_RTCERR4(SetLocalSSRC, - channel_id, primary_ssrc, webrtc::kViEStreamTypeNormal, idx); - return false; - } - - uint32 rtx_ssrc = 0; - if (sp.GetFidSsrc(primary_ssrc, &rtx_ssrc)) { - LOG(LS_INFO) << "Set rtx ssrc " << rtx_ssrc - << " on channel " << channel_id << " idx " << idx; - if (engine()->vie()->rtp()->SetLocalSSRC( - channel_id, rtx_ssrc, webrtc::kViEStreamTypeRtx, idx) != 0) { - LOG_RTCERR4(SetLocalSSRC, - channel_id, rtx_ssrc, webrtc::kViEStreamTypeRtx, idx); - return false; - } - } - return true; -} - -bool WebRtcVideoMediaChannel::SetLimitedNumberOfSendSsrcs( - int channel_id, const StreamParams& sp, size_t limit) { - const SsrcGroup* sim_group = sp.get_ssrc_group(kSimSsrcGroupSemantics); - if (!sim_group || limit == 1) { - return SetPrimaryAndRtxSsrcs(channel_id, 0, sp.first_ssrc(), sp); - } - - std::vector ssrcs = sim_group->ssrcs; - for (size_t i = 0; i < ssrcs.size() && i < limit; ++i) { - if (!SetPrimaryAndRtxSsrcs(channel_id, static_cast(i), ssrcs[i], sp)) { - return false; - } - } - return true; -} - -bool WebRtcVideoMediaChannel::SetSendSsrcs(int channel_id, - const StreamParams& sp, - const webrtc::VideoCodec& codec) { - size_t limit = codec.numberOfSimulcastStreams; - return SetLimitedNumberOfSendSsrcs(channel_id, sp, limit); -} - -void WebRtcVideoMediaChannel::MaybeConnectCapturer(VideoCapturer* capturer) { - if (capturer && GetSendChannelNum(capturer) == 1) { - capturer->SignalVideoFrame.connect(this, - &WebRtcVideoMediaChannel::SendFrame); - } -} - -void WebRtcVideoMediaChannel::MaybeDisconnectCapturer(VideoCapturer* capturer) { - if (capturer && GetSendChannelNum(capturer) == 1) { - capturer->SignalVideoFrame.disconnect(this); - } -} - -void WebRtcVideoMediaChannel::SetReceiverReportSsrc(uint32 ssrc) { - for (RecvChannelMap::const_iterator it = recv_channels_.begin(); - it != recv_channels_.end(); ++it) { - int channel_id = it->second->channel_id(); - if (engine()->vie()->rtp()->SetLocalSSRC(channel_id, ssrc) != 0) { - LOG_RTCERR2(SetLocalSSRC, channel_id, ssrc); - ASSERT(false); - } - } - receiver_report_ssrc_ = ssrc; -} - -} // namespace cricket - -#endif // HAVE_WEBRTC_VIDEO +// TODO(pbos): Remove this file when it's no longer built in Chromium. diff --git a/talk/media/webrtc/webrtcvideoengine.h b/talk/media/webrtc/webrtcvideoengine.h deleted file mode 100644 index f48d77906..000000000 --- a/talk/media/webrtc/webrtcvideoengine.h +++ /dev/null @@ -1,548 +0,0 @@ -/* - * libjingle - * Copyright 2004 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TALK_MEDIA_WEBRTCVIDEOENGINE_H_ -#define TALK_MEDIA_WEBRTCVIDEOENGINE_H_ - -#include -#include - -#include "talk/media/base/codec.h" -#include "talk/media/base/videocommon.h" -#include "talk/media/webrtc/webrtccommon.h" -#include "talk/media/webrtc/webrtcexport.h" -#include "talk/media/webrtc/webrtcvideoencoderfactory.h" -#include "talk/session/media/channel.h" -#include "webrtc/base/scoped_ptr.h" -#include "webrtc/video_engine/include/vie_base.h" - -#if !defined(LIBPEERCONNECTION_LIB) && \ - !defined(LIBPEERCONNECTION_IMPLEMENTATION) -// If you hit this, then you've tried to include this header from outside -// a shared library. An instance of this class must only be created from -// within the library that actually implements it. -#error "Bogus include." -#endif - -namespace webrtc { -class VideoCaptureModule; -class VideoDecoder; -class VideoEncoder; -class VideoRender; -class ViEExternalCapture; -class ViERTP_RTCP; -} - -namespace rtc { -class CpuMonitor; -} // namespace rtc - -namespace cricket { - -class CoordinatedVideoAdapter; -class ViETraceWrapper; -class ViEWrapper; -class VideoCapturer; -class VideoFrame; -class VideoProcessor; -class VideoRenderer; -class VoiceMediaChannel; -class WebRtcDecoderObserver; -class WebRtcEncoderObserver; -class WebRtcLocalStreamInfo; -class WebRtcRenderAdapter; -class WebRtcVideoChannelRecvInfo; -class WebRtcVideoChannelSendInfo; -class WebRtcVideoDecoderFactory; -class WebRtcVideoEncoderFactory; -class WebRtcVideoMediaChannel; -class WebRtcVoiceEngine; - -struct CapturedFrame; -struct Device; - -// This set of methods is declared here for the sole purpose of sharing code -// between webrtc video engine v1 and v2. -std::vector DefaultVideoCodecList(); -bool CodecIsInternallySupported(const std::string& codec_name); -void AddDefaultFeedbackParams(VideoCodec* codec); - -class WebRtcVideoEngine : public sigslot::has_slots<> { - public: - // Creates the WebRtcVideoEngine with internal VideoCaptureModule. - explicit WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine); - // For testing purposes. Allows the WebRtcVoiceEngine, - // ViEWrapper and CpuMonitor to be mocks. - // TODO(juberti): Remove the 3-arg ctor once fake tracing is implemented. - WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine, - ViEWrapper* vie_wrapper, - rtc::CpuMonitor* cpu_monitor); - WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine, - ViEWrapper* vie_wrapper, - ViETraceWrapper* tracing, - rtc::CpuMonitor* cpu_monitor); - virtual ~WebRtcVideoEngine(); - - // Basic video engine implementation. - bool Init(rtc::Thread* worker_thread); - void Terminate(); - - int GetCapabilities(); - bool SetDefaultEncoderConfig(const VideoEncoderConfig& config); - - // TODO(pbos): Remove when all call sites use VideoOptions. - virtual WebRtcVideoMediaChannel* CreateChannel( - VoiceMediaChannel* voice_channel); - virtual WebRtcVideoMediaChannel* CreateChannel( - const VideoOptions& options, - VoiceMediaChannel* voice_channel); - - const std::vector& codecs() const; - const std::vector& rtp_header_extensions() const; - void SetLogging(int min_sev, const char* filter); - - // Set a WebRtcVideoDecoderFactory for external decoding. Video engine does - // not take the ownership of |decoder_factory|. The caller needs to make sure - // that |decoder_factory| outlives the video engine. - void SetExternalDecoderFactory(WebRtcVideoDecoderFactory* decoder_factory); - // Set a WebRtcVideoEncoderFactory for external encoding. Video engine does - // not take the ownership of |encoder_factory|. The caller needs to make sure - // that |encoder_factory| outlives the video engine. - virtual void SetExternalEncoderFactory( - WebRtcVideoEncoderFactory* encoder_factory); - // Enable the render module with timing control. - bool EnableTimedRender(); - - // Returns an external decoder for the given codec type. The return value - // can be NULL if decoder factory is not given or it does not support the - // codec type. The caller takes the ownership of the returned object. - webrtc::VideoDecoder* CreateExternalDecoder(webrtc::VideoCodecType type); - // Releases the decoder instance created by CreateExternalDecoder(). - void DestroyExternalDecoder(webrtc::VideoDecoder* decoder); - - // Returns an external encoder for the given codec type. The return value - // can be NULL if encoder factory is not given or it does not support the - // codec type. The caller takes the ownership of the returned object. - // On success, |internal_source| is set to true if the encoder has an internal - // frame source, meaning that it doesn't expect/require frames through the - // normal camera pipeline. See ViEExternalCodec::RegisterExternalSendCodec for - // more information. - webrtc::VideoEncoder* CreateExternalEncoder(webrtc::VideoCodecType type, - bool* internal_source); - // Releases the encoder instance created by CreateExternalEncoder(). - void DestroyExternalEncoder(webrtc::VideoEncoder* encoder); - - // Returns true if the codec type is supported by the external encoder. - bool IsExternalEncoderCodecType(webrtc::VideoCodecType type) const; - - // Functions called by WebRtcVideoMediaChannel. - rtc::Thread* worker_thread() { return worker_thread_; } - ViEWrapper* vie() { return vie_wrapper_.get(); } - const VideoFormat& default_codec_format() const { - return default_codec_format_; - } - int GetLastEngineError(); - bool FindCodec(const VideoCodec& in); - bool CanSendCodec(const VideoCodec& in, const VideoCodec& current, - VideoCodec* out); - void RegisterChannel(WebRtcVideoMediaChannel* channel); - void UnregisterChannel(WebRtcVideoMediaChannel* channel); - bool ConvertFromCricketVideoCodec(const VideoCodec& in_codec, - webrtc::VideoCodec* out_codec); - int GetNumOfChannels(); - - rtc::CpuMonitor* cpu_monitor() { return cpu_monitor_.get(); } - - protected: - class TraceCallbackImpl : public webrtc::TraceCallback { - public: - TraceCallbackImpl(WebRtcVoiceEngine* voice_engine) - : voice_engine_(voice_engine) {} - ~TraceCallbackImpl() override {} - - private: - void Print(webrtc::TraceLevel level, const char* trace, - int length) override; - - WebRtcVoiceEngine* const voice_engine_; - }; - - bool initialized() const { - return initialized_; - } - - // When a video processor registers with the engine. - // SignalMediaFrame will be invoked for every video frame. - // See videoprocessor.h for param reference. - sigslot::signal3 SignalMediaFrame; - - private: - typedef std::vector VideoChannels; - - void Construct(ViEWrapper* vie_wrapper, - ViETraceWrapper* tracing, - WebRtcVoiceEngine* voice_engine, - rtc::CpuMonitor* cpu_monitor); - bool SetDefaultCodec(const VideoCodec& codec); - bool RebuildCodecList(const VideoCodec& max_codec); - void SetTraceFilter(int filter); - void SetTraceOptions(const std::string& options); - bool InitVideoEngine(); - bool VerifyApt(const VideoCodec& in, int expected_apt) const; - - rtc::Thread* worker_thread_; - rtc::scoped_ptr vie_wrapper_; - bool vie_wrapper_base_initialized_; - rtc::scoped_ptr tracing_; - WebRtcVoiceEngine* const voice_engine_; - rtc::scoped_ptr render_module_; - rtc::scoped_ptr simulcast_encoder_factory_; - WebRtcVideoEncoderFactory* encoder_factory_; - WebRtcVideoDecoderFactory* decoder_factory_; - std::vector video_codecs_; - std::vector default_video_codec_list_; - std::vector rtp_header_extensions_; - VideoFormat default_codec_format_; - TraceCallbackImpl trace_callback_; - - bool initialized_; - rtc::CriticalSection channels_crit_; - VideoChannels channels_; - - bool capture_started_; - - rtc::scoped_ptr cpu_monitor_; -}; - -struct CapturedFrameInfo; - -// TODO(pthatcher): Add VideoOptions. -struct VideoSendParams { - webrtc::VideoCodec codec; - StreamParams stream; -}; - -class WebRtcVideoMediaChannel : public rtc::MessageHandler, - public VideoMediaChannel, - public webrtc::Transport { - public: - WebRtcVideoMediaChannel(WebRtcVideoEngine* engine, - VoiceMediaChannel* voice_channel); - virtual ~WebRtcVideoMediaChannel(); - bool Init(); - - WebRtcVideoEngine* engine() { return engine_; } - VoiceMediaChannel* voice_channel() { return voice_channel_; } - bool sending() const { return sending_; } - - // Public for testing purpose. - uint32 GetDefaultSendChannelSsrc(); - int GetDefaultChannelId() const { return default_channel_id_; } - - // VideoMediaChannel implementation - bool SetRecvCodecs(const std::vector& codecs) override; - bool SetSendCodecs(const std::vector& codecs) override; - bool GetSendCodec(VideoCodec* send_codec) override; - bool SetSendStreamFormat(uint32 ssrc, const VideoFormat& format) override; - bool SetRender(bool render) override; - bool SetSend(bool send) override; - - bool AddSendStream(const StreamParams& sp) override; - bool RemoveSendStream(uint32 ssrc) override; - bool AddRecvStream(const StreamParams& sp) override; - bool RemoveRecvStream(uint32 ssrc) override; - bool SetRenderer(uint32 ssrc, VideoRenderer* renderer) override; - bool GetStats(VideoMediaInfo* info) override; - bool SetCapturer(uint32 ssrc, VideoCapturer* capturer) override; - bool SendIntraFrame() override; - bool RequestIntraFrame() override; - - void OnPacketReceived(rtc::Buffer* packet, - const rtc::PacketTime& packet_time) override; - void OnRtcpReceived(rtc::Buffer* packet, - const rtc::PacketTime& packet_time) override; - void OnReadyToSend(bool ready) override; - bool MuteStream(uint32 ssrc, bool on) override; - bool SetRecvRtpHeaderExtensions( - const std::vector& extensions) override; - bool SetSendRtpHeaderExtensions( - const std::vector& extensions) override; - int GetRtpSendTimeExtnId() const override; - bool SetMaxSendBandwidth(int bps) override; - bool SetOptions(const VideoOptions& options) override; - bool GetOptions(VideoOptions* options) const override { - *options = options_; - return true; - } - void SetInterface(NetworkInterface* iface) override; - void UpdateAspectRatio(int ratio_w, int ratio_h) override; - - // Public functions for use by tests and other specialized code. - uint32 send_ssrc() const { return 0; } - bool GetRenderer(uint32 ssrc, VideoRenderer** renderer); - bool GetVideoAdapter(uint32 ssrc, CoordinatedVideoAdapter** video_adapter); - void SendFrame(VideoCapturer* capturer, const VideoFrame* frame); - bool SendFrame(WebRtcVideoChannelSendInfo* channel_info, - const VideoFrame* frame, bool is_screencast); - - // Thunk functions for use with HybridVideoEngine - void OnLocalFrame(VideoCapturer* capturer, const VideoFrame* frame) { - SendFrame(0u, frame, capturer->IsScreencast()); - } - void OnLocalFrameFormat(VideoCapturer* capturer, const VideoFormat* format) { - } - - // rtc::MessageHandler: - void OnMessage(rtc::Message* msg) override; - - protected: - void Terminate(); - int GetLastEngineError() { return engine()->GetLastEngineError(); } - - // webrtc::Transport: - int SendPacket(int channel, const void* data, size_t len) override; - int SendRTCPPacket(int channel, const void* data, size_t len) override; - - bool ConferenceModeIsEnabled() const { - return options_.conference_mode.GetWithDefaultIfUnset(false); - } - - // We take lots of things as input from applications (packaged in - // params), but ViE wants lots of those packed instead as a - // webrtc::VideoCodec. This is where we convert between the inputs - // we get from the applications and the input to give to ViE. We - // also configure the codec differently depending on the latest - // frame that we have received (in particular, depending on the - // resolution and whether the it was a screencast frame or not). - virtual bool ConfigureVieCodecFromSendParams( - int channel_id, - const VideoSendParams& send_params, - const CapturedFrameInfo& last_captured_frame_info, - webrtc::VideoCodec* codec); - // Checks the current bitrate estimate and modifies the bitrates - // accordingly, including converting kAutoBandwidth to the correct defaults. - virtual void SanitizeBitrates( - int channel_id, webrtc::VideoCodec* video_codec); - virtual void LogSendCodecChange(const std::string& reason); - bool SetPrimaryAndRtxSsrcs( - int channel_id, int idx, uint32 primary_ssrc, - const StreamParams& send_params); - bool SetLimitedNumberOfSendSsrcs( - int channel_id, const StreamParams& send_params, size_t limit); - virtual bool SetSendSsrcs( - int channel_id, const StreamParams& send_params, - const webrtc::VideoCodec& codec); - - private: - typedef std::map RecvChannelMap; - typedef std::map SendChannelMap; - typedef std::map SsrcMap; - typedef int (webrtc::ViERTP_RTCP::* ExtensionSetterFunction)(int, bool, int); - - enum MediaDirection { MD_RECV, MD_SEND, MD_SENDRECV }; - - // Creates and initializes a ViE channel. When successful - // |channel_id| will contain the new channel's ID. If |receiving| is - // true |ssrc| is the remote ssrc. If |sending| is true the ssrc is - // local ssrc. If both |receiving| and |sending| is true the ssrc - // must be kDefaultChannelSsrcKey and the channel will be created as - // a default channel. The ssrc must be different for receive - // channels and it must be different for send channels. If the same - // SSRC is being used for creating channel more than once, this - // function will fail returning false. - bool CreateChannel(uint32 ssrc_key, MediaDirection direction, - int* channel_id); - bool CreateUnsignalledRecvChannel(uint32 ssrc_key, int* channel_id); - bool ConfigureChannel(int channel_id, MediaDirection direction, - uint32 ssrc_key); - bool ConfigureReceiving(int channel_id, uint32 remote_ssrc_key); - bool ConfigureSending(int channel_id, uint32 local_ssrc_key); - bool SetNackFec(int channel_id, int red_payload_type, int fec_payload_type, - bool nack_enabled); - bool SetSendCodec(const webrtc::VideoCodec& codec); - bool SetSendCodec(WebRtcVideoChannelSendInfo* send_channel, - const webrtc::VideoCodec& codec); - bool SetSendParams(WebRtcVideoChannelSendInfo* send_channel, - const VideoSendParams& params); - - // Prepares the channel with channel id |info->channel_id()| to receive all - // codecs in |receive_codecs_| and start receive packets. - bool SetReceiveCodecs(WebRtcVideoChannelRecvInfo* info); - // Returns the channel ID that receives the stream with SSRC |ssrc|. - int GetRecvChannelId(uint32 ssrc); - bool MaybeSetRtxSsrc(const StreamParams& sp, int channel_id); - // Create and register an external endcoder if it's possible to do - // so and one isn't already registered. - bool MaybeRegisterExternalEncoder( - WebRtcVideoChannelSendInfo* send_channel, - const webrtc::VideoCodec& codec); - // Helper function for starting the sending of media on all channels or - // |channel_id|. Note that these two function do not change |sending_|. - bool StartSend(); - bool StartSend(WebRtcVideoChannelSendInfo* send_channel); - // Helper function for stop the sending of media on all channels or - // |channel_id|. Note that these two function do not change |sending_|. - bool StopSend(); - bool StopSend(WebRtcVideoChannelSendInfo* send_channel); - bool SendIntraFrame(int channel_id); - - bool HasReadySendChannels(); - bool DefaultSendChannelIsActive(); - - // Returns the ssrc key corresponding to the provided local SSRC in - // |ssrc_key|. The return value is true upon success. If the local - // ssrc correspond to that of the default channel the key is - // kDefaultChannelSsrcKey. For all other channels the returned ssrc - // key will be the same as the local ssrc. If a stream has more - // than one ssrc, the first (corresponding to - // StreamParams::first_ssrc()) is used as the key. - bool GetSendChannelSsrcKey(uint32 local_ssrc, uint32* ssrc_key); - WebRtcVideoChannelSendInfo* GetDefaultSendChannel(); - WebRtcVideoChannelSendInfo* GetSendChannelBySsrcKey(uint32 ssrc_key); - WebRtcVideoChannelSendInfo* GetSendChannelBySsrc(uint32 local_ssrc); - // Creates a new unique ssrc key that can be used for inserting a - // new send channel into |send_channels_| - bool CreateSendChannelSsrcKey(uint32 local_ssrc, uint32* ssrc_key); - // Get the number of the send channels |capturer| registered with. - int GetSendChannelNum(VideoCapturer* capturer); - - bool IsDefaultChannelId(int channel_id) const { - return channel_id == default_channel_id_; - } - bool DeleteSendChannel(uint32 ssrc_key); - - WebRtcVideoChannelRecvInfo* GetDefaultRecvChannel(); - WebRtcVideoChannelRecvInfo* GetRecvChannelBySsrc(uint32 ssrc); - - bool RemoveCapturer(uint32 ssrc); - - rtc::MessageQueue* worker_thread() { return engine_->worker_thread(); } - void QueueBlackFrame(uint32 ssrc, int64 timestamp, int interval); - void FlushBlackFrame(uint32 ssrc, int64 timestamp, int interval); - - void SetNetworkTransmissionState(bool is_transmitting); - - bool SetHeaderExtension(ExtensionSetterFunction setter, int channel_id, - const RtpHeaderExtension* extension); - bool SetHeaderExtension(ExtensionSetterFunction setter, int channel_id, - const std::vector& extensions, - const char header_extension_uri[]); - - // Signal when cpu adaptation has no further scope to adapt. - void OnCpuAdaptationUnable(); - - // Connect |capturer| to WebRtcVideoMediaChannel if it is only registered - // to one send channel, i.e. the first send channel. - void MaybeConnectCapturer(VideoCapturer* capturer); - // Disconnect |capturer| from WebRtcVideoMediaChannel if it is only registered - // to one send channel, i.e. the last send channel. - void MaybeDisconnectCapturer(VideoCapturer* capturer); - - bool RemoveRecvStreamInternal(uint32 ssrc); - - // Set the ssrc to use for RTCP receiver reports. - void SetReceiverReportSsrc(uint32 ssrc); - - // Global state. - WebRtcVideoEngine* engine_; - VoiceMediaChannel* voice_channel_; - int default_channel_id_; - bool nack_enabled_; - // Receiver Estimated Max Bitrate - bool remb_enabled_; - VideoOptions options_; - - // Global recv side state. - // Note the default channel (default_channel_id_), i.e. the send channel - // corresponding to all the receive channels (this must be done for REMB to - // work properly), resides in both recv_channels_ and send_channels_ with the - // ssrc key kDefaultChannelSsrcKey. - RecvChannelMap recv_channels_; // Contains all receive channels. - // A map from the SSRCs on which RTX packets are received to the media SSRCs - // the RTX packets are associated with. RTX packets will be delivered to the - // streams matching the primary SSRC. - SsrcMap rtx_to_primary_ssrc_; - std::vector receive_codecs_; - // A map from codec payload types to their associated payload types, if any. - // TODO(holmer): This is a temporary solution until webrtc::VideoCodec has - // an associated payload type member, when it does we can rely on - // receive_codecs_. - std::map associated_payload_types_; - bool render_started_; - uint32 first_receive_ssrc_; - uint32 receiver_report_ssrc_; - std::vector receive_extensions_; - int num_unsignalled_recv_channels_; - - // Global send side state. - SendChannelMap send_channels_; - rtc::scoped_ptr send_codec_; - // A map from RTX payload types to their associated payload types. - std::map send_rtx_associated_types_; - int send_red_type_; - int send_fec_type_; - bool sending_; - std::vector send_extensions_; - - // The aspect ratio that the channel desires. 0 means there is no desired - // aspect ratio - int ratio_w_; - int ratio_h_; -}; - -// An encoder factory that wraps Create requests for simulcastable codec types -// with a webrtc::SimulcastEncoderAdapter. Non simulcastable codec type -// requests are just passed through to the contained encoder factory. -// Exposed here for code to be shared with WebRtcVideoEngine2, not to be used -// externally. -class WebRtcSimulcastEncoderFactory - : public cricket::WebRtcVideoEncoderFactory { - public: - // WebRtcSimulcastEncoderFactory doesn't take ownership of |factory|, which is - // owned by e.g. PeerConnectionFactory. - explicit WebRtcSimulcastEncoderFactory( - cricket::WebRtcVideoEncoderFactory* factory); - virtual ~WebRtcSimulcastEncoderFactory(); - - static bool UseSimulcastEncoderFactory(const std::vector& codecs); - - webrtc::VideoEncoder* CreateVideoEncoder( - webrtc::VideoCodecType type) override; - const std::vector& codecs() const override; - bool EncoderTypeHasInternalSource(webrtc::VideoCodecType type) const override; - void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override; - - private: - cricket::WebRtcVideoEncoderFactory* factory_; - // A list of encoders that were created without being wrapped in a - // SimulcastEncoderAdapter. - std::vector non_simulcast_encoders_; -}; - -} // namespace cricket - -#endif // TALK_MEDIA_WEBRTCVIDEOENGINE_H_ diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index eee67faa9..93bd447aa 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -32,19 +32,20 @@ #include #include -#include "libyuv/convert_from.h" #include "talk/media/base/videocapturer.h" #include "talk/media/base/videorenderer.h" #include "talk/media/webrtc/constants.h" #include "talk/media/webrtc/simulcast.h" #include "talk/media/webrtc/webrtcvideocapturer.h" -#include "talk/media/webrtc/webrtcvideoengine.h" +#include "talk/media/webrtc/webrtcvideoencoderfactory.h" #include "talk/media/webrtc/webrtcvideoframe.h" #include "talk/media/webrtc/webrtcvoiceengine.h" #include "webrtc/base/buffer.h" #include "webrtc/base/logging.h" #include "webrtc/base/stringutils.h" #include "webrtc/call.h" +#include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h" +#include "webrtc/system_wrappers/interface/field_trial.h" #include "webrtc/system_wrappers/interface/trace_event.h" #include "webrtc/video_decoder.h" #include "webrtc/video_encoder.h" @@ -55,6 +56,126 @@ namespace cricket { namespace { + +// Wrap cricket::WebRtcVideoEncoderFactory as a webrtc::VideoEncoderFactory. +class EncoderFactoryAdapter : public webrtc::VideoEncoderFactory { + public: + // EncoderFactoryAdapter doesn't take ownership of |factory|, which is owned + // by e.g. PeerConnectionFactory. + explicit EncoderFactoryAdapter(cricket::WebRtcVideoEncoderFactory* factory) + : factory_(factory) {} + virtual ~EncoderFactoryAdapter() {} + + // Implement webrtc::VideoEncoderFactory. + webrtc::VideoEncoder* Create() override { + return factory_->CreateVideoEncoder(webrtc::kVideoCodecVP8); + } + + void Destroy(webrtc::VideoEncoder* encoder) override { + return factory_->DestroyVideoEncoder(encoder); + } + + private: + cricket::WebRtcVideoEncoderFactory* const factory_; +}; + +// An encoder factory that wraps Create requests for simulcastable codec types +// with a webrtc::SimulcastEncoderAdapter. Non simulcastable codec type +// requests are just passed through to the contained encoder factory. +class WebRtcSimulcastEncoderFactory + : public cricket::WebRtcVideoEncoderFactory { + public: + // WebRtcSimulcastEncoderFactory doesn't take ownership of |factory|, which is + // owned by e.g. PeerConnectionFactory. + explicit WebRtcSimulcastEncoderFactory( + cricket::WebRtcVideoEncoderFactory* factory) + : factory_(factory) {} + + static bool UseSimulcastEncoderFactory( + const std::vector& codecs) { + // If any codec is VP8, use the simulcast factory. If asked to create a + // non-VP8 codec, we'll just return a contained factory encoder directly. + for (const auto& codec : codecs) { + if (codec.type == webrtc::kVideoCodecVP8) { + return true; + } + } + return false; + } + + webrtc::VideoEncoder* CreateVideoEncoder( + webrtc::VideoCodecType type) override { + ASSERT(factory_ != NULL); + // If it's a codec type we can simulcast, create a wrapped encoder. + if (type == webrtc::kVideoCodecVP8) { + return new webrtc::SimulcastEncoderAdapter( + new EncoderFactoryAdapter(factory_)); + } + webrtc::VideoEncoder* encoder = factory_->CreateVideoEncoder(type); + if (encoder) { + non_simulcast_encoders_.push_back(encoder); + } + return encoder; + } + + const std::vector& codecs() const override { + return factory_->codecs(); + } + + bool EncoderTypeHasInternalSource( + webrtc::VideoCodecType type) const override { + return factory_->EncoderTypeHasInternalSource(type); + } + + void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override { + // Check first to see if the encoder wasn't wrapped in a + // SimulcastEncoderAdapter. In that case, ask the factory to destroy it. + if (std::remove(non_simulcast_encoders_.begin(), + non_simulcast_encoders_.end(), + encoder) != non_simulcast_encoders_.end()) { + factory_->DestroyVideoEncoder(encoder); + return; + } + + // Otherwise, SimulcastEncoderAdapter can be deleted directly, and will call + // DestroyVideoEncoder on the factory for individual encoder instances. + delete encoder; + } + + private: + cricket::WebRtcVideoEncoderFactory* factory_; + // A list of encoders that were created without being wrapped in a + // SimulcastEncoderAdapter. + std::vector non_simulcast_encoders_; +}; + +bool CodecIsInternallySupported(const std::string& codec_name) { + if (CodecNamesEq(codec_name, kVp8CodecName)) { + return true; + } + if (CodecNamesEq(codec_name, kVp9CodecName)) { + const std::string group_name = + webrtc::field_trial::FindFullName("WebRTC-SupportVP9"); + return group_name == "Enabled" || group_name == "EnabledByFlag"; + } + return false; +} + +void AddDefaultFeedbackParams(VideoCodec* codec) { + codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamCcm, kRtcpFbCcmParamFir)); + codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kParamValueEmpty)); + codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kRtcpFbNackParamPli)); + codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamRemb, kParamValueEmpty)); +} + +static VideoCodec MakeVideoCodecWithDefaultFeedbackParams(int payload_type, + const char* name) { + VideoCodec codec(payload_type, name, kDefaultVideoMaxWidth, + kDefaultVideoMaxHeight, kDefaultVideoMaxFramerate, 0); + AddDefaultFeedbackParams(&codec); + return codec; +} + static std::string CodecVectorToString(const std::vector& codecs) { std::stringstream out; out << '{'; @@ -179,6 +300,15 @@ static void MergeFecConfig(const webrtc::FecConfig& other, } } // namespace +// Constants defined in talk/media/webrtc/constants.h +// TODO(pbos): Move these to a separate constants.cc file. +const int kMinVideoBitrate = 30; +const int kStartVideoBitrate = 300; +const int kMaxVideoBitrate = 2000; + +const int kVideoMtu = 1200; +const int kVideoRtpBufferSize = 65536; + // This constant is really an on/off, lower-level configurable NACK history // duration hasn't been implemented. static const int kNackHistoryMs = 1000; @@ -193,6 +323,22 @@ const int kMinBandwidthBps = 30000; const int kStartBandwidthBps = 300000; const int kMaxBandwidthBps = 2000000; +std::vector DefaultVideoCodecList() { + std::vector codecs; + if (CodecIsInternallySupported(kVp9CodecName)) { + codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp9PlType, + kVp9CodecName)); + // TODO(andresp): Add rtx codec for vp9 and verify it works. + } + codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp8PlType, + kVp8CodecName)); + codecs.push_back( + VideoCodec::CreateRtxCodec(kDefaultRtxVp8PlType, kDefaultVp8PlType)); + codecs.push_back(VideoCodec(kDefaultRedPlType, kRedCodecName)); + codecs.push_back(VideoCodec(kDefaultUlpfecType, kUlpfecCodecName)); + return codecs; +} + static bool FindFirstMatchingCodec(const std::vector& codecs, const VideoCodec& requested_codec, VideoCodec* matching_codec) { diff --git a/talk/media/webrtc/webrtcvideoengine2.h b/talk/media/webrtc/webrtcvideoengine2.h index b6b976415..a0fde8f9b 100644 --- a/talk/media/webrtc/webrtcvideoengine2.h +++ b/talk/media/webrtc/webrtcvideoengine2.h @@ -75,6 +75,9 @@ class WebRtcVoiceEngine; struct CapturedFrame; struct Device; +// Exposed here for unittests. +std::vector DefaultVideoCodecList(); + class UnsignalledSsrcHandler { public: enum Action { diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc index 7bcab5574..681115591 100644 --- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc +++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc @@ -35,7 +35,6 @@ #include "talk/media/webrtc/fakewebrtcvideoengine.h" #include "talk/media/webrtc/simulcast.h" #include "talk/media/webrtc/webrtcvideochannelfactory.h" -#include "talk/media/webrtc/webrtcvideoengine.h" #include "talk/media/webrtc/webrtcvideoengine2.h" #include "talk/media/webrtc/webrtcvoiceengine.h" #include "webrtc/base/arraysize.h" diff --git a/talk/media/webrtc/webrtcvideoengine_unittest.cc b/talk/media/webrtc/webrtcvideoengine_unittest.cc deleted file mode 100644 index 60e7e364a..000000000 --- a/talk/media/webrtc/webrtcvideoengine_unittest.cc +++ /dev/null @@ -1,4644 +0,0 @@ -/* - * libjingle - * Copyright 2004 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "talk/media/base/constants.h" -#include "talk/media/base/fakenetworkinterface.h" -#include "talk/media/base/fakevideorenderer.h" -#include "talk/media/base/mediachannel.h" -#include "talk/media/base/testutils.h" -#include "talk/media/base/videoadapter.h" -#include "talk/media/base/videoengine_unittest.h" -#include "talk/media/webrtc/fakewebrtcvideoengine.h" -#include "talk/media/webrtc/simulcast.h" -#include "talk/media/webrtc/webrtcvideoengine.h" -#include "talk/media/webrtc/webrtcvideoframe.h" -#include "talk/media/webrtc/webrtcvoiceengine.h" -#include "talk/session/media/mediasession.h" -#include "webrtc/base/fakecpumonitor.h" -#include "webrtc/base/gunit.h" -#include "webrtc/base/logging.h" -#include "webrtc/base/scoped_ptr.h" -#include "webrtc/base/stream.h" -#include "webrtc/system_wrappers/interface/trace.h" - -// Tests for the WebRtcVideoEngine/VideoChannel code. - -using cricket::kRtpTimestampOffsetHeaderExtension; -using cricket::kRtpAbsoluteSenderTimeHeaderExtension; -using cricket::kRtpVideoRotationHeaderExtension; - -static const cricket::VideoCodec kVP8Codec720p(100, "VP8", 1280, 720, 30, 0); -static const cricket::VideoCodec kVP8Codec360p(100, "VP8", 640, 360, 30, 0); -static const cricket::VideoCodec kVP8Codec270p(100, "VP8", 480, 270, 30, 0); - -static const cricket::VideoCodec kVP8Codec(100, "VP8", 640, 400, 30, 0); -static const cricket::VideoCodec kH264Codec(127, "H264", 640, 400, 30, 0); -static const cricket::VideoCodec kRedCodec(101, "red", 0, 0, 0, 0); -static const cricket::VideoCodec kUlpFecCodec(102, "ulpfec", 0, 0, 0, 0); -static const cricket::VideoCodec* const kVideoCodecs[] = { - &kVP8Codec, - &kRedCodec, - &kUlpFecCodec -}; - -static const unsigned int kStartBandwidthKbps = 300; -static const unsigned int kMinBandwidthKbps = 30; -static const unsigned int kMaxBandwidthKbps = 2000; - -static const uint32 kSsrcs1[] = {1}; -static const uint32 kSsrcs2[] = {1, 2}; -static const uint32 kSsrcs3[] = {1, 2, 3}; -static const uint32 kRtxSsrcs1[] = {4}; -static const uint32 kRtxSsrcs3[] = {4, 5, 6}; - -static const int kPayloadTypes1[] = {96}; -static const int kPayloadTypes2[] = {96, 97}; - -class FakeViEWrapper : public cricket::ViEWrapper { - public: - explicit FakeViEWrapper(cricket::FakeWebRtcVideoEngine* engine) - : cricket::ViEWrapper(engine, // base - engine, // codec - engine, // capture - engine, // network - engine, // render - engine, // rtp - engine, // image - engine) { // external decoder - } -}; - -// Test fixture to test WebRtcVideoEngine with a fake webrtc::VideoEngine. -// Useful for testing failure paths. -class WebRtcVideoEngineTestFake : public testing::Test, - public sigslot::has_slots<> { - public: - WebRtcVideoEngineTestFake() - : vie_(kVideoCodecs, ARRAY_SIZE(kVideoCodecs)), - cpu_monitor_(new rtc::FakeCpuMonitor( - rtc::Thread::Current())), - engine_(NULL, // cricket::WebRtcVoiceEngine - new FakeViEWrapper(&vie_), cpu_monitor_), - channel_(NULL), - voice_channel_(NULL), - last_error_(cricket::VideoMediaChannel::ERROR_NONE) { - } - bool SetupEngine() { - bool result = engine_.Init(rtc::Thread::Current()); - if (result) { - channel_ = engine_.CreateChannel(cricket::VideoOptions(), voice_channel_); - channel_->SignalMediaError.connect(this, - &WebRtcVideoEngineTestFake::OnMediaError); - result = (channel_ != NULL); - } - return result; - } - void OnMediaError(uint32 ssrc, cricket::VideoMediaChannel::Error error) { - last_error_ = error; - } - bool SendI420Frame(int width, int height) { - if (NULL == channel_) { - return false; - } - cricket::WebRtcVideoFrame frame; - if (!frame.InitToBlack(width, height, 1, 1, 0, 0)) { - return false; - } - cricket::FakeVideoCapturer capturer; - channel_->SendFrame(&capturer, &frame); - return true; - } - bool SendI420ScreencastFrame(int width, int height) { - return SendI420ScreencastFrameWithTimestamp(width, height, 0); - } - bool SendI420ScreencastFrameWithTimestamp( - int width, int height, int64 timestamp) { - if (NULL == channel_) { - return false; - } - cricket::WebRtcVideoFrame frame; - if (!frame.InitToBlack(width, height, 1, 1, 0, 0)) { - return false; - } - cricket::FakeVideoCapturer capturer; - capturer.SetScreencast(true); - channel_->SendFrame(&capturer, &frame); - return true; - } - void TestSetSendRtpHeaderExtensions(const std::string& ext) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - // Verify extensions are off by default. - EXPECT_EQ(-1, vie_.GetSendRtpExtensionId(channel_num, ext)); - - // Enable extension. - const int id = 1; - std::vector extensions; - extensions.push_back(cricket::RtpHeaderExtension(ext, id)); - - // Verify the send extension id. - EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); - EXPECT_EQ(id, vie_.GetSendRtpExtensionId(channel_num, ext)); - // Verify call with same set of extensions returns true. - EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); - EXPECT_EQ(id, vie_.GetSendRtpExtensionId(channel_num, ext)); - - // Add a new send stream and verify the extension is set. - // The first send stream to occupy the default channel. - EXPECT_TRUE( - channel_->AddSendStream(cricket::StreamParams::CreateLegacy(123))); - EXPECT_TRUE( - channel_->AddSendStream(cricket::StreamParams::CreateLegacy(234))); - int new_send_channel_num = vie_.GetLastChannel(); - EXPECT_NE(channel_num, new_send_channel_num); - EXPECT_EQ(id, vie_.GetSendRtpExtensionId(new_send_channel_num, ext)); - - // Remove the extension id. - std::vector empty_extensions; - EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(empty_extensions)); - EXPECT_EQ(-1, vie_.GetSendRtpExtensionId(channel_num, ext)); - EXPECT_EQ(-1, vie_.GetSendRtpExtensionId(new_send_channel_num, ext)); - } - void TestSetRecvRtpHeaderExtensions(const std::string& ext) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - // Verify extensions are off by default. - EXPECT_EQ(-1, vie_.GetReceiveRtpExtensionId(channel_num, ext)); - - // Enable extension. - const int id = 2; - std::vector extensions; - extensions.push_back(cricket::RtpHeaderExtension(ext, id)); - - // Verify receive extension id. - EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); - EXPECT_EQ(id, vie_.GetReceiveRtpExtensionId(channel_num, ext)); - // Verify call with same set of extensions returns true. - EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); - EXPECT_EQ(id, vie_.GetReceiveRtpExtensionId(channel_num, ext)); - - // Add a new receive stream and verify the extension is set. - // The first send stream to occupy the default channel. - EXPECT_TRUE( - channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(345))); - EXPECT_TRUE( - channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(456))); - int new_recv_channel_num = vie_.GetLastChannel(); - EXPECT_NE(channel_num, new_recv_channel_num); - EXPECT_EQ(id, vie_.GetReceiveRtpExtensionId(new_recv_channel_num, ext)); - - // Remove the extension id. - std::vector empty_extensions; - EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(empty_extensions)); - EXPECT_EQ(-1, vie_.GetReceiveRtpExtensionId(channel_num, ext)); - EXPECT_EQ(-1, vie_.GetReceiveRtpExtensionId(new_recv_channel_num, ext)); - } - void VerifyCodecFeedbackParams(const cricket::VideoCodec& codec) { - EXPECT_TRUE(codec.HasFeedbackParam( - cricket::FeedbackParam(cricket::kRtcpFbParamNack, - cricket::kParamValueEmpty))); - EXPECT_TRUE(codec.HasFeedbackParam( - cricket::FeedbackParam(cricket::kRtcpFbParamNack, - cricket::kRtcpFbNackParamPli))); - EXPECT_TRUE(codec.HasFeedbackParam( - cricket::FeedbackParam(cricket::kRtcpFbParamRemb, - cricket::kParamValueEmpty))); - EXPECT_TRUE(codec.HasFeedbackParam( - cricket::FeedbackParam(cricket::kRtcpFbParamCcm, - cricket::kRtcpFbCcmParamFir))); - } - void VerifyVP8SendCodec(int channel_num, - unsigned int width, - unsigned int height, - unsigned int layers = 0, - unsigned int max_bitrate = kMaxBandwidthKbps, - unsigned int min_bitrate = kMinBandwidthKbps, - unsigned int start_bitrate = kStartBandwidthKbps, - unsigned int fps = 30, - unsigned int max_quantization = 0 - ) { - webrtc::VideoCodec gcodec; - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec)); - - // Video codec properties. - EXPECT_EQ(webrtc::kVideoCodecVP8, gcodec.codecType); - EXPECT_STREQ("VP8", gcodec.plName); - EXPECT_EQ(100, gcodec.plType); - EXPECT_EQ(width, gcodec.width); - EXPECT_EQ(height, gcodec.height); - EXPECT_EQ(std::min(start_bitrate, max_bitrate), gcodec.startBitrate); - EXPECT_EQ(max_bitrate, gcodec.maxBitrate); - EXPECT_EQ(min_bitrate, gcodec.minBitrate); - EXPECT_EQ(fps, gcodec.maxFramerate); - // VP8 specific. - EXPECT_FALSE(gcodec.codecSpecific.VP8.pictureLossIndicationOn); - EXPECT_FALSE(gcodec.codecSpecific.VP8.feedbackModeOn); - EXPECT_EQ(webrtc::kComplexityNormal, gcodec.codecSpecific.VP8.complexity); - EXPECT_EQ(webrtc::kResilienceOff, gcodec.codecSpecific.VP8.resilience); - EXPECT_EQ(max_quantization, gcodec.qpMax); - } - virtual void TearDown() { - delete channel_; - engine_.Terminate(); - } - - protected: - cricket::FakeWebRtcVideoEngine vie_; - cricket::FakeWebRtcVideoDecoderFactory decoder_factory_; - cricket::FakeWebRtcVideoEncoderFactory encoder_factory_; - rtc::FakeCpuMonitor* cpu_monitor_; - cricket::WebRtcVideoEngine engine_; - cricket::WebRtcVideoMediaChannel* channel_; - cricket::WebRtcVoiceMediaChannel* voice_channel_; - cricket::VideoMediaChannel::Error last_error_; -}; - -// Test fixtures to test WebRtcVideoEngine with a real webrtc::VideoEngine. -class WebRtcVideoEngineTest - : public VideoEngineTest { - protected: - typedef VideoEngineTest Base; -}; -class WebRtcVideoMediaChannelTest - : public VideoMediaChannelTest< - cricket::WebRtcVideoEngine, cricket::WebRtcVideoMediaChannel> { - protected: - typedef VideoMediaChannelTest Base; - virtual cricket::VideoCodec DefaultCodec() { return kVP8Codec; } - virtual void SetUp() { - Base::SetUp(); - } - virtual void TearDown() { - Base::TearDown(); - } -}; - -///////////////////////// -// Tests with fake ViE // -///////////////////////// - -// Tests that our stub library "works". -TEST_F(WebRtcVideoEngineTestFake, StartupShutdown) { - EXPECT_FALSE(vie_.IsInited()); - EXPECT_TRUE(engine_.Init(rtc::Thread::Current())); - EXPECT_TRUE(vie_.IsInited()); - engine_.Terminate(); -} - -// Tests that webrtc logs are logged when they should be. -TEST_F(WebRtcVideoEngineTest, WebRtcShouldLog) { - const char webrtc_log[] = "WebRtcVideoEngineTest.WebRtcShouldLog"; - EXPECT_TRUE(engine_.Init(rtc::Thread::Current())); - engine_.SetLogging(rtc::LS_INFO, ""); - std::string str; - rtc::StringStream stream(str); - rtc::LogMessage::AddLogToStream(&stream, rtc::LS_INFO); - EXPECT_EQ(rtc::LS_INFO, rtc::LogMessage::GetLogToStream(&stream)); - webrtc::Trace::Add(webrtc::kTraceStateInfo, webrtc::kTraceUndefined, 0, - webrtc_log); - rtc::Thread::Current()->ProcessMessages(100); - rtc::LogMessage::RemoveLogToStream(&stream); - // Access |str| after LogMessage is done with it to avoid data racing. - EXPECT_NE(std::string::npos, str.find(webrtc_log)); -} - -// Tests that webrtc logs are not logged when they should't be. -TEST_F(WebRtcVideoEngineTest, WebRtcShouldNotLog) { - const char webrtc_log[] = "WebRtcVideoEngineTest.WebRtcShouldNotLog"; - EXPECT_TRUE(engine_.Init(rtc::Thread::Current())); - // WebRTC should never be logged lower than LS_INFO. - engine_.SetLogging(rtc::LS_WARNING, ""); - std::string str; - rtc::StringStream stream(str); - // Make sure that WebRTC is not logged, even at lowest severity - rtc::LogMessage::AddLogToStream(&stream, rtc::LS_SENSITIVE); - EXPECT_EQ(rtc::LS_SENSITIVE, - rtc::LogMessage::GetLogToStream(&stream)); - webrtc::Trace::Add(webrtc::kTraceStateInfo, webrtc::kTraceUndefined, 0, - webrtc_log); - rtc::Thread::Current()->ProcessMessages(10); - EXPECT_EQ(std::string::npos, str.find(webrtc_log)); - rtc::LogMessage::RemoveLogToStream(&stream); -} - -// Tests that we can create and destroy a channel. -TEST_F(WebRtcVideoEngineTestFake, CreateChannel) { - EXPECT_TRUE(engine_.Init(rtc::Thread::Current())); - channel_ = engine_.CreateChannel(cricket::VideoOptions(), voice_channel_); - EXPECT_TRUE(channel_ != NULL); - EXPECT_EQ(1, engine_.GetNumOfChannels()); - delete channel_; - channel_ = NULL; - EXPECT_EQ(0, engine_.GetNumOfChannels()); -} - -// Tests that we properly handle failures in CreateChannel. -TEST_F(WebRtcVideoEngineTestFake, CreateChannelFail) { - vie_.set_fail_create_channel(true); - EXPECT_TRUE(engine_.Init(rtc::Thread::Current())); - channel_ = engine_.CreateChannel(cricket::VideoOptions(), voice_channel_); - EXPECT_TRUE(channel_ == NULL); -} - -// Tests that we properly handle failures in AllocateExternalCaptureDevice. -TEST_F(WebRtcVideoEngineTestFake, AllocateExternalCaptureDeviceFail) { - vie_.set_fail_alloc_capturer(true); - EXPECT_TRUE(engine_.Init(rtc::Thread::Current())); - channel_ = engine_.CreateChannel(cricket::VideoOptions(), voice_channel_); - EXPECT_TRUE(channel_ == NULL); -} - -// Test that we apply our default codecs properly. -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecs) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector codecs(engine_.codecs()); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(vie_.GetHybridNackFecStatus(channel_num)); - EXPECT_FALSE(vie_.GetNackStatus(channel_num)); - EXPECT_EQ(1, vie_.GetNumSetSendCodecs()); - // TODO(juberti): Check RTCP, PLI, TMMBR. -} - -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsBeforeFrameRegistersTinyFormat) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector codecs(engine_.codecs()); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - VerifyVP8SendCodec(channel_num, 176, 144); -} - -// Test that ViE Channel doesn't call SetSendCodec again if same codec is tried -// to apply. -TEST_F(WebRtcVideoEngineTestFake, DontResetSetSendCodec) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector codecs(engine_.codecs()); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(vie_.GetHybridNackFecStatus(channel_num)); - EXPECT_FALSE(vie_.GetNackStatus(channel_num)); - EXPECT_EQ(1, vie_.GetNumSetSendCodecs()); - // Try setting same code again. - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - // Since it's exact same codec which is already set, media channel shouldn't - // send the codec to ViE. - EXPECT_EQ(1, vie_.GetNumSetSendCodecs()); -} - -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsWithMinMaxBitrate) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector codecs(engine_.codecs()); - codecs[0].params[cricket::kCodecParamMinBitrate] = "10"; - codecs[0].params[cricket::kCodecParamMaxBitrate] = "20"; - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - VerifyVP8SendCodec( - channel_num, kVP8Codec.width, kVP8Codec.height, 0, 20, 10, 20); - - cricket::VideoCodec codec; - EXPECT_TRUE(channel_->GetSendCodec(&codec)); - EXPECT_EQ("10", codec.params[cricket::kCodecParamMinBitrate]); - EXPECT_EQ("20", codec.params[cricket::kCodecParamMaxBitrate]); -} - -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsWithStartBitrate) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector codecs(engine_.codecs()); - codecs[0].params[cricket::kCodecParamStartBitrate] = "450"; - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - VerifyVP8SendCodec(channel_num, - kVP8Codec.width, - kVP8Codec.height, - 0, - kMaxBandwidthKbps, - kMinBandwidthKbps, - 450); - - cricket::VideoCodec codec; - EXPECT_TRUE(channel_->GetSendCodec(&codec)); - EXPECT_EQ("450", codec.params[cricket::kCodecParamStartBitrate]); -} - -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsWithMinMaxStartBitrate) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector codecs(engine_.codecs()); - codecs[0].params[cricket::kCodecParamMinBitrate] = "10"; - codecs[0].params[cricket::kCodecParamMaxBitrate] = "20"; - codecs[0].params[cricket::kCodecParamStartBitrate] = "14"; - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - VerifyVP8SendCodec( - channel_num, kVP8Codec.width, kVP8Codec.height, 0, 20, 10, 14); - - cricket::VideoCodec codec; - EXPECT_TRUE(channel_->GetSendCodec(&codec)); - EXPECT_EQ("10", codec.params[cricket::kCodecParamMinBitrate]); - EXPECT_EQ("20", codec.params[cricket::kCodecParamMaxBitrate]); - EXPECT_EQ("14", codec.params[cricket::kCodecParamStartBitrate]); -} - -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsWithMinMaxBitrateInvalid) { - EXPECT_TRUE(SetupEngine()); - std::vector codecs(engine_.codecs()); - codecs[0].params[cricket::kCodecParamMinBitrate] = "30"; - codecs[0].params[cricket::kCodecParamMaxBitrate] = "20"; - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_FALSE(channel_->SetSendCodecs(codecs)); -} - -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsWithLargeMinMaxBitrate) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector codecs(engine_.codecs()); - codecs[0].params[cricket::kCodecParamMinBitrate] = "1000"; - codecs[0].params[cricket::kCodecParamMaxBitrate] = "3000"; - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - VerifyVP8SendCodec( - channel_num, kVP8Codec.width, kVP8Codec.height, 0, 3000, 1000, - 1000); -} - -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsWithMaxQuantization) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector codecs(engine_.codecs()); - codecs[0].params[cricket::kCodecParamMaxQuantization] = "21"; - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - VerifyVP8SendCodec(channel_num, - kVP8Codec.width, - kVP8Codec.height, - 0, - kMaxBandwidthKbps, - kMinBandwidthKbps, - 300, - 30, - 21); - - cricket::VideoCodec codec; - EXPECT_TRUE(channel_->GetSendCodec(&codec)); - EXPECT_EQ("21", codec.params[cricket::kCodecParamMaxQuantization]); -} - -TEST_F(WebRtcVideoEngineTestFake, SetOptionsWithMaxBitrate) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector codecs(engine_.codecs()); - codecs[0].params[cricket::kCodecParamMinBitrate] = "10"; - codecs[0].params[cricket::kCodecParamMaxBitrate] = "20"; - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - VerifyVP8SendCodec( - channel_num, kVP8Codec.width, kVP8Codec.height, 0, 20, 10, 20); - - // Verify that max bitrate doesn't change after SetOptions(). - cricket::VideoOptions options; - options.video_noise_reduction.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - VerifyVP8SendCodec( - channel_num, kVP8Codec.width, kVP8Codec.height, 0, 20, 10, 20); - - options.video_noise_reduction.Set(false); - options.conference_mode.Set(false); - EXPECT_TRUE(channel_->SetOptions(options)); - VerifyVP8SendCodec( - channel_num, kVP8Codec.width, kVP8Codec.height, 0, 20, 10, 20); -} - -TEST_F(WebRtcVideoEngineTestFake, MaxBitrateResetWithConferenceMode) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector codecs(engine_.codecs()); - codecs[0].params[cricket::kCodecParamMinBitrate] = "10"; - codecs[0].params[cricket::kCodecParamMaxBitrate] = "20"; - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - VerifyVP8SendCodec( - channel_num, kVP8Codec.width, kVP8Codec.height, 0, 20, 10, 20); - - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - options.conference_mode.Set(false); - EXPECT_TRUE(channel_->SetOptions(options)); - VerifyVP8SendCodec( - channel_num, kVP8Codec.width, kVP8Codec.height, 0, - kMaxBandwidthKbps, 10, kStartBandwidthKbps); -} - -// Verify the current send bitrate is used as start bitrate when reconfiguring -// the send codec. -TEST_F(WebRtcVideoEngineTestFake, StartSendBitrate) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(1))); - int send_channel = vie_.GetLastChannel(); - cricket::VideoCodec codec(kVP8Codec); - std::vector codec_list; - codec_list.push_back(codec); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - VerifyVP8SendCodec(send_channel, kVP8Codec.width, kVP8Codec.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, - kStartBandwidthKbps); - EXPECT_EQ(0, vie_.StartSend(send_channel)); - - // Increase the send bitrate and verify it is used as start bitrate. - const unsigned int kIncreasedSendBitrateBps = 768000; - vie_.SetSendBitrates(send_channel, kIncreasedSendBitrateBps, 0, 0); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - VerifyVP8SendCodec(send_channel, kVP8Codec.width, kVP8Codec.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, - kIncreasedSendBitrateBps / 1000); - - // Never set a start bitrate higher than the max bitrate. - vie_.SetSendBitrates(send_channel, kMaxBandwidthKbps + 500, 0, 0); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - VerifyVP8SendCodec(send_channel, kVP8Codec.width, kVP8Codec.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, - kStartBandwidthKbps); - - // Use the default start bitrate if the send bitrate is lower. - vie_.SetSendBitrates(send_channel, kStartBandwidthKbps - 50, 0, - 0); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - VerifyVP8SendCodec(send_channel, kVP8Codec.width, kVP8Codec.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, - kStartBandwidthKbps); -} - - -// Test that we constrain send codecs properly. -TEST_F(WebRtcVideoEngineTestFake, ConstrainSendCodecs) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - // Set max settings of 640x400x30. - EXPECT_TRUE(engine_.SetDefaultEncoderConfig( - cricket::VideoEncoderConfig(kVP8Codec))); - - // Send codec format bigger than max setting. - cricket::VideoCodec codec(kVP8Codec); - codec.width = 1280; - codec.height = 800; - codec.framerate = 60; - std::vector codec_list; - codec_list.push_back(codec); - - // Set send codec and verify codec has been constrained. - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height); -} - -// Test that SetSendCodecs rejects bad format. -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsRejectBadFormat) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - // Set w = 0. - cricket::VideoCodec codec(kVP8Codec); - codec.width = 0; - std::vector codec_list; - codec_list.push_back(codec); - - // Verify SetSendCodecs failed and send codec is not changed on engine. - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_FALSE(channel_->SetSendCodecs(codec_list)); - webrtc::VideoCodec gcodec; - // Set plType to something other than the value to test against ensuring - // that failure will happen if it is not changed. - gcodec.plType = 1; - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(0, gcodec.plType); - - // Set h = 0. - codec_list[0].width = 640; - codec_list[0].height = 0; - - // Verify SetSendCodecs failed and send codec is not changed on engine. - EXPECT_FALSE(channel_->SetSendCodecs(codec_list)); - // Set plType to something other than the value to test against ensuring - // that failure will happen if it is not changed. - gcodec.plType = 1; - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(0, gcodec.plType); -} - -// Test that SetSendCodecs rejects bad codec. -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsRejectBadCodec) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - // Set bad codec name. - cricket::VideoCodec codec(kVP8Codec); - codec.name = "bad"; - std::vector codec_list; - codec_list.push_back(codec); - - // Verify SetSendCodecs failed and send codec is not changed on engine. - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_FALSE(channel_->SetSendCodecs(codec_list)); - webrtc::VideoCodec gcodec; - // Set plType to something other than the value to test against ensuring - // that failure will happen if it is not changed. - gcodec.plType = 1; - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(0, gcodec.plType); -} - -// Test that vie send codec is reset on new video frame size. -TEST_F(WebRtcVideoEngineTestFake, ResetVieSendCodecOnNewFrameSize) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - // Set send codec. - std::vector codec_list; - codec_list.push_back(kVP8Codec); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(123))); - EXPECT_TRUE(channel_->SetSend(true)); - - // Capture a smaller frame and verify vie send codec has been reset to - // the new size. - SendI420Frame(kVP8Codec.width / 2, kVP8Codec.height / 2); - VerifyVP8SendCodec(channel_num, kVP8Codec.width / 2, kVP8Codec.height / 2); - - // Capture a frame bigger than send_codec_ and verify vie send codec has been - // reset (and clipped) to send_codec_. - SendI420Frame(kVP8Codec.width * 2, kVP8Codec.height * 2); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height); -} - -// Test that we set our inbound codecs properly. -TEST_F(WebRtcVideoEngineTestFake, SetRecvCodecs) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); - - webrtc::VideoCodec wcodec; - EXPECT_TRUE(engine_.ConvertFromCricketVideoCodec(kVP8Codec, &wcodec)); - EXPECT_TRUE(vie_.ReceiveCodecRegistered(channel_num, wcodec)); -} - -// Test that we set our inbound RTX codecs properly. -TEST_F(WebRtcVideoEngineTestFake, SetRecvCodecsWithRtx) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); - codecs.push_back(rtx_codec); - // Should fail since there's no associated payload type set. - EXPECT_FALSE(channel_->SetRecvCodecs(codecs)); - - codecs[0].SetParam("apt", 97); - // Should still fail since the we don't support RTX on this APT. - EXPECT_FALSE(channel_->SetRecvCodecs(codecs)); - - codecs[0].SetParam("apt", kVP8Codec.id); - // Should still fail since the associated payload type is unknown. - EXPECT_FALSE(channel_->SetRecvCodecs(codecs)); - - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); - - webrtc::VideoCodec wcodec; - // Should not have been registered as a WebRTC codec. - EXPECT_TRUE(engine_.ConvertFromCricketVideoCodec(rtx_codec, &wcodec)); - EXPECT_STREQ("rtx", wcodec.plName); - EXPECT_FALSE(vie_.ReceiveCodecRegistered(channel_num, wcodec)); - - EXPECT_EQ(vie_.GetRtxRecvPayloadTypes(channel_num), - MAKE_VECTOR(kPayloadTypes1)); -} - -// Test that RTX packets are routed to the default video channel if -// there's only one recv stream. -TEST_F(WebRtcVideoEngineTestFake, TestReceiveRtxOneStream) { - EXPECT_TRUE(SetupEngine()); - - // Setup one channel with an associated RTX stream. - cricket::StreamParams params = - cricket::StreamParams::CreateLegacy(kSsrcs1[0]); - params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]); - EXPECT_TRUE(channel_->AddRecvStream(params)); - int channel_num = vie_.GetLastChannel(); - EXPECT_EQ(static_cast(kRtxSsrcs1[0]), - vie_.GetRemoteRtxSsrc(channel_num)); - - // Register codecs. - std::vector codec_list; - codec_list.push_back(kVP8Codec720p); - cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); - rtx_codec.SetParam("apt", kVP8Codec.id); - codec_list.push_back(rtx_codec); - EXPECT_TRUE(channel_->SetRecvCodecs(codec_list)); - - // Construct a fake RTX packet and verify that it is passed to the - // right WebRTC channel. - const size_t kDataLength = 12; - uint8_t data[kDataLength]; - memset(data, 0, sizeof(data)); - data[0] = 0x80; - data[1] = rtx_codec.id; - rtc::SetBE32(&data[8], kRtxSsrcs1[0]); - rtc::Buffer packet(data, kDataLength); - rtc::PacketTime packet_time; - channel_->OnPacketReceived(&packet, packet_time); - EXPECT_EQ(rtx_codec.id, vie_.GetLastRecvdPayloadType(channel_num)); -} - -// Verify we don't crash when inserting packets after removing the default -// receive channel. -TEST_F(WebRtcVideoEngineTestFake, TestReceiveRtxWithRemovedDefaultChannel) { - EXPECT_TRUE(SetupEngine()); - - // Setup one channel with an associated RTX stream. - cricket::StreamParams params = - cricket::StreamParams::CreateLegacy(kSsrcs1[0]); - params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]); - EXPECT_TRUE(channel_->AddRecvStream(params)); - int channel_num = vie_.GetLastChannel(); - EXPECT_EQ(static_cast(kRtxSsrcs1[0]), - vie_.GetRemoteRtxSsrc(channel_num)); - - // Register codecs. - std::vector codec_list; - codec_list.push_back(kVP8Codec720p); - cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); - rtx_codec.SetParam("apt", kVP8Codec.id); - codec_list.push_back(rtx_codec); - EXPECT_TRUE(channel_->SetRecvCodecs(codec_list)); - - // Construct a fake RTX packet and verify that it is passed to the - // right WebRTC channel. - const size_t kDataLength = 12; - uint8_t data[kDataLength]; - memset(data, 0, sizeof(data)); - data[0] = 0x80; - data[1] = rtx_codec.id; - rtc::SetBE32(&data[8], kRtxSsrcs1[0]); - rtc::Buffer packet(data, kDataLength); - rtc::PacketTime packet_time; - channel_->OnPacketReceived(&packet, packet_time); - EXPECT_EQ(rtx_codec.id, vie_.GetLastRecvdPayloadType(channel_num)); - - // Remove the default channel and insert one more packet. - EXPECT_TRUE(channel_->RemoveRecvStream(kSsrcs1[0])); - channel_->OnPacketReceived(&packet, packet_time); -} - -// Test that RTX packets are routed to the correct video channel. -TEST_F(WebRtcVideoEngineTestFake, TestReceiveRtxThreeStreams) { - EXPECT_TRUE(SetupEngine()); - - // Setup three channels with associated RTX streams. - int channel_num[ARRAY_SIZE(kSsrcs3)]; - for (size_t i = 0; i < ARRAY_SIZE(kSsrcs3); ++i) { - cricket::StreamParams params = - cricket::StreamParams::CreateLegacy(kSsrcs3[i]); - params.AddFidSsrc(kSsrcs3[i], kRtxSsrcs3[i]); - EXPECT_TRUE(channel_->AddRecvStream(params)); - channel_num[i] = vie_.GetLastChannel(); - } - - // Register codecs. - std::vector codec_list; - codec_list.push_back(kVP8Codec720p); - cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); - rtx_codec.SetParam("apt", kVP8Codec.id); - codec_list.push_back(rtx_codec); - EXPECT_TRUE(channel_->SetRecvCodecs(codec_list)); - - // Construct a fake RTX packet and verify that it is passed to the - // right WebRTC channel. - const size_t kDataLength = 12; - uint8_t data[kDataLength]; - memset(data, 0, sizeof(data)); - data[0] = 0x80; - data[1] = rtx_codec.id; - rtc::SetBE32(&data[8], kRtxSsrcs3[1]); - rtc::Buffer packet(data, kDataLength); - rtc::PacketTime packet_time; - channel_->OnPacketReceived(&packet, packet_time); - EXPECT_NE(rtx_codec.id, vie_.GetLastRecvdPayloadType(channel_num[0])); - EXPECT_EQ(rtx_codec.id, vie_.GetLastRecvdPayloadType(channel_num[1])); - EXPECT_NE(rtx_codec.id, vie_.GetLastRecvdPayloadType(channel_num[2])); -} - -// Test that channel connects and disconnects external capturer correctly. -TEST_F(WebRtcVideoEngineTestFake, HasExternalCapturer) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - EXPECT_EQ(1, vie_.GetNumCapturers()); - int capture_id = vie_.GetCaptureId(channel_num); - EXPECT_EQ(channel_num, vie_.GetCaptureChannelId(capture_id)); - - // Delete the channel should disconnect the capturer. - delete channel_; - channel_ = NULL; - EXPECT_EQ(0, vie_.GetNumCapturers()); -} - -// Test that channel adds and removes renderer correctly. -TEST_F(WebRtcVideoEngineTestFake, HasRenderer) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - EXPECT_TRUE(vie_.GetHasRenderer(channel_num)); - EXPECT_FALSE(vie_.GetRenderStarted(channel_num)); -} - -// Test that rtcp is enabled on the channel. -TEST_F(WebRtcVideoEngineTestFake, RtcpEnabled) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - EXPECT_EQ(webrtc::kRtcpCompound_RFC4585, vie_.GetRtcpStatus(channel_num)); -} - -// Test that key frame request method is set on the channel. -TEST_F(WebRtcVideoEngineTestFake, KeyFrameRequestEnabled) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - EXPECT_EQ(webrtc::kViEKeyFrameRequestPliRtcp, - vie_.GetKeyFrameRequestMethod(channel_num)); -} - -// Test that remb receive and send is enabled for the default channel in a 1:1 -// call. -TEST_F(WebRtcVideoEngineTestFake, RembEnabled) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(1))); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - EXPECT_TRUE(vie_.GetRembStatusBwPartition(channel_num)); - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_TRUE(vie_.GetRembStatusBwPartition(channel_num)); - EXPECT_TRUE(vie_.GetRembStatusContribute(channel_num)); -} - -// When in conference mode, test that remb is enabled on a receive channel but -// not for the default channel and that it uses the default channel for sending -// remb packets. -TEST_F(WebRtcVideoEngineTestFake, RembEnabledOnReceiveChannels) { - EXPECT_TRUE(SetupEngine()); - int default_channel = vie_.GetLastChannel(); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(1))); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - EXPECT_TRUE(vie_.GetRembStatusBwPartition(default_channel)); - EXPECT_TRUE(vie_.GetRembStatusContribute(default_channel)); - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); - int new_channel_num = vie_.GetLastChannel(); - EXPECT_NE(default_channel, new_channel_num); - - EXPECT_TRUE(vie_.GetRembStatusBwPartition(default_channel)); - EXPECT_TRUE(vie_.GetRembStatusContribute(default_channel)); - EXPECT_FALSE(vie_.GetRembStatusBwPartition(new_channel_num)); - EXPECT_TRUE(vie_.GetRembStatusContribute(new_channel_num)); -} - -TEST_F(WebRtcVideoEngineTestFake, RecvStreamWithRtx) { - EXPECT_TRUE(SetupEngine()); - int default_channel = vie_.GetLastChannel(); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimWithRtxStreamParams("cname", - MAKE_VECTOR(kSsrcs3), - MAKE_VECTOR(kRtxSsrcs3)))); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_TRUE(channel_->AddRecvStream( - cricket::CreateSimWithRtxStreamParams("cname", - MAKE_VECTOR(kSsrcs1), - MAKE_VECTOR(kRtxSsrcs1)))); - int new_channel_num = vie_.GetLastChannel(); - EXPECT_NE(default_channel, new_channel_num); - EXPECT_EQ(4, vie_.GetRemoteRtxSsrc(new_channel_num)); -} - -TEST_F(WebRtcVideoEngineTestFake, RecvStreamNoRtx) { - EXPECT_TRUE(SetupEngine()); - int default_channel = vie_.GetLastChannel(); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimWithRtxStreamParams("cname", - MAKE_VECTOR(kSsrcs3), - MAKE_VECTOR(kRtxSsrcs3)))); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); - int new_channel_num = vie_.GetLastChannel(); - EXPECT_NE(default_channel, new_channel_num); - EXPECT_EQ(-1, vie_.GetRemoteRtxSsrc(new_channel_num)); -} - -// Test support for RTP timestamp offset header extension. -TEST_F(WebRtcVideoEngineTestFake, SendRtpTimestampOffsetHeaderExtensions) { - TestSetSendRtpHeaderExtensions(kRtpTimestampOffsetHeaderExtension); -} -TEST_F(WebRtcVideoEngineTestFake, RecvRtpTimestampOffsetHeaderExtensions) { - TestSetRecvRtpHeaderExtensions(kRtpTimestampOffsetHeaderExtension); -} - -// Test support for absolute send time header extension. -TEST_F(WebRtcVideoEngineTestFake, SendAbsoluteSendTimeHeaderExtensions) { - TestSetSendRtpHeaderExtensions(kRtpAbsoluteSenderTimeHeaderExtension); -} -TEST_F(WebRtcVideoEngineTestFake, RecvAbsoluteSendTimeHeaderExtensions) { - TestSetRecvRtpHeaderExtensions(kRtpAbsoluteSenderTimeHeaderExtension); -} - -// Test support for Coordination of Video Orientation (CVO) header extension. -TEST_F(WebRtcVideoEngineTestFake, SendVideoRotationHeaderExtensions) { - TestSetSendRtpHeaderExtensions(kRtpVideoRotationHeaderExtension); -} -TEST_F(WebRtcVideoEngineTestFake, RecvVideoRotationHeaderExtensions) { - TestSetRecvRtpHeaderExtensions(kRtpVideoRotationHeaderExtension); -} - -TEST_F(WebRtcVideoEngineTestFake, LeakyBucketTest) { - EXPECT_TRUE(SetupEngine()); - - // Verify this is on by default. - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(1))); - int first_send_channel = vie_.GetLastChannel(); - EXPECT_TRUE(vie_.GetTransmissionSmoothingStatus(first_send_channel)); - - // Add a new send stream and verify leaky bucket is enabled. - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(3))); - int second_send_channel = vie_.GetLastChannel(); - EXPECT_NE(first_send_channel, second_send_channel); - EXPECT_TRUE(vie_.GetTransmissionSmoothingStatus(second_send_channel)); -} - -// Verify that SuspendBelowMinBitrate is enabled if it is set in the options. -TEST_F(WebRtcVideoEngineTestFake, SuspendBelowMinBitrateTest) { - EXPECT_TRUE(SetupEngine()); - - // Verify this is off by default. - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(1))); - int first_send_channel = vie_.GetLastChannel(); - EXPECT_FALSE(vie_.GetSuspendBelowMinBitrateStatus(first_send_channel)); - - // Enable the experiment and verify. - cricket::VideoOptions options; - options.suspend_below_min_bitrate.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(vie_.GetSuspendBelowMinBitrateStatus(first_send_channel)); - - // Add a new send stream and verify suspend_below_min_bitrate is enabled. - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(2))); - int second_send_channel = vie_.GetLastChannel(); - EXPECT_NE(first_send_channel, second_send_channel); - EXPECT_TRUE(vie_.GetSuspendBelowMinBitrateStatus(second_send_channel)); -} - -TEST_F(WebRtcVideoEngineTestFake, BufferedModeLatency) { - EXPECT_TRUE(SetupEngine()); - - // Verify this is off by default. - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(1))); - int first_send_channel = vie_.GetLastChannel(); - EXPECT_EQ(0, vie_.GetSenderTargetDelay(first_send_channel)); - EXPECT_EQ(0, vie_.GetReceiverTargetDelay(first_send_channel)); - - // Enable the experiment and verify. The default channel will have both - // sender and receiver buffered mode enabled. - cricket::VideoOptions options; - options.conference_mode.Set(true); - options.buffered_mode_latency.Set(100); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_EQ(100, vie_.GetSenderTargetDelay(first_send_channel)); - EXPECT_EQ(100, vie_.GetReceiverTargetDelay(first_send_channel)); - - // Add a receive channel and verify sender buffered mode isn't enabled. - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); - int recv_channel_num = vie_.GetLastChannel(); - EXPECT_NE(first_send_channel, recv_channel_num); - EXPECT_EQ(0, vie_.GetSenderTargetDelay(recv_channel_num)); - EXPECT_EQ(100, vie_.GetReceiverTargetDelay(recv_channel_num)); - - // Add a new send stream and verify sender buffered mode is enabled. - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(3))); - int second_send_channel = vie_.GetLastChannel(); - EXPECT_NE(first_send_channel, second_send_channel); - EXPECT_EQ(100, vie_.GetSenderTargetDelay(second_send_channel)); - EXPECT_EQ(0, vie_.GetReceiverTargetDelay(second_send_channel)); - - // Disable sender buffered mode and verify. - options.buffered_mode_latency.Set(cricket::kBufferedModeDisabled); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_EQ(0, vie_.GetSenderTargetDelay(first_send_channel)); - EXPECT_EQ(0, vie_.GetReceiverTargetDelay(first_send_channel)); - EXPECT_EQ(0, vie_.GetSenderTargetDelay(second_send_channel)); - EXPECT_EQ(0, vie_.GetReceiverTargetDelay(second_send_channel)); - EXPECT_EQ(0, vie_.GetSenderTargetDelay(recv_channel_num)); - EXPECT_EQ(0, vie_.GetReceiverTargetDelay(recv_channel_num)); -} - -TEST_F(WebRtcVideoEngineTestFake, AdditiveVideoOptions) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(1))); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - channel_->SetSendCodecs(engine_.codecs()); - - int first_send_channel = vie_.GetLastChannel(); - EXPECT_EQ(0, vie_.GetSenderTargetDelay(first_send_channel)); - EXPECT_EQ(0, vie_.GetReceiverTargetDelay(first_send_channel)); - - cricket::VideoOptions options1; - options1.buffered_mode_latency.Set(100); - EXPECT_TRUE(channel_->SetOptions(options1)); - EXPECT_EQ(100, vie_.GetSenderTargetDelay(first_send_channel)); - EXPECT_EQ(100, vie_.GetReceiverTargetDelay(first_send_channel)); - EXPECT_TRUE(vie_.GetTransmissionSmoothingStatus(first_send_channel)); - - int kBoostedStartBandwidthKbps = 1000; - cricket::VideoOptions options2; - options2.video_start_bitrate.Set(kBoostedStartBandwidthKbps); - EXPECT_TRUE(channel_->SetOptions(options2)); - // Check that start bitrate has changed to the new value. - VerifyVP8SendCodec(first_send_channel, kVP8Codec.width, kVP8Codec.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, kBoostedStartBandwidthKbps); - // The buffered_mode_latency should still take effect. - EXPECT_EQ(100, vie_.GetSenderTargetDelay(first_send_channel)); - EXPECT_EQ(100, vie_.GetReceiverTargetDelay(first_send_channel)); -} - -TEST_F(WebRtcVideoEngineTestFake, SetCpuOveruseOptionsWithCaptureJitterMethod) { - EXPECT_TRUE(SetupEngine()); - - // Verify this is off by default. - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(1))); - int first_send_channel = vie_.GetLastChannel(); - webrtc::CpuOveruseOptions cpu_option = - vie_.GetCpuOveruseOptions(first_send_channel); - EXPECT_EQ(0, cpu_option.low_capture_jitter_threshold_ms); - EXPECT_EQ(0, cpu_option.high_capture_jitter_threshold_ms); - EXPECT_FALSE(cpu_option.enable_capture_jitter_method); - EXPECT_FALSE(cpu_option.enable_encode_usage_method); - - // Set low and high threshold and verify that cpu options are set. - cricket::VideoOptions options; - options.conference_mode.Set(true); - options.cpu_underuse_threshold.Set(10); - options.cpu_overuse_threshold.Set(20); - EXPECT_TRUE(channel_->SetOptions(options)); - cpu_option = vie_.GetCpuOveruseOptions(first_send_channel); - EXPECT_EQ(10, cpu_option.low_capture_jitter_threshold_ms); - EXPECT_EQ(20, cpu_option.high_capture_jitter_threshold_ms); - EXPECT_TRUE(cpu_option.enable_capture_jitter_method); - EXPECT_FALSE(cpu_option.enable_encode_usage_method); - - // Add a receive channel and verify that cpu options are not set. - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); - int recv_channel_num = vie_.GetLastChannel(); - EXPECT_NE(first_send_channel, recv_channel_num); - cpu_option = vie_.GetCpuOveruseOptions(recv_channel_num); - EXPECT_EQ(0, cpu_option.low_capture_jitter_threshold_ms); - EXPECT_EQ(0, cpu_option.high_capture_jitter_threshold_ms); - EXPECT_FALSE(cpu_option.enable_capture_jitter_method); - EXPECT_FALSE(cpu_option.enable_encode_usage_method); - - // Add a new send stream and verify that cpu options are set from start. - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(3))); - int second_send_channel = vie_.GetLastChannel(); - EXPECT_NE(first_send_channel, second_send_channel); - cpu_option = vie_.GetCpuOveruseOptions(second_send_channel); - EXPECT_EQ(10, cpu_option.low_capture_jitter_threshold_ms); - EXPECT_EQ(20, cpu_option.high_capture_jitter_threshold_ms); - EXPECT_TRUE(cpu_option.enable_capture_jitter_method); - EXPECT_FALSE(cpu_option.enable_encode_usage_method); -} - -TEST_F(WebRtcVideoEngineTestFake, SetInvalidCpuOveruseThresholds) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(1))); - int channel_num = vie_.GetLastChannel(); - - // Only low threshold set. Verify that cpu options are not set. - cricket::VideoOptions options; - options.conference_mode.Set(true); - options.cpu_underuse_threshold.Set(10); - EXPECT_TRUE(channel_->SetOptions(options)); - webrtc::CpuOveruseOptions cpu_option = vie_.GetCpuOveruseOptions(channel_num); - EXPECT_EQ(0, cpu_option.low_capture_jitter_threshold_ms); - EXPECT_EQ(0, cpu_option.high_capture_jitter_threshold_ms); - EXPECT_FALSE(cpu_option.enable_capture_jitter_method); - EXPECT_FALSE(cpu_option.enable_encode_usage_method); - - // Set high threshold to a negative value. Verify that options are not set. - options.cpu_overuse_threshold.Set(-1); - EXPECT_TRUE(channel_->SetOptions(options)); - cpu_option = vie_.GetCpuOveruseOptions(channel_num); - EXPECT_EQ(0, cpu_option.low_capture_jitter_threshold_ms); - EXPECT_EQ(0, cpu_option.high_capture_jitter_threshold_ms); - EXPECT_FALSE(cpu_option.enable_capture_jitter_method); - EXPECT_FALSE(cpu_option.enable_encode_usage_method); - - // Low and high threshold valid. Verify that cpu options are set. - options.cpu_overuse_threshold.Set(20); - EXPECT_TRUE(channel_->SetOptions(options)); - cpu_option = vie_.GetCpuOveruseOptions(channel_num); - EXPECT_EQ(10, cpu_option.low_capture_jitter_threshold_ms); - EXPECT_EQ(20, cpu_option.high_capture_jitter_threshold_ms); - EXPECT_TRUE(cpu_option.enable_capture_jitter_method); - EXPECT_FALSE(cpu_option.enable_encode_usage_method); -} - -TEST_F(WebRtcVideoEngineTestFake, SetCpuOveruseOptionsWithEncodeUsageMethod) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(1))); - int first_send_channel = vie_.GetLastChannel(); - - // Set low and high threshold and enable encode usage method. - // Verify that cpu options are set. - cricket::VideoOptions options; - options.conference_mode.Set(true); - options.cpu_underuse_threshold.Set(10); - options.cpu_overuse_threshold.Set(20); - options.cpu_overuse_encode_usage.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - webrtc::CpuOveruseOptions cpu_option = - vie_.GetCpuOveruseOptions(first_send_channel); - EXPECT_EQ(10, cpu_option.low_encode_usage_threshold_percent); - EXPECT_EQ(20, cpu_option.high_encode_usage_threshold_percent); - EXPECT_FALSE(cpu_option.enable_capture_jitter_method); - EXPECT_TRUE(cpu_option.enable_encode_usage_method); - // Verify that optional encode rsd thresholds are not set. - EXPECT_EQ(-1, cpu_option.low_encode_time_rsd_threshold); - EXPECT_EQ(-1, cpu_option.high_encode_time_rsd_threshold); - - // Add a new send stream and verify that cpu options are set from start. - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(3))); - int second_send_channel = vie_.GetLastChannel(); - EXPECT_NE(first_send_channel, second_send_channel); - cpu_option = vie_.GetCpuOveruseOptions(second_send_channel); - EXPECT_EQ(10, cpu_option.low_encode_usage_threshold_percent); - EXPECT_EQ(20, cpu_option.high_encode_usage_threshold_percent); - EXPECT_FALSE(cpu_option.enable_capture_jitter_method); - EXPECT_TRUE(cpu_option.enable_encode_usage_method); - // Verify that optional encode rsd thresholds are not set. - EXPECT_EQ(-1, cpu_option.low_encode_time_rsd_threshold); - EXPECT_EQ(-1, cpu_option.high_encode_time_rsd_threshold); -} - -TEST_F(WebRtcVideoEngineTestFake, SetCpuOveruseOptionsWithEncodeRsdThresholds) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(1))); - int first_send_channel = vie_.GetLastChannel(); - - // Set optional encode rsd thresholds and verify cpu options. - cricket::VideoOptions options; - options.conference_mode.Set(true); - options.cpu_underuse_threshold.Set(10); - options.cpu_overuse_threshold.Set(20); - options.cpu_underuse_encode_rsd_threshold.Set(30); - options.cpu_overuse_encode_rsd_threshold.Set(40); - options.cpu_overuse_encode_usage.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - webrtc::CpuOveruseOptions cpu_option = - vie_.GetCpuOveruseOptions(first_send_channel); - EXPECT_EQ(10, cpu_option.low_encode_usage_threshold_percent); - EXPECT_EQ(20, cpu_option.high_encode_usage_threshold_percent); - EXPECT_FALSE(cpu_option.enable_capture_jitter_method); - EXPECT_TRUE(cpu_option.enable_encode_usage_method); - EXPECT_EQ(30, cpu_option.low_encode_time_rsd_threshold); - EXPECT_EQ(40, cpu_option.high_encode_time_rsd_threshold); - - // Add a new send stream and verify that cpu options are set from start. - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(3))); - int second_send_channel = vie_.GetLastChannel(); - EXPECT_NE(first_send_channel, second_send_channel); - cpu_option = vie_.GetCpuOveruseOptions(second_send_channel); - EXPECT_EQ(10, cpu_option.low_encode_usage_threshold_percent); - EXPECT_EQ(20, cpu_option.high_encode_usage_threshold_percent); - EXPECT_FALSE(cpu_option.enable_capture_jitter_method); - EXPECT_TRUE(cpu_option.enable_encode_usage_method); - EXPECT_EQ(30, cpu_option.low_encode_time_rsd_threshold); - EXPECT_EQ(40, cpu_option.high_encode_time_rsd_threshold); -} - -// Test that AddRecvStream doesn't create new channel for 1:1 call. -TEST_F(WebRtcVideoEngineTestFake, AddRecvStream1On1) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); - EXPECT_EQ(channel_num, vie_.GetLastChannel()); -} - -// Test that NACK, PLI and REMB are enabled for internal codec. -TEST_F(WebRtcVideoEngineTestFake, InternalCodecFeedbackParams) { - EXPECT_TRUE(SetupEngine()); - - std::vector codecs(engine_.codecs()); - // Vp8 will appear at the beginning. - size_t pos = 0; - EXPECT_EQ("VP8", codecs[pos].name); - VerifyCodecFeedbackParams(codecs[pos]); -} - -// Test that AddRecvStream doesn't change remb for 1:1 call. -TEST_F(WebRtcVideoEngineTestFake, NoRembChangeAfterAddRecvStream) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(1))); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - EXPECT_TRUE(vie_.GetRembStatusBwPartition(channel_num)); - EXPECT_TRUE(vie_.GetRembStatusContribute(channel_num)); - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); - EXPECT_TRUE(vie_.GetRembStatusBwPartition(channel_num)); - EXPECT_TRUE(vie_.GetRembStatusContribute(channel_num)); -} - -// Verify default REMB setting and that it can be turned on and off. -TEST_F(WebRtcVideoEngineTestFake, RembOnOff) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - // Verify REMB sending is always off by default. - EXPECT_FALSE(vie_.GetRembStatusBwPartition(channel_num)); - - // Verify that REMB is turned on when setting default codecs since the - // default codecs have REMB enabled. - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - EXPECT_TRUE(vie_.GetRembStatusBwPartition(channel_num)); - - // Verify that REMB is turned off when codecs without REMB are set. - std::vector codecs = engine_.codecs(); - // Clearing the codecs' FeedbackParams and setting send codecs should disable - // REMB. - for (std::vector::iterator iter = codecs.begin(); - iter != codecs.end(); ++iter) { - // Intersecting with empty will clear the FeedbackParams. - cricket::FeedbackParams empty_params; - iter->feedback_params.Intersect(empty_params); - EXPECT_TRUE(iter->feedback_params.params().empty()); - } - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_FALSE(vie_.GetRembStatusBwPartition(channel_num)); -} - -// Test that nack is enabled on the channel if we don't offer red/fec. -TEST_F(WebRtcVideoEngineTestFake, NackEnabled) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector codecs(engine_.codecs()); - codecs.resize(1); // toss out red and ulpfec - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_TRUE(vie_.GetNackStatus(channel_num)); -} - -// Test that we enable hybrid NACK FEC mode. -TEST_F(WebRtcVideoEngineTestFake, HybridNackFec) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - EXPECT_TRUE(channel_->SetRecvCodecs(engine_.codecs())); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - EXPECT_TRUE(vie_.GetHybridNackFecStatus(channel_num)); - EXPECT_FALSE(vie_.GetNackStatus(channel_num)); -} - -// Test that we enable hybrid NACK FEC mode when calling SetSendCodecs and -// SetReceiveCodecs in reversed order. -TEST_F(WebRtcVideoEngineTestFake, HybridNackFecReversedOrder) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - EXPECT_TRUE(channel_->SetRecvCodecs(engine_.codecs())); - EXPECT_TRUE(vie_.GetHybridNackFecStatus(channel_num)); - EXPECT_FALSE(vie_.GetNackStatus(channel_num)); -} - -// Test NACK vs Hybrid NACK/FEC interop call setup, i.e. only use NACK even if -// red/fec is offered as receive codec. -TEST_F(WebRtcVideoEngineTestFake, VideoProtectionInterop) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector recv_codecs(engine_.codecs()); - std::vector send_codecs(engine_.codecs()); - // Only add VP8 as send codec. - send_codecs.resize(1); - EXPECT_TRUE(channel_->SetRecvCodecs(recv_codecs)); - EXPECT_TRUE(channel_->SetSendCodecs(send_codecs)); - EXPECT_FALSE(vie_.GetHybridNackFecStatus(channel_num)); - EXPECT_TRUE(vie_.GetNackStatus(channel_num)); -} - -// Test NACK vs Hybrid NACK/FEC interop call setup, i.e. only use NACK even if -// red/fec is offered as receive codec. Call order reversed compared to -// VideoProtectionInterop. -TEST_F(WebRtcVideoEngineTestFake, VideoProtectionInteropReversed) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - std::vector recv_codecs(engine_.codecs()); - std::vector send_codecs(engine_.codecs()); - // Only add VP8 as send codec. - send_codecs.resize(1); - EXPECT_TRUE(channel_->SetSendCodecs(send_codecs)); - EXPECT_TRUE(channel_->SetRecvCodecs(recv_codecs)); - EXPECT_FALSE(vie_.GetHybridNackFecStatus(channel_num)); - EXPECT_TRUE(vie_.GetNackStatus(channel_num)); -} - -// Test that NACK, not hybrid mode, is enabled in conference mode. -TEST_F(WebRtcVideoEngineTestFake, HybridNackFecConference) { - EXPECT_TRUE(SetupEngine()); - // Setup the send channel. - int send_channel_num = vie_.GetLastChannel(); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(channel_->SetRecvCodecs(engine_.codecs())); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - EXPECT_FALSE(vie_.GetHybridNackFecStatus(send_channel_num)); - EXPECT_TRUE(vie_.GetNackStatus(send_channel_num)); - // Add a receive stream. - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); - int receive_channel_num = vie_.GetLastChannel(); - EXPECT_FALSE(vie_.GetHybridNackFecStatus(receive_channel_num)); - EXPECT_TRUE(vie_.GetNackStatus(receive_channel_num)); -} - -// Test that when AddRecvStream in conference mode, a new channel is created -// for receiving. And the new channel's "original channel" is the send channel. -TEST_F(WebRtcVideoEngineTestFake, AddRemoveRecvStreamConference) { - EXPECT_TRUE(SetupEngine()); - // Setup the send channel. - int send_channel_num = vie_.GetLastChannel(); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - // Add a receive stream. - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); - int receive_channel_num = vie_.GetLastChannel(); - EXPECT_EQ(send_channel_num, vie_.GetOriginalChannelId(receive_channel_num)); - EXPECT_TRUE(channel_->RemoveRecvStream(1)); - EXPECT_FALSE(vie_.IsChannel(receive_channel_num)); -} - -// Test that adding/removing stream with 0 ssrc should fail (and not crash). -// For crbug/351699 and 350988. -TEST_F(WebRtcVideoEngineTestFake, AddRemoveRecvStreamWith0Ssrc) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); - EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(0))); - EXPECT_FALSE(channel_->RemoveRecvStream(0)); - EXPECT_TRUE(channel_->RemoveRecvStream(1)); -} - -TEST_F(WebRtcVideoEngineTestFake, AddRemoveSendStreamWith0Ssrc) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(1))); - EXPECT_FALSE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(0))); - EXPECT_FALSE(channel_->RemoveSendStream(0)); - EXPECT_TRUE(channel_->RemoveSendStream(1)); -} - -// Test that we can create a channel and start/stop rendering out on it. -TEST_F(WebRtcVideoEngineTestFake, SetRender) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - // Verify we can start/stop/start/stop rendering. - EXPECT_TRUE(channel_->SetRender(true)); - EXPECT_TRUE(vie_.GetRenderStarted(channel_num)); - EXPECT_TRUE(channel_->SetRender(false)); - EXPECT_FALSE(vie_.GetRenderStarted(channel_num)); - EXPECT_TRUE(channel_->SetRender(true)); - EXPECT_TRUE(vie_.GetRenderStarted(channel_num)); - EXPECT_TRUE(channel_->SetRender(false)); - EXPECT_FALSE(vie_.GetRenderStarted(channel_num)); -} - -// Test that we can create a channel and start/stop sending out on it. -TEST_F(WebRtcVideoEngineTestFake, SetSend) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - // Verify receiving is also started. - EXPECT_TRUE(vie_.GetReceive(channel_num)); - - // Set send codecs on the channel. - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(123))); - - // Verify we can start/stop/start/stop sending. - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_TRUE(vie_.GetSend(channel_num)); - EXPECT_TRUE(channel_->SetSend(false)); - EXPECT_FALSE(vie_.GetSend(channel_num)); - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_TRUE(vie_.GetSend(channel_num)); - EXPECT_TRUE(channel_->SetSend(false)); - EXPECT_FALSE(vie_.GetSend(channel_num)); -} - -// Test that we set bandwidth properly when using full auto bandwidth mode. -TEST_F(WebRtcVideoEngineTestFake, SetBandwidthAuto) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - EXPECT_TRUE(channel_->SetMaxSendBandwidth(cricket::kAutoBandwidth)); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height); -} - -// Test that we set bandwidth properly when using auto with upper bound. -TEST_F(WebRtcVideoEngineTestFake, SetBandwidthCapped) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - EXPECT_TRUE(channel_->SetMaxSendBandwidth(768000)); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, 768U); -} - -// Test that we reduce the start bandwidth when the requested max is less than -// the default start bandwidth. -TEST_F(WebRtcVideoEngineTestFake, SetMaxBandwidthBelowDefaultStart) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - int max_bandwidth_kbps = (kMinBandwidthKbps + kStartBandwidthKbps) / 2; - EXPECT_TRUE(channel_->SetMaxSendBandwidth(max_bandwidth_kbps * 1000)); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, - max_bandwidth_kbps, kMinBandwidthKbps, max_bandwidth_kbps); -} - -// Test that we reduce the min bandwidth when the requested max is less than -// the min bandwidth. -TEST_F(WebRtcVideoEngineTestFake, SetMaxBandwidthBelowMin) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - int max_bandwidth_kbps = kMinBandwidthKbps / 2; - EXPECT_TRUE(channel_->SetMaxSendBandwidth(max_bandwidth_kbps * 1000)); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, - max_bandwidth_kbps, max_bandwidth_kbps, max_bandwidth_kbps); -} - -// Test that the start bandwidth can be controlled by VideoOptions. -TEST_F(WebRtcVideoEngineTestFake, SetStartBandwidthOption) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, kStartBandwidthKbps); - - // Set the start bitrate option. - unsigned int kBoostedStartBandwidthKbps = 1000; - ASSERT_NE(kStartBandwidthKbps, kBoostedStartBandwidthKbps); - cricket::VideoOptions options; - options.video_start_bitrate.Set(kBoostedStartBandwidthKbps); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Check that start bitrate has changed to the new value. - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, kBoostedStartBandwidthKbps); -} - -// Test that SetMaxSendBandwidth works as expected in conference mode. -TEST_F(WebRtcVideoEngineTestFake, SetBandwidthInConference) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height); - - // Set send bandwidth. - EXPECT_TRUE(channel_->SetMaxSendBandwidth(768000)); - - // Verify that the max bitrate has changed. - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, - 768, kMinBandwidthKbps, kStartBandwidthKbps); -} - -// Test that sending screencast frames doesn't change bitrate. -TEST_F(WebRtcVideoEngineTestFake, SetBandwidthScreencast) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - // Set send codec. - cricket::VideoCodec codec(kVP8Codec); - std::vector codec_list; - codec_list.push_back(codec); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(123))); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - EXPECT_TRUE(channel_->SetMaxSendBandwidth(111000)); - EXPECT_TRUE(channel_->SetSend(true)); - - SendI420ScreencastFrame(kVP8Codec.width, kVP8Codec.height); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, 111); -} - -// Test SetSendSsrc. -TEST_F(WebRtcVideoEngineTestFake, SetSendSsrcAndCname) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - cricket::StreamParams stream; - stream.ssrcs.push_back(1234); - stream.cname = "cname"; - channel_->AddSendStream(stream); - - unsigned int ssrc = 0; - EXPECT_EQ(0, vie_.GetLocalSSRC(channel_num, ssrc)); - EXPECT_EQ(1234U, ssrc); - EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num)); - - char rtcp_cname[256]; - EXPECT_EQ(0, vie_.GetRTCPCName(channel_num, rtcp_cname)); - EXPECT_STREQ("cname", rtcp_cname); -} - -// Test that the local SSRC is the same on sending and receiving channels if the -// receive channel is created before the send channel. -TEST_F(WebRtcVideoEngineTestFake, SetSendSsrcAfterCreatingReceiveChannel) { - EXPECT_TRUE(SetupEngine()); - - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); - int receive_channel_num = vie_.GetLastChannel(); - cricket::StreamParams stream = cricket::StreamParams::CreateLegacy(1234); - EXPECT_TRUE(channel_->AddSendStream(stream)); - int send_channel_num = vie_.GetLastChannel(); - unsigned int ssrc = 0; - EXPECT_EQ(0, vie_.GetLocalSSRC(send_channel_num, ssrc)); - EXPECT_EQ(1234U, ssrc); - EXPECT_EQ(1, vie_.GetNumSsrcs(send_channel_num)); - ssrc = 0; - EXPECT_EQ(0, vie_.GetLocalSSRC(receive_channel_num, ssrc)); - EXPECT_EQ(1234U, ssrc); - EXPECT_EQ(1, vie_.GetNumSsrcs(receive_channel_num)); -} - -// Test SetOptions with denoising flag. -TEST_F(WebRtcVideoEngineTestFake, SetOptionsWithDenoising) { - EXPECT_TRUE(SetupEngine()); - EXPECT_EQ(1, vie_.GetNumCapturers()); - int channel_num = vie_.GetLastChannel(); - int capture_id = vie_.GetCaptureId(channel_num); - // Set send codecs on the channel. - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - // Set options with OPT_VIDEO_NOISE_REDUCTION flag. - cricket::VideoOptions options; - options.video_noise_reduction.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Verify capture has denoising turned on. - webrtc::VideoCodec send_codec; - memset(&send_codec, 0, sizeof(send_codec)); // avoid uninitialized warning - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, send_codec)); - EXPECT_TRUE(send_codec.codecSpecific.VP8.denoisingOn); - EXPECT_FALSE(vie_.GetCaptureDenoising(capture_id)); - - // Set options back to zero. - options.video_noise_reduction.Set(false); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Verify capture has denoising turned off. - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, send_codec)); - EXPECT_FALSE(send_codec.codecSpecific.VP8.denoisingOn); - EXPECT_FALSE(vie_.GetCaptureDenoising(capture_id)); -} - -TEST_F(WebRtcVideoEngineTestFake, MultipleSendStreamsWithOneCapturer) { - EXPECT_TRUE(SetupEngine()); - - // Start the capturer - cricket::FakeVideoCapturer capturer; - cricket::VideoFormat capture_format_vga = cricket::VideoFormat(640, 480, - cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420); - EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_vga)); - - // Add send streams and connect the capturer - for (unsigned int i = 0; i < sizeof(kSsrcs2)/sizeof(kSsrcs2[0]); ++i) { - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(kSsrcs2[i]))); - // Register the capturer to the ssrc. - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[i], &capturer)); - } - - const int channel0 = vie_.GetChannelFromLocalSsrc(kSsrcs2[0]); - ASSERT_NE(-1, channel0); - const int channel1 = vie_.GetChannelFromLocalSsrc(kSsrcs2[1]); - ASSERT_NE(-1, channel1); - ASSERT_NE(channel0, channel1); - - // Both channels should have started receiving after created. - EXPECT_TRUE(vie_.GetReceive(channel0)); - EXPECT_TRUE(vie_.GetReceive(channel1)); - - // Set send codec. - std::vector codecs; - cricket::VideoCodec send_codec(100, "VP8", 640, 480, 30, 0); - codecs.push_back(send_codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_TRUE(vie_.GetSend(channel0)); - EXPECT_TRUE(vie_.GetSend(channel1)); - - EXPECT_TRUE(capturer.CaptureFrame()); - EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel0)); - EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel1)); - - EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs2[0])); - EXPECT_TRUE(capturer.CaptureFrame()); - // channel0 is the default channel, so it won't be deleted. - // But it should be disconnected from the capturer. - EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel0)); - EXPECT_EQ(2, vie_.GetIncomingFrameNum(channel1)); - - EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs2[1])); - EXPECT_TRUE(capturer.CaptureFrame()); - EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel0)); - // channel1 has already been deleted. - EXPECT_EQ(-1, vie_.GetIncomingFrameNum(channel1)); -} - -TEST_F(WebRtcVideoEngineTestFake, SendReceiveBitratesStats) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(1))); - int first_send_channel = vie_.GetLastChannel(); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(2))); - int second_send_channel = vie_.GetLastChannel(); - cricket::VideoCodec codec(kVP8Codec720p); - std::vector codec_list; - codec_list.push_back(codec); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - - EXPECT_TRUE(channel_->AddRecvStream( - cricket::StreamParams::CreateLegacy(3))); - int first_receive_channel = vie_.GetLastChannel(); - EXPECT_NE(first_send_channel, first_receive_channel); - EXPECT_TRUE(channel_->AddRecvStream( - cricket::StreamParams::CreateLegacy(4))); - int second_receive_channel = vie_.GetLastChannel(); - EXPECT_NE(first_receive_channel, second_receive_channel); - - cricket::VideoMediaInfo info; - EXPECT_TRUE(channel_->GetStats(&info)); - ASSERT_EQ(1U, info.bw_estimations.size()); - ASSERT_EQ(0, info.bw_estimations[0].actual_enc_bitrate); - ASSERT_EQ(0, info.bw_estimations[0].transmit_bitrate); - ASSERT_EQ(0, info.bw_estimations[0].retransmit_bitrate); - ASSERT_EQ(0, info.bw_estimations[0].available_send_bandwidth); - ASSERT_EQ(0, info.bw_estimations[0].available_recv_bandwidth); - ASSERT_EQ(0, info.bw_estimations[0].target_enc_bitrate); - - // Start sending and receiving on one of the channels and verify bitrates. - EXPECT_EQ(0, vie_.StartSend(first_send_channel)); - int send_video_bitrate = 800; - int send_fec_bitrate = 100; - int send_nack_bitrate = 20; - int send_total_bitrate = send_video_bitrate + send_fec_bitrate + - send_nack_bitrate; - int send_bandwidth = 1900; - vie_.SetSendBitrates(first_send_channel, send_video_bitrate, send_fec_bitrate, - send_nack_bitrate); - vie_.SetSendBandwidthEstimate(first_send_channel, send_bandwidth); - - EXPECT_EQ(0, vie_.StartReceive(first_receive_channel)); - int receive_bandwidth = 600; - vie_.SetReceiveBandwidthEstimate(first_receive_channel, receive_bandwidth); - - info.Clear(); - EXPECT_TRUE(channel_->GetStats(&info)); - ASSERT_EQ(1U, info.bw_estimations.size()); - ASSERT_EQ(send_video_bitrate, info.bw_estimations[0].actual_enc_bitrate); - ASSERT_EQ(send_total_bitrate, info.bw_estimations[0].transmit_bitrate); - ASSERT_EQ(send_nack_bitrate, info.bw_estimations[0].retransmit_bitrate); - ASSERT_EQ(send_bandwidth, info.bw_estimations[0].available_send_bandwidth); - ASSERT_EQ(receive_bandwidth, info.bw_estimations[0].available_recv_bandwidth); - ASSERT_EQ(send_video_bitrate, info.bw_estimations[0].target_enc_bitrate); - - // Start receiving on the second channel and verify received rate. - EXPECT_EQ(0, vie_.StartSend(second_send_channel)); - vie_.SetSendBitrates(second_send_channel, - send_video_bitrate, - send_fec_bitrate, - send_nack_bitrate); - EXPECT_EQ(0, vie_.StartReceive(second_receive_channel)); - - info.Clear(); - EXPECT_TRUE(channel_->GetStats(&info)); - ASSERT_EQ(1U, info.bw_estimations.size()); - ASSERT_EQ(2 * send_video_bitrate, info.bw_estimations[0].actual_enc_bitrate); - ASSERT_EQ(2 * send_total_bitrate, info.bw_estimations[0].transmit_bitrate); - ASSERT_EQ(2 * send_nack_bitrate, info.bw_estimations[0].retransmit_bitrate); - ASSERT_EQ(send_bandwidth, info.bw_estimations[0].available_send_bandwidth); - ASSERT_EQ(receive_bandwidth, info.bw_estimations[0].available_recv_bandwidth); - ASSERT_EQ(2 * send_video_bitrate, info.bw_estimations[0].target_enc_bitrate); -} - -TEST_F(WebRtcVideoEngineTestFake, TestSetAdaptInputToCpuUsage) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options_in, options_out; - bool cpu_adapt = false; - channel_->SetOptions(options_in); - EXPECT_TRUE(channel_->GetOptions(&options_out)); - EXPECT_FALSE(options_out.adapt_input_to_cpu_usage.Get(&cpu_adapt)); - // Set adapt input CPU usage option. - options_in.adapt_input_to_cpu_usage.Set(true); - EXPECT_TRUE(channel_->SetOptions(options_in)); - EXPECT_TRUE(channel_->GetOptions(&options_out)); - EXPECT_TRUE(options_out.adapt_input_to_cpu_usage.Get(&cpu_adapt)); - EXPECT_TRUE(cpu_adapt); -} - -TEST_F(WebRtcVideoEngineTestFake, TestSetCpuThreshold) { - EXPECT_TRUE(SetupEngine()); - float low, high; - cricket::VideoOptions options_in, options_out; - // Verify that initial values are set. - EXPECT_TRUE(channel_->GetOptions(&options_out)); - EXPECT_TRUE(options_out.system_low_adaptation_threshhold.Get(&low)); - EXPECT_EQ(low, 0.65f); - EXPECT_TRUE(options_out.system_high_adaptation_threshhold.Get(&high)); - EXPECT_EQ(high, 0.85f); - // Set new CPU threshold values. - options_in.system_low_adaptation_threshhold.Set(0.45f); - options_in.system_high_adaptation_threshhold.Set(0.95f); - EXPECT_TRUE(channel_->SetOptions(options_in)); - EXPECT_TRUE(channel_->GetOptions(&options_out)); - EXPECT_TRUE(options_out.system_low_adaptation_threshhold.Get(&low)); - EXPECT_EQ(low, 0.45f); - EXPECT_TRUE(options_out.system_high_adaptation_threshhold.Get(&high)); - EXPECT_EQ(high, 0.95f); -} - -TEST_F(WebRtcVideoEngineTestFake, TestSetInvalidCpuThreshold) { - EXPECT_TRUE(SetupEngine()); - float low, high; - cricket::VideoOptions options_in, options_out; - // Valid range is [0, 1]. - options_in.system_low_adaptation_threshhold.Set(-1.5f); - options_in.system_high_adaptation_threshhold.Set(1.5f); - EXPECT_TRUE(channel_->SetOptions(options_in)); - EXPECT_TRUE(channel_->GetOptions(&options_out)); - EXPECT_TRUE(options_out.system_low_adaptation_threshhold.Get(&low)); - EXPECT_EQ(low, 0.0f); - EXPECT_TRUE(options_out.system_high_adaptation_threshhold.Get(&high)); - EXPECT_EQ(high, 1.0f); -} - -TEST_F(WebRtcVideoEngineTestFake, ResetCodecOnScreencast) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.video_noise_reduction.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Set send codec. - cricket::VideoCodec codec(kVP8Codec); - std::vector codec_list; - codec_list.push_back(codec); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(123))); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_EQ(1, vie_.GetNumSetSendCodecs()); - - webrtc::VideoCodec gcodec; - memset(&gcodec, 0, sizeof(gcodec)); - int channel_num = vie_.GetLastChannel(); - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec)); - EXPECT_TRUE(gcodec.codecSpecific.VP8.denoisingOn); - - // Send a screencast frame with the same size. - // Verify that denoising is turned off. - SendI420ScreencastFrame(kVP8Codec.width, kVP8Codec.height); - EXPECT_EQ(2, vie_.GetNumSetSendCodecs()); - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec)); - EXPECT_FALSE(gcodec.codecSpecific.VP8.denoisingOn); -} - -TEST_F(WebRtcVideoEngineTestFake, DontRegisterDecoderIfFactoryIsNotGiven) { - engine_.SetExternalDecoderFactory(NULL); - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); - - EXPECT_EQ(0, vie_.GetNumExternalDecoderRegistered(channel_num)); -} - -TEST_F(WebRtcVideoEngineTestFake, RegisterDecoderIfFactoryIsGiven) { - decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8); - engine_.SetExternalDecoderFactory(&decoder_factory_); - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); - - EXPECT_TRUE(vie_.ExternalDecoderRegistered(channel_num, 100)); - EXPECT_EQ(1, vie_.GetNumExternalDecoderRegistered(channel_num)); -} - -TEST_F(WebRtcVideoEngineTestFake, DontRegisterDecoderMultipleTimes) { - decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8); - engine_.SetExternalDecoderFactory(&decoder_factory_); - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); - - EXPECT_TRUE(vie_.ExternalDecoderRegistered(channel_num, 100)); - EXPECT_EQ(1, vie_.GetNumExternalDecoderRegistered(channel_num)); - EXPECT_EQ(1, decoder_factory_.GetNumCreatedDecoders()); - - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); - EXPECT_EQ(1, vie_.GetNumExternalDecoderRegistered(channel_num)); - EXPECT_EQ(1, decoder_factory_.GetNumCreatedDecoders()); -} - -TEST_F(WebRtcVideoEngineTestFake, DontRegisterDecoderForNonVP8) { - decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8); - engine_.SetExternalDecoderFactory(&decoder_factory_); - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kRedCodec); - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); - - EXPECT_EQ(0, vie_.GetNumExternalDecoderRegistered(channel_num)); -} - -TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderIfFactoryIsNotGiven) { - engine_.SetExternalEncoderFactory(NULL); - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - EXPECT_EQ(0, vie_.GetNumExternalEncoderRegistered(channel_num)); -} - -TEST_F(WebRtcVideoEngineTestFake, RegisterEncoderIfFactoryIsGiven) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); - encoder_factory_.set_encoders_have_internal_sources(false); - engine_.SetExternalEncoderFactory(&encoder_factory_); - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(kSsrc))); - - EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100)); - EXPECT_FALSE(vie_.ExternalEncoderHasInternalSource(channel_num, 100)); - EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num)); - - // Remove stream previously added to free the external encoder instance. - EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); -} - -TEST_F(WebRtcVideoEngineTestFake, RegisterEncoderWithInternalSource) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); - encoder_factory_.set_encoders_have_internal_sources(true); - engine_.SetExternalEncoderFactory(&encoder_factory_); - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - EXPECT_TRUE( - channel_->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); - - ASSERT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100)); - EXPECT_TRUE(vie_.ExternalEncoderHasInternalSource(channel_num, 100)); - EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num)); - - // Remove stream previously added to free the external encoder instance. - EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); -} - -TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderMultipleTimes) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); - engine_.SetExternalEncoderFactory(&encoder_factory_); - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(kSsrc))); - - EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100)); - EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num)); - - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num)); - - // Remove stream previously added to free the external encoder instance. - EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); -} - -TEST_F(WebRtcVideoEngineTestFake, RegisterEncoderWithMultipleSendStreams) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); - engine_.SetExternalEncoderFactory(&encoder_factory_); - EXPECT_TRUE(SetupEngine()); - - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_EQ(1, vie_.GetTotalNumExternalEncoderRegistered()); - - // When we add the first stream (1234), it reuses the default send channel, - // so it doesn't increase the registration count of external encoders. - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(1234))); - EXPECT_EQ(1, vie_.GetTotalNumExternalEncoderRegistered()); - - // When we add the second stream (2345), it creates a new channel and - // increments the registration count. - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(2345))); - EXPECT_EQ(2, vie_.GetTotalNumExternalEncoderRegistered()); - - // At this moment the total registration count is two, but only one encoder - // is registered per channel. - int channel_num = vie_.GetLastChannel(); - EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num)); - - // Removing send streams decrements the registration count. - EXPECT_TRUE(channel_->RemoveSendStream(1234)); - EXPECT_EQ(1, vie_.GetTotalNumExternalEncoderRegistered()); - - // When we remove the last send stream, it also destroys the last send - // channel and causes the registration count to drop to zero. It is a little - // weird, but not a bug. - EXPECT_TRUE(channel_->RemoveSendStream(2345)); - EXPECT_EQ(0, vie_.GetTotalNumExternalEncoderRegistered()); -} - -TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderForNonVP8) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric, - "GENERIC"); - engine_.SetExternalEncoderFactory(&encoder_factory_); - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - // Note: unlike the SetRecvCodecs, we must set a valid video codec for - // channel_->SetSendCodecs() to succeed. - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - EXPECT_EQ(0, vie_.GetNumExternalEncoderRegistered(channel_num)); -} - -// Test that NACK, PLI and REMB are enabled for external codec. -TEST_F(WebRtcVideoEngineTestFake, ExternalCodecFeedbackParams) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric, - "GENERIC"); - engine_.SetExternalEncoderFactory(&encoder_factory_); - EXPECT_TRUE(SetupEngine()); - - std::vector codecs(engine_.codecs()); - // The external codec will appear at last. - size_t pos = codecs.size() - 1; - EXPECT_EQ("GENERIC", codecs[pos].name); - VerifyCodecFeedbackParams(codecs[pos]); -} - -// Test external codec will be added to the end of the supported codec list. -TEST_F(WebRtcVideoEngineTestFake, ExternalCodecAddedToTheEnd) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric, - "GENERIC"); - engine_.SetExternalEncoderFactory(&encoder_factory_); - EXPECT_TRUE(SetupEngine()); - - std::vector codecs(engine_.codecs()); - EXPECT_EQ("VP8", codecs[0].name); - - codecs = engine_.codecs(); - cricket::VideoCodec internal_codec = codecs[0]; - cricket::VideoCodec external_codec = codecs[codecs.size() - 1]; - // The external codec will appear at last. - EXPECT_EQ("GENERIC", external_codec.name); - // The internal codec is preferred. - EXPECT_GE(internal_codec.preference, external_codec.preference); -} - -// Test that external codecs that we support internally are not added as -// duplicate entries to the codecs list. -TEST_F(WebRtcVideoEngineTestFake, ExternalCodecIgnored) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); - engine_.SetExternalEncoderFactory(&encoder_factory_); - EXPECT_TRUE(SetupEngine()); - - std::vector internal_codecs(engine_.codecs()); - EXPECT_EQ("VP8", internal_codecs[0].name); - - std::vector codecs = engine_.codecs(); - EXPECT_EQ("VP8", codecs[0].name); - EXPECT_EQ(internal_codecs[0].height, codecs[0].height); - EXPECT_EQ(internal_codecs[0].width, codecs[0].width); - // Verify the last codec is not the external codec. - EXPECT_NE("VP8", codecs[codecs.size() - 1].name); -} - -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsWithExternalH264) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264"); - engine_.SetExternalEncoderFactory(&encoder_factory_); - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kH264Codec); - cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); - rtx_codec.SetParam("apt", kH264Codec.id); - codecs.push_back(rtx_codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - EXPECT_EQ(vie_.GetRtxSendPayloadTypes(channel_num), - MAKE_VECTOR(kPayloadTypes1)); - - cricket::StreamParams params = - cricket::StreamParams::CreateLegacy(kSsrcs1[0]); - params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]); - EXPECT_TRUE(channel_->AddSendStream(params)); - - EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetNumRtxSsrcs(channel_num)); - EXPECT_EQ(static_cast(kRtxSsrcs1[0]), vie_.GetRtxSsrc(channel_num, 0)); - - EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 127)); - EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num)); - EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders()); - - EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs1[0])); -} - -TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsWithVP8AndExternalH264) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264"); - engine_.SetExternalEncoderFactory(&encoder_factory_); - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kH264Codec); - cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); - rtx_codec.SetParam("apt", kH264Codec.id); - codecs.push_back(rtx_codec); - codecs.push_back(kVP8Codec); - cricket::VideoCodec rtx_codec2(97, "rtx", 0, 0, 0, 0); - rtx_codec2.SetParam("apt", kVP8Codec.id); - codecs.push_back(rtx_codec2); - - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - - // The first matched codec should be set, i.e., H.264. - EXPECT_EQ(vie_.GetRtxSendPayloadTypes(channel_num), - MAKE_VECTOR(kPayloadTypes1)); - - cricket::StreamParams params = - cricket::StreamParams::CreateLegacy(kSsrcs1[0]); - params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]); - EXPECT_TRUE(channel_->AddSendStream(params)); - - EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetNumRtxSsrcs(channel_num)); - EXPECT_EQ(static_cast(kRtxSsrcs1[0]), vie_.GetRtxSsrc(channel_num, 0)); - - EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 127)); - EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num)); - EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders()); - - EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs1[0])); -} - -TEST_F(WebRtcVideoEngineTestFake, SetRecvCodecsWithExternalH264) { - // WebRtcVideoEngine assumes that if we have encode support for a codec, we - // also have decode support. It doesn't support decode only support. Therefore - // we here have to register both an encoder and a decoder factory with H264 - // support, to be able to test the decoder factory. - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264"); - decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264); - EXPECT_TRUE(SetupEngine()); - engine_.SetExternalEncoderFactory(&encoder_factory_); - engine_.SetExternalDecoderFactory(&decoder_factory_); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - codecs.push_back(kH264Codec); - cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); - rtx_codec.SetParam("apt", kH264Codec.id); - codecs.push_back(rtx_codec); - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); - - EXPECT_EQ(vie_.GetRtxRecvPayloadTypes(channel_num), - MAKE_VECTOR(kPayloadTypes1)); - - cricket::StreamParams params = - cricket::StreamParams::CreateLegacy(kSsrcs1[0]); - params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]); - EXPECT_TRUE(channel_->AddRecvStream(params)); - - EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(static_cast(kRtxSsrcs1[0]), - vie_.GetRemoteRtxSsrc(channel_num)); - - EXPECT_TRUE(vie_.ExternalDecoderRegistered(channel_num, 127)); - EXPECT_EQ(1, vie_.GetNumExternalDecoderRegistered(channel_num)); - EXPECT_EQ(1, decoder_factory_.GetNumCreatedDecoders()); - - EXPECT_TRUE(channel_->RemoveRecvStream(kSsrcs1[0])); -} - -TEST_F(WebRtcVideoEngineTestFake, SetRecvCodecsWithVP8AndExternalH264) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264"); - decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264); - EXPECT_TRUE(SetupEngine()); - engine_.SetExternalEncoderFactory(&encoder_factory_); - engine_.SetExternalDecoderFactory(&decoder_factory_); - int channel_num = vie_.GetLastChannel(); - - std::vector codecs; - cricket::VideoCodec rtx_codec(97, "rtx", 0, 0, 0, 0); - rtx_codec.SetParam("apt", kH264Codec.id); - codecs.push_back(kH264Codec); - codecs.push_back(rtx_codec); - - cricket::VideoCodec rtx_codec2(96, "rtx", 0, 0, 0, 0); - rtx_codec2.SetParam("apt", kVP8Codec.id); - codecs.push_back(kVP8Codec); - codecs.push_back(rtx_codec2); - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); - EXPECT_EQ(vie_.GetRtxRecvPayloadTypes(channel_num), - MAKE_VECTOR(kPayloadTypes2)); - - codecs.pop_back(); - // One RTX codec should be fine. - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); - - // TODO(changbin): The Rtx key can still be found from the Rtx-Apt map - // if the new codec list doesn't assign it with a new value. - // Should pass a map to SetRtxRecvPayloadType in future. - EXPECT_EQ(vie_.GetRtxRecvPayloadTypes(channel_num), - MAKE_VECTOR(kPayloadTypes2)); -} - -// Tests that OnReadyToSend will be propagated into ViE. -TEST_F(WebRtcVideoEngineTestFake, OnReadyToSend) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - EXPECT_TRUE(vie_.GetIsTransmitting(channel_num)); - - channel_->OnReadyToSend(false); - EXPECT_FALSE(vie_.GetIsTransmitting(channel_num)); - - channel_->OnReadyToSend(true); - EXPECT_TRUE(vie_.GetIsTransmitting(channel_num)); -} - -#if 0 -TEST_F(WebRtcVideoEngineTestFake, CaptureFrameTimestampToNtpTimestamp) { - EXPECT_TRUE(SetupEngine()); - int capture_id = vie_.GetCaptureId(vie_.GetLastChannel()); - - // Set send codec. - cricket::VideoCodec codec(kVP8Codec); - std::vector codec_list; - codec_list.push_back(codec); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(123))); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - EXPECT_TRUE(channel_->SetSend(true)); - - int64 timestamp = time(NULL) * rtc::kNumNanosecsPerSec; - SendI420ScreencastFrameWithTimestamp( - kVP8Codec.width, kVP8Codec.height, timestamp); - EXPECT_EQ(rtc::UnixTimestampNanosecsToNtpMillisecs(timestamp), - vie_.GetCaptureLastTimestamp(capture_id)); - - SendI420ScreencastFrameWithTimestamp(kVP8Codec.width, kVP8Codec.height, 0); - EXPECT_EQ(0, vie_.GetCaptureLastTimestamp(capture_id)); -} -#endif - -///////////////////////// -// Tests with real ViE // -///////////////////////// - -// Tests that we can find codecs by name or id. -TEST_F(WebRtcVideoEngineTest, FindCodec) { - // We should not need to init engine in order to get codecs. - const std::vector& c = engine_.codecs(); - EXPECT_EQ(cricket::DefaultVideoCodecList().size(), c.size()); - - cricket::VideoCodec vp8(104, "VP8", 320, 200, 30, 0); - EXPECT_TRUE(engine_.FindCodec(vp8)); - - cricket::VideoCodec vp8_ci(104, "vp8", 320, 200, 30, 0); - EXPECT_TRUE(engine_.FindCodec(vp8)); - - cricket::VideoCodec vp8_diff_fr_diff_pref(104, "VP8", 320, 200, 50, 50); - EXPECT_TRUE(engine_.FindCodec(vp8_diff_fr_diff_pref)); - - cricket::VideoCodec vp8_diff_id(95, "VP8", 320, 200, 30, 0); - EXPECT_FALSE(engine_.FindCodec(vp8_diff_id)); - vp8_diff_id.id = 97; - EXPECT_TRUE(engine_.FindCodec(vp8_diff_id)); - - cricket::VideoCodec vp8_diff_res(104, "VP8", 320, 111, 30, 0); - // FindCodec ignores the codec size. - // Test that FindCodec can accept uncommon codec size. - EXPECT_TRUE(engine_.FindCodec(vp8_diff_res)); - - // PeerConnection doesn't negotiate the resolution at this point. - // Test that FindCodec can handle the case when width/height is 0. - cricket::VideoCodec vp8_zero_res(104, "VP8", 0, 0, 30, 0); - EXPECT_TRUE(engine_.FindCodec(vp8_zero_res)); - - cricket::VideoCodec red(101, "RED", 0, 0, 30, 0); - EXPECT_TRUE(engine_.FindCodec(red)); - - cricket::VideoCodec red_ci(101, "red", 0, 0, 30, 0); - EXPECT_TRUE(engine_.FindCodec(red)); - - cricket::VideoCodec fec(102, "ULPFEC", 0, 0, 30, 0); - EXPECT_TRUE(engine_.FindCodec(fec)); - - cricket::VideoCodec fec_ci(102, "ulpfec", 0, 0, 30, 0); - EXPECT_TRUE(engine_.FindCodec(fec)); - - cricket::VideoCodec rtx(96, "rtx", 0, 0, 30, 0); - rtx.SetParam("apt", kVP8Codec.id); - EXPECT_TRUE(engine_.FindCodec(rtx)); -} - -TEST_F(WebRtcVideoEngineTest, RtxCodecHasAptSet) { - std::vector::const_iterator it; - bool apt_checked = false; - for (it = engine_.codecs().begin(); it != engine_.codecs().end(); ++it) { - if (_stricmp(cricket::kRtxCodecName, it->name.c_str()) || it->id != 96) { - continue; - } - int apt; - EXPECT_TRUE(it->GetParam("apt", &apt)); - EXPECT_EQ(100, apt); - apt_checked = true; - } - EXPECT_TRUE(apt_checked); -} - -TEST_F(WebRtcVideoEngineTest, StartupShutdown) { - EXPECT_TRUE(engine_.Init(rtc::Thread::Current())); - engine_.Terminate(); -} - -TEST_PRE_VIDEOENGINE_INIT(WebRtcVideoEngineTest, ConstrainNewCodec2) -TEST_POST_VIDEOENGINE_INIT(WebRtcVideoEngineTest, ConstrainNewCodec2) - -// TODO(juberti): Figure out why ViE is munging the COM refcount. -#ifdef WIN32 -TEST_F(WebRtcVideoEngineTest, DISABLED_CheckCoInitialize) { - Base::CheckCoInitialize(); -} -#endif - -TEST_F(WebRtcVideoEngineTest, CreateChannel) { - EXPECT_TRUE(engine_.Init(rtc::Thread::Current())); - cricket::VideoMediaChannel* channel = - engine_.CreateChannel(cricket::VideoOptions(), NULL); - EXPECT_TRUE(channel != NULL); - delete channel; -} - -TEST_F(WebRtcVideoMediaChannelTest, SetRecvCodecs) { - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); -} -TEST_F(WebRtcVideoMediaChannelTest, SetRecvCodecsWrongPayloadType) { - std::vector codecs; - codecs.push_back(kVP8Codec); - codecs[0].id = 99; - EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); -} -TEST_F(WebRtcVideoMediaChannelTest, SetRecvCodecsUnsupportedCodec) { - std::vector codecs; - codecs.push_back(kVP8Codec); - codecs.push_back(cricket::VideoCodec(101, "VP1", 640, 400, 30, 0)); - EXPECT_FALSE(channel_->SetRecvCodecs(codecs)); -} - -TEST_F(WebRtcVideoMediaChannelTest, GetRtpSendTimeExtension) { - // Enable RTP timestamp extension. - const int id = 12; - std::vector extensions; - extensions.push_back(cricket::RtpHeaderExtension( - "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time", id)); - - // Verify the send extension id. - EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); - EXPECT_EQ(id, channel_->GetRtpSendTimeExtnId()); -} - -TEST_F(WebRtcVideoMediaChannelTest, SetSend) { - Base::SetSend(); -} -TEST_F(WebRtcVideoMediaChannelTest, SetSendWithoutCodecs) { - Base::SetSendWithoutCodecs(); -} -TEST_F(WebRtcVideoMediaChannelTest, SetSendSetsTransportBufferSizes) { - Base::SetSendSetsTransportBufferSizes(); -} - -TEST_F(WebRtcVideoMediaChannelTest, SendAndReceiveVp8Vga) { - SendAndReceive(cricket::VideoCodec(100, "VP8", 640, 400, 30, 0)); -} -TEST_F(WebRtcVideoMediaChannelTest, SendAndReceiveVp8Qvga) { - SendAndReceive(cricket::VideoCodec(100, "VP8", 320, 200, 30, 0)); -} -TEST_F(WebRtcVideoMediaChannelTest, SendAndReceiveVp8Qqvga) { - SendAndReceive(cricket::VideoCodec(100, "VP8", 160, 100, 30, 0)); -} -TEST_F(WebRtcVideoMediaChannelTest, SendManyResizeOnce) { - SendManyResizeOnce(); -} - -TEST_F(WebRtcVideoMediaChannelTest, DISABLED_SendVp8HdAndReceiveAdaptedVp8Vga) { - EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL)); - channel_->UpdateAspectRatio(1280, 720); - video_capturer_.reset(new cricket::FakeVideoCapturer); - const std::vector* formats = - video_capturer_->GetSupportedFormats(); - cricket::VideoFormat capture_format_hd = (*formats)[0]; - EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format_hd)); - EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get())); - - // Capture format HD -> adapt (OnOutputFormatRequest VGA) -> VGA. - cricket::VideoCodec codec(100, "VP8", 1280, 720, 30, 0); - EXPECT_TRUE(SetOneCodec(codec)); - codec.width /= 2; - codec.height /= 2; - EXPECT_TRUE(SetSend(true)); - EXPECT_TRUE(channel_->SetRender(true)); - EXPECT_EQ(0, renderer_.num_rendered_frames()); - EXPECT_TRUE(SendFrame()); - EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout); -} - -TEST_F(WebRtcVideoMediaChannelTest, GetStats) { - Base::GetStats(); -} - -TEST_F(WebRtcVideoMediaChannelTest, GetStatsMultipleRecvStreams) { - Base::GetStatsMultipleRecvStreams(); -} - -TEST_F(WebRtcVideoMediaChannelTest, GetStatsMultipleSendStreams) { - Base::GetStatsMultipleSendStreams(); -} - -TEST_F(WebRtcVideoMediaChannelTest, SetSendBandwidth) { - Base::SetSendBandwidth(); -} -TEST_F(WebRtcVideoMediaChannelTest, SetSendSsrc) { - Base::SetSendSsrc(); -} -TEST_F(WebRtcVideoMediaChannelTest, SetSendSsrcAfterSetCodecs) { - Base::SetSendSsrcAfterSetCodecs(); -} - -TEST_F(WebRtcVideoMediaChannelTest, SetRenderer) { - Base::SetRenderer(); -} - -TEST_F(WebRtcVideoMediaChannelTest, AddRemoveRecvStreams) { - Base::AddRemoveRecvStreams(); -} - -// Flaky on Linux and Windows. See webrtc:4452. -#if defined(WEBRTC_WIN) || defined(WEBRTC_LINUX) -#define MAYBE_AddRemoveRecvStreamAndRender DISABLED_AddRemoveRecvStreamAndRender -#else -#define MAYBE_AddRemoveRecvStreamAndRender AddRemoveRecvStreamAndRender -#endif -TEST_F(WebRtcVideoMediaChannelTest, MAYBE_AddRemoveRecvStreamAndRender) { - Base::AddRemoveRecvStreamAndRender(); -} - -TEST_F(WebRtcVideoMediaChannelTest, AddRemoveRecvStreamsNoConference) { - Base::AddRemoveRecvStreamsNoConference(); -} - -TEST_F(WebRtcVideoMediaChannelTest, AddRemoveSendStreams) { - Base::AddRemoveSendStreams(); -} - -TEST_F(WebRtcVideoMediaChannelTest, SimulateConference) { - Base::SimulateConference(); -} - -TEST_F(WebRtcVideoMediaChannelTest, AddRemoveCapturer) { - Base::AddRemoveCapturer(); -} - -TEST_F(WebRtcVideoMediaChannelTest, RemoveCapturerWithoutAdd) { - Base::RemoveCapturerWithoutAdd(); -} - -TEST_F(WebRtcVideoMediaChannelTest, AddRemoveCapturerMultipleSources) { - Base::AddRemoveCapturerMultipleSources(); -} - -// This test verifies DSCP settings are properly applied on video media channel. -TEST_F(WebRtcVideoMediaChannelTest, TestSetDscpOptions) { - rtc::scoped_ptr network_interface( - new cricket::FakeNetworkInterface); - channel_->SetInterface(network_interface.get()); - cricket::VideoOptions options; - options.dscp.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_EQ(rtc::DSCP_AF41, network_interface->dscp()); - // Verify previous value is not modified if dscp option is not set. - cricket::VideoOptions options1; - EXPECT_TRUE(channel_->SetOptions(options1)); - EXPECT_EQ(rtc::DSCP_AF41, network_interface->dscp()); - options.dscp.Set(false); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp()); - channel_->SetInterface(NULL); -} - -TEST_F(WebRtcVideoMediaChannelTest, HighAspectHighHeightCapturer) { - Base::HighAspectHighHeightCapturer(); -} - -TEST_F(WebRtcVideoMediaChannelTest, SetOptionsSucceedsWhenSending) { - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Verify SetOptions returns true on a different options. - cricket::VideoOptions options2; - options2.adapt_input_to_cpu_usage.Set(true); - EXPECT_TRUE(channel_->SetOptions(options2)); - - // Set send codecs on the channel and start sending. - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_TRUE(channel_->SetSend(true)); - - // Verify SetOptions returns true if channel is already sending. - cricket::VideoOptions options3; - options3.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options3)); -} - -// Tests empty StreamParams is rejected. -TEST_F(WebRtcVideoMediaChannelTest, RejectEmptyStreamParams) { - Base::RejectEmptyStreamParams(); -} - -TEST_F(WebRtcVideoMediaChannelTest, AdaptResolution16x10) { - Base::AdaptResolution16x10(); -} - -TEST_F(WebRtcVideoMediaChannelTest, AdaptResolution4x3) { - Base::AdaptResolution4x3(); -} - -TEST_F(WebRtcVideoMediaChannelTest, MuteStream) { - Base::MuteStream(); -} - -TEST_F(WebRtcVideoMediaChannelTest, MultipleSendStreams) { - Base::MultipleSendStreams(); -} - -// TODO(juberti): Restore this test once we support sending 0 fps. -TEST_F(WebRtcVideoMediaChannelTest, DISABLED_AdaptDropAllFrames) { - Base::AdaptDropAllFrames(); -} -// TODO(juberti): Understand why we get decode errors on this test. -TEST_F(WebRtcVideoMediaChannelTest, DISABLED_AdaptFramerate) { - Base::AdaptFramerate(); -} - -TEST_F(WebRtcVideoMediaChannelTest, SetSendStreamFormat0x0) { - Base::SetSendStreamFormat0x0(); -} - -// TODO(zhurunz): Fix the flakey test. -TEST_F(WebRtcVideoMediaChannelTest, DISABLED_SetSendStreamFormat) { - Base::SetSendStreamFormat(); -} - -TEST_F(WebRtcVideoMediaChannelTest, TwoStreamsSendAndReceive) { - Base::TwoStreamsSendAndReceive(cricket::VideoCodec(100, "VP8", 640, 400, 30, - 0)); -} - -TEST_F(WebRtcVideoMediaChannelTest, TwoStreamsReUseFirstStream) { - Base::TwoStreamsReUseFirstStream(cricket::VideoCodec(100, "VP8", 640, 400, 30, - 0)); -} - -TEST_F(WebRtcVideoMediaChannelTest, DISABLED_TwoStreamsSendAndUnsignalledRecv) { - Base::TwoStreamsSendAndUnsignalledRecv(cricket::VideoCodec(100, "VP8", 640, - 400, 30, 0)); -} - -TEST_F(WebRtcVideoMediaChannelTest, - TwoStreamsSendAndFailUnsignalledRecv) { - Base::TwoStreamsSendAndFailUnsignalledRecv( - cricket::VideoCodec(100, "VP8", 640, 400, 30, 0)); -} - -TEST_F(WebRtcVideoMediaChannelTest, - TwoStreamsSendAndFailUnsignalledRecvInOneToOne) { - Base::TwoStreamsSendAndFailUnsignalledRecvInOneToOne( - cricket::VideoCodec(100, "VP8", 640, 400, 30, 0)); -} - -TEST_F(WebRtcVideoMediaChannelTest, - TwoStreamsAddAndRemoveUnsignalledRecv) { - Base::TwoStreamsAddAndRemoveUnsignalledRecv(cricket::VideoCodec(100, "VP8", - 640, 400, 30, - 0)); -} - -// Test that sequence number are not reset if stopping and then -// resuming a stream. -TEST_F(WebRtcVideoMediaChannelTest, DontResetSequenceNumbers) { - cricket::VideoCodec codec = DefaultCodec(); - EXPECT_TRUE(SetOneCodec(codec)); - - uint16_t seq_before = - engine_.vie() - ->rtp() - ->GetRtpStateForSsrc(channel_->GetDefaultChannelId(), kSsrc) - .sequence_number; - - // Deactive. - EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); - EXPECT_TRUE(SetOneCodec(codec)); - - // Reactivate. - EXPECT_TRUE(channel_->AddSendStream(DefaultSendStreamParams())); - EXPECT_TRUE(SetOneCodec(codec)); - - // Sequence number should now have changed. - uint16_t seq_after = - engine_.vie() - ->rtp() - ->GetRtpStateForSsrc(channel_->GetDefaultChannelId(), kSsrc) - .sequence_number; - - EXPECT_EQ(seq_before, seq_after); -} - -static const unsigned int kNumberOfTemporalLayers = 1; -static const unsigned int kSimulcastNumberOfTemporalLayers = 3; -static const unsigned int kSimStream0Bitrate = 100; -static const unsigned int kSimStream0MaxBitrateBoosted = 200; -static const unsigned int kSimStream0MaxBitrateXd = 200; -static const unsigned int kSimStream0TargetBitrateBoosted = 150; -static const unsigned int kSimStream0TargetBitrateXd = 150; -static const unsigned int kSimStream1Bitrate = 350; -static const unsigned int kSimStream1MaxBitrateBoosted = 450; -static const unsigned int kSimStream1MaxBitrateXd = 450; -static const unsigned int kSimStream1TargetBitrateBoosted = 350; -static const unsigned int kSimStream1TargetBitrateXd = 350; -static const unsigned int kSimStream2Bitrate = 500; -static const unsigned int kSimStream2MaxBitrateBoosted = 700; -static const unsigned int kSimStream2MaxBitrateXd = 700; -static const unsigned int kSimStream2TargetBitrateBoosted = 500; -static const unsigned int kSimStream2TargetBitrateXd = 500; -static const unsigned int kSimStream3Bitrate = 900; -static const unsigned int kSimStream3MaxBitrateBoosted = 900; -static const unsigned int kSimStream3MaxBitrateXd = 900; -static const unsigned int kSimStream3TargetBitrateBoosted = 900; -static const unsigned int kSimStream3TargetBitrateXd = 900; -static const unsigned int kSimStream4Bitrate = 1200; -static const unsigned int kSimStream4MaxBitrateBoosted = 1200; -static const unsigned int kSimStream4MaxBitrateXd = 2500; -static const unsigned int kSimStream4TargetBitrateBoosted = 1200; -static const unsigned int kSimStream4TargetBitrateXd = 2500; - -struct SimulcastFormat { - unsigned int width; - unsigned int height; - unsigned int max_layers; - unsigned int max_bitrate[cricket::SBM_COUNT]; - unsigned int target_bitrate[cricket::SBM_COUNT]; -}; - -static const SimulcastFormat kSimulcastFormats[] = { - {1280, 720, 3, - {kSimStream4Bitrate, kSimStream4MaxBitrateBoosted, - kSimStream4MaxBitrateXd}, - {kSimStream4Bitrate, kSimStream4TargetBitrateBoosted, - kSimStream4TargetBitrateXd}}, - {960, 540, 3, - {kSimStream3Bitrate, kSimStream3MaxBitrateBoosted, - kSimStream3MaxBitrateXd}, - {kSimStream3Bitrate, kSimStream3TargetBitrateBoosted, - kSimStream3TargetBitrateXd}}, - {640, 360, 2, - {kSimStream2Bitrate, kSimStream2MaxBitrateBoosted, - kSimStream2MaxBitrateXd}, - {kSimStream2Bitrate, kSimStream2TargetBitrateBoosted, - kSimStream2TargetBitrateXd}}, - {480, 270, 2, - {kSimStream1Bitrate, kSimStream1MaxBitrateBoosted, - kSimStream1MaxBitrateXd}, - {kSimStream1Bitrate, kSimStream1TargetBitrateBoosted, - kSimStream1TargetBitrateXd}}, - {320, 180, 1, - {kSimStream0Bitrate, kSimStream0MaxBitrateBoosted, - kSimStream0MaxBitrateXd}, - {kSimStream0Bitrate, kSimStream0TargetBitrateBoosted, - kSimStream0TargetBitrateXd}}, - {0, 0, 1, - {kSimStream0Bitrate, kSimStream0MaxBitrateBoosted, - kSimStream0MaxBitrateXd}, - {kSimStream0Bitrate, kSimStream0TargetBitrateBoosted, - kSimStream0TargetBitrateXd}} -}; - -// Test fixture to test WebRtcVideoEngine with a fake webrtc::VideoEngine. -// Useful for testing failure paths. -class WebRtcVideoEngineSimulcastTestFake : public testing::Test, - public sigslot::has_slots<> { - public: - WebRtcVideoEngineSimulcastTestFake() - : vie_(kVideoCodecs, ARRAY_SIZE(kVideoCodecs)), - cpu_monitor_(new rtc::FakeCpuMonitor( - rtc::Thread::Current())), - engine_(NULL, // cricket::WebRtcVoiceEngineExtended - new FakeViEWrapper(&vie_), cpu_monitor_), - channel_(NULL), - voice_channel_(NULL), - last_error_(cricket::VideoMediaChannel::ERROR_NONE) { - } - bool SetupEngine() { - bool result = engine_.Init(rtc::Thread::Current()); - if (result) { - channel_ = engine_.CreateChannel(cricket::VideoOptions(), voice_channel_); - channel_->SignalMediaError.connect(this, - &WebRtcVideoEngineSimulcastTestFake::OnMediaError); - result = (channel_ != NULL); - } - return result; - } - void OnMediaError(uint32 ssrc, cricket::VideoMediaChannel::Error error) { - last_error_ = error; - } - bool SendI420Frame(int width, int height) { - cricket::FakeVideoCapturer capturer; - return SendI420Frame(&capturer, width, height); - } - - bool SendI420Frame( - cricket::FakeVideoCapturer* capturer, int width, int height) { - if (NULL == channel_) { - return false; - } - cricket::WebRtcVideoFrame frame; - if (!frame.InitToBlack(width, height, 1, 1, 0, 0)) { - return false; - } - channel_->SendFrame(capturer, &frame); - return true; - } - bool SendI420ScreencastFrame(int width, int height) { - return SendI420ScreencastFrameWithTimestamp(width, height, 0); - } - bool SendI420ScreencastFrameWithTimestamp( - int width, int height, int64 timestamp) { - if (NULL == channel_) { - return false; - } - cricket::WebRtcVideoFrame frame; - if (!frame.InitToBlack(width, height, 1, 1, 0, 0)) { - return false; - } - cricket::FakeVideoCapturer capturer; - capturer.SetScreencast(true); - channel_->SendFrame(&capturer, &frame); - return true; - } - void VerifyVP8SendCodec( - int channel_num, - unsigned int width, - unsigned int height, - unsigned int layers = 0, - unsigned int max_bitrate = kMaxBandwidthKbps, - unsigned int min_bitrate = kMinBandwidthKbps, - unsigned int start_bitrate = kStartBandwidthKbps, - unsigned int fps = 30, - unsigned int max_quantization = 0, - cricket::SimulcastBitrateMode bitrate_mode = cricket::SBM_NORMAL) { - webrtc::VideoCodec gcodec; - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec)); - - // Video codec properties. - EXPECT_EQ(webrtc::kVideoCodecVP8, gcodec.codecType); - EXPECT_STREQ("VP8", gcodec.plName); - EXPECT_EQ(100, gcodec.plType); - EXPECT_EQ(width, gcodec.width); - EXPECT_EQ(height, gcodec.height); - EXPECT_EQ(std::min(start_bitrate, max_bitrate), gcodec.startBitrate); - EXPECT_EQ(max_bitrate, gcodec.maxBitrate); - EXPECT_EQ(min_bitrate, gcodec.minBitrate); - EXPECT_EQ(fps, gcodec.maxFramerate); - // VP8 specific. - EXPECT_FALSE(gcodec.codecSpecific.VP8.pictureLossIndicationOn); - EXPECT_FALSE(gcodec.codecSpecific.VP8.feedbackModeOn); - EXPECT_EQ(webrtc::kComplexityNormal, gcodec.codecSpecific.VP8.complexity); - EXPECT_EQ(webrtc::kResilienceOff, gcodec.codecSpecific.VP8.resilience); - EXPECT_EQ(max_quantization, gcodec.qpMax); - // Simulcast. - EXPECT_EQ(layers, gcodec.numberOfSimulcastStreams); - if (layers > 0) { - EXPECT_EQ(kSimulcastNumberOfTemporalLayers, - gcodec.codecSpecific.VP8.numberOfTemporalLayers); - } else { - EXPECT_EQ(kNumberOfTemporalLayers, - gcodec.codecSpecific.VP8.numberOfTemporalLayers); - } - for (int i = 0; i < static_cast(layers) - 1; ++i) { - EXPECT_EQ(gcodec.width / (0x01 << (layers - 1 - i)), - gcodec.simulcastStream[i].width); - EXPECT_EQ(gcodec.height / (0x01 << (layers - 1 - i)), - gcodec.simulcastStream[i].height); - EXPECT_EQ(kSimulcastNumberOfTemporalLayers, - gcodec.simulcastStream[i].numberOfTemporalLayers); - EXPECT_EQ(FindSimulcastMaxBitrate(gcodec.simulcastStream[i].width, - gcodec.simulcastStream[i].height, - bitrate_mode), - gcodec.simulcastStream[i].maxBitrate); - EXPECT_EQ(gcodec.qpMax, - gcodec.simulcastStream[i].qpMax); - } - if (layers > 0) - EXPECT_EQ(kMinBandwidthKbps, gcodec.simulcastStream[0].minBitrate); - } - unsigned int FindSimulcastMaxBitrate( - unsigned int width, - unsigned int height, - cricket::SimulcastBitrateMode bitrate_mode) { - for (size_t i = 0; i < ARRAY_SIZE(kSimulcastFormats); ++i) { - if (width >= kSimulcastFormats[i].width && - height >= kSimulcastFormats[i].height) { - return kSimulcastFormats[i].max_bitrate[bitrate_mode]; - } - } - return 0; - } - void SetUp2SimulcastStreams( - cricket::VideoOptions::HighestBitrate high_bitrate_mode, - const cricket::VideoCodec& codec) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - options.video_highest_bitrate.Set(high_bitrate_mode); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - std::vector codec_list; - codec_list.push_back(codec); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - } - void SetUp3SimulcastStreams( - cricket::VideoOptions::HighestBitrate high_bitrate_mode, - const cricket::VideoCodec& codec) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - options.video_highest_bitrate.Set(high_bitrate_mode); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Set max settings of 1280x720x30 to make sure we can have maximumly 3 - // simulcast streams. - EXPECT_TRUE(engine_.SetDefaultEncoderConfig( - cricket::VideoEncoderConfig(kVP8Codec720p))); - - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3)))); - std::vector codec_list; - codec_list.push_back(codec); - SendI420Frame(kVP8Codec720p.width, kVP8Codec720p.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - } - void TestSimulcastAdapter(const cricket::VideoCodec& send_codec, - bool expect_use_adapter) { - // Setup - engine_.SetExternalEncoderFactory(&encoder_factory_); - EXPECT_TRUE(SetupEngine()); - std::vector codecs; - codecs.push_back(send_codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(kSsrc))); - - // Verify - int channel_num = vie_.GetLastChannel(); - EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num)); - // If simulcast adapter is used, no external encoder instance will be - // created at this point. Otherwise 1 instance should have been created. - int num_enc_instance = expect_use_adapter ? 0 : 1; - EXPECT_EQ(num_enc_instance, encoder_factory_.GetNumCreatedEncoders()); - - // Clean up - EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); - } - virtual void TearDown() { - delete channel_; - engine_.Terminate(); - } - - protected: - cricket::FakeWebRtcVideoEngine vie_; - cricket::FakeWebRtcVideoDecoderFactory decoder_factory_; - cricket::FakeWebRtcVideoEncoderFactory encoder_factory_; - rtc::FakeCpuMonitor* cpu_monitor_; - cricket::WebRtcVideoEngine engine_; - cricket::WebRtcVideoMediaChannel* channel_; - cricket::WebRtcVoiceMediaChannel* voice_channel_; - cricket::VideoMediaChannel::Error last_error_; -}; - -// Test fixtures to test WebRtcVideoEngine with a real -// webrtc::VideoEngine. -class WebRtcVideoEngineSimulcastTest - : public VideoEngineTest { - protected: - typedef VideoEngineTest Base; -}; -class WebRtcVideoMediaChannelSimulcastTest - : public VideoMediaChannelTest< - cricket::WebRtcVideoEngine, cricket::WebRtcVideoMediaChannel> { - protected: - typedef VideoMediaChannelTest Base; - virtual cricket::VideoCodec DefaultCodec() { return kVP8Codec; } - virtual void SetUp() { - Base::SetUp(); - } - virtual void TearDown() { - Base::TearDown(); - } - // Tests that simulcast sends rtp packets containing expected number of - // layers and payload type. - void SimulcastSend(const cricket::VideoCodec& codec, - const std::vector& ssrcs) { - // Remove stream added in Setup. - EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); - - // Setup channel for sending and receiving simulcast packets. - cricket::VideoOptions vmo; - vmo.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(vmo)); - EXPECT_TRUE(SetOneCodec(codec)); - if (ssrcs.size() > 1) { - cricket::StreamParams sp; - cricket::SsrcGroup sg(cricket::kSimSsrcGroupSemantics, ssrcs); - sp.ssrcs = ssrcs; - sp.ssrc_groups.push_back(sg); - sp.cname = "cname"; - EXPECT_TRUE(channel_->AddSendStream(sp)); - } else { - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(ssrcs[0]))); - } - - // Re-configure capturer. - channel_->SetCapturer(kSsrc, NULL); - cricket::VideoFormat capture_format(codec.width, codec.height, - cricket::VideoFormat::FpsToInterval(codec.framerate), - cricket::FOURCC_I420); - EXPECT_TRUE(channel_->SetCapturer(ssrcs[0], video_capturer_.get())); - EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format)); - - EXPECT_TRUE(SetSend(true)); - - // Send one frame. - EXPECT_EQ(0, NumRtpPackets()); - EXPECT_EQ(0, NumRtpBytes()); - EXPECT_EQ(0, NumSentSsrcs()); - EXPECT_TRUE(SendFrame()); - - // Verify received expected simulcast layers. - EXPECT_TRUE_WAIT(NumSentSsrcs() == static_cast(ssrcs.size()), - 10 * kTimeout); - - // Stop sending before counting the packets, as padding will keep being sent - // which can cause a difference between total number of packets and the - // sum of packets on each ssrc if padding is sent in the summation loop. - EXPECT_TRUE(SetSend(false)); - - int total_num_packets = 0; - int total_num_bytes = 0; - for (size_t i = 0; i < ssrcs.size(); ++i) { - EXPECT_GE(NumRtpPackets(ssrcs[i]), 1); - EXPECT_GT(NumRtpBytes(ssrcs[i]), NumRtpPackets(ssrcs[i])); - total_num_packets += NumRtpPackets(ssrcs[i]); - total_num_bytes += NumRtpBytes(ssrcs[i]); - } - EXPECT_EQ(total_num_packets, NumRtpPackets()); - EXPECT_EQ(total_num_bytes, NumRtpBytes()); - - // All packets have the given payload type. - for (int i = 0; i < total_num_packets; ++i) { - rtc::scoped_ptr p(GetRtpPacket(i)); - EXPECT_EQ(codec.id, GetPayloadType(p.get())); - } - } - void TestScreencastSettings() { - // Remove stream added in SetUp. - EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); - - cricket::VideoOptions options; - options.conference_mode.Set(true); - // Enable noise reduction to ensure that it's being disabled for - // screencasting. - options.video_noise_reduction.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Setup a simulcast stream and verify that we have the correct - // settings. - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - cricket::VideoCodec codec(DefaultCodec()); - EXPECT_TRUE(SetOneCodec(codec)); - - channel_->SetCapturer(kSsrc, NULL); - cricket::VideoFormat capture_format(codec.width, codec.height, - cricket::VideoFormat::FpsToInterval(codec.framerate), - cricket::FOURCC_I420); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[0], video_capturer_.get())); - EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format)); - - EXPECT_TRUE(SetSend(true)); - EXPECT_TRUE(SendFrame()); - webrtc::VideoCodec video_codec; - int default_channel_id = channel_->GetDefaultChannelId(); - EXPECT_EQ(0, channel_->engine()->vie()->codec()->GetSendCodec( - default_channel_id, video_codec)); - EXPECT_FALSE(video_codec.codecSpecific.VP8.automaticResizeOn); - EXPECT_TRUE(video_codec.codecSpecific.VP8.denoisingOn); - EXPECT_EQ(webrtc::kRealtimeVideo, video_codec.mode); - EXPECT_EQ(3, video_codec.codecSpecific.VP8.numberOfTemporalLayers); - EXPECT_EQ(2, video_codec.numberOfSimulcastStreams); - EXPECT_NE(0u, video_codec.simulcastStream[0].minBitrate); - EXPECT_NE(0u, video_codec.simulcastStream[0].targetBitrate); - EXPECT_NE(0u, video_codec.simulcastStream[0].maxBitrate); - EXPECT_NE(0u, video_codec.simulcastStream[1].minBitrate); - EXPECT_NE(0u, video_codec.simulcastStream[1].targetBitrate); - EXPECT_NE(0u, video_codec.simulcastStream[1].maxBitrate); - - // Register a fake screencast capturer and verify that the video settings - // change as expected. - rtc::scoped_ptr capturer( - new cricket::FakeVideoCapturer); - capturer->SetScreencast(true); - const std::vector* formats = - capturer->GetSupportedFormats(); - capture_format = (*formats)[0]; - EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(capture_format)); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[0], capturer.get())); - EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30)); - EXPECT_TRUE(capturer->CaptureFrame()); - default_channel_id = channel_->GetDefaultChannelId(); - EXPECT_EQ(0, channel_->engine()->vie()->codec()->GetSendCodec( - default_channel_id, video_codec)); - EXPECT_FALSE(video_codec.codecSpecific.VP8.automaticResizeOn); - EXPECT_FALSE(video_codec.codecSpecific.VP8.denoisingOn); - EXPECT_EQ(webrtc::kScreensharing, video_codec.mode); - const int expected_num_layers = 2; - EXPECT_EQ(expected_num_layers, - video_codec.codecSpecific.VP8.numberOfTemporalLayers); - EXPECT_EQ(2, video_codec.numberOfSimulcastStreams); - EXPECT_EQ(0u, video_codec.simulcastStream[0].minBitrate); - EXPECT_EQ(0u, video_codec.simulcastStream[0].targetBitrate); - EXPECT_EQ(0u, video_codec.simulcastStream[0].maxBitrate); - - // Make sure that removing screencast restores the simulcast settings. - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[0], video_capturer_.get())); - EXPECT_TRUE(WaitAndSendFrame(30)); - EXPECT_EQ(0, channel_->engine()->vie()->codec()->GetSendCodec( - default_channel_id, video_codec)); - EXPECT_FALSE(video_codec.codecSpecific.VP8.automaticResizeOn); - EXPECT_TRUE(video_codec.codecSpecific.VP8.denoisingOn); - EXPECT_EQ(webrtc::kRealtimeVideo, video_codec.mode); - EXPECT_EQ(3, video_codec.codecSpecific.VP8.numberOfTemporalLayers); - EXPECT_EQ(2, video_codec.numberOfSimulcastStreams); - EXPECT_NE(0u, video_codec.simulcastStream[0].minBitrate); - EXPECT_NE(0u, video_codec.simulcastStream[0].targetBitrate); - EXPECT_NE(0u, video_codec.simulcastStream[0].maxBitrate); - EXPECT_NE(0u, video_codec.simulcastStream[1].minBitrate); - EXPECT_NE(0u, video_codec.simulcastStream[1].targetBitrate); - EXPECT_NE(0u, video_codec.simulcastStream[1].maxBitrate); - } -}; - -// Test that we apply send codec with simulcast properly. -TEST_F(WebRtcVideoEngineSimulcastTestFake, SetSendCodecsWith1SimulcastStreams) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // One ssrc simulcast StreamParams should be rejected. - EXPECT_FALSE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs1)))); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, SetSendCodecsWith2SimulcastStreams) { - cricket::VideoCodec codec(kVP8Codec); - SetUp2SimulcastStreams(cricket::VideoOptions::NORMAL, codec); - int channel_num = vie_.GetLastChannel(); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, SetSendCodecsWith3SimulcastStreams) { - cricket::VideoCodec codec(kVP8Codec720p); - SetUp3SimulcastStreams(cricket::VideoOptions::NORMAL, codec); - int channel_num = vie_.GetLastChannel(); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 3, - kSimStream0Bitrate + kSimStream2Bitrate + - kSimStream4Bitrate); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, - SetSendCodecsWith2SimulcastStreamsHighBitrateMode) { - cricket::VideoCodec codec(kVP8Codec); - SetUp2SimulcastStreams(cricket::VideoOptions::HIGH, codec); - int channel_num = vie_.GetLastChannel(); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 2, - kSimStream0TargetBitrateBoosted + - kSimStream2MaxBitrateBoosted, kMinBandwidthKbps, - kStartBandwidthKbps, 30, 0, cricket::SBM_HIGH); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, - SetSendCodecsWith3SimulcastStreamsHighBitrateMode) { - cricket::VideoCodec codec(kVP8Codec720p); - SetUp3SimulcastStreams(cricket::VideoOptions::HIGH, codec); - int channel_num = vie_.GetLastChannel(); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 3, - kSimStream0TargetBitrateBoosted + - kSimStream2TargetBitrateBoosted + - kSimStream4MaxBitrateBoosted, kMinBandwidthKbps, - kStartBandwidthKbps, 30, 0, cricket::SBM_HIGH); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, - SetSendCodecsWith2SimulcastStreamsVeryHighBitrateMode) { - cricket::VideoCodec codec(kVP8Codec); - SetUp2SimulcastStreams(cricket::VideoOptions::VERY_HIGH, - codec); - int channel_num = vie_.GetLastChannel(); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 2, - kSimStream0TargetBitrateXd + - kSimStream2MaxBitrateXd, kMinBandwidthKbps, - kStartBandwidthKbps, 30, 0, cricket::SBM_VERY_HIGH); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, - SetSendCodecsWith3SimulcastStreamsVeryHighBitrateMode) { - cricket::VideoCodec codec(kVP8Codec720p); - SetUp3SimulcastStreams(cricket::VideoOptions::VERY_HIGH, - codec); - int channel_num = vie_.GetLastChannel(); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 3, - kSimStream0TargetBitrateXd + - kSimStream2TargetBitrateXd + - kSimStream4MaxBitrateXd, kMinBandwidthKbps, - kStartBandwidthKbps, 30, 0, cricket::SBM_VERY_HIGH); -} - -// Test that we normalize send codec format size in simulcast. -TEST_F(WebRtcVideoEngineSimulcastTestFake, - SetSendCodecsWithOddSizeInSimulcast) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - int channel_num = vie_.GetLastChannel(); - - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - - // Set send codec and verify we get two simulcast sub-streams with - // normalized size. - cricket::VideoCodec codec(kVP8Codec270p); - codec.width += 0x01; - codec.height += 0x01; - std::vector codec_list; - codec_list.push_back(codec); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - - codec.width &= ~0x01; - codec.height &= ~0x01; - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 2, - kSimStream0Bitrate + kSimStream1MaxBitrateBoosted); -} - -// Test that if we add a stream with RTX SSRC's, SSRC's get set correctly. -TEST_F(WebRtcVideoEngineSimulcastTestFake, TestStreamWithRtx) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - int channel_num = vie_.GetLastChannel(); - - // Set max settings of 1280x720x30 to make sure we can have maximumly 3 - // simulcast streams. - EXPECT_TRUE(engine_.SetDefaultEncoderConfig( - cricket::VideoEncoderConfig(kVP8Codec720p))); - - // Verify only the first SSRC is set here. - // The rest are set during SetSendCodecs. - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimWithRtxStreamParams("cname", - MAKE_VECTOR(kSsrcs3), - MAKE_VECTOR(kRtxSsrcs3)))); - EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetNumRtxSsrcs(channel_num)); - - std::vector codec_list; - codec_list.push_back(kVP8Codec720p); - cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); - rtx_codec.SetParam("apt", kVP8Codec.id); - codec_list.push_back(rtx_codec); - SendI420Frame(kVP8Codec720p.width, kVP8Codec720p.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - - // RTX payload type should now be set. - EXPECT_EQ(vie_.GetRtxSendPayloadTypes(channel_num), - MAKE_VECTOR(kPayloadTypes1)); - - // Verify all SSRCs are set after SetSendCodecs. - EXPECT_EQ(3, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(3, vie_.GetNumRtxSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); - EXPECT_EQ(3, vie_.GetSsrc(channel_num, 2)); - EXPECT_EQ(4, vie_.GetRtxSsrc(channel_num, 0)); - EXPECT_EQ(5, vie_.GetRtxSsrc(channel_num, 1)); - EXPECT_EQ(6, vie_.GetRtxSsrc(channel_num, 2)); - uint32 ssrc; - EXPECT_EQ(0, vie_.GetLocalSSRC(channel_num, ssrc)); - EXPECT_EQ(1U, ssrc); -} - -// Test that if we get too few ssrcs are given in AddSendStream(), -// only supported sub-streams will be added. -TEST_F(WebRtcVideoEngineSimulcastTestFake, TooFewSimulcastSsrcs) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - int channel_num = vie_.GetLastChannel(); - - // Set max settings of 1280x720x30 to make sure we can have maximumly 3 - // simulcast streams. - EXPECT_TRUE(engine_.SetDefaultEncoderConfig( - cricket::VideoEncoderConfig(kVP8Codec720p))); - - // Verify only the first SSRC is set here. - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num)); - - cricket::VideoCodec codec(kVP8Codec720p); - std::vector codec_list; - codec_list.push_back(codec); - SendI420Frame(kVP8Codec720p.width, kVP8Codec720p.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - - // Verify all SSRCs are set after SetSendCodecs. - EXPECT_EQ(2, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); - uint32 ssrc; - EXPECT_EQ(0, vie_.GetLocalSSRC(channel_num, ssrc)); - EXPECT_EQ(1U, ssrc); - VerifyVP8SendCodec(channel_num, 640, 360, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); -} - -// Test that even more than enough ssrcs are given in AddSendStream(), -// only supported sub-streams will be added. -TEST_F(WebRtcVideoEngineSimulcastTestFake, MoreThanEnoughSimulcastSscrs) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - int channel_num = vie_.GetLastChannel(); - - // Set max settings of 1280x720x30 to make sure we can have maximumly 3 - // simulcast streams. - EXPECT_TRUE(engine_.SetDefaultEncoderConfig( - cricket::VideoEncoderConfig(kVP8Codec720p))); - - // Verify only the first SSRC is set here. - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs4)))); - EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num)); - - cricket::VideoCodec codec(kVP8Codec720p); - std::vector codec_list; - codec_list.push_back(codec); - SendI420Frame(kVP8Codec720p.width, kVP8Codec720p.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - - // Verify all SSRCs are set after SetSendCodecs. - EXPECT_EQ(3, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); - EXPECT_EQ(3, vie_.GetSsrc(channel_num, 2)); - uint32 ssrc; - EXPECT_EQ(0, vie_.GetLocalSSRC(channel_num, ssrc)); - EXPECT_EQ(1U, ssrc); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 3, - kSimStream0Bitrate + kSimStream2Bitrate + kSimStream4Bitrate); -} - -// Test that SetSendStreamFormat works well with simulcast. -TEST_F(WebRtcVideoEngineSimulcastTestFake, SetSendStreamFormatWithSimulcast) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - int channel_num = vie_.GetLastChannel(); - - // Verify SetSendStreamFormat fail before there is a send stream. - cricket::VideoFormat format = engine_.default_codec_format(); - EXPECT_FALSE(channel_->SetSendStreamFormat(1, format)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - - // Capture format HD - cricket::FakeVideoCapturer video_capturer; - const std::vector* formats = - video_capturer.GetSupportedFormats(); - cricket::VideoFormat capture_format_hd = (*formats)[0]; - EXPECT_EQ(cricket::CS_RUNNING, video_capturer.Start(capture_format_hd)); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[0], &video_capturer)); - - cricket::VideoCodec codec(kVP8Codec360p); - std::vector codec_list; - codec_list.push_back(codec); - SendI420Frame(&video_capturer, kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - - EXPECT_EQ(2, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); - - // Verify SetSendStreamFormat with the same resolution doesn't - // change the number of simulcast sub-streams. - format.width = codec.width; - format.height = codec.height; - EXPECT_TRUE(channel_->SetSendStreamFormat(1, format)); - EXPECT_EQ(2, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); - - // Capture format HD -> adapt (OnOutputFormatRequest VGA) -> VGA. - EXPECT_TRUE(video_capturer.CaptureFrame()); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); - - // Now, ask for a small resolution and verify that we only get one stream. - format.width = codec.width / 2; - format.height = codec.height / 2; - EXPECT_TRUE(channel_->SetSendStreamFormat(1, format)); - // Capture format HD -> adapt (OnOutputFormatRequest QVGA) -> QVGA. - EXPECT_TRUE(video_capturer.CaptureFrame()); - VerifyVP8SendCodec(channel_num, format.width, format.height, 1, - kSimStream0MaxBitrateBoosted); - - // Bump resolution back and verify there are 2 sub-streams again. - format.width = codec.width; - format.height = codec.height; - EXPECT_TRUE(channel_->SetSendStreamFormat(1, format)); - EXPECT_EQ(2, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); - // Capture format HD -> adapt (OnOutputFormatRequest VGA) -> VGA. - EXPECT_TRUE(video_capturer.CaptureFrame()); - VerifyVP8SendCodec(channel_num, format.width, format.height, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); - - // Verify SetSendStreamFormat can use either ssrc in the simulcast - // ssrc group. - format.width = codec.width / 2; - format.height = codec.height / 2; - EXPECT_TRUE(channel_->SetSendStreamFormat(2, format)); - EXPECT_EQ(2, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); - // Capture format HD -> adapt (OnOutputFormatRequest QVGA) -> QVGA. - EXPECT_TRUE(video_capturer.CaptureFrame()); - VerifyVP8SendCodec(channel_num, format.width, format.height, 1, - kSimStream0MaxBitrateBoosted); - - // Verify SetSendStreamFormat with bad ssrc fail. - format.width = codec.width; - format.height = codec.height; - EXPECT_FALSE(channel_->SetSendStreamFormat(3, format)); - EXPECT_EQ(2, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); - VerifyVP8SendCodec(channel_num, format.width / 2, format.height / 2, 1, - kSimStream0MaxBitrateBoosted); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[0], NULL)); -} - -// Test that simulcast send codec is reset on new video frame size. -TEST_F(WebRtcVideoEngineSimulcastTestFake, - ResetSimulcastSendCodecOnNewFrameSize) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - int channel_num = vie_.GetLastChannel(); - - // Set send codec. - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - cricket::VideoCodec codec(kVP8Codec); - std::vector codec_list; - codec_list.push_back(codec); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_EQ(1, vie_.GetNumSetSendCodecs()); - - // Feed in frames with different sizes and verify simulcast send codec - // changes accordingly. - - // Send an odd frame. Verify format size get normalized. - SendI420Frame(kVP8Codec.width | 0x01, kVP8Codec.height | 0x01); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); - EXPECT_EQ(2, vie_.GetNumSetSendCodecs()); - - // Send a big frame. Verify format size never exceed original send codec - // format size. - SendI420Frame(kVP8Codec.width * 2, kVP8Codec.height * 2); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); - EXPECT_EQ(2, vie_.GetNumSetSendCodecs()); - - // Send a small frame. Verify format size is bumped in order to meet - // the minimum simulcast reqirement while keeping the aspect ratio. - SendI420Frame(kVP8Codec.width / 2, kVP8Codec.height / 2); - // Need at least 480x270 to have simulcast. - VerifyVP8SendCodec(channel_num, kVP8Codec.width / 2, kVP8Codec.height / 2, 1, - kSimStream0MaxBitrateBoosted); - EXPECT_EQ(3, vie_.GetNumSetSendCodecs()); - - // Send a normal frame. Verify format size is back to normal. - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); - EXPECT_EQ(4, vie_.GetNumSetSendCodecs()); - - // Send an odd frame again. - SendI420Frame(kVP8Codec.width | 0x01, kVP8Codec.height | 0x01); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); - EXPECT_EQ(4, vie_.GetNumSetSendCodecs()); -} - -// Test that simulcast send codec is reset on new portait mode video frame. -TEST_F(WebRtcVideoEngineSimulcastTestFake, - ResetSimulcastSendCodecOnNewPortaitFrame) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - int channel_num = vie_.GetLastChannel(); - - // Set send codec. - EXPECT_TRUE(engine_.SetDefaultEncoderConfig( - cricket::VideoEncoderConfig(kVP8Codec720p))); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - cricket::VideoCodec codec(kVP8Codec720p); - std::vector codec_list; - codec_list.push_back(codec); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_EQ(1, vie_.GetNumSetSendCodecs()); - - // Feed in frames with different sizes and verify simulcast send codec - // changes accordingly. - - // Send a portait mode frame. - SendI420Frame(kVP8Codec.height, kVP8Codec.width); - VerifyVP8SendCodec(channel_num, kVP8Codec.height, kVP8Codec.width, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); - EXPECT_EQ(2, vie_.GetNumSetSendCodecs()); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, - SetBandwidthInConferenceWithSimulcast) { - cricket::VideoCodec ccodec(kVP8Codec720p); - SetUp3SimulcastStreams(cricket::VideoOptions::NORMAL, ccodec); - - // A higher value than the sum of max of all layers should add the extra - // bandwidth to the higher layer. - uint32 max_bandwidth = 5000; - EXPECT_TRUE(channel_->SetMaxSendBandwidth(max_bandwidth * 1000)); - - int channel_num = vie_.GetLastChannel(); - webrtc::VideoCodec codec; - codec.width = 0; codec.height = 0; - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, codec)); - EXPECT_EQ(max_bandwidth, codec.maxBitrate); - - int nr_layers = 3; - uint32 sum_bandwidth = 0; - for (int i = 0; i < nr_layers; ++i) { - if (i == nr_layers - 1) { - EXPECT_EQ(max_bandwidth - sum_bandwidth, - codec.simulcastStream[i].maxBitrate); - } else { - EXPECT_EQ(FindSimulcastMaxBitrate(codec.simulcastStream[i].width, - codec.simulcastStream[i].height, - cricket::SBM_NORMAL), - codec.simulcastStream[i].maxBitrate); - sum_bandwidth += codec.simulcastStream[i].maxBitrate; - } - } - - // Test setting max bandwidth below the sum of layer specific max bandwidth. - // Basically, the simulcast max overrides the SetMaxSendBandwidth value. - EXPECT_TRUE(channel_->SetMaxSendBandwidth(1)); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 3, - kSimStream0Bitrate + kSimStream2Bitrate + - kSimStream4Bitrate); -} - -// Test that sending screencast frames in conference mode changes -// bitrate. -TEST_F(WebRtcVideoEngineSimulcastTestFake, SetBandwidthScreencastInConference) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - // Set send codec. - cricket::VideoCodec codec(kVP8Codec); - std::vector codec_list; - codec_list.push_back(codec); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(123))); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - EXPECT_TRUE(channel_->SetMaxSendBandwidth(1200000)); - EXPECT_EQ(2, vie_.GetNumSetSendCodecs()); - - // Set conference mode and verify that this caps maxBitrate. - webrtc::VideoCodec gcodec; - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec)); - EXPECT_GT(gcodec.maxBitrate, 1000u); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(channel_->SetSend(true)); - SendI420ScreencastFrame(kVP8Codec.width, kVP8Codec.height); - EXPECT_EQ(3, vie_.GetNumSetSendCodecs()); - EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(1000u, gcodec.maxBitrate); -} - -// Test AddSendStream with simulcast rejects bad StreamParams. -TEST_F(WebRtcVideoEngineSimulcastTestFake, AddSendStreamWithBadStreamParams) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Verify non-sim StreamParams is rejected. - cricket::StreamParams sp_bad; - std::vector ssrcs; - ssrcs.push_back(1234); - ssrcs.push_back(5678); - cricket::SsrcGroup sg("bad", ssrcs); - sp_bad.ssrcs = ssrcs; - sp_bad.ssrc_groups.push_back(sg); - sp_bad.cname = "cname"; - EXPECT_FALSE(channel_->AddSendStream(sp_bad)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); -} - -// Test AddSendStream with simulcast sets ssrc and cname correctly. -TEST_F(WebRtcVideoEngineSimulcastTestFake, AddSendStreamWithSimulcast) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - int channel_num = vie_.GetLastChannel(); - - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - - unsigned int ssrc = 0; - EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(0, vie_.GetLocalSSRC(channel_num, ssrc)); - EXPECT_EQ(1U, ssrc); - - char rtcp_cname[256]; - EXPECT_EQ(0, vie_.GetRTCPCName(channel_num, rtcp_cname)); - EXPECT_STREQ("cname", rtcp_cname); - - EXPECT_TRUE(channel_->RemoveSendStream(1)); -} - -// Test RemoveSendStream with simulcast. -TEST_F(WebRtcVideoEngineSimulcastTestFake, RemoveSendStreamWithSimulcast) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // RemoveSendStream should fail when there is no send stream. - EXPECT_FALSE(channel_->RemoveSendStream(1)); - - cricket::StreamParams stream = - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)); - EXPECT_TRUE(channel_->AddSendStream(stream)); - - // RemoveSendStream should fail with bad ssrc. - EXPECT_FALSE(channel_->RemoveSendStream(3)); - EXPECT_TRUE(channel_->RemoveSendStream(1)); - - // RemoveSendStream should work with either ssrc. - EXPECT_TRUE(channel_->AddSendStream(stream)); - EXPECT_TRUE(channel_->RemoveSendStream(1)); - EXPECT_TRUE(channel_->AddSendStream(stream)); - EXPECT_TRUE(channel_->RemoveSendStream(2)); - - // RemoveSendStream should fail when there is no send stream. - EXPECT_FALSE(channel_->RemoveSendStream(1)); -} - -// Test AddSendStream after send codec has already been set will reset -// send codec with simulcast settings. -TEST_F(WebRtcVideoEngineSimulcastTestFake, - AddSimulcastStreamAfterSetSendCodec) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - int channel_num = vie_.GetLastChannel(); - - // Set send codec. - cricket::VideoCodec codec(kVP8Codec); - std::vector codec_list; - codec_list.push_back(codec); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - VerifyVP8SendCodec(channel_num, codec.width, codec.height); - - // Add simulcast send stream and verify send codec has been reset. - // Provide 3 ssrcs here and only 2 layers should be added. - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3)))); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); - - // Verify local SSRCs are now populated correctly. - EXPECT_EQ(2, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); - uint32 ssrc; - EXPECT_EQ(0, vie_.GetLocalSSRC(channel_num, ssrc)); - EXPECT_EQ(1U, ssrc); - - // Remove the stream and reset send codec with a smaller size. - EXPECT_TRUE(channel_->RemoveSendStream(1)); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); - codec_list.clear(); - codec.width /= 2; - codec.height /= 2; - codec_list.push_back(codec); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - VerifyVP8SendCodec(channel_num, codec.width, codec.height); - - // Add simulcast send stream again and verify simulcast have one stream. - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 1, - kSimStream0MaxBitrateBoosted); - - // Verify we still have 2 SSRCs. - EXPECT_EQ(2, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); - EXPECT_EQ(0, vie_.GetLocalSSRC(channel_num, ssrc)); - EXPECT_EQ(1U, ssrc); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, GetStatsWithMultipleSsrcs) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Add simulcast stream. - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - - // Set send codec and verify we get two simulcast sub-streams. - cricket::VideoCodec codec(kVP8Codec); - std::vector codec_list; - codec_list.push_back(codec); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - EXPECT_TRUE(channel_->SetSend(true)); - - cricket::FakeVideoCapturer video_capturer; - const std::vector* formats = - video_capturer.GetSupportedFormats(); - cricket::VideoFormat capture_format_vga = (*formats)[1]; - EXPECT_EQ(cricket::CS_RUNNING, video_capturer.Start(capture_format_vga)); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[0], &video_capturer)); - - // Only require one cpu sample for testing whether the adapter is hooked up. - cricket::CoordinatedVideoAdapter* video_adapter = NULL; - ASSERT_TRUE(channel_->GetVideoAdapter(0u, &video_adapter)); - video_adapter->set_cpu_load_min_samples(1); - cpu_monitor_->SignalUpdate(1, 1, 0.1f, 0.85f); - - // Capture format VGA -> adapt (OnCpuLoadUpdate downgrade) -> VGA/2. - EXPECT_TRUE(video_capturer.CaptureFrame()); - - // Get stats and verify there are 2 ssrcs. - cricket::VideoMediaInfo info; - EXPECT_TRUE(channel_->GetStats(&info)); - ASSERT_EQ(1U, info.senders.size()); - ASSERT_EQ(2U, info.senders[0].ssrcs().size()); - EXPECT_EQ(1U, info.senders[0].ssrcs()[0]); - EXPECT_EQ(2U, info.senders[0].ssrcs()[1]); - // Verify the input/send width/height. - EXPECT_EQ(capture_format_vga.width, info.senders[0].input_frame_width); - EXPECT_EQ(capture_format_vga.height, info.senders[0].input_frame_height); - EXPECT_EQ(capture_format_vga.width * 3 / 4, - info.senders[0].send_frame_width); - EXPECT_EQ(capture_format_vga.height * 3 / 4, - info.senders[0].send_frame_height); - - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[0], NULL)); -} - -// Test receiving channel(s) local ssrc is set to the same as the first -// simulcast sending ssrc. -TEST_F(WebRtcVideoEngineSimulcastTestFake, - AddSimulcastStreamAfterCreatingRecvChannels) { - EXPECT_TRUE(SetupEngine()); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - int channel_num = vie_.GetLastChannel(); - - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(10))); - int receive_channel_1 = vie_.GetLastChannel(); - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(11))); - int receive_channel_2 = vie_.GetLastChannel(); - - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - - unsigned int ssrc = 0; - EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(0, vie_.GetLocalSSRC(channel_num, ssrc)); - EXPECT_EQ(1U, ssrc); - - EXPECT_EQ(0, vie_.GetLocalSSRC(receive_channel_1, ssrc)); - EXPECT_EQ(1U, ssrc); - EXPECT_EQ(1, vie_.GetNumSsrcs(receive_channel_1)); - - EXPECT_EQ(0, vie_.GetLocalSSRC(receive_channel_2, ssrc)); - EXPECT_EQ(1U, ssrc); - EXPECT_EQ(1, vie_.GetNumSsrcs(receive_channel_2)); -} - -// Test 1:1 call never turn on simulcast. -TEST_F(WebRtcVideoEngineSimulcastTestFake, NoSimulcastWith1on1) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - - // Set send codec and verify there is no simulcast sub-streams. - cricket::VideoCodec codec(kVP8Codec); - std::vector codec_list; - codec_list.push_back(codec); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - VerifyVP8SendCodec(channel_num, codec.width, codec.height); - EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num)); - - // Set options with OPT_CONFERENCE flag and set send codec again. - // Verify simulcast is used now. - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - VerifyVP8SendCodec(channel_num, codec.width, codec.height, 2, - kSimStream0Bitrate + kSimStream2MaxBitrateBoosted); - EXPECT_EQ(2, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); - - // Remove OPT_CONFERENCE flag and set send codec again. - // Verify simulcast is off again. - options.conference_mode.Set(false); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - VerifyVP8SendCodec(channel_num, codec.width, codec.height); - - // Verify we still have 2 SSRCs. - EXPECT_EQ(2, vie_.GetNumSsrcs(channel_num)); - EXPECT_EQ(1, vie_.GetSsrc(channel_num, 0)); - EXPECT_EQ(2, vie_.GetSsrc(channel_num, 1)); -} - -// Test SetOptions with OPT_CONFERENCE flag. -TEST_F(WebRtcVideoEngineSimulcastTestFake, SetOptionsWithConferenceMode) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - - // Set send codec. - cricket::VideoCodec codec(kVP8Codec); - std::vector codec_list; - codec_list.push_back(codec); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - - // Verify default send codec and bitrate. - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height); - - // Set options with OPT_CONFERENCE flag. - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Change the max bitrate and verify it has changed. - channel_->SetMaxSendBandwidth(kSimStream2MaxBitrateBoosted * 1000); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, - kSimStream2MaxBitrateBoosted); - - // Turn off conference mode and verify the max bandwidth changed - // back. - options.conference_mode.Set(false); - EXPECT_TRUE(channel_->SetOptions(options)); - VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height); - - // Set send codec again with a smaller size. - codec_list.clear(); - codec.width /= 2; - codec.height /= 2; - codec_list.push_back(codec); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - - // Set options with OPT_CONFERENCE flag and set the max bitrate again. - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - channel_->SetMaxSendBandwidth(kSimStream0MaxBitrateBoosted * 1000); - - // Verify channel now has a new max bitrate. - VerifyVP8SendCodec(channel_num, kVP8Codec.width / 2, kVP8Codec.height / 2, 0, - kSimStream0MaxBitrateBoosted); -} - -// Test that two different streams can have different formats. -TEST_F(WebRtcVideoEngineSimulcastTestFake, - MultipleSendStreamsDifferentFormats) { - EXPECT_TRUE(SetupEngine()); - for (unsigned int i = 0; i < sizeof(kSsrcs2)/sizeof(kSsrcs2[0]); ++i) { - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(kSsrcs2[i]))); - } - const int channel0 = vie_.GetChannelFromLocalSsrc(kSsrcs2[0]); - ASSERT_NE(-1, channel0); - const int channel1 = vie_.GetChannelFromLocalSsrc(kSsrcs2[1]); - ASSERT_NE(-1, channel1); - ASSERT_NE(channel0, channel1); - std::vector codecs; - codecs.push_back(kVP8Codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - cricket::VideoFormat format(kVP8Codec.width / 2, kVP8Codec.height / 2, - cricket::VideoFormat::FpsToInterval(kVP8Codec.framerate / 2), - cricket::FOURCC_I420); - EXPECT_TRUE(channel_->SetSendStreamFormat(kSsrcs2[1], format)); - - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - VerifyVP8SendCodec(channel0, kVP8Codec.width, kVP8Codec.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, kStartBandwidthKbps, - kVP8Codec.framerate); - VerifyVP8SendCodec(channel1, kVP8Codec.width / 2, kVP8Codec.height / 2, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, kStartBandwidthKbps, - kVP8Codec.framerate / 2); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, TestAdaptToOutputFormat) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3)))); - - // Capture format HD - cricket::FakeVideoCapturer video_capturer; - const std::vector* formats = - video_capturer.GetSupportedFormats(); - cricket::VideoFormat capture_format_hd = (*formats)[0]; - EXPECT_EQ(cricket::CS_RUNNING, video_capturer.Start(capture_format_hd)); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer)); - - cricket::VideoCodec send_codec(100, "VP8", 800, 600, 30, 0); - cricket::VideoFormat vga_format(640, 360, - cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420); - std::vector codecs; - codecs.push_back(send_codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_TRUE(channel_->SetSendStreamFormat(kSsrcs3[0], vga_format)); - EXPECT_TRUE(channel_->SetSend(true)); - - // Capture format HD -> adapt (OnOutputFormatRequest VGA) -> VGA. - EXPECT_TRUE(video_capturer.CaptureFrame()); - const int channel0 = vie_.GetChannelFromLocalSsrc(kSsrcs3[0]); - ASSERT_NE(-1, channel0); - VerifyVP8SendCodec(channel0, vga_format.width, vga_format.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, kStartBandwidthKbps, - 30); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, TestAdaptToCpuLoad) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3)))); - - // Capture format VGA - cricket::FakeVideoCapturer video_capturer; - const std::vector* formats = - video_capturer.GetSupportedFormats(); - cricket::VideoFormat capture_format_vga = (*formats)[1]; - - // Make OnCpuLoadUpdate trigger downgrade. - cricket::VideoOptions options; - options.adapt_input_to_cpu_usage.Set(true); - options.process_adaptation_threshhold.Set(0.1f); - options.system_low_adaptation_threshhold.Set(0.65f); - options.system_high_adaptation_threshhold.Set(0.85f); - options.cpu_overuse_detection.Set(false); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Verify toggling cpu overuse detection works. - options.cpu_overuse_detection.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - options.cpu_overuse_detection.Set(false); - EXPECT_TRUE(channel_->SetOptions(options)); - - EXPECT_EQ(cricket::CS_RUNNING, video_capturer.Start(capture_format_vga)); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer)); - - // Only require one cpu sample for testing whether the adapter is hooked up. - cricket::CoordinatedVideoAdapter* video_adapter = NULL; - ASSERT_TRUE(channel_->GetVideoAdapter(0u, &video_adapter)); - video_adapter->set_cpu_load_min_samples(1); - - cpu_monitor_->SignalUpdate(1, 1, 0.1f, 0.85f); - - cricket::VideoCodec send_codec(100, "VP8", 640, 480, 30, 0); - std::vector codecs; - codecs.push_back(send_codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_TRUE(channel_->SetSend(true)); - - // Capture format VGA -> adapt (OnCpuLoadUpdate downgrade) -> VGA/2. - EXPECT_TRUE(video_capturer.CaptureFrame()); - const int channel0 = vie_.GetChannelFromLocalSsrc(kSsrcs3[0]); - ASSERT_NE(-1, channel0); - VerifyVP8SendCodec( - channel0, 3 * send_codec.width / 4, 3 * send_codec.height / 4, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, kStartBandwidthKbps, - send_codec.framerate); - - // Trigger more downgrades and check for multiple unable to adapt signal. - EXPECT_EQ(cricket::VideoMediaChannel::ERROR_NONE, last_error_); - cpu_monitor_->SignalUpdate(1, 1, 0.1f, 0.85f); - cpu_monitor_->SignalUpdate(1, 1, 0.1f, 0.85f); - EXPECT_EQ(cricket::VideoMediaChannel::ERROR_REC_CPU_MAX_CANT_DOWNGRADE, - last_error_); - - last_error_ = cricket::VideoMediaChannel::ERROR_NONE; - cpu_monitor_->SignalUpdate(1, 1, 0.1f, 0.85f); - EXPECT_EQ(cricket::VideoMediaChannel::ERROR_REC_CPU_MAX_CANT_DOWNGRADE, - last_error_); - - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, TestAdaptToCpuLoadDisabled) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3)))); - - // Capture format VGA - cricket::FakeVideoCapturer video_capturer; - const std::vector* formats = - video_capturer.GetSupportedFormats(); - cricket::VideoFormat capture_format_vga = (*formats)[1]; - EXPECT_EQ(cricket::CS_RUNNING, video_capturer.Start(capture_format_vga)); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer)); - - // Make OnCpuLoadUpdate trigger downgrade. - cricket::VideoOptions options; - options.adapt_input_to_cpu_usage.Set(false); - options.process_adaptation_threshhold.Set(0.1f); - options.system_low_adaptation_threshhold.Set(0.65f); - options.system_high_adaptation_threshhold.Set(0.85f); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Only require one cpu sample for testing whether the adapter is hooked up. - cricket::CoordinatedVideoAdapter* video_adapter = NULL; - ASSERT_TRUE(channel_->GetVideoAdapter(0u, &video_adapter)); - video_adapter->set_cpu_load_min_samples(1); - cpu_monitor_->SignalUpdate(1, 1, 0.1f, 0.85f); - - cricket::VideoCodec send_codec(100, "VP8", 640, 480, 30, 0); - std::vector codecs; - codecs.push_back(send_codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_TRUE(channel_->SetSend(true)); - - // Capture format VGA -> no adapt -> VGA. - EXPECT_TRUE(video_capturer.CaptureFrame()); - const int channel0 = vie_.GetChannelFromLocalSsrc(kSsrcs3[0]); - ASSERT_NE(-1, channel0); - VerifyVP8SendCodec(channel0, capture_format_vga.width, - capture_format_vga.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, kStartBandwidthKbps, - send_codec.framerate); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, TestAdaptWithCpuOveruseObserver) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3)))); - - // Verify that the CpuOveruseObserver is not set by default. - const int channel0 = vie_.GetChannelFromLocalSsrc(kSsrcs3[0]); - ASSERT_NE(-1, channel0); - webrtc::CpuOveruseObserver* observer = vie_.GetCpuOveruseObserver(channel0); - EXPECT_TRUE(observer == NULL); - - // Capture format VGA. - cricket::FakeVideoCapturer video_capturer; - const std::vector* formats = - video_capturer.GetSupportedFormats(); - cricket::VideoFormat capture_format_vga = (*formats)[1]; - EXPECT_EQ(cricket::CS_RUNNING, video_capturer.Start(capture_format_vga)); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer)); - - // Verify that the CpuOveruseObserver is registered and trigger downgrade. - cricket::VideoOptions options; - options.cpu_overuse_detection.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - observer = vie_.GetCpuOveruseObserver(channel0); - ASSERT_TRUE(observer != NULL); - observer->OveruseDetected(); - - cricket::VideoCodec send_codec(100, "VP8", 640, 480, 30, 0); - std::vector codecs; - codecs.push_back(send_codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_TRUE(channel_->SetSend(true)); - - // Capture format VGA -> adapt (OnCpuResolutionRequest downgrade) -> VGA/2. - EXPECT_TRUE(video_capturer.CaptureFrame()); - VerifyVP8SendCodec( - channel0, 3 * send_codec.width / 4, 3 * send_codec.height / 4, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, kStartBandwidthKbps, - send_codec.framerate); - - // Trigger upgrade and verify that we adapt back up to VGA. - observer->NormalUsage(); - EXPECT_TRUE(video_capturer.CaptureFrame()); - VerifyVP8SendCodec( - channel0, send_codec.width, send_codec.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, kStartBandwidthKbps, - send_codec.framerate); - - // Verify that the CpuOveruseObserver is deregistered. - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); - EXPECT_TRUE(vie_.GetCpuOveruseObserver(channel0) == NULL); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, - TestAdaptWithCpuOveruseObserverDisabled) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3)))); - - // Verify that the CpuOveruseObserver is not set by default. - const int channel0 = vie_.GetChannelFromLocalSsrc(kSsrcs3[0]); - ASSERT_NE(-1, channel0); - webrtc::CpuOveruseObserver* observer = vie_.GetCpuOveruseObserver(channel0); - EXPECT_TRUE(observer == NULL); - - // Capture format VGA. - cricket::FakeVideoCapturer video_capturer; - const std::vector* formats = - video_capturer.GetSupportedFormats(); - cricket::VideoFormat capture_format_vga = (*formats)[1]; - EXPECT_EQ(cricket::CS_RUNNING, video_capturer.Start(capture_format_vga)); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer)); - - // Disable cpu overuse detection. - cricket::VideoOptions options; - options.cpu_overuse_detection.Set(false); - EXPECT_TRUE(channel_->SetOptions(options)); - cricket::CoordinatedVideoAdapter* video_adapter = NULL; - ASSERT_TRUE(channel_->GetVideoAdapter(0u, &video_adapter)); - EXPECT_FALSE(video_adapter->cpu_adaptation()); - - // Verify that the CpuOveruseObserver is registered and trigger downgrade. - observer = vie_.GetCpuOveruseObserver(channel0); - ASSERT_TRUE(observer != NULL); - observer->OveruseDetected(); - - cricket::VideoCodec send_codec(100, "VP8", 640, 480, 30, 0); - std::vector codecs; - codecs.push_back(send_codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_TRUE(channel_->SetSend(true)); - - // Capture format VGA -> no adapt -> VGA. - EXPECT_TRUE(video_capturer.CaptureFrame()); - VerifyVP8SendCodec( - channel0, capture_format_vga.width, capture_format_vga.height, 0, - kMaxBandwidthKbps, kMinBandwidthKbps, kStartBandwidthKbps, - send_codec.framerate); - - // Verify that the CpuOveruseObserver is deregistered. - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); - EXPECT_TRUE(vie_.GetCpuOveruseObserver(channel0) == NULL); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, GetAdaptStats) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3)))); - - // Capture format VGA. - cricket::FakeVideoCapturer video_capturer_vga; - const std::vector* formats = - video_capturer_vga.GetSupportedFormats(); - cricket::VideoFormat capture_format_vga = (*formats)[1]; - EXPECT_EQ(cricket::CS_RUNNING, video_capturer_vga.Start(capture_format_vga)); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer_vga)); - EXPECT_TRUE(video_capturer_vga.CaptureFrame()); - - cricket::VideoCodec send_codec(100, "VP8", 640, 480, 30, 0); - std::vector codecs; - codecs.push_back(send_codec); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_TRUE(channel_->SetSend(true)); - - // Verify that the CpuOveruseObserver is registered and trigger downgrade. - cricket::VideoOptions options; - options.cpu_overuse_detection.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - const int channel0 = vie_.GetChannelFromLocalSsrc(kSsrcs3[0]); - ASSERT_NE(-1, channel0); - webrtc::CpuOveruseObserver* observer = vie_.GetCpuOveruseObserver(channel0); - ASSERT_TRUE(observer != NULL); - observer->OveruseDetected(); - - // Capture format VGA -> adapt (OnCpuResolutionRequest downgrade) -> VGA/2. - EXPECT_TRUE(video_capturer_vga.CaptureFrame()); - cricket::VideoMediaInfo info; - EXPECT_TRUE(channel_->GetStats(&info)); - ASSERT_EQ(1U, info.senders.size()); - EXPECT_EQ(1, info.senders[0].adapt_changes); - EXPECT_EQ(cricket::CoordinatedVideoAdapter::ADAPTREASON_CPU, - info.senders[0].adapt_reason); - - // Trigger upgrade and verify that we adapt back up to VGA. - observer->NormalUsage(); - EXPECT_TRUE(video_capturer_vga.CaptureFrame()); - info.Clear(); - EXPECT_TRUE(channel_->GetStats(&info)); - ASSERT_EQ(1U, info.senders.size()); - EXPECT_EQ(2, info.senders[0].adapt_changes); - EXPECT_EQ(cricket::CoordinatedVideoAdapter::ADAPTREASON_NONE, - info.senders[0].adapt_reason); - - // No capturer (no adapter). Adapt changes from old adapter should be kept. - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); - EXPECT_TRUE(vie_.GetCpuOveruseObserver(channel0) == NULL); - info.Clear(); - EXPECT_TRUE(channel_->GetStats(&info)); - ASSERT_EQ(1U, info.senders.size()); - EXPECT_EQ(2, info.senders[0].adapt_changes); - EXPECT_EQ(cricket::CoordinatedVideoAdapter::ADAPTREASON_NONE, - info.senders[0].adapt_reason); - - // Set new capturer, capture format HD. - cricket::FakeVideoCapturer video_capturer_hd; - cricket::VideoFormat capture_format_hd = (*formats)[0]; - EXPECT_EQ(cricket::CS_RUNNING, video_capturer_hd.Start(capture_format_hd)); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer_hd)); - EXPECT_TRUE(video_capturer_hd.CaptureFrame()); - observer = vie_.GetCpuOveruseObserver(channel0); - ASSERT_TRUE(observer != NULL); - - // Trigger overuse, HD -> adapt (OnCpuResolutionRequest downgrade) -> HD/2. - observer->OveruseDetected(); - EXPECT_TRUE(video_capturer_hd.CaptureFrame()); - info.Clear(); - EXPECT_TRUE(channel_->GetStats(&info)); - ASSERT_EQ(1U, info.senders.size()); - EXPECT_EQ(3, info.senders[0].adapt_changes); - EXPECT_EQ(cricket::CoordinatedVideoAdapter::ADAPTREASON_CPU, - info.senders[0].adapt_reason); - - EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); -} - -// Test that the codec is not reset for every frame sent in -// non-conference and non-screencast mode. -TEST_F(WebRtcVideoEngineSimulcastTestFake, DontResetCodecOnSendFrame) { - EXPECT_TRUE(SetupEngine()); - - // Set send codec. - cricket::VideoCodec codec(kVP8Codec); - std::vector codec_list; - codec_list.push_back(codec); - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(123))); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_TRUE(channel_->SetSendCodecs(codec_list)); - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_EQ(1, vie_.GetNumSetSendCodecs()); - - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_EQ(1, vie_.GetNumSetSendCodecs()); - SendI420Frame(kVP8Codec.width, kVP8Codec.height); - EXPECT_EQ(1, vie_.GetNumSetSendCodecs()); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, - UseSimulcastAdapterOnVp8OnlyFactory) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); - TestSimulcastAdapter(kVP8Codec, true); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, - UsesSimulcastAdapterForVp8WithCombinedVP8AndH264Factory) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric, - "H264"); - TestSimulcastAdapter(kVP8Codec, true); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, - DontUseSimulcastAdapterForH264WithCombinedVP8AndH264Factory) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric, - "H264"); - static const cricket::VideoCodec kH264Codec(100, "H264", 640, 400, 30, 0); - TestSimulcastAdapter(kH264Codec, false); -} - -TEST_F(WebRtcVideoEngineSimulcastTestFake, - DontUseSimulcastAdapterOnNonVp8Factory) { - encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric, - "H264"); - static const cricket::VideoCodec kH264Codec(100, "H264", 640, 400, 30, 0); - TestSimulcastAdapter(kH264Codec, false); -} - -// Flaky on Windows and tsan. https://code.google.com/p/webrtc/issues/detail?id=4135 -#if defined(WIN32) || defined(THREAD_SANITIZER) -#define MAYBE_SimulcastSend_1280x800 DISABLED_SimulcastSend_1280x800 -#else -#define MAYBE_SimulcastSend_1280x800 SimulcastSend_1280x800 -#endif -TEST_F(WebRtcVideoMediaChannelSimulcastTest, MAYBE_SimulcastSend_1280x800) { - cricket::VideoCodec codec = kVP8Codec; - codec.width = 1280; - codec.height = 800; - // TODO(zhurunz): Support 3 layers of simulcast. - SimulcastSend(codec, MAKE_VECTOR(kSsrcs2)); -} - -// Flaky on Windows and tsan. https://code.google.com/p/webrtc/issues/detail?id=4135 -#if defined(WIN32) || defined(THREAD_SANITIZER) -#define MAYBE_SimulcastSend_1280x720 DISABLED_SimulcastSend_1280x720 -#else -#define MAYBE_SimulcastSend_1280x720 SimulcastSend_1280x720 -#endif -TEST_F(WebRtcVideoMediaChannelSimulcastTest, MAYBE_SimulcastSend_1280x720) { - cricket::VideoCodec codec = kVP8Codec; - codec.width = 1280; - codec.height = 720; - // TODO(zhurunz): Support 3 layers of simulcast. - SimulcastSend(codec, MAKE_VECTOR(kSsrcs2)); -} - -// Flaky on Windows and tsan. https://code.google.com/p/webrtc/issues/detail?id=4135 -#if defined(WIN32) || defined(THREAD_SANITIZER) -#define MAYBE_SimulcastSend_960x540 DISABLED_SimulcastSend_960x540 -#else -#define MAYBE_SimulcastSend_960x540 SimulcastSend_960x540 -#endif -TEST_F(WebRtcVideoMediaChannelSimulcastTest, MAYBE_SimulcastSend_960x540) { - cricket::VideoCodec codec = kVP8Codec; - codec.width = 960; - codec.height = 540; - // TODO(zhurunz): Support 3 layers of simulcast. - SimulcastSend(codec, MAKE_VECTOR(kSsrcs2)); -} - -// Flaky on Windows and tsan. https://code.google.com/p/webrtc/issues/detail?id=4135 -#if defined(WIN32) || defined(THREAD_SANITIZER) -#define MAYBE_SimulcastSend_960x600 DISABLED_SimulcastSend_960x600 -#else -#define MAYBE_SimulcastSend_960x600 SimulcastSend_960x600 -#endif -TEST_F(WebRtcVideoMediaChannelSimulcastTest, MAYBE_SimulcastSend_960x600) { - cricket::VideoCodec codec = kVP8Codec; - codec.width = 960; - codec.height = 600; - // TODO(zhurunz): Support 3 layers of simulcast. - SimulcastSend(codec, MAKE_VECTOR(kSsrcs2)); -} - -// Flaky on Windows and tsan. https://code.google.com/p/webrtc/issues/detail?id=4135 -#if defined(WIN32) || defined(THREAD_SANITIZER) -#define MAYBE_SimulcastSend_640x400 DISABLED_SimulcastSend_640x400 -#else -#define MAYBE_SimulcastSend_640x400 SimulcastSend_640x400 -#endif -TEST_F(WebRtcVideoMediaChannelSimulcastTest, MAYBE_SimulcastSend_640x400) { - cricket::VideoCodec codec = kVP8Codec; - codec.width = 640; - codec.height = 400; - SimulcastSend(codec, MAKE_VECTOR(kSsrcs2)); -} - -// Flaky on Windows and tsan. https://code.google.com/p/webrtc/issues/detail?id=4135 -#if defined(WIN32) || defined(THREAD_SANITIZER) -#define MAYBE_SimulcastSend_640x360 DISABLED_SimulcastSend_640x360 -#else -#define MAYBE_SimulcastSend_640x360 SimulcastSend_640x360 -#endif -TEST_F(WebRtcVideoMediaChannelSimulcastTest, MAYBE_SimulcastSend_640x360) { - cricket::VideoCodec codec = kVP8Codec; - codec.width = 640; - codec.height = 360; - SimulcastSend(codec, MAKE_VECTOR(kSsrcs2)); -} - -// Flaky on Windows and tsan. https://code.google.com/p/webrtc/issues/detail?id=4135 -#if defined(WIN32) || defined(THREAD_SANITIZER) -#define MAYBE_SimulcastSend_480x300 DISABLED_SimulcastSend_480x300 -#else -#define MAYBE_SimulcastSend_480x300 SimulcastSend_480x300 -#endif -TEST_F(WebRtcVideoMediaChannelSimulcastTest, MAYBE_SimulcastSend_480x300) { - cricket::VideoCodec codec = kVP8Codec; - codec.width = 480; - codec.height = 300; - SimulcastSend(codec, MAKE_VECTOR(kSsrcs2)); -} - -TEST_F(WebRtcVideoMediaChannelSimulcastTest, DISABLED_SimulcastSend_480x270) { - cricket::VideoCodec codec = kVP8Codec; - codec.width = 480; - codec.height = 270; - SimulcastSend(codec, MAKE_VECTOR(kSsrcs2)); -} - -// Flaky on Windows and tsan. https://code.google.com/p/webrtc/issues/detail?id=4135 -#if defined(WIN32) || defined(THREAD_SANITIZER) -#define MAYBE_SimulcastSend_320x200 DISABLED_SimulcastSend_320x200 -#else -#define MAYBE_SimulcastSend_320x200 SimulcastSend_320x200 -#endif -TEST_F(WebRtcVideoMediaChannelSimulcastTest, MAYBE_SimulcastSend_320x200) { - cricket::VideoCodec codec = kVP8Codec; - codec.width = 320; - codec.height = 200; - SimulcastSend(codec, MAKE_VECTOR(kSsrcs1)); -} - -// Flaky on Windows and tsan. https://code.google.com/p/webrtc/issues/detail?id=4135 -#if defined(WIN32) || defined(THREAD_SANITIZER) -#define MAYBE_SimulcastSend_320x180 DISABLED_SimulcastSend_320x180 -#else -#define MAYBE_SimulcastSend_320x180 SimulcastSend_320x180 -#endif -TEST_F(WebRtcVideoMediaChannelSimulcastTest, MAYBE_SimulcastSend_320x180) { - cricket::VideoCodec codec = kVP8Codec; - codec.width = 320; - codec.height = 180; - SimulcastSend(codec, MAKE_VECTOR(kSsrcs1)); -} - -// Test reset send codec with simulcast. -// Disabled per b/6773425 -TEST_F(WebRtcVideoMediaChannelSimulcastTest, DISABLED_SimulcastResetSendCodec) { - // Remove stream added in Setup. - EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); - - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - cricket::VideoCodec codec(DefaultCodec()); - EXPECT_TRUE(SetOneCodec(codec)); - EXPECT_TRUE(SetSend(true)); - int packets = 0; - - // Send the first frame with default format size. - EXPECT_TRUE(SendFrame()); - EXPECT_TRUE_WAIT(NumRtpPackets() > packets, kTimeout); - DrainOutgoingPackets(); - packets = NumRtpPackets(); - - // Simulate capture frame size changes. - // Verify there is new rtp packet coming out of the encoder. - - // Send an odd frame. - EXPECT_TRUE(SendCustomVideoFrame(DefaultCodec().width | 0x01, - DefaultCodec().height | 0x01)); - EXPECT_TRUE_WAIT(NumRtpPackets() > packets, kTimeout); - packets = DrainOutgoingPackets(); - - // Send a small frame in width. - EXPECT_TRUE(SendCustomVideoFrame(DefaultCodec().width / 2, - DefaultCodec().height)); - EXPECT_TRUE_WAIT(NumRtpPackets() > packets, kTimeout); - packets = DrainOutgoingPackets(); - - // Send a small frame in height. - EXPECT_TRUE(SendCustomVideoFrame(DefaultCodec().width, - DefaultCodec().height / 2)); - EXPECT_TRUE_WAIT(NumRtpPackets() > packets, kTimeout); - packets = DrainOutgoingPackets(); - - // Send a big frame in width. - EXPECT_TRUE(SendCustomVideoFrame(DefaultCodec().width * 2, - DefaultCodec().height)); - EXPECT_TRUE_WAIT(NumRtpPackets() > packets, kTimeout); - packets = DrainOutgoingPackets(); - - // Send a big frame in height. - EXPECT_TRUE(SendCustomVideoFrame(DefaultCodec().width, - DefaultCodec().height * 2)); - EXPECT_TRUE_WAIT(NumRtpPackets() > packets, kTimeout); - packets = DrainOutgoingPackets(); - - // Send a normal frame. - EXPECT_TRUE(SendCustomVideoFrame(DefaultCodec().width, - DefaultCodec().height)); - EXPECT_TRUE_WAIT(NumRtpPackets() > packets, kTimeout); - packets = DrainOutgoingPackets(); -} - -// Test simulcast streams are decodeable with expected sizes. -TEST_F(WebRtcVideoMediaChannelSimulcastTest, SimulcastStreams) { - // Remove stream added in Setup. - EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); - - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - cricket::VideoCodec codec(DefaultCodec()); - EXPECT_TRUE(SetOneCodec(codec)); - - // Re-configure capturer. - channel_->SetCapturer(kSsrc, NULL); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[0], video_capturer_.get())); - cricket::VideoFormat capture_format(codec.width, codec.height, - cricket::VideoFormat::FpsToInterval(codec.framerate), - cricket::FOURCC_I420); - EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format)); - - EXPECT_TRUE(SetSend(true)); - - cricket::FakeVideoRenderer renderer1, renderer2; - EXPECT_TRUE(channel_->AddRecvStream( - cricket::StreamParams::CreateLegacy(kSsrcs2[0]))); - EXPECT_TRUE(channel_->AddRecvStream( - cricket::StreamParams::CreateLegacy(kSsrcs2[1]))); - EXPECT_TRUE(channel_->SetRenderer(kSsrcs2[0], &renderer1)); - EXPECT_TRUE(channel_->SetRenderer(kSsrcs2[1], &renderer2)); - EXPECT_TRUE(channel_->SetRender(true)); - EXPECT_EQ(0, renderer1.num_rendered_frames()); - EXPECT_EQ(0, renderer2.num_rendered_frames()); - - EXPECT_TRUE(SendFrame()); - EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 1, - DefaultCodec().width / 2, DefaultCodec().height / 2, kTimeout); - EXPECT_FRAME_ON_RENDERER_WAIT(renderer2, 1, - DefaultCodec().width, DefaultCodec().height, kTimeout); - EXPECT_EQ(1, renderer1.num_set_sizes()); - EXPECT_EQ(1, renderer2.num_set_sizes()); -} - -// Simulcast and resolution resizing should be turned off when screencasting -// but not otherwise. -// TODO(dmunene): Fix flaky test with bug 15773660. -TEST_F(WebRtcVideoMediaChannelSimulcastTest, DISABLED_ScreencastRendering) { - // Remove stream added in SetUp. - EXPECT_TRUE(channel_->RemoveSendStream(kSsrc)); - - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Setup a simulcast stream and verify that frames are rendered on - // both renderers. - EXPECT_TRUE(channel_->AddSendStream( - cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2)))); - cricket::VideoCodec codec(DefaultCodec()); - EXPECT_TRUE(SetOneCodec(codec)); - EXPECT_TRUE(SetSend(true)); - - cricket::FakeVideoRenderer renderer1, renderer2; - EXPECT_TRUE(channel_->AddRecvStream( - cricket::StreamParams::CreateLegacy(kSsrcs2[0]))); - EXPECT_TRUE(channel_->AddRecvStream( - cricket::StreamParams::CreateLegacy(kSsrcs2[1]))); - EXPECT_TRUE(channel_->SetRenderer(kSsrcs2[0], &renderer1)); - EXPECT_TRUE(channel_->SetRenderer(kSsrcs2[1], &renderer2)); - EXPECT_TRUE(channel_->SetRender(true)); - EXPECT_EQ(0, renderer1.num_rendered_frames()); - EXPECT_EQ(0, renderer2.num_rendered_frames()); - - // Re-configure capturer. - channel_->SetCapturer(kSsrc, NULL); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[0], video_capturer_.get())); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[1], video_capturer_.get())); - cricket::VideoFormat capture_format(codec.width, codec.height, - cricket::VideoFormat::FpsToInterval(codec.framerate), - cricket::FOURCC_I420); - EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format)); - - EXPECT_TRUE(SendFrame()); - EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 1, codec.width / 2, codec.height / 2, - kTimeout); - EXPECT_FRAME_ON_RENDERER_WAIT(renderer2, 1, codec.width, codec.height, - kTimeout); - - // Register a fake screencast capturer and verify that frames are only - // rendered to a single renderer. - rtc::scoped_ptr capturer( - new cricket::FakeVideoCapturer); - capturer->SetScreencast(true); - const std::vector* formats = - capturer->GetSupportedFormats(); - capture_format = (*formats)[0]; - EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(capture_format)); - // Capture a frame to increment the frame timestamp since the default video - // capturer starts at the same timestamp. - EXPECT_TRUE(capturer->CaptureFrame()); - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[0], capturer.get())); - EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30)); - EXPECT_TRUE(capturer->CaptureFrame()); - EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 2, capture_format.width, - capture_format.height, kTimeout); - // When screencasting we only encode a single stream (no simulcast), which is - // why we only expect frames to be rendered in one of the renderers. - EXPECT_EQ(1, renderer2.num_rendered_frames()); - - // Disable screencast and make sure frames are now rendered in both renderers. - EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[0], NULL)); - EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 3, codec.width / 2, codec.height / 2, - kTimeout); - EXPECT_FRAME_ON_RENDERER_WAIT(renderer2, 2, codec.width, codec.height, - kTimeout); -} - -// Disable for TSan v2, see -// https://code.google.com/p/webrtc/issues/detail?id=3525 for details. -#if !defined(THREAD_SANITIZER) -// Ensures that the correct settings are applied to the codec when two temporal -// layer screencasting is enabled, and that the correct simulcast settings are -// reapplied when disabling screencasting. -TEST_F(WebRtcVideoMediaChannelSimulcastTest, ConferenceModeScreencastSettings) { - TestScreencastSettings(); -} -#endif // if !defined(THREAD_SANITIZER) diff --git a/talk/session/media/channelmanager.cc b/talk/session/media/channelmanager.cc index e4de6d4d2..9c30a9748 100644 --- a/talk/session/media/channelmanager.cc +++ b/talk/session/media/channelmanager.cc @@ -76,16 +76,6 @@ static DataEngineInterface* ConstructDataEngine() { #endif } -#if !defined(DISABLE_MEDIA_ENGINE_FACTORY) -ChannelManager::ChannelManager(rtc::Thread* worker_thread) { - Construct(MediaEngineFactory::Create(), - ConstructDataEngine(), - cricket::DeviceManagerFactory::Create(), - new CaptureManager(), - worker_thread); -} -#endif - ChannelManager::ChannelManager(MediaEngineInterface* me, DataEngineInterface* dme, DeviceManagerInterface* dm, diff --git a/talk/session/media/channelmanager.h b/talk/session/media/channelmanager.h index ca95f65d3..a8eb88d5d 100644 --- a/talk/session/media/channelmanager.h +++ b/talk/session/media/channelmanager.h @@ -60,11 +60,6 @@ class VoiceProcessor; class ChannelManager : public rtc::MessageHandler, public sigslot::has_slots<> { public: -#if !defined(DISABLE_MEDIA_ENGINE_FACTORY) - // Creates the channel manager, and specifies the worker thread to use. - explicit ChannelManager(rtc::Thread* worker); -#endif - // For testing purposes. Allows the media engine and data media // engine and dev manager to be mocks. The ChannelManager takes // ownership of these objects.